]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFspPkg/Tools/GenCfgOpt.py
Add IntelFspPkg to support create FSP bin based on EDKII.
[mirror_edk2.git] / IntelFspPkg / Tools / GenCfgOpt.py
diff --git a/IntelFspPkg/Tools/GenCfgOpt.py b/IntelFspPkg/Tools/GenCfgOpt.py
new file mode 100644 (file)
index 0000000..4417bc3
--- /dev/null
@@ -0,0 +1,894 @@
+## @ GenCfgOpt.py\r
+#\r
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials are licensed and made available under\r
+# the terms and conditions of the BSD License that accompanies this distribution.\r
+# The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+import os\r
+import re\r
+import sys\r
+import struct\r
+from   datetime import date\r
+\r
+# Generated file copyright header\r
+\r
+__copyright_txt__ = """## @file\r
+#\r
+#  THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.\r
+#\r
+#  This file lists all VPD informations for a platform collected by build.exe.\r
+#\r
+# Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+"""\r
+\r
+__copyright_bsf__ = """/** @file\r
+\r
+  Boot Setting File for Platform Configuration.\r
+\r
+  Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+  This file is automatically generated. Please do NOT modify !!!\r
+\r
+**/\r
+\r
+"""\r
+\r
+__copyright_h__ = """/** @file\r
+\r
+Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
+\r
+Redistribution and use in source and binary forms, with or without modification,\r
+are permitted provided that the following conditions are met:\r
+\r
+* Redistributions of source code must retain the above copyright notice, this\r
+  list of conditions and the following disclaimer.\r
+* Redistributions in binary form must reproduce the above copyright notice, this\r
+  list of conditions and the following disclaimer in the documentation and/or\r
+  other materials provided with the distribution.\r
+* Neither the name of Intel Corporation nor the names of its contributors may\r
+  be used to endorse or promote products derived from this software without\r
+  specific prior written permission.\r
+\r
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r
+  THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+  This file is automatically generated. Please do NOT modify !!!\r
+\r
+**/\r
+"""\r
+\r
+class CGenCfgOpt:\r
+    def __init__(self):\r
+        self.Error          = ''\r
+\r
+        self._GlobalDataDef = """\r
+GlobalDataDef\r
+    SKUID = 0, "DEFAULT"\r
+EndGlobalData\r
+\r
+"""\r
+        self._BuidinOptionTxt = """\r
+List &EN_DIS\r
+    Selection 0x1 , "Enabled"\r
+    Selection 0x0 , "Disabled"\r
+EndList\r
+\r
+"""\r
+\r
+        self._BsfKeyList    = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
+        self._HdrKeyList    = ['HEADER','STRUCT']\r
+        self._BuidinOption  = {'$EN_DIS' : 'EN_DIS'}\r
+\r
+        self._MacroDict   = {}\r
+        self._CfgBlkDict  = {}\r
+        self._CfgPageDict = {}\r
+        self._CfgItemList = []\r
+        self._DscFile     = ''\r
+        self._FvDir       = ''\r
+        self._MapVer      = 0\r
+\r
+    def ParseMacros (self, MacroDefStr):\r
+        # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
+        self._MacroDict = {}\r
+        IsExpression = False\r
+        for Macro in MacroDefStr:\r
+            if Macro.startswith('-D'):\r
+                IsExpression = True\r
+                if len(Macro) > 2:\r
+                    Macro = Macro[2:]\r
+                else :\r
+                    continue\r
+            if IsExpression:\r
+                IsExpression = False\r
+                Match = re.match("(\w+)=(.+)", Macro)\r
+                if Match:\r
+                    self._MacroDict[Match.group(1)] = Match.group(2)\r
+                else:\r
+                    Match = re.match("(\w+)", Macro)\r
+                    if Match:\r
+                        self._MacroDict[Match.group(1)] = ''\r
+        if len(self._MacroDict) == 0:\r
+            self.Error = "Invalid MACRO arguments"\r
+            Error = 1\r
+        else:\r
+            Error = 0\r
+        return Error\r
+\r
+\r
+    def ParseDscFile (self, DscFile, FvDir):\r
+        self._CfgItemList = []\r
+        self._CfgPageDict = {}\r
+        self._CfgBlkDict  = {}\r
+        self._DscFile     = DscFile\r
+        self._FvDir       = FvDir\r
+\r
+        IsDefSect       = False\r
+        IsUpdSect       = False\r
+        IsVpdSect       = False\r
+        Found           = False\r
+\r
+        IfStack         = [True]\r
+        ElifStack       = []\r
+        Error           = 0\r
+\r
+        DscFd        = open(DscFile, "r")\r
+        DscLines     = DscFd.readlines()\r
+        DscFd.close()\r
+\r
+        ConfigDict      = {}\r
+\r
+        for DscLine in DscLines:\r
+            Handle     = False\r
+            DscLine = DscLine.strip()\r
+            Match = re.match("^\[(.+)\]", DscLine)\r
+            if Match is not None:\r
+                if  Match.group(1).lower() == "Defines".lower():\r
+                    IsDefSect = True\r
+                    IsVpdSect = False\r
+                    IsUpdSect = False\r
+                elif Match.group(1).lower() == "PcdsDynamicVpd".lower():\r
+                    ConfigDict = {}\r
+                    ConfigDict['header']  = 'ON'\r
+                    ConfigDict['region']  = 'VPD'\r
+                    ConfigDict['order']   = -1\r
+                    ConfigDict['page']    = ''\r
+                    ConfigDict['name']    = ''\r
+                    ConfigDict['find']    = ''\r
+                    ConfigDict['struct']  = ''\r
+                    ConfigDict['subreg']  = []\r
+                    IsDefSect = False\r
+                    IsVpdSect = True\r
+                    IsUpdSect = False\r
+                elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
+                    ConfigDict = {}\r
+                    ConfigDict['header']  = 'ON'\r
+                    ConfigDict['region']  = 'UPD'\r
+                    ConfigDict['order']   = -1\r
+                    ConfigDict['page']    = ''\r
+                    ConfigDict['name']    = ''\r
+                    ConfigDict['find']    = ''\r
+                    ConfigDict['struct']  = ''\r
+                    ConfigDict['subreg']  = []\r
+                    IsDefSect = False\r
+                    IsUpdSect = True\r
+                    IsVpdSect = False\r
+                    Found     = True\r
+                else:\r
+                    IsDefSect = False\r
+                    IsUpdSect = False\r
+                    IsVpdSect = False\r
+            else:\r
+                if IsDefSect or IsUpdSect or IsVpdSect:\r
+                    if DscLine == "!else":\r
+                        IfStack[-1] = not IfStack[-1]\r
+                    elif DscLine == "!endif":\r
+                        IfStack.pop()\r
+                        Level = ElifStack.pop()\r
+                        while Level > 0:\r
+                            IfStack.pop()\r
+                            Level = Level - 1\r
+                    else:\r
+                        Result = False\r
+                        Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", DscLine)\r
+                        if Match is not None:\r
+                            if Match.group(2) in self._MacroDict:\r
+                                if Match.group(1) == 'ifdef':\r
+                                    Result = True\r
+                            else:\r
+                                if Match.group(1) == 'ifndef':\r
+                                    Result = True\r
+                            ElifStack.append(0)\r
+                            IfStack.append(Result)\r
+                        else:\r
+                            Match = re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine)\r
+                            if Match is not None:\r
+                                if Match.group(2) in self._MacroDict:\r
+                                    MacroName = self._MacroDict[Match.group(2)]\r
+                                else:\r
+                                    MacroName = ''\r
+                                Value = Match.group(3)\r
+                                if Value.startswith('$'):\r
+                                    if Value[2:-1] in self._MacroDict:\r
+                                        Value = self._MacroDict[Value[2:-1]]\r
+                                    else:\r
+                                        Value = ''\r
+                                if MacroName == Value:\r
+                                    Result = True\r
+                                if Match.group(1) == "if":\r
+                                    ElifStack.append(0)\r
+                                    IfStack.append(Result)\r
+                                else:   #elseif\r
+                                    IfStack[-1] = not IfStack[-1]\r
+                                    IfStack.append(Result)\r
+                                    ElifStack[-1] = ElifStack[-1] + 1\r
+                            else:\r
+                                if len(DscLine) > 0 and DscLine[0] == '!':\r
+                                    self.Error = "Invalid DscLine '%s'" % DscLine\r
+                                    Error = 3\r
+                                    break;\r
+                                else:\r
+                                    if reduce(lambda x,y: x and y, IfStack):\r
+                                        Handle = True\r
+\r
+            if not Handle:\r
+                continue\r
+\r
+            if IsDefSect:\r
+                #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
+                Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine)\r
+                if Match:\r
+                    self._MacroDict[Match.group(1)] = Match.group(2)\r
+            else:\r
+                Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)\r
+                if Match:\r
+                    Remaining = Match.group(2)\r
+                    if Match.group(1) == 'BSF':\r
+                        Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
+                        if Match:\r
+                            # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
+                            PageList = Match.group(1).split(',')\r
+                            for Page in PageList:\r
+                                Page  = Page.strip()\r
+                                Match = re.match("(\w+):\"(.+)\"", Page)\r
+                                self._CfgPageDict[Match.group(1)] = Match.group(2)\r
+\r
+                        Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
+                        if Match:\r
+                            self._CfgBlkDict['name'] = Match.group(1)\r
+                            self._CfgBlkDict['ver']  = Match.group(2)\r
+\r
+                        for Key in self._BsfKeyList:\r
+                            Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
+                            if Match:\r
+                                if Key in ['HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
+                                    ConfigDict[Key.lower()] += Match.group(1)[1:]\r
+                                else:\r
+                                    ConfigDict[Key.lower()]  = Match.group(1)\r
+                    else:\r
+                        for Key in self._HdrKeyList:\r
+                            Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
+                            if Match:\r
+                                ConfigDict[Key.lower()]  = Match.group(1)\r
+\r
+                # Check VPD/UPD\r
+                if IsUpdSect:\r
+                    Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]{4})\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r
+                else:\r
+                    Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?",  DscLine)\r
+                if Match:\r
+                    ConfigDict['space']  = Match.group(1)\r
+                    ConfigDict['cname']  = Match.group(2)\r
+                    ConfigDict['offset'] = int (Match.group(3), 16)\r
+                    if ConfigDict['order'] == -1:\r
+                        ConfigDict['order'] = ConfigDict['offset'] << 8\r
+                    else:\r
+                        (Major, Minor) = ConfigDict['order'].split('.')\r
+                        ConfigDict['order'] = (int (Major, 16) << 8 ) +  int (Minor, 16)\r
+                    if IsUpdSect:\r
+                        Value = Match.group(5).strip()\r
+                        if Match.group(4).startswith("0x"):\r
+                            Length  = int (Match.group(4), 16)\r
+                        else :\r
+                            Length  = int (Match.group(4))\r
+                    else:\r
+                        Value = Match.group(4)\r
+                        if Value is None:\r
+                            Value = ''\r
+                        Value = Value.strip()\r
+                        if '|' in Value:\r
+                            Match = re.match("^.+\s*\|\s*(.+)", Value)\r
+                            if Match:\r
+                                Value = Match.group(1)\r
+                        Length = -1\r
+\r
+                    ConfigDict['length'] = Length\r
+                    Match = re.match("\$\((\w+)\)", Value)\r
+                    if Match:\r
+                        if Match.group(1) in self._MacroDict:\r
+                            Value = self._MacroDict[Match.group(1)]\r
+                    ConfigDict['value']  = Value\r
+                    if ConfigDict['name']  == '':\r
+                        # Clear BSF specific items\r
+                        ConfigDict['help']   = ''\r
+                        ConfigDict['type']   = ''\r
+                        ConfigDict['option'] = ''\r
+\r
+                    self._CfgItemList.append(ConfigDict.copy())\r
+                    ConfigDict['name']   = ''\r
+                    ConfigDict['find']   = ''\r
+                    ConfigDict['struct'] = ''\r
+                    ConfigDict['order']  = -1\r
+                    ConfigDict['subreg'] = []\r
+                else:\r
+                    # It could be a virtual item as below\r
+                    # !BSF FIELD:{1:SerialDebugPortAddress0}\r
+                    Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)\r
+                    if Match:\r
+                        SubCfgDict = ConfigDict\r
+                        SubCfgDict['cname']  = Match.group(1)\r
+                        SubCfgDict['length'] = int (Match.group(2))\r
+                        if SubCfgDict['length'] > 0:\r
+                            LastItem =  self._CfgItemList[-1]\r
+                            if len(LastItem['subreg']) == 0:\r
+                                SubOffset  = 0\r
+                            else:\r
+                                SubOffset += LastItem['subreg'][-1]['length']\r
+                            SubCfgDict['offset'] = SubOffset\r
+                            LastItem['subreg'].append (SubCfgDict.copy())\r
+                        ConfigDict['name']   = ''\r
+        return Error\r
+\r
+    def UpdateSubRegionDefaultValue (self):\r
+        Error = 0\r
+        for Item in self._CfgItemList:\r
+            if len(Item['subreg']) == 0:\r
+                continue\r
+            bytearray = []\r
+            if Item['value'][0] == '{':\r
+                binlist = Item['value'][1:-1].split(',')\r
+                for each in binlist:\r
+                    each = each.strip()\r
+                    if each.startswith('0x'):\r
+                        value = int(each, 16)\r
+                    else:\r
+                        value = int(each)\r
+                    bytearray.append(value)\r
+            else:\r
+                if Item['value'].startswith('0x'):\r
+                    value = int(Item['value'], 16)\r
+                else:\r
+                    value = int(Item['value'])\r
+                idx = 0;\r
+                while  idx < Item['length']:\r
+                    bytearray.append(value & 0xFF)\r
+                    value = value >> 8\r
+                    idx = idx + 1\r
+            for SubItem in Item['subreg']:\r
+                if SubItem['length'] in (1,2,4,8):\r
+                    valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]\r
+                    valuelist.reverse()\r
+                    valuestr = "".join('%02X' % b for b in valuelist)\r
+                    SubItem['value'] = '0x%s' % valuestr\r
+                else:\r
+                    valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])\r
+                    SubItem['value'] = '{%s}' % valuestr\r
+        return Error\r
+\r
+    def UpdateVpdSizeField (self):\r
+        FvDir = self._FvDir;\r
+\r
+        if 'VPD_TOOL_GUID' not in self._MacroDict:\r
+            self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
+            return 1\r
+\r
+        VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')\r
+        if not os.path.exists(VpdMapFile):\r
+            self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile\r
+            return 2\r
+\r
+        MapFd       = open(VpdMapFile, "r")\r
+        MapLines    = MapFd.readlines()\r
+        MapFd.close()\r
+\r
+        VpdDict  = {}\r
+        PcdDict  = {}\r
+        for MapLine in MapLines:\r
+            #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346\r
+            #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346\r
+            #gPlatformFspPkgTokenSpaceGuid.PcdTest          | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}\r
+            Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine)\r
+            if Match:\r
+                Space  = Match.group(1)\r
+                Name   = Match.group(2)\r
+                if (self._MapVer == 0) and (Match.group(3) != None):\r
+                    self._MapVer = 1\r
+                Offset = int (Match.group(4), 16)\r
+                if Match.group(5).startswith("0x"):\r
+                    Length = int (Match.group(5), 16)\r
+                else :\r
+                    Length = int (Match.group(5))\r
+                PcdDict["len"]   = Length\r
+                PcdDict["value"]   = Match.group(6)\r
+                VpdDict[Space+'.'+Name] = dict(PcdDict)\r
+\r
+        for Item in self._CfgItemList:\r
+            if Item['value'] == '':\r
+                Item['value']  = VpdDict[Item['space']+'.'+Item['cname']]['value']\r
+            if Item['length'] == -1:\r
+                Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']\r
+            if Item['struct'] != '':\r
+                Type = Item['struct'].strip()\r
+                if Type.endswith('*') and (Item['length'] != 4):\r
+                    self.Error = "Struct pointer '%s' has invalid size" % Type\r
+                    return 3\r
+\r
+        return 0\r
+\r
+    def CreateUpdTxtFile (self, UpdTxtFile):\r
+        FvDir = self._FvDir\r
+        if 'UPD_TOOL_GUID' not in self._MacroDict:\r
+            self.Error = "UPD_TOOL_GUID definition is missing in DSC file"\r
+            return 1\r
+\r
+        if UpdTxtFile == '':\r
+            UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')\r
+\r
+        ReCreate = False\r
+        if not os.path.exists(UpdTxtFile):\r
+            ReCreate = True\r
+        else:\r
+            DscTime = os.path.getmtime(self._DscFile)\r
+            TxtTime = os.path.getmtime(UpdTxtFile)\r
+            if DscTime > TxtTime:\r
+                ReCreate = True\r
+\r
+        if not  ReCreate:\r
+            # DSC has not been modified yet\r
+            # So don't have to re-generate other files\r
+            self.Error = 'No DSC file change, skip to create UPD TXT file'\r
+            return 256\r
+\r
+        TxtFd = open(UpdTxtFile, "w")\r
+        TxtFd.write("%s\n"   % (__copyright_txt__ % date.today().year))\r
+\r
+        NextOffset = 0\r
+        SpaceIdx   = 0\r
+        if self._MapVer == 1:\r
+            Default = 'DEFAULT|'\r
+        else:\r
+            Default = ''\r
+        for Item in self._CfgItemList:\r
+            if Item['region'] != 'UPD':\r
+                continue\r
+            Offset = Item['offset']\r
+            if NextOffset < Offset:\r
+                # insert one line\r
+                TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))\r
+                SpaceIdx = SpaceIdx + 1\r
+            NextOffset = Offset + Item['length']\r
+            TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))\r
+        TxtFd.close()\r
+        return 0\r
+\r
+    def CreateField (self, Name, Length, Offset, Struct):\r
+        PosName    = 28\r
+        PosComment = 30\r
+\r
+        IsArray = False\r
+        if Length == 1:\r
+            Type = "UINT8"\r
+        elif Length == 2:\r
+            Type = "UINT16"\r
+        elif Length == 4:\r
+            Type = "UINT32"\r
+        elif Length == 8:\r
+            Type = "UINT64"\r
+        else:\r
+            Type = "UINT8"\r
+            IsArray = True\r
+\r
+        if Struct != '':\r
+            IsArray = False\r
+            Type = Struct\r
+\r
+        if IsArray:\r
+            Name = Name + '[%d]' % Length\r
+\r
+        if len(Type) < PosName:\r
+            Space1 = PosName - len(Type)\r
+        else:\r
+            Space1 = 1\r
+\r
+        if len(Name) < PosComment:\r
+            Space2 = PosComment - len(Name)\r
+        else:\r
+            Space2 = 1\r
+\r
+        return "  %s%s%s;%s/* Offset 0x%04X */\n" % (Type, ' ' * Space1, Name, ' ' * Space2, Offset)\r
+\r
+\r
+    def CreateHeaderFile (self, InputHeaderFile, IsInternal):\r
+        Error = 0\r
+        FvDir = self._FvDir\r
+\r
+        if IsInternal:\r
+            HeaderFile = os.path.join(FvDir, 'VpdHeader.h')\r
+        else:\r
+            HeaderFile = os.path.join(FvDir, 'fsp_vpd.h')\r
+\r
+        # Check if header needs to be recreated\r
+        ReCreate = False\r
+        if IsInternal:\r
+            if not os.path.exists(HeaderFile):\r
+                ReCreate = True\r
+            else:\r
+                DscTime  = os.path.getmtime(self._DscFile)\r
+                HeadTime = os.path.getmtime(HeaderFile)\r
+                if not os.path.exists(InputHeaderFile):\r
+                    InpTime =  HeadTime\r
+                else:\r
+                    InpTime  = os.path.getmtime(InputHeaderFile)\r
+                if DscTime > HeadTime or InpTime > HeadTime:\r
+                    ReCreate = True\r
+\r
+            if not ReCreate:\r
+                self.Error = "No DSC or input header file is changed, skip the header file generating"\r
+                return 256\r
+\r
+        HeaderFd = open(HeaderFile, "w")\r
+        FileBase = os.path.basename(HeaderFile)\r
+        FileName = FileBase.replace(".", "_").upper()\r
+        HeaderFd.write("%s\n"   % (__copyright_h__ % date.today().year))\r
+        HeaderFd.write("#ifndef __%s__\n"   % FileName)\r
+        HeaderFd.write("#define __%s__\n\n" % FileName)\r
+        HeaderFd.write("#pragma pack(1)\n\n")\r
+\r
+        if InputHeaderFile != '':\r
+            if not os.path.exists(InputHeaderFile):\r
+                 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
+                 return 2\r
+\r
+            InFd         = open(InputHeaderFile, "r")\r
+            IncLines     = InFd.readlines()\r
+            InFd.close()\r
+\r
+            Export = False\r
+            for Line in IncLines:\r
+                Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
+                if Match:\r
+                    if Match.group(1) == "BEGIN":\r
+                        Export = True\r
+                        continue\r
+                    else:\r
+                        Export = False\r
+                        continue\r
+                if Export:\r
+                    HeaderFd.write(Line)\r
+            HeaderFd.write("\n\n")\r
+\r
+        for Region in ['UPD', 'VPD']:\r
+\r
+            # Write  PcdVpdRegionSign and PcdImageRevision\r
+            if Region[0] == 'V':\r
+                if 'VPD_TOOL_GUID' not in self._MacroDict:\r
+                    self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
+                    Error = 1\r
+                    break\r
+\r
+                BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")\r
+                if not os.path.exists(BinFile):\r
+                    self.Error = "VPD binary file '%s' does not exist" % BinFile\r
+                    Error = 2\r
+                    break\r
+\r
+                BinFd = open(BinFile, "rb")\r
+                IdStr    = BinFd.read(0x08)\r
+                ImageId  = struct.unpack('Q', IdStr)\r
+                ImageRev = struct.unpack('L', BinFd.read(0x04))\r
+                BinFd.close()\r
+\r
+                HeaderFd.write("#define VPD_IMAGE_ID    0x%016X        /* '%s' */\n" % (ImageId[0], IdStr))\r
+                HeaderFd.write("#define VPD_IMAGE_REV   0x%08X \n\n" % ImageRev[0])\r
+\r
+            HeaderFd.write("typedef struct _" + Region[0]  + "PD_DATA_REGION {\n")\r
+            NextOffset  = 0\r
+            SpaceIdx    = 0\r
+            Offset      = 0\r
+\r
+            LastVisible = True\r
+            ResvOffset  = 0\r
+            ResvIdx     = 0\r
+            LineBuffer  = []\r
+            for Item in self._CfgItemList:\r
+                if Item['region'] != Region:\r
+                    continue\r
+\r
+                NextVisible = LastVisible\r
+                if not IsInternal:\r
+                    if LastVisible and (Item['header'] == 'OFF'):\r
+                        NextVisible = False\r
+                        ResvOffset  = Item['offset']\r
+                    elif (not LastVisible) and Item['header'] == 'ON':\r
+                        NextVisible = True\r
+                        Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
+                        ResvIdx = ResvIdx + 1\r
+                        HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, ''))\r
+\r
+                if  Offset < Item["offset"]:\r
+                    if IsInternal or LastVisible:\r
+                        Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
+                        LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, ''))\r
+                    SpaceIdx = SpaceIdx + 1\r
+                    Offset   = Item["offset"]\r
+\r
+                if Offset != Item["offset"]:\r
+                    print "Unsorted offset 0x%04X\n" % Item["offset"]\r
+                    error = 2\r
+                    break;\r
+\r
+                LastVisible = NextVisible\r
+\r
+                Offset = Offset + Item["length"]\r
+                if IsInternal or LastVisible:\r
+                    for Each in LineBuffer:\r
+                        HeaderFd.write (Each)\r
+                    LineBuffer = []\r
+                    HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct']))\r
+\r
+            HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")\r
+        HeaderFd.write("#pragma pack()\n\n")\r
+        HeaderFd.write("#endif\n")\r
+        HeaderFd.close()\r
+\r
+        return Error\r
+\r
+    def WriteBsfStruct  (self, BsfFd, Item):\r
+        if Item['type'] == "None":\r
+            Space = "gPlatformFspPkgTokenSpaceGuid"\r
+        else:\r
+            Space = Item['space']\r
+        Line = "    $%s_%s" % (Space, Item['cname'])\r
+        Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
+        if Match:\r
+            DefaultValue = Match.group(1).strip()\r
+        else:\r
+            DefaultValue = Item['value'].strip()\r
+        BsfFd.write("    %s%s%4d bytes    $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
+        TmpList = []\r
+        if  Item['type'] == "Combo":\r
+            if not Item['option'] in self._BuidinOption:\r
+                OptList = Item['option'].split(',')\r
+                for Option in OptList:\r
+                    Option = Option.strip()\r
+                    (OpVal, OpStr) = Option.split(':')\r
+                    TmpList.append((OpVal, OpStr))\r
+        return  TmpList\r
+\r
+    def WriteBsfOption  (self, BsfFd, Item):\r
+        PcdName   = Item['space'] + '_' + Item['cname']\r
+        WriteHelp = 0\r
+        if Item['type'] == "Combo":\r
+            if Item['option'] in self._BuidinOption:\r
+                Options = self._BuidinOption[Item['option']]\r
+            else:\r
+                Options = PcdName\r
+            BsfFd.write('    %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));\r
+            WriteHelp = 1\r
+        elif Item['type'].startswith("EditNum"):\r
+            Match = re.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item['type'])\r
+            if Match:\r
+                BsfFd.write('    EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));\r
+                WriteHelp = 2\r
+        elif Item['type'].startswith("EditText"):\r
+            BsfFd.write('    %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));\r
+            WriteHelp = 1\r
+\r
+        if WriteHelp  > 0:\r
+            HelpLines = Item['help'].split('\\n\\r')\r
+            FirstLine = True\r
+            for HelpLine in HelpLines:\r
+                if FirstLine:\r
+                    FirstLine = False\r
+                    BsfFd.write('        Help "%s"\n' % (HelpLine));\r
+                else:\r
+                    BsfFd.write('             "%s"\n' % (HelpLine));\r
+            if WriteHelp == 2:\r
+                    BsfFd.write('             "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));\r
+\r
+    def GenerateBsfFile (self, BsfFile):\r
+\r
+        if BsfFile == '':\r
+            self.Error = "BSF output file '%s' is invalid" % BsfFile\r
+            return 1\r
+\r
+        Error = 0\r
+        OptionDict = {}\r
+        BsfFd      = open(BsfFile, "w")\r
+        BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
+        BsfFd.write("%s\n" % self._GlobalDataDef);\r
+        BsfFd.write("StructDef\n")\r
+        NextOffset = -1\r
+        for Item in self._CfgItemList:\r
+            if Item['find'] != '':\r
+                BsfFd.write('\n    Find "%s"\n' % Item['find'])\r
+                NextOffset = Item['offset'] + Item['length']\r
+            if Item['name'] != '':\r
+                if NextOffset != Item['offset']:\r
+                    BsfFd.write("        Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
+                if len(Item['subreg']) > 0:\r
+                    NextOffset =  Item['offset']\r
+                    for SubItem in Item['subreg']:\r
+                        NextOffset += SubItem['length']\r
+                        if SubItem['name'] == '':\r
+                            BsfFd.write("        Skip %d bytes\n" % (SubItem['length']))\r
+                        else:\r
+                            Options = self.WriteBsfStruct(BsfFd, SubItem)\r
+                            if len(Options) > 0:\r
+                                OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
+                    if (Item['offset'] + Item['length']) <  NextOffset:\r
+                        self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])\r
+                        return 2\r
+                else:\r
+                    NextOffset = Item['offset'] + Item['length']\r
+                    Options = self.WriteBsfStruct(BsfFd, Item)\r
+                    if len(Options) > 0:\r
+                        OptionDict[Item['space']+'_'+Item['cname']] = Options\r
+        BsfFd.write("\nEndStruct\n\n")\r
+\r
+        BsfFd.write("%s" % self._BuidinOptionTxt);\r
+\r
+        for Each in OptionDict:\r
+            BsfFd.write("List &%s\n" % Each);\r
+            for Item in OptionDict[Each]:\r
+                BsfFd.write('    Selection %s , "%s"\n' % (Item[0], Item[1]));\r
+            BsfFd.write("EndList\n\n");\r
+\r
+        BsfFd.write("BeginInfoBlock\n");\r
+        BsfFd.write('    PPVer       "%s"\n' % (self._CfgBlkDict['ver']));\r
+        BsfFd.write('    Description "%s"\n' % (self._CfgBlkDict['name']));\r
+        BsfFd.write("EndInfoBlock\n\n");\r
+\r
+        for Each in self._CfgPageDict:\r
+            BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);\r
+            BsfItems = []\r
+            for Item in self._CfgItemList:\r
+                if Item['name'] != '':\r
+                    if Item['page'] != Each:\r
+                        continue\r
+                    if len(Item['subreg']) > 0:\r
+                        for SubItem in Item['subreg']:\r
+                            if SubItem['name'] != '':\r
+                                BsfItems.append(SubItem)\r
+                    else:\r
+                        BsfItems.append(Item)\r
+\r
+            BsfItems.sort(key=lambda x: x['order'])\r
+\r
+            for Item in BsfItems:\r
+                self.WriteBsfOption (BsfFd, Item)\r
+            BsfFd.write("EndPage\n\n");\r
+\r
+        BsfFd.close()\r
+        return  Error\r
+\r
+\r
+def Usage():\r
+    print "GenCfgOpt Version 0.50"\r
+    print "Usage:"\r
+    print "    GenCfgOpt  UPDTXT  PlatformDscFile BuildFvDir  [TxtOutFile]     [-D Macros]"\r
+    print "    GenCfgOpt  HEADER  PlatformDscFile BuildFvDir  [InputHFile]     [-D Macros]"\r
+    print "    GenCfgOpt  GENBSF  PlatformDscFile BuildFvDir  BsfOutFile       [-D Macros]"\r
+\r
+def Main():\r
+    #\r
+    # Parse the options and args\r
+    #\r
+    GenCfgOpt = CGenCfgOpt()\r
+    argc = len(sys.argv)\r
+    if argc < 4:\r
+        Usage()\r
+        return 1\r
+    else:\r
+        DscFile = sys.argv[2]\r
+        if not os.path.exists(DscFile):\r
+            print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
+            return 2\r
+\r
+        OutFile = ''\r
+        if argc > 4:\r
+            if sys.argv[4][0] == '-':\r
+                Start = 4\r
+            else:\r
+                OutFile = sys.argv[4]\r
+                Start = 5\r
+            if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
+                print "ERROR: %s !" % GenCfgOpt.Error\r
+                return 3\r
+\r
+        FvDir = sys.argv[3]\r
+        if not os.path.isdir(FvDir):\r
+            print "ERROR: FV folder '%s' is invalid !" % FvDir\r
+            return 4\r
+\r
+        if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
+            print "ERROR: %s !" % GenCfgOpt.Error\r
+            return 5\r
+\r
+\r
+        if GenCfgOpt.UpdateVpdSizeField() != 0:\r
+            print "ERROR: %s !" % GenCfgOpt.Error\r
+            return 6\r
+\r
+        if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
+            print "ERROR: %s !" % GenCfgOpt.Error\r
+            return 7\r
+\r
+        if sys.argv[1] == "UPDTXT":\r
+            Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)\r
+            if Ret != 0:\r
+                # No change is detected\r
+                if Ret == 256:\r
+                    print "INFO: %s !" % (GenCfgOpt.Error)\r
+                else :\r
+                    print "ERROR: %s !" % (GenCfgOpt.Error)\r
+                return Ret\r
+        elif sys.argv[1] == "HEADER":\r
+            Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)\r
+            if Ret != 0:\r
+                # No change is detected\r
+                if Ret == 256:\r
+                    print "INFO: %s !" % (GenCfgOpt.Error)\r
+                else :\r
+                    print "ERROR: %s !" % (GenCfgOpt.Error)\r
+                return Ret\r
+            if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:\r
+                print "ERROR: %s !" % GenCfgOpt.Error\r
+                return 8\r
+        elif sys.argv[1] == "GENBSF":\r
+            if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
+                print "ERROR: %s !" % GenCfgOpt.Error\r
+                return 9\r
+        else:\r
+            if argc < 5:\r
+                Usage()\r
+                return 1\r
+            print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
+            Usage()\r
+            return 1\r
+        return 0\r
+    return 0\r
+\r
+\r
+if __name__ == '__main__':\r
+    sys.exit(Main())\r