From: Liming Gao Date: Fri, 24 Nov 2017 06:46:58 +0000 (+0800) Subject: BaseTools: Collect DynamicHii PCD values and assign it to VPD PCD Value X-Git-Tag: edk2-stable201903~2765 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=34952f493c24c02f5eba6ae86ed758d3311cddb1;hp=ae7b6df816e913394a7f11264f24953658ff34ba 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 Reviewed-by: Liming Gao --- 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.
+# 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]