<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 13, 2021, at 4:45 AM, Bob Feng <<a href="mailto:bob.c.feng@intel.com" class="">bob.c.feng@intel.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">REF: <a href="https://bugzilla.tianocore.org/show_bug.cgi?id=3562" class="">https://bugzilla.tianocore.org/show_bug.cgi?id=3562</a><br class=""><br class="">Create a new build option to enable vfrcompile to generate Json<br class="">format EFI variable information file and read it to generate <br class="">the EFI variable default value binary file.<br class=""><br class="">Signed-off-by: Bob Feng <<a href="mailto:bob.c.feng@intel.com" class="">bob.c.feng@intel.com</a>><br class="">Cc: Liming Gao <<a href="mailto:gaoliming@byosoft.com.cn" class="">gaoliming@byosoft.com.cn</a>><br class="">Cc: Yuwei Chen <<a href="mailto:yuwei.chen@intel.com" class="">yuwei.chen@intel.com</a>><br class="">---<br class=""> BaseTools/Source/Python/AutoGen/DataPipe.py   |   2 +<br class=""> .../Source/Python/AutoGen/GenDefaultVar.py    | 498 ++++++++++++++++++<br class=""> .../Source/Python/AutoGen/ModuleAutoGen.py    |   9 +<br class=""> .../Python/AutoGen/ModuleAutoGenHelper.py     |   4 +<br class=""> BaseTools/Source/Python/Common/GlobalData.py  |   5 +<br class=""> BaseTools/Source/Python/build/build.py        |  18 +<br class=""> BaseTools/Source/Python/build/buildoptions.py |   1 +<br class=""> 7 files changed, 537 insertions(+)<br class=""> create mode 100644 BaseTools/Source/Python/AutoGen/GenDefaultVar.py<br class=""><br class="">diff --git a/BaseTools/Source/Python/AutoGen/DataPipe.py b/BaseTools/Source/Python/AutoGen/DataPipe.py<br class="">index 86ac2b928d9c..fa0c36b98f21 100755<br class="">--- a/BaseTools/Source/Python/AutoGen/DataPipe.py<br class="">+++ b/BaseTools/Source/Python/AutoGen/DataPipe.py<br class="">@@ -165,5 +165,7 @@ class MemoryDataPipe(DataPipe):<br class="">         self.DataContainer = {"BinCacheSource":GlobalData.gBinCacheSource}<br class=""><br class="">         self.DataContainer = {"BinCacheDest":GlobalData.gBinCacheDest}<br class=""><br class="">         self.DataContainer = {"EnableGenfdsMultiThread":GlobalData.gEnableGenfdsMultiThread}<br class="">+<br class="">+        self.DataContainer = {"GenDefaultVarBin": GlobalData.gGenDefaultVarBin}<br class="">diff --git a/BaseTools/Source/Python/AutoGen/GenDefaultVar.py b/BaseTools/Source/Python/AutoGen/GenDefaultVar.py<br class="">new file mode 100644<br class="">index 000000000000..b82cce18ed26<br class="">--- /dev/null<br class="">+++ b/BaseTools/Source/Python/AutoGen/GenDefaultVar.py<br class="">@@ -0,0 +1,498 @@<br class="">+import json<br class="">+from ctypes import *<br class="">+import re<br class="">+import copy<br class="">+from struct import unpack<br class="">+import os<br class="">+<br class="">+class GUID(Structure):<br class=""></div></div></blockquote><div><br class=""></div><div>We should use (LittleEndianStructure) vs. (Structure). Structure is the endian of the Host, and EFI is little endian. Same comment for all the ctype structs. LittleEndianStructure is like using < with struct.pack()/struct.unpack(). </div><br class=""><blockquote type="cite" class=""><div class=""><div class="">+    _fields_ = [<br class="">+        ('Guid1',            c_uint32),<br class="">+        ('Guid2',            c_uint16),<br class="">+        ('Guid3',            c_uint16),<br class="">+        ('Guid4',            ARRAY(c_uint8, 8)),<br class="">+    ]<br class="">+<br class=""></div></div></blockquote><div><br class=""></div><div><div>I think it would be better to use the same field names as the EFI C structures. </div><div><br class=""></div><div><table class="js-file-line-container highlight tab-size" data-tab-size="8" data-paste-markdown-skip="" style="box-sizing: border-box; border-collapse: collapse; border-spacing: 0px; tab-size: 8; caret-color: rgb(36, 41, 46); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px;"><tbody style="box-sizing: border-box;" class=""><tr style="box-sizing: border-box;" class=""><td id="L222" class="blob-num js-line-number" data-line-number="222" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC222" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;"><span class="pl-k" style="box-sizing: border-box; color: var(--color-prettylights-syntax-keyword);">typedef</span> <span class="pl-k" style="box-sizing: border-box; color: var(--color-prettylights-syntax-keyword);">struct</span> {</td></tr><tr style="box-sizing: border-box;" class=""><td id="L223" class="blob-num js-line-number" data-line-number="223" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC223" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;">  UINT32  Data1;</td></tr><tr style="box-sizing: border-box;" class=""><td id="L224" class="blob-num js-line-number" data-line-number="224" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC224" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;">  UINT16  Data2;</td></tr><tr style="box-sizing: border-box;" class=""><td id="L225" class="blob-num js-line-number" data-line-number="225" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC225" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;">  UINT16  Data3;</td></tr><tr style="box-sizing: border-box;" class=""><td id="L226" class="blob-num js-line-number" data-line-number="226" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC226" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;">  UINT8   Data4[<span class="pl-c1" style="box-sizing: border-box; color: var(--color-prettylights-syntax-constant);">8</span>];</td></tr><tr style="box-sizing: border-box;" class=""><td id="L227" class="blob-num js-line-number" data-line-number="227" style="box-sizing: border-box; padding: 0px 10px; color: var(--color-diff-blob-num-text); cursor: pointer; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; line-height: 20px; min-width: 50px; text-align: right; -webkit-user-select: none; vertical-align: top; white-space: nowrap; width: 50px;"></td><td id="LC227" class="js-file-line blob-code-inner blob-code" style="box-sizing: border-box; padding: 0px 10px; line-height: 20px; position: relative; vertical-align: top; word-wrap: normal; color: var(--color-text-primary); font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; font-size: 12px; overflow: visible; white-space: pre;">} GUID

</td></tr></tbody></table></div></div><div><br class=""></div><div>Longer term I think the BaseBools should have a GUID class that can be shared that abstracts things GUIDs. It should store GUIDs as Python uuid.UUID() or at least in the common string form, and have useful operations. </div><div><br class=""></div><div>I’ve got an example GUID class in my gdb patch set, but it also loads the GUID database and deals with C name, C GUID structure init form, and strings. But it feels like we could pull out a common lower level GUID class out of that. </div><div><br class=""></div><div></div><div><table class="js-file-line-container highlight tab-size" data-tab-size="8" data-paste-markdown-skip="" style="box-sizing: border-box; border-collapse: collapse; border-spacing: 0px; tab-size: 8; caret-color: rgb(36, 41, 46); color: rgb(36, 41, 46); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 14px;"><tbody style="box-sizing: border-box;" class=""></tbody></table></div><blockquote type="cite" class=""><div class=""><div class="">+    def from_list(self, listformat):<br class="">+        self.Guid1 = listformat[0]<br class="">+        self.Guid2 = listformat[1]<br class="">+        self.Guid3 = listformat[2]<br class="">+        for i in range(8):<br class="">+            self.Guid4[i] = listformat[i+3]<br class="">+<br class="">+    def __cmp__(self, otherguid):<br class="">+        if isinstance(otherguid, GUID):<br class="">+            return 1<br class="">+        rt = False<br class="">+        if self.Guid1 == otherguid.Guid1 and self.Guid2 == otherguid.Guid2 and self.Guid3 == otherguid.Guid3:<br class="">+            rt = True<br class="">+            for i in range(8):<br class="">+                rt = rt & (self.Guid4[i] == otherguid.Guid4[i])<br class="">+        return rt<br class="">+<br class="">+<br class="">+class TIME(Structure):<br class="">+    _fields_ = [<br class="">+        ('Year',             c_uint16),<br class="">+        ('Month',            c_uint8),<br class="">+        ('Day',              c_uint8),<br class="">+        ('Hour',             c_uint8),<br class="">+        ('Minute',           c_uint8),<br class="">+        ('Second',           c_uint8),<br class="">+        ('Pad1',             c_uint8),<br class="">+        ('Nanosecond',       c_uint32),<br class="">+        ('TimeZone',         c_uint16),<br class="">+        ('Daylight',         c_uint8),<br class="">+        ('Pad2',             c_uint8),<br class="">+    ]<br class="">+    def __init__(self):<br class="">+        self.Year = 0x0<br class="">+        self.Month = 0x0<br class="">+        self.Day = 0x0<br class="">+        self.Hour = 0x0<br class="">+        self.Minute = 0x0<br class="">+        self.Second = 0x0<br class="">+        self.Pad1 = 0x0<br class="">+        self.Nanosecond = 0x0<br class="">+        self.TimeZone = 0x0<br class="">+        self.Daylight = 0x0<br class="">+        self.Pad2 = 0x0<br class="">+<br class="">+<br class="">+EFI_VARIABLE_GUID = [0xddcf3616, 0x3275, 0x4164,<br class="">+                     0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d]<br class="">+EFI_AUTHENTICATED_VARIABLE_GUID = [<br class="">+    0xaaf32c78, 0x947b, 0x439a, 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92]<br class="">+<br class="">+AuthVarGuid = GUID()<br class="">+AuthVarGuid.from_list(EFI_AUTHENTICATED_VARIABLE_GUID)<br class="">+VarGuid = GUID()<br class="">+VarGuid.from_list(EFI_VARIABLE_GUID)<br class="">+<br class="">+# Variable Store Header Format.<br class="">+VARIABLE_STORE_FORMATTED = 0x5a<br class="">+# Variable Store Header State.<br class="">+VARIABLE_STORE_HEALTHY = 0xfe<br class="">+<br class="">+<br class="">+class VARIABLE_STORE_HEADER(Structure):<br class="">+    _fields_ = [<br class="">+        ('Signature',                GUID),<br class="">+        ('Size',                     c_uint32),<br class="">+        ('Format',                   c_uint8),<br class="">+        ('State',                    c_uint8),<br class="">+        ('Reserved',                 c_uint16),<br class="">+        ('Reserved1',                c_uint32),<br class="">+    ]<br class="">+<br class="">+<br class="">+# Variable data start flag.<br class="">+VARIABLE_DATA = 0x55AA<br class="">+<br class="">+# Variable State flags.<br class="">+VAR_IN_DELETED_TRANSITION = 0xfe<br class="">+VAR_DELETED = 0xfd<br class="">+VAR_HEADER_VALID_ONLY = 0x7f<br class="">+VAR_ADDED = 0x3f<br class="">+<br class="">+<br class="">+class VARIABLE_HEADER(Structure):<br class="">+    _fields_ = [<br class="">+        ('StartId',                  c_uint16),<br class="">+        ('State',                    c_uint8),<br class="">+        ('Reserved',                 c_uint8),<br class="">+        ('Attributes',               c_uint32),<br class="">+        ('NameSize',                 c_uint32),<br class="">+        ('DataSize',                 c_uint32),<br class="">+        ('VendorGuid',               GUID),<br class="">+    ]<br class="">+<br class="">+<br class="">+class AUTHENTICATED_VARIABLE_HEADER(Structure):<br class="">+    _fields_ = [<br class="">+        ('StartId',                  c_uint16),<br class="">+        ('State',                    c_uint8),<br class="">+        ('Reserved',                 c_uint8),<br class="">+        ('Attributes',               c_uint32),<br class="">+        ('MonotonicCount',           c_uint64),<br class="">+        ('TimeStamp',                TIME),<br class="">+        ('PubKeyIndex',              c_uint32),<br class="">+        ('NameSize',                 c_uint32),<br class="">+        ('DataSize',                 c_uint32),<br class="">+        ('VendorGuid',               GUID),<br class="">+    ]<br class="">+    _pack_ = 1<br class="">+<br class="">+<br class="">+# Alignment of Variable Data Header in Variable Store region.<br class="">+HEADER_ALIGNMENT = 4<br class="">+<br class="">+<br class="">+class DEFAULT_INFO(Structure):<br class="">+    _fields_ = [<br class="">+        ('DefaultId',                c_uint16),<br class="">+        ('BoardId',                  c_uint16),<br class="">+    ]<br class="">+<br class="">+<br class="">+class DEFAULT_DATA(Structure):<br class="">+    _fields_ = [<br class="">+        ('HeaderSize',               c_uint16),<br class="">+        ('DefaultInfo',              DEFAULT_INFO),<br class="">+    ]<br class="">+<br class="">+class DELTA_DATA(Structure):<br class="">+    _fields_ = [<br class="">+        ('Offset', c_uint16),<br class="">+        ('Value', c_uint8),<br class="">+    ]<br class="">+    _pack_ = 1<br class="">+<br class="">+array_re = re.compile(<br class="">+    "(?P<mType>[a-z_A-Z][a-z_A-Z0-9]*)\[(?P<mSize>[1-9][0-9]*)\]")<br class="">+<br class="">+<br class="">+class VarField():<br class="">+    def __init__(self):<br class="">+        self.Offset = 0<br class="">+        self.Value = 0<br class="">+        self.Size = 0<br class="">+<br class="">+    @property<br class="">+    def Type(self):<br class="">+        if self.Size == 1:<br class="">+            return "UINT8"<br class="">+        if self.Size == 2:<br class="">+            return "UINT16"<br class="">+        if self.Size == 4:<br class="">+            return "UINT32"<br class="">+        if self.Size == 8:<br class="">+            return "UINT64"<br class="">+<br class="">+        return "UINT8"<br class="">+<br class="">+<br class="">+BASIC_TYPE = {<br class="">+    "BOOLEAN": 1,<br class="">+    "UINT8": 1,<br class="">+    "UINT16": 2,<br class="">+    "UINT32": 4,<br class="">+    "UINT64": 8<br class="">+}<br class=""></div></div></blockquote><div><br class=""></div><div>This might be more of a phase 2….</div><div><br class=""></div><div>I think you made a lot of extra work by inventing your own type system. You should just convert to ctype as fast as you can. </div><div><br class=""></div><div><div>BASIC_TYPE = {</div><div>    "BOOLEAN": c_uint8,</div><div>    "UINT8": c_uint8,</div><div>    "UINT16": c_uint16,</div><div>    "UINT32": c_uint32,</div><div>    "UINT64": c_uint64</div><div>}</div><div class=""><br class=""></div><div class="">Then you can just sizeof() to get the size</div><div class=""><br class=""></div><div class="">FYI I wrote this ctype dumper in case it is useful debugging this code.  It picks off EFI_GUID so it can print it as a proper UUID using the GUID class I mentioned above, so basically a nicer print option. </div><div class=""><br class=""></div><div class=""><div class="">def ctype_to_str(ctype, indent='', hide_list=[]):</div><div class="">    '''</div><div class="">    Given a ctype object print out as a string by walking the _fields_</div><div class="">    in the cstring Class</div><div class="">     '''</div><div class="">    result = ''</div><div class="">    for field in ctype._fields_:</div><div class="">        attr = getattr(ctype, field[0])</div><div class="">        tname = type(attr).__name__</div><div class="">        if field[0] in hide_list:</div><div class="">            continue</div><div class=""><br class=""></div><div class="">        result += indent + f'{field[0]} = '</div><div class="">        if tname == 'EFI_GUID':</div><div class="">            result += GuidNames.to_name(GuidNames.to_uuid(attr)) + '\n'</div><div class="">        elif issubclass(type(attr), Structure):</div><div class="">            result += f'{tname}\n' + \</div><div class="">                ctype_to_str(attr, indent + '  ', hide_list)</div><div class="">        elif isinstance(attr, int):</div><div class="">            result += f'0x{attr:x}\n'</div><div class="">        else:</div><div class="">            result += f'{attr}\n'</div><div class=""><br class=""></div><div class="">    return result</div></div><div class=""><br class=""></div></div>Thanks,</div><div><br class=""></div><div>Andrew Fish</div><div><br class=""><blockquote type="cite" class=""><div class=""><div class="">+class CStruct():<br class="">+<br class="">+<br class="">+    def __init__(self, typedefs):<br class="">+        self.TypeDefs = typedefs<br class="">+        self.TypeStack = copy.deepcopy(typedefs)<br class="">+        self.finalDefs = {}<br class="">+<br class="">+    def CalStuctSize(self, sType):<br class="">+        rt = 0<br class="">+        if sType in BASIC_TYPE:<br class="">+            return BASIC_TYPE[sType]<br class="">+<br class="">+        ma = array_re.match(sType)<br class="">+        if ma:<br class="">+            mType = ma.group('mType')<br class="">+            mSize = ma.group('mSize')<br class="">+            rt += int(mSize) * self.CalStuctSize(mType)<br class="">+        else:<br class="">+            for subType in self.TypeDefs[sType]:<br class="">+                rt += self.CalStuctSize(subType['Type'])<br class="">+<br class="">+        return rt<br class="">+<br class="">+    def expend(self, fielditem):<br class="">+        fieldname = fielditem['Name']<br class="">+        fieldType = fielditem['Type']<br class="">+        fieldOffset = fielditem['Offset']<br class="">+<br class="">+        ma = array_re.match(fieldType)<br class="">+        if ma:<br class="">+            mType = ma.group('mType')<br class="">+            mSize = ma.group('mSize')<br class="">+            return [{"Name": "%s[%d]" % (fieldname, i), "Type": mType, "Offset": (fieldOffset + i*self.CalStuctSize(mType))} for i in range(int(mSize))]<br class="">+        else:<br class="">+            return [{"Name": "%s.%s" % (fieldname, item['Name']), "Type":item['Type'], "Offset": (fieldOffset + item['Offset'])} for item in self.TypeDefs[fielditem['Type']]]<br class="">+<br class="">+    def ExpandTypes(self):<br class="">+        if not self.finalDefs:<br class="">+            for datatype in self.TypeStack:<br class="">+                result = []<br class="">+                mTypeStack = self.TypeStack[datatype]<br class="">+                while len(mTypeStack) > 0:<br class="">+                    item = mTypeStack.pop()<br class="">+                    if item['Type'] in self.BASIC_TYPE:<br class="">+                        result.append(item)<br class="">+                    elif item['Type'] == '(null)':<br class="">+                        continue<br class="">+                    else:<br class="">+                        for expand_item in self.expend(item):<br class="">+                            mTypeStack.append(expand_item)<br class="">+                self.finalDefs[datatype] = result<br class="">+            self.finalDefs<br class="">+        return self.finalDefs<br class="">+<br class="">+def Get_Occupied_Size(FileLength, alignment):<br class="">+    if FileLength % alignment == 0:<br class="">+        return FileLength<br class="">+    return FileLength + (alignment-(FileLength % alignment))<br class="">+<br class="">+def Occupied_Size(buffer, alignment):<br class="">+    FileLength = len(buffer)<br class="">+    if FileLength % alignment != 0:<br class="">+        buffer += b'\0' * (alignment-(FileLength % alignment))<br class="">+    return buffer<br class="">+<br class="">+def PackStruct(cStruct):<br class="">+    length = sizeof(cStruct)<br class="">+    p = cast(pointer(cStruct), POINTER(c_char * length))<br class="">+    return p.contents.raw<br class="">+<br class="">+def calculate_delta(default, theother):<br class="">+<br class="">+    if len(default) - len(theother) != 0:<br class="">+        return []<br class="">+<br class="">+    data_delta = []<br class="">+    for i in range(len(default)):<br class="">+        if default[i] != theother[i]:<br class="">+            data_delta.append([i, theother[i]])<br class="">+    return data_delta<br class="">+<br class="">+class Variable():<br class="">+    def __init__(self):<br class="">+        self.mAlign = 1<br class="">+        self.mTotalSize = 1<br class="">+        self.mValue = {}  # {defaultstore: value}<br class="">+        self.mBin = {}<br class="">+        self.fields = {}  # {defaultstore: fileds}<br class="">+        self.delta = {}<br class="">+        self.attributes = 0<br class="">+        self.mType = ''<br class="">+        self.guid = ''<br class="">+        self.mName = ''<br class="">+        self.cDefs = None<br class="">+<br class="">+    @property<br class="">+    def GuidArray(self):<br class="">+<br class="">+        guid_array = []<br class="">+        guid = self.guid.strip().strip("{").strip("}")<br class="">+        for item in guid.split(","):<br class="">+            field = item.strip().strip("{").strip("}")<br class="">+            guid_array.append(int(field,16))<br class="">+        return guid_array<br class="">+<br class="">+    def update_delta_offset(self,base):<br class="">+        for default_id in self.delta:<br class="">+            for delta_list in self.delta[default_id]:<br class="">+                delta_list[0] += base<br class="">+<br class="">+    def pack(self):<br class="">+<br class="">+        for defaultid in self.mValue:<br class="">+            var_value = self.mValue[defaultid]<br class="">+            auth_var = AUTHENTICATED_VARIABLE_HEADER()<br class="">+            auth_var.StartId = VARIABLE_DATA<br class="">+            auth_var.State = VAR_ADDED<br class="">+            auth_var.Reserved = 0x00<br class="">+            auth_var.Attributes = 0x00000007<br class="">+            auth_var.MonotonicCount = 0x0<br class="">+            auth_var.TimeStamp = TIME()<br class="">+            auth_var.PubKeyIndex = 0x0<br class="">+            var_name_buffer = self.mName.encode('utf-16le') + b'\0\0'<br class="">+            auth_var.NameSize = len(var_name_buffer)<br class="">+            auth_var.DataSize = len(var_value)<br class="">+            vendor_guid = GUID()<br class="">+            vendor_guid.from_list(self.GuidArray)<br class="">+            auth_var.VendorGuid = vendor_guid<br class="">+<br class="">+            self.mBin[defaultid] = PackStruct(auth_var) + Occupied_Size(var_name_buffer + var_value, 4)<br class="">+<br class="">+    def TypeCheck(self,data_type, data_size):<br class="">+        if BASIC_TYPE[data_type] == data_size:<br class="">+            return True<br class="">+        return False<br class="">+<br class="">+    def ValueToBytes(self,data_type,data_value,data_size):<br class="">+<br class="">+        rt = b''<br class="">+        if not self.TypeCheck(data_type, data_size):<br class="">+            print(data_type,data_value,data_size)<br class="">+<br class="">+        if data_type == "BOOLEAN" or data_type == 'UINT8':<br class="">+            p = cast(pointer(c_uint8(int(data_value,16))), POINTER(c_char * 1))<br class="">+            rt = p.contents.raw<br class="">+        elif data_type == 'UINT16':<br class="">+            p = cast(pointer(c_uint16(int(data_value,16))), POINTER(c_char * 2))<br class="">+            rt = p.contents.raw<br class="">+        elif data_type == 'UINT32':<br class="">+            p = cast(pointer(c_uint32(int(data_value,16))), POINTER(c_char * 4))<br class="">+            rt = p.contents.raw<br class="">+        elif data_type == 'UINT64':<br class="">+            p = cast(pointer(c_uint64(int(data_value,16))), POINTER(c_char * 8))<br class="">+            rt = p.contents.raw<br class="">+<br class="">+        return rt<br class="">+<br class="">+    def serial(self):<br class="">+        for defaultstore in self.fields:<br class="">+            vValue = b''<br class="">+            vfields = {vf.Offset: vf for vf in self.fields[defaultstore]}<br class="">+            i = 0<br class="">+            while i < self.mTotalSize:<br class="">+                if i in vfields:<br class="">+                    vfield = vfields[i]<br class="">+                    vValue += self.ValueToBytes(vfield.Type, vfield.Value,vfield.Size)<br class="">+                    i += vfield.Size<br class="">+                else:<br class="">+                    vValue += self.ValueToBytes('UINT8','0x00',1)<br class="">+                    i += 1<br class="">+<br class="">+            self.mValue[defaultstore] = vValue<br class="">+        standard_default = self.mValue[0]<br class="">+<br class="">+        for defaultid in self.mValue:<br class="">+            if defaultid == 0:<br class="">+                continue<br class="">+            others_default = self.mValue[defaultid]<br class="">+<br class="">+            self.delta.setdefault(defaultid, []).extend(calculate_delta(<br class="">+                standard_default, others_default))<br class="">+<br class="">+class DefaultVariableGenerator():<br class="">+    def __init__(self):<br class="">+        self.NvVarInfo = []<br class="">+<br class="">+    def LoadNvVariableInfo(self, VarInfoFilelist):<br class="">+<br class="">+        VarDataDict = {}<br class="">+        DataStruct = {}<br class="">+        VarDefine = {}<br class="">+        VarAttributes = {}<br class="">+        for VarInfoFile in VarInfoFilelist:<br class="">+            with open(VarInfoFile.strip(), "r") as fd:<br class="">+                data = json.load(fd)<br class="">+<br class="">+            DataStruct.update(data.get("DataStruct", {}))<br class="">+            Data = data.get("Data")<br class="">+            VarDefine.update(data.get("VarDefine"))<br class="">+            VarAttributes.update(data.get("DataStructAttribute"))<br class="">+<br class="">+            for vardata in Data:<br class="">+                if vardata['VendorGuid'] == 'NA':<br class="">+                    continue<br class="">+                VarDataDict.setdefault(<br class="">+                    (vardata['VendorGuid'], vardata["VarName"]), []).append(vardata)<br class="">+<br class="">+        cStructDefs = CStruct(DataStruct)<br class="">+        for guid, varname in VarDataDict:<br class="">+            v = Variable()<br class="">+            v.guid = guid<br class="">+            vardef = VarDefine.get(varname)<br class="">+            if vardef is None:<br class="">+                for var in VarDefine:<br class="">+                    if VarDefine[var]['Type'] == varname:<br class="">+                        vardef = VarDefine[var]<br class="">+                        break<br class="">+                else:<br class="">+                    continue<br class="">+            v.attributes = vardef['Attributes']<br class="">+            v.mType = vardef['Type']<br class="">+            v.mAlign = VarAttributes[v.mType]['Alignment']<br class="">+            v.mTotalSize = VarAttributes[v.mType]['TotalSize']<br class="">+            v.Struct = DataStruct[v.mType]<br class="">+            v.mName = varname<br class="">+            v.cDefs = cStructDefs<br class="">+            for fieldinfo in VarDataDict.get((guid, varname), []):<br class="">+                vf = VarField()<br class="">+                vf.Offset = fieldinfo['Offset']<br class="">+                vf.Value = fieldinfo['Value']<br class="">+                vf.Size = fieldinfo['Size']<br class="">+                v.fields.setdefault(<br class="">+                    int(fieldinfo['DefaultStore'], 10), []).append(vf)<br class="">+            v.serial()<br class="">+            v.pack()<br class="">+            self.NvVarInfo.append(v)<br class="">+<br class="">+    def PackDeltaData(self):<br class="">+<br class="">+        default_id_set = set()<br class="">+        for v in self.NvVarInfo:<br class="">+            default_id_set |= set(v.mBin.keys())<br class="">+<br class="">+        if default_id_set:<br class="">+            default_id_set.remove(0)<br class="">+        delta_buff_set = {}<br class="">+        for defaultid in default_id_set:<br class="">+            delta_buff = b''<br class="">+            for v in self.NvVarInfo:<br class="">+                delta_list = v.delta.get(defaultid,[])<br class="">+                for delta in delta_list:<br class="">+                    delta_data = DELTA_DATA()<br class="">+                    delta_data.Offset, delta_data.Value = delta<br class="">+                    delta_buff += PackStruct(delta_data)<br class="">+            delta_buff_set[defaultid] = delta_buff<br class="">+<br class="">+        return delta_buff_set<br class="">+<br class="">+    def PackDefaultData(self):<br class="">+<br class="">+        default_data_header = DEFAULT_DATA()<br class="">+        default_data_header.HeaderSize = sizeof(DEFAULT_DATA)<br class="">+        default_data_header.DefaultInfo.DefaultId = 0x0<br class="">+        default_data_header.DefaultInfo.BoardId = 0x0<br class="">+        default_data_header_buffer = PackStruct(default_data_header)<br class="">+<br class="">+<br class="">+        variable_store = VARIABLE_STORE_HEADER()<br class="">+        variable_store.Signature = AuthVarGuid<br class="">+<br class="">+        variable_store_size = Get_Occupied_Size(sizeof(DEFAULT_DATA) + sizeof(VARIABLE_STORE_HEADER), 4)<br class="">+        for v in self.NvVarInfo:<br class="">+            variable_store_size += Get_Occupied_Size(len(v.mBin[0]), 4)<br class="">+<br class="">+        variable_store.Size = variable_store_size<br class="">+        variable_store.Format = VARIABLE_STORE_FORMATTED<br class="">+        variable_store.State = VARIABLE_STORE_HEALTHY<br class="">+        variable_store.Reserved = 0x0<br class="">+        variable_store.Reserved2 = 0x0<br class="">+<br class="">+        variable_storage_header_buffer = PackStruct(variable_store)<br class="">+<br class="">+        variable_data = b''<br class="">+        v_offset = 0<br class="">+        for v in self.NvVarInfo:<br class="">+            v.update_delta_offset(v_offset)<br class="">+            variable_data += Occupied_Size(v.mBin[0],4)<br class="">+            v_offset += Get_Occupied_Size(len(v.mBin[0]),4)<br class="">+<br class="">+<br class="">+        final_buff = Occupied_Size(default_data_header_buffer + variable_storage_header_buffer,4) + variable_data<br class="">+<br class="">+        return final_buff<br class="">+<br class="">+    def generate(self, jsonlistfile,output_folder):<br class="">+        if not os.path.exists(jsonlistfile):<br class="">+            return<br class="">+        if not os.path.exists(output_folder):<br class="">+            os.makedirs(output_folder)<br class="">+        try:<br class="">+            with open(jsonlistfile,"r") as fd:<br class="">+                filelist = fd.readlines()<br class="">+            genVar = DefaultVariableGenerator()<br class="">+            genVar.LoadNvVariableInfo(filelist)<br class="">+            with open(os.path.join(output_folder, "default.bin"), "wb") as fd:<br class="">+                fd.write(genVar.PackDefaultData())<br class="">+<br class="">+            delta_set = genVar.PackDeltaData()<br class="">+            for default_id in delta_set:<br class="">+                with open(os.path.join(output_folder, "defaultdelta_%s.bin" % default_id), "wb") as fd:<br class="">+                    fd.write(delta_set[default_id])<br class="">+        except:<br class="">+            print("generate varbin file failed")<br class="">+<br class="">+<br class="">+<br class="">diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py<br class="">index d70b0d7ae828..0daf3352f91b 100755<br class="">--- a/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py<br class="">+++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py<br class="">@@ -433,10 +433,19 @@ class ModuleAutoGen(AutoGen):<br class="">     ## Return the directory to store auto-gened source files of the module<br class="">     @cached_property<br class="">     def DebugDir(self):<br class="">         return _MakeDir((self.BuildDir, "DEBUG"))<br class=""><br class="">+<br class="">+    @cached_property<br class="">+    def DefaultVarJsonFiles(self):<br class="">+        rt = []<br class="">+        for SrcFile in self.SourceFileList:<br class="">+            if SrcFile.Ext.lower() == '.vfr':<br class="">+                rt.append(os.path.join(self.DebugDir,os.path.join(os.path.dirname(SrcFile.File), "{}_var.json".format(SrcFile.BaseName))))<br class="">+        return rt<br class="">+<br class="">     ## Return the path of custom file<br class="">     @cached_property<br class="">     def CustomMakefile(self):<br class="">         RetVal = {}<br class="">         for Type in self.Module.CustomMakefile:<br class="">diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py<br class="">index 036fdac3d7df..b46d041f58ab 100644<br class="">--- a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py<br class="">+++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py<br class="">@@ -644,10 +644,14 @@ class PlatformInfo(AutoGenInfo):<br class="">                             if Attr != 'PATH':<br class="">                                 BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)<br class="">                             else:<br class="">                                 BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)<br class=""><br class="">+        if self.DataPipe.Get("GenDefaultVarBin"):<br class="">+            if BuildOptions.get('VFR',{}).get('FLAGS'):<br class="">+                BuildOptions['VFR']['FLAGS'] += " " + "--variable"<br class="">+<br class="">         return BuildOptions, BuildRuleOrder<br class=""><br class="">     def ApplyLibraryInstance(self,module):<br class="">         alldeps = self.DataPipe.Get("DEPS")<br class="">         if alldeps is None:<br class="">diff --git a/BaseTools/Source/Python/Common/GlobalData.py b/BaseTools/Source/Python/Common/GlobalData.py<br class="">index 61ab3f7e24cd..c68ca8fbb3f7 100755<br class="">--- a/BaseTools/Source/Python/Common/GlobalData.py<br class="">+++ b/BaseTools/Source/Python/Common/GlobalData.py<br class="">@@ -88,10 +88,15 @@ gIgnoreSource = False<br class=""> #<br class=""> gFdfParser = None<br class=""><br class=""> BuildOptionPcd = []<br class=""><br class="">+#<br class="">+# Build flag for generate default variable binary file<br class="">+#<br class="">+gGenDefaultVarBin = False<br class="">+<br class=""> #<br class=""> # Mixed PCD name dict<br class=""> #<br class=""> MixedPcd = {}<br class=""><br class="">diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py<br class="">index 02b489892422..2f6fc6b20faf 100755<br class="">--- a/BaseTools/Source/Python/build/build.py<br class="">+++ b/BaseTools/Source/Python/build/build.py<br class="">@@ -750,10 +750,11 @@ class Build():<br class="">         GlobalData.gUseHashCache = BuildOptions.UseHashCache<br class="">         GlobalData.gBinCacheDest   = BuildOptions.BinCacheDest<br class="">         GlobalData.gBinCacheSource = BuildOptions.BinCacheSource<br class="">         GlobalData.gEnableGenfdsMultiThread = not BuildOptions.NoGenfdsMultiThread<br class="">         GlobalData.gDisableIncludePathCheck = BuildOptions.DisableIncludePathCheck<br class="">+        GlobalData.gGenDefaultVarBin = BuildOptions.GenDefaultVarBin<br class=""><br class="">         if GlobalData.gBinCacheDest and not GlobalData.gUseHashCache:<br class="">             EdkLogger.error("build", OPTION_NOT_SUPPORTED, ExtraData="--binary-destination must be used together with --hash.")<br class=""><br class="">         if GlobalData.gBinCacheSource and not GlobalData.gUseHashCache:<br class="">@@ -1459,10 +1460,14 @@ class Build():<br class="">             self.BuildModules = []<br class="">             return True<br class=""><br class="">         # genfds<br class="">         if Target == 'fds':<br class="">+            if GlobalData.gGenDefaultVarBin:<br class="">+                from AutoGen.GenDefaultVar import DefaultVariableGenerator<br class="">+                variable_info_filelist = os.path.join(AutoGenObject.BuildDir,"variable_info_filelist.txt")<br class="">+                DefaultVariableGenerator().generate(variable_info_filelist,AutoGenObject.FvDir)<br class="">             if GenFdsApi(AutoGenObject.GenFdsCommandDict, self.Db):<br class="">                 EdkLogger.error("build", COMMAND_FAILURE)<br class="">             Threshold = self.GetFreeSizeThreshold()<br class="">             if Threshold:<br class="">                 self.CheckFreeSizeThreshold(Threshold, AutoGenObject.FvDir)<br class="">@@ -2247,10 +2252,19 @@ class Build():<br class="">         AutoGenIdFile = os.path.join(GlobalData.gConfDirectory,".AutoGenIdFile.txt")<br class="">         with open(AutoGenIdFile,"w") as fw:<br class="">             fw.write("Arch=%s\n" % "|".join((Wa.ArchList)))<br class="">             fw.write("BuildDir=%s\n" % Wa.BuildDir)<br class="">             fw.write("PlatformGuid=%s\n" % str(Wa.AutoGenObjectList[0].Guid))<br class="">+        variable_info_filelist = os.path.join(Wa.BuildDir,"variable_info_filelist.txt")<br class="">+        vfr_var_json = []<br class="">+        if GlobalData.gGenDefaultVarBin:<br class="">+            for ma in self.AllModules:<br class="">+                vfr_var_json.extend(ma.DefaultVarJsonFiles)<br class="">+            SaveFileOnChange(variable_info_filelist, "\n".join(vfr_var_json), False)<br class="">+        else:<br class="">+            if os.path.exists(variable_info_filelist):<br class="">+                os.remove(variable_info_filelist)<br class=""><br class="">         if GlobalData.gBinCacheSource:<br class="">             BuildModules.extend(self.MakeCacheMiss)<br class="">         elif GlobalData.gUseHashCache and not GlobalData.gBinCacheDest:<br class="">             BuildModules.extend(self.PreMakeCacheMiss)<br class="">@@ -2359,10 +2373,14 @@ class Build():<br class=""><br class="">                     if self.Fdf:<br class="">                         #<br class="">                         # Generate FD image if there's a FDF file found<br class="">                         #<br class="">+                        if GlobalData.gGenDefaultVarBin:<br class="">+                            from AutoGen.GenDefaultVar import DefaultVariableGenerator<br class="">+                            variable_info_filelist = os.path.join(Wa.BuildDir,"variable_info_filelist.txt")<br class="">+                            DefaultVariableGenerator().generate(variable_info_filelist,Wa.FvDir)<br class="">                         GenFdsStart = time.time()<br class="">                         if GenFdsApi(Wa.GenFdsCommandDict, self.Db):<br class="">                             EdkLogger.error("build", COMMAND_FAILURE)<br class="">                         Threshold = self.GetFreeSizeThreshold()<br class="">                         if Threshold:<br class="">diff --git a/BaseTools/Source/Python/build/buildoptions.py b/BaseTools/Source/Python/build/buildoptions.py<br class="">index 39d92cff209d..6886ba7f8eb6 100644<br class="">--- a/BaseTools/Source/Python/build/buildoptions.py<br class="">+++ b/BaseTools/Source/Python/build/buildoptions.py<br class="">@@ -99,7 +99,8 @@ class MyOptionParser():<br class="">         Parser.add_option("--hash", action="store_true", dest="UseHashCache", default=False, help="Enable hash-based caching during build process.")<br class="">         Parser.add_option("--binary-destination", action="store", type="string", dest="BinCacheDest", help="Generate a cache of binary files in the specified directory.")<br class="">         Parser.add_option("--binary-source", action="store", type="string", dest="BinCacheSource", help="Consume a cache of binary files from the specified directory.")<br class="">         Parser.add_option("--genfds-multi-thread", action="store_true", dest="GenfdsMultiThread", default=True, help="Enable GenFds multi thread to generate ffs file.")<br class="">         Parser.add_option("--no-genfds-multi-thread", action="store_true", dest="NoGenfdsMultiThread", default=False, help="Disable GenFds multi thread to generate ffs file.")<br class="">+        Parser.add_option("--gen-default-variable-bin", action="store_true", dest="GenDefaultVarBin", default=False, help="Generate default variable binary file.")<br class="">         Parser.add_option("--disable-include-path-check", action="store_true", dest="DisableIncludePathCheck", default=False, help="Disable the include path check for outside of package.")<br class="">         self.BuildOption, self.BuildTarget = Parser.parse_args()<br class="">-- <br class="">2.18.0.windows.1<br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class=""></div></div></blockquote></div><br class=""></body></html>


 <div width="1" style="color:white;clear:both">_._,_._,_</div> <hr>   Groups.io Links:<p>   You receive all messages sent to this group.    <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/79282">View/Reply Online (#79282)</a> |    |  <a target="_blank" href="https://groups.io/mt/84861462/1813853">Mute This Topic</a>  | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br>    <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> |  <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a>  [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>