diff options
author | Liming Gao <liming.gao@intel.com> | 2017-11-24 14:46:58 +0800 |
---|---|---|
committer | Liming Gao <liming.gao@intel.com> | 2017-12-25 11:05:46 +0800 |
commit | 34952f493c24c02f5eba6ae86ed758d3311cddb1 (patch) | |
tree | a382c9d5cea9ce166bc4566aab73622b5092ed7b | |
parent | ae7b6df816e913394a7f11264f24953658ff34ba (diff) | |
download | edk2-34952f493c24c02f5eba6ae86ed758d3311cddb1.tar.gz |
BaseTools: Collect DynamicHii PCD values and assign it to VPD PCD Value
https://bugzilla.tianocore.org/show_bug.cgi?id=661
Collect all DynamicHii and DynamicExHii PCD value into PCD
PcdNvStoreDefaultValueBuffer, then firmware can access this PCD value
to get the variable default setting.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Feng Bob C <bob.c.feng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
-rw-r--r-- | BaseTools/Source/Python/AutoGen/AutoGen.py | 32 | ||||
-rw-r--r-- | BaseTools/Source/Python/AutoGen/GenPcdDb.py | 25 | ||||
-rw-r--r-- | BaseTools/Source/Python/AutoGen/GenVar.py | 297 | ||||
-rw-r--r-- | BaseTools/Source/Python/Common/Misc.py | 23 | ||||
-rw-r--r-- | BaseTools/Source/Python/Workspace/BuildClassObject.py | 4 |
5 files changed, 356 insertions, 25 deletions
diff --git a/BaseTools/Source/Python/AutoGen/AutoGen.py b/BaseTools/Source/Python/AutoGen/AutoGen.py index 12861399ac..783305c7cc 100644 --- a/BaseTools/Source/Python/AutoGen/AutoGen.py +++ b/BaseTools/Source/Python/AutoGen/AutoGen.py @@ -44,6 +44,7 @@ from Common.MultipleWorkspace import MultipleWorkspace as mws import InfSectionParser
import datetime
import hashlib
+from GenVar import Variable,var_info
## Regular expression for splitting Dependency Expression string into tokens
gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
@@ -1352,6 +1353,26 @@ class PlatformAutoGen(AutoGen): if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
LibAuto.ConstPcd[key] = Pcd.DefaultValue
+ def CollectVariables(self, DynamicPcdSet):
+ VariableInfo = Variable()
+ Index = 0
+ for Pcd in DynamicPcdSet:
+ if not hasattr(Pcd,"DefaultStoreName"):
+ Pcd.DefaultStoreName = ['0']
+ for StorageName in Pcd.DefaultStoreName:
+ pcdname = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))
+ for SkuName in Pcd.SkuInfoList:
+ Sku = Pcd.SkuInfoList[SkuName]
+ SkuId = Sku.SkuId
+ if SkuId == None or SkuId == '':
+ continue
+ if len(Sku.VariableName) > 0:
+ VariableGuidStructure = Sku.VariableGuidValue
+ VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
+ if Pcd.Phase == "DXE":
+ VariableInfo.append_variable(var_info(Index,pcdname,StorageName,SkuId, StringToArray(Sku.VariableName),VariableGuid, Sku.VariableAttribute , Pcd.DefaultValue,Sku.HiiDefaultValue,Pcd.DatumType))
+ Index += 1
+ return VariableInfo
## Collect dynamic PCDs
#
# Gather dynamic PCDs list from each module and their settings from platform
@@ -1582,6 +1603,17 @@ class PlatformAutoGen(AutoGen): if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
+ #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
+ PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))
+ if PcdNvStoreDfBuffer:
+ var_info = self.CollectVariables(self._DynamicPcdList)
+ default_skuobj = PcdNvStoreDfBuffer.SkuInfoList.get("DEFAULT")
+ default_skuobj.DefaultValue = var_info.dump()
+ if default_skuobj:
+ PcdNvStoreDfBuffer.SkuInfoList.clear()
+ PcdNvStoreDfBuffer.SkuInfoList['DEFAULT'] = default_skuobj
+ PcdNvStoreDfBuffer.MaxDatumSize = len(default_skuobj.DefaultValue.split(","))
+
PlatformPcds = self._PlatformPcds.keys()
PlatformPcds.sort()
#
diff --git a/BaseTools/Source/Python/AutoGen/GenPcdDb.py b/BaseTools/Source/Python/AutoGen/GenPcdDb.py index ddbfe281b8..40743d1fd6 100644 --- a/BaseTools/Source/Python/AutoGen/GenPcdDb.py +++ b/BaseTools/Source/Python/AutoGen/GenPcdDb.py @@ -628,31 +628,6 @@ def GetMatchedIndex(Key1, List1, Key2, List2): return -1
-## Get the integer value from string like "14U" or integer like 2
-#
-# @param Input The object that may be either a integer value or a string
-#
-# @retval Value The integer value that the input represents
-#
-def GetIntegerValue(Input):
- if type(Input) in (int, long):
- return Input
- String = Input
- if String.endswith("U"):
- String = String[:-1]
- if String.endswith("ULL"):
- String = String[:-3]
- if String.endswith("LL"):
- String = String[:-2]
-
- if String.startswith("0x") or String.startswith("0X"):
- return int(String, 16)
- elif String == '':
- return 0
- else:
- return int(String)
-
-
## convert StringArray like {0x36, 0x00, 0x34, 0x00, 0x21, 0x00, 0x36, 0x00, 0x34, 0x00, 0x00, 0x00}
# to List like [0x36, 0x00, 0x34, 0x00, 0x21, 0x00, 0x36, 0x00, 0x34, 0x00, 0x00, 0x00]
#
diff --git a/BaseTools/Source/Python/AutoGen/GenVar.py b/BaseTools/Source/Python/AutoGen/GenVar.py new file mode 100644 index 0000000000..9b76078a07 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/GenVar.py @@ -0,0 +1,297 @@ +# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+#
+# This file is used to collect the Variable checking information
+#
+
+# #
+# Import Modules
+#
+from struct import pack,unpack
+import collections
+import copy
+from Common.VariableAttributes import VariableAttributes
+from Common.Misc import *
+import collections
+
+var_info = collections.namedtuple("uefi_var", "pcdindex,pcdname,defaultstoragename,skuname,var_name, var_guid, var_attribute,pcd_default_value, default_value, data_type")
+NvStorageHeaderSize = 28
+VariableHeaderSize = 32
+
+def StringArrayToList(StringArray):
+ StringArray = StringArray[1:-1]
+ StringArray = '[' + StringArray + ']'
+ return eval(StringArray)
+
+def PackGUID(Guid):
+ GuidBuffer = pack('=LHHBBBBBBBB',
+ int(Guid[0], 16),
+ int(Guid[1], 16),
+ int(Guid[2], 16),
+ int(Guid[3][-4:-2], 16),
+ int(Guid[3][-2:], 16),
+ int(Guid[4][-12:-10], 16),
+ int(Guid[4][-10:-8], 16),
+ int(Guid[4][-8:-6], 16),
+ int(Guid[4][-6:-4], 16),
+ int(Guid[4][-4:-2], 16),
+ int(Guid[4][-2:], 16)
+ )
+ return GuidBuffer
+
+class Variable(object):
+ def __init__(self,):
+ self.VarInfo = []
+
+ def append_variable(self,uefi_var):
+ self.VarInfo.append(uefi_var)
+
+ def process_variable_data(self):
+
+ var_data = dict()
+
+ indexedvarinfo = collections.OrderedDict()
+ for item in self.VarInfo:
+ if item.pcdindex not in indexedvarinfo:
+ indexedvarinfo[item.pcdindex] = dict()
+ indexedvarinfo[item.pcdindex][(int(item.skuname),int(item.defaultstoragename))] = item
+
+ for index in indexedvarinfo:
+ sku_var_info = indexedvarinfo[index]
+
+ default_data_buffer = ""
+ others_data_buffer = ""
+ tail = None
+ default_sku_default = indexedvarinfo.get(index).get((0,0))
+
+ if default_sku_default.data_type not in ["UINT8","UINT16","UINT32","UINT64","BOOLEAN"]:
+ var_max_len = max([len(var_item.default_value.split(",")) for var_item in sku_var_info.values()])
+ if len(default_sku_default.default_value.split(",")) < var_max_len:
+ tail = ",".join([ "0x00" for i in range(var_max_len-len(default_sku_default.default_value.split(",")))])
+
+ default_data_buffer = self.PACK_VARIABLES_DATA(default_sku_default.default_value,default_sku_default.data_type,tail)
+
+ default_data_array = ()
+ for item in default_data_buffer:
+ default_data_array += unpack("B",item)
+
+ if (0,0) not in var_data:
+ var_data[(0,0)] = collections.OrderedDict()
+ var_data[(0,0)][index] = (default_data_buffer,sku_var_info[(0,0)])
+
+ for (skuid,defaultstoragename) in indexedvarinfo.get(index):
+ tail = None
+ if (skuid,defaultstoragename) == (0,0):
+ continue
+ other_sku_other = indexedvarinfo.get(index).get((skuid,defaultstoragename))
+
+ if default_sku_default.data_type not in ["UINT8","UINT16","UINT32","UINT64","BOOLEAN"]:
+ if len(other_sku_other.default_value.split(",")) < var_max_len:
+ tail = ",".join([ "0x00" for i in range(var_max_len-len(other_sku_other.default_value.split(",")))])
+
+ others_data_buffer = self.PACK_VARIABLES_DATA(other_sku_other.default_value,other_sku_other.data_type,tail)
+
+ others_data_array = ()
+ for item in others_data_buffer:
+ others_data_array += unpack("B",item)
+
+ data_delta = self.calculate_delta(default_data_array, others_data_array)
+
+ if (skuid,defaultstoragename) not in var_data:
+ var_data[(skuid,defaultstoragename)] = collections.OrderedDict()
+ var_data[(skuid,defaultstoragename)][index] = (data_delta,sku_var_info[(skuid,defaultstoragename)])
+ return var_data
+
+ def new_process_varinfo(self):
+
+ var_data = self.process_variable_data()
+
+ pcds_default_data = var_data.get((0,0))
+ NvStoreDataBuffer = ""
+ var_data_offset = collections.OrderedDict()
+ offset = NvStorageHeaderSize
+ for default_data,default_info in pcds_default_data.values():
+ var_name_buffer = self.PACK_VARIABLE_NAME(default_info.var_name)
+
+ vendorguid = default_info.var_guid.split('-')
+
+ if default_info.var_attribute:
+ var_attr_value,_ = VariableAttributes.GetVarAttributes(default_info.var_attribute)
+ else:
+ var_attr_value = 0x07
+
+ print "default var_name_buffer"
+ print self.format_data(var_name_buffer)
+ print "default var_buffer"
+ print self.format_data(default_data)
+
+ DataBuffer = self.AlignData(var_name_buffer + default_data)
+
+ data_size = len(DataBuffer)
+ offset += VariableHeaderSize + len(default_info.var_name.split(","))
+ var_data_offset[default_info.pcdindex] = offset
+ offset += data_size - len(default_info.var_name.split(","))
+
+ var_header_buffer = self.PACK_VARIABLE_HEADER(var_attr_value, len(default_info.var_name.split(",")), data_size, vendorguid)
+ NvStoreDataBuffer += (var_header_buffer + DataBuffer)
+
+ variable_storage_header_buffer = self.PACK_VARIABLE_STORE_HEADER(len(NvStoreDataBuffer) + 28)
+
+ nv_default_part = self.AlignData(self.PACK_DEFAULT_DATA(0, 0, self.unpack_data(variable_storage_header_buffer+NvStoreDataBuffer)))
+
+ print "default whole data \n",self.format_data(nv_default_part)
+
+ data_delta_structure_buffer = ""
+ for skuid,defaultid in var_data:
+ if (skuid,defaultid) == (0,0):
+ continue
+ pcds_sku_data = var_data.get((skuid,defaultid))
+ delta_data_set = []
+ for pcdindex in pcds_sku_data:
+ offset = var_data_offset[pcdindex]
+ delta_data,_ = pcds_sku_data[pcdindex]
+ delta_data = [(item[0] + offset, item[1]) for item in delta_data]
+ delta_data_set.extend(delta_data)
+
+ data_delta_structure_buffer += self.AlignData(self.PACK_DELTA_DATA(defaultid,skuid,delta_data_set))
+ print "delta data"
+ print delta_data_set
+ print self.format_data(self.AlignData(self.PACK_DELTA_DATA(defaultid,skuid,delta_data_set)))
+
+ return self.format_data(nv_default_part + data_delta_structure_buffer)
+
+
+ def format_data(self,data):
+
+ return [hex(item) for item in self.unpack_data(data)]
+
+ def unpack_data(self,data):
+ final_data = ()
+ for item in data:
+ final_data += unpack("B",item)
+ return final_data
+
+ def calculate_delta(self, default, theother):
+ print "default data \n", default
+ print "other data \n",theother
+ if len(default) - len(theother) != 0:
+ EdkLogger.error("build", FORMAT_INVALID, 'The variable data length is not the same for the same PCD.')
+ data_delta = []
+ for i in range(len(default)):
+ if default[i] != theother[i]:
+ data_delta.append((i,theother[i]))
+ return data_delta
+
+ def dump(self):
+
+ default_var_bin = self.new_process_varinfo()
+ value_str = "{"
+ default_var_bin_strip = [ data.strip("""'""") for data in default_var_bin]
+ value_str += ",".join(default_var_bin_strip)
+ value_str += "}"
+ return value_str
+
+ def PACK_VARIABLE_STORE_HEADER(self,size):
+ #Signature: gEfiVariableGuid
+ Guid = "{ 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}"
+ Guid = GuidStructureStringToGuidString(Guid)
+ GuidBuffer = PackGUID(Guid.split('-'))
+
+ SizeBuffer = pack('=L',size)
+ FormatBuffer = pack('=B',0x5A)
+ StateBuffer = pack('=B',0xFE)
+ reservedBuffer = pack('=H',0)
+ reservedBuffer += pack('=L',0)
+
+ return GuidBuffer + SizeBuffer + FormatBuffer + StateBuffer + reservedBuffer
+
+
+ def PACK_VARIABLE_HEADER(self,attribute,namesize,datasize,vendorguid):
+
+ Buffer = pack('=H',0x55AA) # pack StartID
+ Buffer += pack('=B',0x3F) # pack State
+ Buffer += pack('=B',0) # pack reserved
+
+ Buffer += pack('=L',attribute)
+ Buffer += pack('=L',namesize)
+ Buffer += pack('=L',datasize)
+
+ Buffer += PackGUID(vendorguid)
+
+ return Buffer
+
+ def PACK_VARIABLES_DATA(self, var_value,data_type, tail = None):
+ Buffer = ""
+ data_len = 0
+ if data_type == "VOID*":
+ for value_char in var_value.strip("{").strip("}").split(","):
+ Buffer += pack("=B",int(value_char,16))
+ data_len += len(var_value.split(","))
+ if tail:
+ for value_char in tail.split(","):
+ Buffer += pack("=B",int(value_char,16))
+ data_len += len(tail.split(","))
+ elif data_type == "BOOLEAN":
+ Buffer += pack("=B",True) if var_value.upper() == "TRUE" else pack("=B",False)
+ data_len += 1
+ elif data_type == "UINT8":
+ Buffer += pack("=B",GetIntegerValue(var_value))
+ data_len += 1
+ elif data_type == "UINT16":
+ Buffer += pack("=H",GetIntegerValue(var_value))
+ data_len += 2
+ elif data_type == "UINT32":
+ Buffer += pack("=L",GetIntegerValue(var_value))
+ data_len += 4
+ elif data_type == "UINT64":
+ Buffer += pack("=Q",GetIntegerValue(var_value))
+ data_len += 8
+
+ return Buffer
+
+ def PACK_DEFAULT_DATA(self, defaultstoragename,skuid,var_value):
+ Buffer = ""
+ Buffer += pack("=H",6)
+ Buffer += pack("=H",int(defaultstoragename))
+ Buffer += pack("=H",int(skuid))
+
+ for item in var_value:
+ Buffer += pack("=B",item)
+
+ Buffer = pack("=L",len(Buffer)+4) + Buffer
+
+ return Buffer
+
+ def PACK_DELTA_DATA(self,defaultstoragename,skuid,delta_list):
+ Buffer = ""
+ Buffer += pack("=H",6)
+ Buffer += pack("=H",int(defaultstoragename))
+ Buffer += pack("=H",int(skuid))
+ for (delta_offset,value) in delta_list:
+ Buffer += pack("=L",delta_offset)
+ Buffer = Buffer[:-1] + pack("=B",value)
+
+ Buffer = pack("=L",len(Buffer) + 4) + Buffer
+
+ return Buffer
+
+ def AlignData(self,data, align = 4):
+ mybuffer = data
+ for i in range(len(data) % align):
+ mybuffer += pack("=B",0)
+
+ return mybuffer
+
+ def PACK_VARIABLE_NAME(self, var_name):
+ Buffer = ""
+ for name_char in var_name.strip("{").strip("}").split(","):
+ Buffer += pack("=B",int(name_char,16))
+
+ return Buffer
\ No newline at end of file diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 2bbd9945fc..3ae2ec5b59 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -2201,6 +2201,29 @@ def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Val elif Value == 'FALSE' or Value == '0':
Value = '0'
return Value
+## Get the integer value from string like "14U" or integer like 2
+#
+# @param Input The object that may be either a integer value or a string
+#
+# @retval Value The integer value that the input represents
+#
+def GetIntegerValue(Input):
+ if type(Input) in (int, long):
+ return Input
+ String = Input
+ if String.endswith("U"):
+ String = String[:-1]
+ if String.endswith("ULL"):
+ String = String[:-3]
+ if String.endswith("LL"):
+ String = String[:-2]
+
+ if String.startswith("0x") or String.startswith("0X"):
+ return int(String, 16)
+ elif String == '':
+ return 0
+ else:
+ return int(String)
##
#
diff --git a/BaseTools/Source/Python/Workspace/BuildClassObject.py b/BaseTools/Source/Python/Workspace/BuildClassObject.py index da265b68f1..6150557cfb 100644 --- a/BaseTools/Source/Python/Workspace/BuildClassObject.py +++ b/BaseTools/Source/Python/Workspace/BuildClassObject.py @@ -122,12 +122,16 @@ class StructurePcd(PcdClassObject): return self.TypeName
def AddDefaultValue (self, FieldName, Value, FileName="", LineNo=0):
+ if FieldName in self.DefaultValues:
+ del self.DefaultValues[FieldName]
self.DefaultValues[FieldName] = [Value.strip(), FileName, LineNo]
return self.DefaultValues[FieldName]
def AddOverrideValue (self, FieldName, Value, SkuName, FileName="", LineNo=0):
if SkuName not in self.SkuOverrideValues:
self.SkuOverrideValues[SkuName] = collections.OrderedDict({})
+ if FieldName in self.SkuOverrideValues[SkuName]:
+ del self.SkuOverrideValues[SkuName][FieldName]
self.SkuOverrideValues[SkuName][FieldName] = [Value.strip(), FileName, LineNo]
return self.SkuOverrideValues[SkuName][FieldName]
|