[Patch 2/2] BaseTools: a new build option for variable default value generation


Bob Feng
 

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 <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.chen@intel.com>
---
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<mType>[a-z_A-Z][a-z_A-Z0-9]*)\[(?P<mSize>[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

Join devel@edk2.groups.io to automatically receive all group messages.