IntelFspPkg/GenCfgOpt tool add embed structure.
authorMa, Maurice <maurice.ma@intel.com>
Tue, 2 Jun 2015 14:02:39 +0000 (14:02 +0000)
committerjyao1 <jyao1@Edk2>
Tue, 2 Jun 2015 14:02:39 +0000 (14:02 +0000)
The EMBED command allows you to put one or more UPD data into a specify data structure.
 You can utilize it as a group of UPD for example.
 You must specify a start and an end for the specify data structure.
Example:
     !HDR EMBED:{MY_DATA_STRUCT:MyDataStructure:START}
     gTokenSpaceGuid.Upd1  | 0x0020 | 0x01 | 0x00
     gTokenSpaceGuid.Upd2  | 0x0021 | 0x01 | 0x00
     !HDR EMBED:{MY_DATA_STRUCT:MyDataStructure:END}
     gTokenSpaceGuid.UpdN  | 0x0022 | 0x01 | 0x00
Result:
                  typedef struct {
                  /** Offset 0x0020
                  **/
                  UINT8                     Upd1;
                  /** Offset 0x0021
                  **/
                  UINT8                     Upd2;
                  /** Offset 0x0022
                  **/
                  UINT8                     UpdN;
                  }  MY_DATA_STRUCT;

                  typedef struct _UPD_DATA_REGION {
                  …
                  /** Offset 0x0020
                  **/
                  MY_DATA_STRUCT    MyDataStruct;
                  …
                    } UPD_DATA_REGION;

Contributed-under: TianoCore Contribution Agreement 1.0

Signed-off-by: "Ma, Maurice" <maurice.ma@intel.com>
Reviewed-by: "Mudusuru, Giri P" <giri.p.mudusuru@intel.com>
Reviewed-by: "Rangarajan, Ravi P" <ravi.p.rangarajan@intel.com>
Reviewed-by: "Yao, Jiewen" <Jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17549 6f19259b-4bc3-4df7-8a09-765794883524

IntelFspPkg/Tools/GenCfgOpt.py

index 224010e..77eaf64 100644 (file)
@@ -305,7 +305,7 @@ EndList
 """\r
 \r
         self._BsfKeyList    = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
-        self._HdrKeyList    = ['HEADER','STRUCT']\r
+        self._HdrKeyList    = ['HEADER','STRUCT', 'EMBED']\r
         self._BuidinOption  = {'$EN_DIS' : 'EN_DIS'}\r
 \r
         self._MacroDict   = {}\r
@@ -425,7 +425,7 @@ EndList
         DscFd.close()\r
 \r
         while len(DscLines):\r
-            DscLine  = DscLines.pop(0).strip()            \r
+            DscLine  = DscLines.pop(0).strip()\r
             Handle   = False\r
             Match    = re.match("^\[(.+)\]", DscLine)\r
             if Match is not None:\r
@@ -442,6 +442,7 @@ EndList
                     ConfigDict['name']    = ''\r
                     ConfigDict['find']    = ''\r
                     ConfigDict['struct']  = ''\r
+                    ConfigDict['embed']   = ''\r
                     ConfigDict['subreg']  = []\r
                     IsDefSect = False\r
                     IsVpdSect = True\r
@@ -455,6 +456,7 @@ EndList
                     ConfigDict['name']    = ''\r
                     ConfigDict['find']    = ''\r
                     ConfigDict['struct']  = ''\r
+                    ConfigDict['embed']   = ''\r
                     ConfigDict['subreg']  = []\r
                     IsDefSect = False\r
                     IsUpdSect = True\r
@@ -527,7 +529,6 @@ EndList
                                         if DscLine.startswith('!'):\r
                                             print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
                                             raise SystemExit\r
-                                        \r
             if not Handle:\r
                 continue\r
 \r
@@ -560,7 +561,7 @@ EndList
                         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
+                                if Key in ['NAME', '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
@@ -572,7 +573,7 @@ EndList
 \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
+                    Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)\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
@@ -613,6 +614,7 @@ EndList
 \r
                     if ConfigDict['name']  == '':\r
                         # Clear BSF specific items\r
+                        ConfigDict['bsfname']   = ''\r
                         ConfigDict['help']   = ''\r
                         ConfigDict['type']   = ''\r
                         ConfigDict['option'] = ''\r
@@ -621,6 +623,7 @@ EndList
                     ConfigDict['name']   = ''\r
                     ConfigDict['find']   = ''\r
                     ConfigDict['struct'] = ''\r
+                    ConfigDict['embed']  = ''\r
                     ConfigDict['order']  = -1\r
                     ConfigDict['subreg'] = []\r
                 else:\r
@@ -774,9 +777,10 @@ EndList
         TxtFd.close()\r
         return 0\r
 \r
-    def CreateField (self, Item, Name, Length, Offset, Struct, Help):\r
+    def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help):\r
         PosName    = 28\r
         PosComment = 30\r
+        NameLine=''\r
         HelpLine=''\r
 \r
         IsArray = False\r
@@ -786,7 +790,7 @@ EndList
             IsArray = True\r
             Type = "UINT8"\r
 \r
-        if Item['value'].startswith('{'):\r
+        if Item and Item['value'].startswith('{'):\r
             Type = "UINT8"\r
             IsArray = True\r
 \r
@@ -807,18 +811,57 @@ EndList
         else:\r
             Space1 = 1\r
 \r
-        if len(Name) < PosComment:\r
-            Space2 = PosComment - len(Name)\r
-        else:\r
-            Space2 = 1\r
-        if Help != '':\r
-            HelpLine="   %s \n" % Help\r
+        if BsfName != '':\r
+            NameLine="    %s\n" % BsfName\r
 \r
-        return "/**Offset 0x%04X \n%s**/\n  %s%s%s;%s\n" % (Offset, HelpLine, Type, ' ' * Space1, Name, ' ' * Space2)\r
+        if Help != '':\r
+            HelpLine="    %s\n" % Help\r
 \r
+        if Offset is None:\r
+            OffsetStr = '????'\r
+        else:\r
+            OffsetStr = '0x%04X' % Offset\r
+\r
+        return "/** Offset %s\n%s%s**/\n  %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, Type, ' ' * Space1, Name,)\r
+\r
+    def PostProcessBody (self, TextBody):\r
+        NewTextBody = []\r
+        OldTextBody = []\r
+        IncludeLine = False\r
+        StructName  = ''\r
+        VariableName = ''\r
+        for Line in TextBody:\r
+           Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
+           if Match:\r
+               Line = Match.group(4)\r
+\r
+           if Match and Match.group(3) == 'START':\r
+               NewTextBody.append ('typedef struct {\n')\r
+               StructName   = Match.group(1)\r
+               VariableName = Match.group(2)\r
+               MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
+               if MatchOffset:\r
+                   Offset = int(MatchOffset.group(1), 16)\r
+               else:\r
+                   Offset = None\r
+               Line\r
+               IncludeLine = True\r
+               OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', ''))\r
+           if IncludeLine:\r
+               NewTextBody.append (Line)\r
+           else:\r
+               OldTextBody.append (Line)\r
+\r
+           if Match and Match.group(3) == 'END':  \r
+               if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
+                   print "Unmatched struct name '%s' and '%s' !"  % (StructName, Match.group(1))\r
+               else:\r
+                   NewTextBody.append ('} %s;\n\n' %  StructName)\r
+               IncludeLine = False\r
+        NewTextBody.extend(OldTextBody)\r
+        return NewTextBody\r
 \r
     def CreateHeaderFile (self, InputHeaderFile, IsInternal):\r
-        Error = 0\r
         FvDir = self._FvDir\r
 \r
         if IsInternal:\r
@@ -845,51 +888,19 @@ EndList
                 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
+        TxtBody = []\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
+                    return 1\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
+                    return 2\r
 \r
                 BinFd = open(BinFile, "rb")\r
                 IdStr    = BinFd.read(0x08)\r
@@ -897,10 +908,10 @@ EndList
                 ImageRev = struct.unpack('<I', BinFd.read(0x04))\r
                 BinFd.close()\r
 \r
-                HeaderFd.write("#define FSP_IMAGE_ID    0x%016X        /* '%s' */\n" % (ImageId[0], IdStr))\r
-                HeaderFd.write("#define FSP_IMAGE_REV   0x%08X \n\n" % ImageRev[0])\r
+                TxtBody.append("#define FSP_IMAGE_ID    0x%016X        /* '%s' */\n" % (ImageId[0], IdStr))\r
+                TxtBody.append("#define FSP_IMAGE_REV   0x%08X \n\n" % ImageRev[0])\r
 \r
-            HeaderFd.write("typedef struct _" + Region[0]  + "PD_DATA_REGION {\n")\r
+            TxtBody.append("typedef struct _" + Region[0]  + "PD_DATA_REGION {\n")\r
             NextOffset  = 0\r
             SpaceIdx    = 0\r
             Offset      = 0\r
@@ -922,35 +933,81 @@ EndList
                         NextVisible = True\r
                         Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
                         ResvIdx = ResvIdx + 1\r
-                        HeaderFd.write(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', ''))\r
+                        TxtBody.append(self.CreateField (Item, 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 (Item, Name, Item["offset"] - Offset, Offset, '',''))\r
+                        LineBuffer.append(self.CreateField (Item, 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
+                    self.Error = "Unsorted offset 0x%04X\n" % Item["offset"]\r
+                    return 3                    \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
+                        TxtBody.append (Each)\r
                     LineBuffer = []\r
-                    HeaderFd.write(self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['help']))\r
+                    Embed = Item["embed"].upper()\r
+                    if Embed.endswith(':START') or Embed.endswith(':END'):\r
+                        Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
+                    else:\r
+                        if Embed == '':\r
+                            Marker = '';\r
+                        else:\r
+                            self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
+                            return 4\r
+                    Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'])\r
+                    TxtBody.append(Line)\r
+                    \r
+            TxtBody.append("} " + Region[0] + "PD_DATA_REGION;\n\n")\r
+        \r
+        # Handle the embedded data structure\r
+        TxtBody = self.PostProcessBody (TxtBody)\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 6\r
+\r
+            InFd         = open(InputHeaderFile, "r")\r
+            IncLines     = InFd.readlines()\r
+            InFd.close()\r
 \r
-            HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n")\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 Line in TxtBody:\r
+            HeaderFd.write (Line)\r
         HeaderFd.write("#pragma pack()\n\n")\r
         HeaderFd.write("#endif\n")\r
         HeaderFd.close()\r
 \r
-        return Error\r
+        return 0\r
 \r
     def WriteBsfStruct  (self, BsfFd, Item):\r
         if Item['type'] == "None":\r
@@ -992,7 +1049,22 @@ EndList
         elif Item['type'].startswith("EditText"):\r
             BsfFd.write('    %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));\r
             WriteHelp = 1\r
-\r
+        elif Item['type'] == "Table":\r
+            Columns = Item['option'].split(',')\r
+            if len(Columns) != 0:\r
+                BsfFd.write('    %s $%s "%s",' % (Item['type'], PcdName, Item['name']));\r
+                for Col in Columns:\r
+                    Fmt = Col.split(':')\r
+                    if len(Fmt) != 3:\r
+                        raise Exception("Column format '%s' is invalid !" % Fmt)\r
+                    try:\r
+                        Dtype = int(Fmt[1].strip())\r
+                    except:\r
+                        raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
+                    BsfFd.write('\n        Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
+                BsfFd.write(',\n')\r
+                WriteHelp = 1\r
+            \r
         if WriteHelp  > 0:\r
             HelpLines = Item['help'].split('\\n\\r')\r
             FirstLine = True\r
@@ -1112,7 +1184,7 @@ def Main():
                 OutFile = sys.argv[4]\r
                 Start = 5\r
             if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
-                print "ERROR: %s !" % GenCfgOpt.Error\r
+                print "ERROR: Macro parsing failed !"\r
                 return 3\r
 \r
         FvDir = sys.argv[3]\r