From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web08.35482.1628855125116238152 for ; Fri, 13 Aug 2021 04:45:25 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: bob.c.feng@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10074"; a="202707179" X-IronPort-AV: E=Sophos;i="5.84,318,1620716400"; d="scan'208";a="202707179" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Aug 2021 04:45:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.84,318,1620716400"; d="scan'208";a="508190698" Received: from shwdepsi1121.ccr.corp.intel.com ([10.239.158.137]) by fmsmga004.fm.intel.com with ESMTP; 13 Aug 2021 04:45:22 -0700 From: "Bob Feng" To: devel@edk2.groups.io Cc: Liming Gao , Yuwei Chen Subject: [Patch 2/2] BaseTools: a new build option for variable default value generation Date: Fri, 13 Aug 2021 19:45:20 +0800 Message-Id: <20210813114520.2057-1-bob.c.feng@intel.com> X-Mailer: git-send-email 2.29.1.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3562 Create a new build option to enable vfrcompile to generate Json format EFI variable information file and read it to generate=20 the EFI variable default value binary file. Signed-off-by: Bob Feng Cc: Liming Gao Cc: Yuwei Chen --- BaseTools/Source/Python/AutoGen/DataPipe.py | 2 + .../Source/Python/AutoGen/GenDefaultVar.py | 498 ++++++++++++++++++ .../Source/Python/AutoGen/ModuleAutoGen.py | 9 + .../Python/AutoGen/ModuleAutoGenHelper.py | 4 + BaseTools/Source/Python/Common/GlobalData.py | 5 + BaseTools/Source/Python/build/build.py | 18 + BaseTools/Source/Python/build/buildoptions.py | 1 + 7 files changed, 537 insertions(+) create mode 100644 BaseTools/Source/Python/AutoGen/GenDefaultVar.py diff --git a/BaseTools/Source/Python/AutoGen/DataPipe.py b/BaseTools/Source= /Python/AutoGen/DataPipe.py index 86ac2b928d9c..fa0c36b98f21 100755 --- a/BaseTools/Source/Python/AutoGen/DataPipe.py +++ b/BaseTools/Source/Python/AutoGen/DataPipe.py @@ -165,5 +165,7 @@ class MemoryDataPipe(DataPipe): self.DataContainer =3D {"BinCacheSource":GlobalData.gBinCacheSourc= e}=0D =0D self.DataContainer =3D {"BinCacheDest":GlobalData.gBinCacheDest}=0D =0D self.DataContainer =3D {"EnableGenfdsMultiThread":GlobalData.gEnab= leGenfdsMultiThread}=0D +=0D + self.DataContainer =3D {"GenDefaultVarBin": GlobalData.gGenDefault= VarBin}=0D diff --git a/BaseTools/Source/Python/AutoGen/GenDefaultVar.py b/BaseTools/S= ource/Python/AutoGen/GenDefaultVar.py new file mode 100644 index 000000000000..b82cce18ed26 --- /dev/null +++ b/BaseTools/Source/Python/AutoGen/GenDefaultVar.py @@ -0,0 +1,498 @@ +import json=0D +from ctypes import *=0D +import re=0D +import copy=0D +from struct import unpack=0D +import os=0D +=0D +class GUID(Structure):=0D + _fields_ =3D [=0D + ('Guid1', c_uint32),=0D + ('Guid2', c_uint16),=0D + ('Guid3', c_uint16),=0D + ('Guid4', ARRAY(c_uint8, 8)),=0D + ]=0D +=0D + def from_list(self, listformat):=0D + self.Guid1 =3D listformat[0]=0D + self.Guid2 =3D listformat[1]=0D + self.Guid3 =3D listformat[2]=0D + for i in range(8):=0D + self.Guid4[i] =3D listformat[i+3]=0D +=0D + def __cmp__(self, otherguid):=0D + if isinstance(otherguid, GUID):=0D + return 1=0D + rt =3D False=0D + if self.Guid1 =3D=3D otherguid.Guid1 and self.Guid2 =3D=3D othergu= id.Guid2 and self.Guid3 =3D=3D otherguid.Guid3:=0D + rt =3D True=0D + for i in range(8):=0D + rt =3D rt & (self.Guid4[i] =3D=3D otherguid.Guid4[i])=0D + return rt=0D +=0D +=0D +class TIME(Structure):=0D + _fields_ =3D [=0D + ('Year', c_uint16),=0D + ('Month', c_uint8),=0D + ('Day', c_uint8),=0D + ('Hour', c_uint8),=0D + ('Minute', c_uint8),=0D + ('Second', c_uint8),=0D + ('Pad1', c_uint8),=0D + ('Nanosecond', c_uint32),=0D + ('TimeZone', c_uint16),=0D + ('Daylight', c_uint8),=0D + ('Pad2', c_uint8),=0D + ]=0D + def __init__(self):=0D + self.Year =3D 0x0=0D + self.Month =3D 0x0=0D + self.Day =3D 0x0=0D + self.Hour =3D 0x0=0D + self.Minute =3D 0x0=0D + self.Second =3D 0x0=0D + self.Pad1 =3D 0x0=0D + self.Nanosecond =3D 0x0=0D + self.TimeZone =3D 0x0=0D + self.Daylight =3D 0x0=0D + self.Pad2 =3D 0x0=0D +=0D +=0D +EFI_VARIABLE_GUID =3D [0xddcf3616, 0x3275, 0x4164,=0D + 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d]=0D +EFI_AUTHENTICATED_VARIABLE_GUID =3D [=0D + 0xaaf32c78, 0x947b, 0x439a, 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, = 0x92]=0D +=0D +AuthVarGuid =3D GUID()=0D +AuthVarGuid.from_list(EFI_AUTHENTICATED_VARIABLE_GUID)=0D +VarGuid =3D GUID()=0D +VarGuid.from_list(EFI_VARIABLE_GUID)=0D +=0D +# Variable Store Header Format.=0D +VARIABLE_STORE_FORMATTED =3D 0x5a=0D +# Variable Store Header State.=0D +VARIABLE_STORE_HEALTHY =3D 0xfe=0D +=0D +=0D +class VARIABLE_STORE_HEADER(Structure):=0D + _fields_ =3D [=0D + ('Signature', GUID),=0D + ('Size', c_uint32),=0D + ('Format', c_uint8),=0D + ('State', c_uint8),=0D + ('Reserved', c_uint16),=0D + ('Reserved1', c_uint32),=0D + ]=0D +=0D +=0D +# Variable data start flag.=0D +VARIABLE_DATA =3D 0x55AA=0D +=0D +# Variable State flags.=0D +VAR_IN_DELETED_TRANSITION =3D 0xfe=0D +VAR_DELETED =3D 0xfd=0D +VAR_HEADER_VALID_ONLY =3D 0x7f=0D +VAR_ADDED =3D 0x3f=0D +=0D +=0D +class VARIABLE_HEADER(Structure):=0D + _fields_ =3D [=0D + ('StartId', c_uint16),=0D + ('State', c_uint8),=0D + ('Reserved', c_uint8),=0D + ('Attributes', c_uint32),=0D + ('NameSize', c_uint32),=0D + ('DataSize', c_uint32),=0D + ('VendorGuid', GUID),=0D + ]=0D +=0D +=0D +class AUTHENTICATED_VARIABLE_HEADER(Structure):=0D + _fields_ =3D [=0D + ('StartId', c_uint16),=0D + ('State', c_uint8),=0D + ('Reserved', c_uint8),=0D + ('Attributes', c_uint32),=0D + ('MonotonicCount', c_uint64),=0D + ('TimeStamp', TIME),=0D + ('PubKeyIndex', c_uint32),=0D + ('NameSize', c_uint32),=0D + ('DataSize', c_uint32),=0D + ('VendorGuid', GUID),=0D + ]=0D + _pack_ =3D 1=0D +=0D +=0D +# Alignment of Variable Data Header in Variable Store region.=0D +HEADER_ALIGNMENT =3D 4=0D +=0D +=0D +class DEFAULT_INFO(Structure):=0D + _fields_ =3D [=0D + ('DefaultId', c_uint16),=0D + ('BoardId', c_uint16),=0D + ]=0D +=0D +=0D +class DEFAULT_DATA(Structure):=0D + _fields_ =3D [=0D + ('HeaderSize', c_uint16),=0D + ('DefaultInfo', DEFAULT_INFO),=0D + ]=0D +=0D +class DELTA_DATA(Structure):=0D + _fields_ =3D [=0D + ('Offset', c_uint16),=0D + ('Value', c_uint8),=0D + ]=0D + _pack_ =3D 1=0D +=0D +array_re =3D re.compile(=0D + "(?P[a-z_A-Z][a-z_A-Z0-9]*)\[(?P[1-9][0-9]*)\]")=0D +=0D +=0D +class VarField():=0D + def __init__(self):=0D + self.Offset =3D 0=0D + self.Value =3D 0=0D + self.Size =3D 0=0D +=0D + @property=0D + def Type(self):=0D + if self.Size =3D=3D 1:=0D + return "UINT8"=0D + if self.Size =3D=3D 2:=0D + return "UINT16"=0D + if self.Size =3D=3D 4:=0D + return "UINT32"=0D + if self.Size =3D=3D 8:=0D + return "UINT64"=0D +=0D + return "UINT8"=0D +=0D +=0D +BASIC_TYPE =3D {=0D + "BOOLEAN": 1,=0D + "UINT8": 1,=0D + "UINT16": 2,=0D + "UINT32": 4,=0D + "UINT64": 8=0D +}=0D +class CStruct():=0D +=0D +=0D + def __init__(self, typedefs):=0D + self.TypeDefs =3D typedefs=0D + self.TypeStack =3D copy.deepcopy(typedefs)=0D + self.finalDefs =3D {}=0D +=0D + def CalStuctSize(self, sType):=0D + rt =3D 0=0D + if sType in BASIC_TYPE:=0D + return BASIC_TYPE[sType]=0D +=0D + ma =3D array_re.match(sType)=0D + if ma:=0D + mType =3D ma.group('mType')=0D + mSize =3D ma.group('mSize')=0D + rt +=3D int(mSize) * self.CalStuctSize(mType)=0D + else:=0D + for subType in self.TypeDefs[sType]:=0D + rt +=3D self.CalStuctSize(subType['Type'])=0D +=0D + return rt=0D +=0D + def expend(self, fielditem):=0D + fieldname =3D fielditem['Name']=0D + fieldType =3D fielditem['Type']=0D + fieldOffset =3D fielditem['Offset']=0D +=0D + ma =3D array_re.match(fieldType)=0D + if ma:=0D + mType =3D ma.group('mType')=0D + mSize =3D ma.group('mSize')=0D + return [{"Name": "%s[%d]" % (fieldname, i), "Type": mType, "Of= fset": (fieldOffset + i*self.CalStuctSize(mType))} for i in range(int(mSize= ))]=0D + else:=0D + return [{"Name": "%s.%s" % (fieldname, item['Name']), "Type":i= tem['Type'], "Offset": (fieldOffset + item['Offset'])} for item in self.Typ= eDefs[fielditem['Type']]]=0D +=0D + def ExpandTypes(self):=0D + if not self.finalDefs:=0D + for datatype in self.TypeStack:=0D + result =3D []=0D + mTypeStack =3D self.TypeStack[datatype]=0D + while len(mTypeStack) > 0:=0D + item =3D mTypeStack.pop()=0D + if item['Type'] in self.BASIC_TYPE:=0D + result.append(item)=0D + elif item['Type'] =3D=3D '(null)':=0D + continue=0D + else:=0D + for expand_item in self.expend(item):=0D + mTypeStack.append(expand_item)=0D + self.finalDefs[datatype] =3D result=0D + self.finalDefs=0D + return self.finalDefs=0D +=0D +def Get_Occupied_Size(FileLength, alignment):=0D + if FileLength % alignment =3D=3D 0:=0D + return FileLength=0D + return FileLength + (alignment-(FileLength % alignment))=0D +=0D +def Occupied_Size(buffer, alignment):=0D + FileLength =3D len(buffer)=0D + if FileLength % alignment !=3D 0:=0D + buffer +=3D b'\0' * (alignment-(FileLength % alignment))=0D + return buffer=0D +=0D +def PackStruct(cStruct):=0D + length =3D sizeof(cStruct)=0D + p =3D cast(pointer(cStruct), POINTER(c_char * length))=0D + return p.contents.raw=0D +=0D +def calculate_delta(default, theother):=0D +=0D + if len(default) - len(theother) !=3D 0:=0D + return []=0D +=0D + data_delta =3D []=0D + for i in range(len(default)):=0D + if default[i] !=3D theother[i]:=0D + data_delta.append([i, theother[i]])=0D + return data_delta=0D +=0D +class Variable():=0D + def __init__(self):=0D + self.mAlign =3D 1=0D + self.mTotalSize =3D 1=0D + self.mValue =3D {} # {defaultstore: value}=0D + self.mBin =3D {}=0D + self.fields =3D {} # {defaultstore: fileds}=0D + self.delta =3D {}=0D + self.attributes =3D 0=0D + self.mType =3D ''=0D + self.guid =3D ''=0D + self.mName =3D ''=0D + self.cDefs =3D None=0D +=0D + @property=0D + def GuidArray(self):=0D +=0D + guid_array =3D []=0D + guid =3D self.guid.strip().strip("{").strip("}")=0D + for item in guid.split(","):=0D + field =3D item.strip().strip("{").strip("}")=0D + guid_array.append(int(field,16))=0D + return guid_array=0D +=0D + def update_delta_offset(self,base):=0D + for default_id in self.delta:=0D + for delta_list in self.delta[default_id]:=0D + delta_list[0] +=3D base=0D +=0D + def pack(self):=0D +=0D + for defaultid in self.mValue:=0D + var_value =3D self.mValue[defaultid]=0D + auth_var =3D AUTHENTICATED_VARIABLE_HEADER()=0D + auth_var.StartId =3D VARIABLE_DATA=0D + auth_var.State =3D VAR_ADDED=0D + auth_var.Reserved =3D 0x00=0D + auth_var.Attributes =3D 0x00000007=0D + auth_var.MonotonicCount =3D 0x0=0D + auth_var.TimeStamp =3D TIME()=0D + auth_var.PubKeyIndex =3D 0x0=0D + var_name_buffer =3D self.mName.encode('utf-16le') + b'\0\0'=0D + auth_var.NameSize =3D len(var_name_buffer)=0D + auth_var.DataSize =3D len(var_value)=0D + vendor_guid =3D GUID()=0D + vendor_guid.from_list(self.GuidArray)=0D + auth_var.VendorGuid =3D vendor_guid=0D +=0D + self.mBin[defaultid] =3D PackStruct(auth_var) + Occupied_Size(= var_name_buffer + var_value, 4)=0D +=0D + def TypeCheck(self,data_type, data_size):=0D + if BASIC_TYPE[data_type] =3D=3D data_size:=0D + return True=0D + return False=0D +=0D + def ValueToBytes(self,data_type,data_value,data_size):=0D +=0D + rt =3D b''=0D + if not self.TypeCheck(data_type, data_size):=0D + print(data_type,data_value,data_size)=0D +=0D + if data_type =3D=3D "BOOLEAN" or data_type =3D=3D 'UINT8':=0D + p =3D cast(pointer(c_uint8(int(data_value,16))), POINTER(c_cha= r * 1))=0D + rt =3D p.contents.raw=0D + elif data_type =3D=3D 'UINT16':=0D + p =3D cast(pointer(c_uint16(int(data_value,16))), POINTER(c_ch= ar * 2))=0D + rt =3D p.contents.raw=0D + elif data_type =3D=3D 'UINT32':=0D + p =3D cast(pointer(c_uint32(int(data_value,16))), POINTER(c_ch= ar * 4))=0D + rt =3D p.contents.raw=0D + elif data_type =3D=3D 'UINT64':=0D + p =3D cast(pointer(c_uint64(int(data_value,16))), POINTER(c_ch= ar * 8))=0D + rt =3D p.contents.raw=0D +=0D + return rt=0D +=0D + def serial(self):=0D + for defaultstore in self.fields:=0D + vValue =3D b''=0D + vfields =3D {vf.Offset: vf for vf in self.fields[defaultstore]= }=0D + i =3D 0=0D + while i < self.mTotalSize:=0D + if i in vfields:=0D + vfield =3D vfields[i]=0D + vValue +=3D self.ValueToBytes(vfield.Type, vfield.Valu= e,vfield.Size)=0D + i +=3D vfield.Size=0D + else:=0D + vValue +=3D self.ValueToBytes('UINT8','0x00',1)=0D + i +=3D 1=0D +=0D + self.mValue[defaultstore] =3D vValue=0D + standard_default =3D self.mValue[0]=0D +=0D + for defaultid in self.mValue:=0D + if defaultid =3D=3D 0:=0D + continue=0D + others_default =3D self.mValue[defaultid]=0D +=0D + self.delta.setdefault(defaultid, []).extend(calculate_delta(=0D + standard_default, others_default))=0D +=0D +class DefaultVariableGenerator():=0D + def __init__(self):=0D + self.NvVarInfo =3D []=0D +=0D + def LoadNvVariableInfo(self, VarInfoFilelist):=0D +=0D + VarDataDict =3D {}=0D + DataStruct =3D {}=0D + VarDefine =3D {}=0D + VarAttributes =3D {}=0D + for VarInfoFile in VarInfoFilelist:=0D + with open(VarInfoFile.strip(), "r") as fd:=0D + data =3D json.load(fd)=0D +=0D + DataStruct.update(data.get("DataStruct", {}))=0D + Data =3D data.get("Data")=0D + VarDefine.update(data.get("VarDefine"))=0D + VarAttributes.update(data.get("DataStructAttribute"))=0D +=0D + for vardata in Data:=0D + if vardata['VendorGuid'] =3D=3D 'NA':=0D + continue=0D + VarDataDict.setdefault(=0D + (vardata['VendorGuid'], vardata["VarName"]), []).appen= d(vardata)=0D +=0D + cStructDefs =3D CStruct(DataStruct)=0D + for guid, varname in VarDataDict:=0D + v =3D Variable()=0D + v.guid =3D guid=0D + vardef =3D VarDefine.get(varname)=0D + if vardef is None:=0D + for var in VarDefine:=0D + if VarDefine[var]['Type'] =3D=3D varname:=0D + vardef =3D VarDefine[var]=0D + break=0D + else:=0D + continue=0D + v.attributes =3D vardef['Attributes']=0D + v.mType =3D vardef['Type']=0D + v.mAlign =3D VarAttributes[v.mType]['Alignment']=0D + v.mTotalSize =3D VarAttributes[v.mType]['TotalSize']=0D + v.Struct =3D DataStruct[v.mType]=0D + v.mName =3D varname=0D + v.cDefs =3D cStructDefs=0D + for fieldinfo in VarDataDict.get((guid, varname), []):=0D + vf =3D VarField()=0D + vf.Offset =3D fieldinfo['Offset']=0D + vf.Value =3D fieldinfo['Value']=0D + vf.Size =3D fieldinfo['Size']=0D + v.fields.setdefault(=0D + int(fieldinfo['DefaultStore'], 10), []).append(vf)=0D + v.serial()=0D + v.pack()=0D + self.NvVarInfo.append(v)=0D +=0D + def PackDeltaData(self):=0D +=0D + default_id_set =3D set()=0D + for v in self.NvVarInfo:=0D + default_id_set |=3D set(v.mBin.keys())=0D +=0D + if default_id_set:=0D + default_id_set.remove(0)=0D + delta_buff_set =3D {}=0D + for defaultid in default_id_set:=0D + delta_buff =3D b''=0D + for v in self.NvVarInfo:=0D + delta_list =3D v.delta.get(defaultid,[])=0D + for delta in delta_list:=0D + delta_data =3D DELTA_DATA()=0D + delta_data.Offset, delta_data.Value =3D delta=0D + delta_buff +=3D PackStruct(delta_data)=0D + delta_buff_set[defaultid] =3D delta_buff=0D +=0D + return delta_buff_set=0D +=0D + def PackDefaultData(self):=0D +=0D + default_data_header =3D DEFAULT_DATA()=0D + default_data_header.HeaderSize =3D sizeof(DEFAULT_DATA)=0D + default_data_header.DefaultInfo.DefaultId =3D 0x0=0D + default_data_header.DefaultInfo.BoardId =3D 0x0=0D + default_data_header_buffer =3D PackStruct(default_data_header)=0D +=0D +=0D + variable_store =3D VARIABLE_STORE_HEADER()=0D + variable_store.Signature =3D AuthVarGuid=0D +=0D + variable_store_size =3D Get_Occupied_Size(sizeof(DEFAULT_DATA) + s= izeof(VARIABLE_STORE_HEADER), 4)=0D + for v in self.NvVarInfo:=0D + variable_store_size +=3D Get_Occupied_Size(len(v.mBin[0]), 4)= =0D +=0D + variable_store.Size =3D variable_store_size=0D + variable_store.Format =3D VARIABLE_STORE_FORMATTED=0D + variable_store.State =3D VARIABLE_STORE_HEALTHY=0D + variable_store.Reserved =3D 0x0=0D + variable_store.Reserved2 =3D 0x0=0D +=0D + variable_storage_header_buffer =3D PackStruct(variable_store)=0D +=0D + variable_data =3D b''=0D + v_offset =3D 0=0D + for v in self.NvVarInfo:=0D + v.update_delta_offset(v_offset)=0D + variable_data +=3D Occupied_Size(v.mBin[0],4)=0D + v_offset +=3D Get_Occupied_Size(len(v.mBin[0]),4)=0D +=0D +=0D + final_buff =3D Occupied_Size(default_data_header_buffer + variable= _storage_header_buffer,4) + variable_data=0D +=0D + return final_buff=0D +=0D + def generate(self, jsonlistfile,output_folder):=0D + if not os.path.exists(jsonlistfile):=0D + return=0D + if not os.path.exists(output_folder):=0D + os.makedirs(output_folder)=0D + try:=0D + with open(jsonlistfile,"r") as fd:=0D + filelist =3D fd.readlines()=0D + genVar =3D DefaultVariableGenerator()=0D + genVar.LoadNvVariableInfo(filelist)=0D + with open(os.path.join(output_folder, "default.bin"), "wb") as= fd:=0D + fd.write(genVar.PackDefaultData())=0D +=0D + delta_set =3D genVar.PackDeltaData()=0D + for default_id in delta_set:=0D + with open(os.path.join(output_folder, "defaultdelta_%s.bin= " % default_id), "wb") as fd:=0D + fd.write(delta_set[default_id])=0D + except:=0D + print("generate varbin file failed")=0D +=0D +=0D +=0D diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py b/BaseTools/S= ource/Python/AutoGen/ModuleAutoGen.py index d70b0d7ae828..0daf3352f91b 100755 --- a/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py +++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py @@ -433,10 +433,19 @@ class ModuleAutoGen(AutoGen): ## Return the directory to store auto-gened source files of the module= =0D @cached_property=0D def DebugDir(self):=0D return _MakeDir((self.BuildDir, "DEBUG"))=0D =0D +=0D + @cached_property=0D + def DefaultVarJsonFiles(self):=0D + rt =3D []=0D + for SrcFile in self.SourceFileList:=0D + if SrcFile.Ext.lower() =3D=3D '.vfr':=0D + rt.append(os.path.join(self.DebugDir,os.path.join(os.path.= dirname(SrcFile.File), "{}_var.json".format(SrcFile.BaseName))))=0D + return rt=0D +=0D ## Return the path of custom file=0D @cached_property=0D def CustomMakefile(self):=0D RetVal =3D {}=0D for Type in self.Module.CustomMakefile:=0D diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/BaseT= ools/Source/Python/AutoGen/ModuleAutoGenHelper.py index 036fdac3d7df..b46d041f58ab 100644 --- a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py +++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py @@ -644,10 +644,14 @@ class PlatformInfo(AutoGenInfo): if Attr !=3D 'PATH':=0D BuildOptions[ExpandedTool][Attr] +=3D " " = + mws.handleWsMacro(Value)=0D else:=0D BuildOptions[ExpandedTool][Attr] =3D mws.h= andleWsMacro(Value)=0D =0D + if self.DataPipe.Get("GenDefaultVarBin"):=0D + if BuildOptions.get('VFR',{}).get('FLAGS'):=0D + BuildOptions['VFR']['FLAGS'] +=3D " " + "--variable"=0D +=0D return BuildOptions, BuildRuleOrder=0D =0D def ApplyLibraryInstance(self,module):=0D alldeps =3D self.DataPipe.Get("DEPS")=0D if alldeps is None:=0D diff --git a/BaseTools/Source/Python/Common/GlobalData.py b/BaseTools/Sourc= e/Python/Common/GlobalData.py index 61ab3f7e24cd..c68ca8fbb3f7 100755 --- a/BaseTools/Source/Python/Common/GlobalData.py +++ b/BaseTools/Source/Python/Common/GlobalData.py @@ -88,10 +88,15 @@ gIgnoreSource =3D False #=0D gFdfParser =3D None=0D =0D BuildOptionPcd =3D []=0D =0D +#=0D +# Build flag for generate default variable binary file=0D +#=0D +gGenDefaultVarBin =3D False=0D +=0D #=0D # Mixed PCD name dict=0D #=0D MixedPcd =3D {}=0D =0D diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Pyth= on/build/build.py index 02b489892422..2f6fc6b20faf 100755 --- a/BaseTools/Source/Python/build/build.py +++ b/BaseTools/Source/Python/build/build.py @@ -750,10 +750,11 @@ class Build(): GlobalData.gUseHashCache =3D BuildOptions.UseHashCache=0D GlobalData.gBinCacheDest =3D BuildOptions.BinCacheDest=0D GlobalData.gBinCacheSource =3D BuildOptions.BinCacheSource=0D GlobalData.gEnableGenfdsMultiThread =3D not BuildOptions.NoGenfdsM= ultiThread=0D GlobalData.gDisableIncludePathCheck =3D BuildOptions.DisableInclud= ePathCheck=0D + GlobalData.gGenDefaultVarBin =3D BuildOptions.GenDefaultVarBin=0D =0D if GlobalData.gBinCacheDest and not GlobalData.gUseHashCache:=0D EdkLogger.error("build", OPTION_NOT_SUPPORTED, ExtraData=3D"--= binary-destination must be used together with --hash.")=0D =0D if GlobalData.gBinCacheSource and not GlobalData.gUseHashCache:=0D @@ -1459,10 +1460,14 @@ class Build(): self.BuildModules =3D []=0D return True=0D =0D # genfds=0D if Target =3D=3D 'fds':=0D + if GlobalData.gGenDefaultVarBin:=0D + from AutoGen.GenDefaultVar import DefaultVariableGenerator= =0D + variable_info_filelist =3D os.path.join(AutoGenObject.Buil= dDir,"variable_info_filelist.txt")=0D + DefaultVariableGenerator().generate(variable_info_filelist= ,AutoGenObject.FvDir)=0D if GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db):=0D EdkLogger.error("build", COMMAND_FAILURE)=0D Threshold =3D self.GetFreeSizeThreshold()=0D if Threshold:=0D self.CheckFreeSizeThreshold(Threshold, AutoGenObject.FvDir= )=0D @@ -2247,10 +2252,19 @@ class Build(): AutoGenIdFile =3D os.path.join(GlobalData.gConfDirectory,".AutoGen= IdFile.txt")=0D with open(AutoGenIdFile,"w") as fw:=0D fw.write("Arch=3D%s\n" % "|".join((Wa.ArchList)))=0D fw.write("BuildDir=3D%s\n" % Wa.BuildDir)=0D fw.write("PlatformGuid=3D%s\n" % str(Wa.AutoGenObjectList[0].G= uid))=0D + variable_info_filelist =3D os.path.join(Wa.BuildDir,"variable_info= _filelist.txt")=0D + vfr_var_json =3D []=0D + if GlobalData.gGenDefaultVarBin:=0D + for ma in self.AllModules:=0D + vfr_var_json.extend(ma.DefaultVarJsonFiles)=0D + SaveFileOnChange(variable_info_filelist, "\n".join(vfr_var_jso= n), False)=0D + else:=0D + if os.path.exists(variable_info_filelist):=0D + os.remove(variable_info_filelist)=0D =0D if GlobalData.gBinCacheSource:=0D BuildModules.extend(self.MakeCacheMiss)=0D elif GlobalData.gUseHashCache and not GlobalData.gBinCacheDest:=0D BuildModules.extend(self.PreMakeCacheMiss)=0D @@ -2359,10 +2373,14 @@ class Build(): =0D if self.Fdf:=0D #=0D # Generate FD image if there's a FDF file found=0D #=0D + if GlobalData.gGenDefaultVarBin:=0D + from AutoGen.GenDefaultVar import DefaultVaria= bleGenerator=0D + variable_info_filelist =3D os.path.join(Wa.Bui= ldDir,"variable_info_filelist.txt")=0D + DefaultVariableGenerator().generate(variable_i= nfo_filelist,Wa.FvDir)=0D GenFdsStart =3D time.time()=0D if GenFdsApi(Wa.GenFdsCommandDict, self.Db):=0D EdkLogger.error("build", COMMAND_FAILURE)=0D Threshold =3D self.GetFreeSizeThreshold()=0D if Threshold:=0D diff --git a/BaseTools/Source/Python/build/buildoptions.py b/BaseTools/Sour= ce/Python/build/buildoptions.py index 39d92cff209d..6886ba7f8eb6 100644 --- a/BaseTools/Source/Python/build/buildoptions.py +++ b/BaseTools/Source/Python/build/buildoptions.py @@ -99,7 +99,8 @@ class MyOptionParser(): Parser.add_option("--hash", action=3D"store_true", dest=3D"UseHash= Cache", default=3DFalse, help=3D"Enable hash-based caching during build pro= cess.")=0D Parser.add_option("--binary-destination", action=3D"store", type= =3D"string", dest=3D"BinCacheDest", help=3D"Generate a cache of binary file= s in the specified directory.")=0D Parser.add_option("--binary-source", action=3D"store", type=3D"str= ing", dest=3D"BinCacheSource", help=3D"Consume a cache of binary files from= the specified directory.")=0D Parser.add_option("--genfds-multi-thread", action=3D"store_true", = dest=3D"GenfdsMultiThread", default=3DTrue, help=3D"Enable GenFds multi thr= ead to generate ffs file.")=0D Parser.add_option("--no-genfds-multi-thread", action=3D"store_true= ", dest=3D"NoGenfdsMultiThread", default=3DFalse, help=3D"Disable GenFds mu= lti thread to generate ffs file.")=0D + Parser.add_option("--gen-default-variable-bin", action=3D"store_tr= ue", dest=3D"GenDefaultVarBin", default=3DFalse, help=3D"Generate default v= ariable binary file.")=0D Parser.add_option("--disable-include-path-check", action=3D"store_= true", dest=3D"DisableIncludePathCheck", default=3DFalse, help=3D"Disable t= he include path check for outside of package.")=0D self.BuildOption, self.BuildTarget =3D Parser.parse_args()=0D --=20 2.18.0.windows.1