IntelFsp2Pkg: Add missing OEM status code defines.
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
1 ## @ GenCfgOpt.py\r
2 #\r
3 # Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>\r
4 # This program and the accompanying materials are licensed and made available under\r
5 # the terms and conditions of the BSD License that accompanies this distribution.\r
6 # The full text of the license may be found at\r
7 # http://opensource.org/licenses/bsd-license.php.\r
8 #\r
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 #\r
12 ##\r
13 \r
14 import os\r
15 import re\r
16 import sys\r
17 import struct\r
18 from   datetime import date\r
19 \r
20 # Generated file copyright header\r
21 \r
22 __copyright_txt__ = """## @file\r
23 #\r
24 #  THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.\r
25 #\r
26 #  This file lists all VPD informations for a platform collected by build.exe.\r
27 #\r
28 # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
29 # This program and the accompanying materials\r
30 # are licensed and made available under the terms and conditions of the BSD License\r
31 # which accompanies this distribution.  The full text of the license may be found at\r
32 # http://opensource.org/licenses/bsd-license.php\r
33 #\r
34 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
35 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
36 #\r
37 """\r
38 \r
39 __copyright_bsf__ = """/** @file\r
40 \r
41   Boot Setting File for Platform Configuration.\r
42 \r
43   Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
44   This program and the accompanying materials\r
45   are licensed and made available under the terms and conditions of the BSD License\r
46   which accompanies this distribution.  The full text of the license may be found at\r
47   http://opensource.org/licenses/bsd-license.php\r
48 \r
49   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
50   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
51 \r
52   This file is automatically generated. Please do NOT modify !!!\r
53 \r
54 **/\r
55 \r
56 """\r
57 \r
58 __copyright_h__ = """/** @file\r
59 \r
60 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
61 \r
62 Redistribution and use in source and binary forms, with or without modification,\r
63 are permitted provided that the following conditions are met:\r
64 \r
65 * Redistributions of source code must retain the above copyright notice, this\r
66   list of conditions and the following disclaimer.\r
67 * Redistributions in binary form must reproduce the above copyright notice, this\r
68   list of conditions and the following disclaimer in the documentation and/or\r
69   other materials provided with the distribution.\r
70 * Neither the name of Intel Corporation nor the names of its contributors may\r
71   be used to endorse or promote products derived from this software without\r
72   specific prior written permission.\r
73 \r
74   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
75   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
76   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
77   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
78   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
79   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
80   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
81   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
82   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
83   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r
84   THE POSSIBILITY OF SUCH DAMAGE.\r
85 \r
86   This file is automatically generated. Please do NOT modify !!!\r
87 \r
88 **/\r
89 """\r
90 \r
91 class CLogicalExpression:\r
92     def __init__(self):\r
93         self.index    = 0\r
94         self.string   = ''\r
95 \r
96     def errExit(self, err = ''):\r
97         print "ERROR: Express parsing for:"\r
98         print "       %s" % self.string\r
99         print "       %s^" % (' ' * self.index)\r
100         if err:\r
101             print "INFO : %s" % err\r
102         raise SystemExit\r
103 \r
104     def getNonNumber (self, n1, n2):\r
105         if not n1.isdigit():\r
106             return n1\r
107         if not n2.isdigit():\r
108             return n2\r
109         return None\r
110 \r
111     def getCurr(self, lens = 1):\r
112         try:\r
113             if lens == -1:\r
114                 return self.string[self.index :]\r
115             else:\r
116                 if self.index + lens > len(self.string):\r
117                     lens = len(self.string) - self.index\r
118                 return self.string[self.index : self.index + lens]\r
119         except Exception:\r
120             return ''\r
121 \r
122     def isLast(self):\r
123         return self.index == len(self.string)\r
124 \r
125     def moveNext(self, len = 1):\r
126         self.index += len\r
127 \r
128     def skipSpace(self):\r
129         while not self.isLast():\r
130             if self.getCurr() in ' \t':\r
131                 self.moveNext()\r
132             else:\r
133                 return\r
134 \r
135     def normNumber (self, val):\r
136         return True if val else False\r
137 \r
138     def getNumber(self, var):\r
139         var = var.strip()\r
140         if   re.match('^0x[a-fA-F0-9]+$', var):\r
141             value = int(var, 16)\r
142         elif re.match('^[+-]?\d+$', var):\r
143             value = int(var, 10)\r
144         else:\r
145             value = None\r
146         return value\r
147 \r
148     def parseValue(self):\r
149         self.skipSpace()\r
150         var = ''\r
151         while not self.isLast():\r
152             char = self.getCurr()\r
153             if re.match('^[\w.]', char):\r
154                 var += char\r
155                 self.moveNext()\r
156             else:\r
157                 break\r
158         val = self.getNumber(var)\r
159         if val is None:\r
160             value = var\r
161         else:\r
162             value = "%d" % val\r
163         return value\r
164 \r
165     def parseSingleOp(self):\r
166         self.skipSpace()\r
167         if re.match('^NOT\W', self.getCurr(-1)):\r
168             self.moveNext(3)\r
169             op  = self.parseBrace()\r
170             val = self.getNumber (op)\r
171             if val is None:\r
172                 self.errExit ("'%s' is not a number" % op)\r
173             return "%d" % (not self.normNumber(int(op)))\r
174         else:\r
175             return self.parseValue()\r
176 \r
177     def parseBrace(self):\r
178         self.skipSpace()\r
179         char = self.getCurr()\r
180         if char == '(':\r
181             self.moveNext()\r
182             value = self.parseExpr()\r
183             self.skipSpace()\r
184             if self.getCurr() != ')':\r
185                 self.errExit ("Expecting closing brace or operator")\r
186             self.moveNext()\r
187             return value\r
188         else:\r
189             value = self.parseSingleOp()\r
190             return value\r
191 \r
192     def parseCompare(self):\r
193         value = self.parseBrace()\r
194         while True:\r
195             self.skipSpace()\r
196             char = self.getCurr()\r
197             if char in ['<', '>']:\r
198                 self.moveNext()\r
199                 next = self.getCurr()\r
200                 if next == '=':\r
201                     op = char + next\r
202                     self.moveNext()\r
203                 else:\r
204                     op = char\r
205                 result = self.parseBrace()\r
206                 test = self.getNonNumber(result, value)\r
207                 if test is None:\r
208                     value = "%d" % self.normNumber(eval (value + op + result))\r
209                 else:\r
210                     self.errExit ("'%s' is not a valid number for comparision" % test)\r
211             elif char in ['=', '!']:\r
212                 op = self.getCurr(2)\r
213                 if op in ['==', '!=']:\r
214                     self.moveNext(2)\r
215                     result = self.parseBrace()\r
216                     test = self.getNonNumber(result, value)\r
217                     if test is None:\r
218                         value = "%d" % self.normNumber((eval (value + op + result)))\r
219                     else:\r
220                         value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))\r
221                 else:\r
222                     break\r
223             else:\r
224                 break\r
225         return value\r
226 \r
227     def parseAnd(self):\r
228         value = self.parseCompare()\r
229         while True:\r
230             self.skipSpace()\r
231             if re.match('^AND\W', self.getCurr(-1)):\r
232                 self.moveNext(3)\r
233                 result = self.parseCompare()\r
234                 test = self.getNonNumber(result, value)\r
235                 if test is None:\r
236                     value = "%d" % self.normNumber(int(value) & int(result))\r
237                 else:\r
238                     self.errExit ("'%s' is not a valid op number for AND" % test)\r
239             else:\r
240                 break\r
241         return value\r
242 \r
243     def parseOrXor(self):\r
244         value  = self.parseAnd()\r
245         op     = None\r
246         while True:\r
247             self.skipSpace()\r
248             op = None\r
249             if re.match('^XOR\W', self.getCurr(-1)):\r
250                 self.moveNext(3)\r
251                 op = '^'\r
252             elif re.match('^OR\W', self.getCurr(-1)):\r
253                 self.moveNext(2)\r
254                 op = '|'\r
255             else:\r
256                 break\r
257             if op:\r
258                 result = self.parseAnd()\r
259                 test = self.getNonNumber(result, value)\r
260                 if test is None:\r
261                     value = "%d" % self.normNumber(eval (value + op + result))\r
262                 else:\r
263                     self.errExit ("'%s' is not a valid op number for XOR/OR" % test)\r
264         return value\r
265 \r
266     def parseExpr(self):\r
267         return self.parseOrXor()\r
268 \r
269     def getResult(self):\r
270         value = self.parseExpr()\r
271         self.skipSpace()\r
272         if not self.isLast():\r
273             self.errExit ("Unexpected character found '%s'" % self.getCurr())\r
274         test = self.getNumber(value)\r
275         if test is None:\r
276             self.errExit ("Result '%s' is not a number" % value)\r
277         return int(value)\r
278 \r
279     def evaluateExpress (self, Expr):\r
280         self.index     = 0\r
281         self.string    = Expr\r
282         if self.getResult():\r
283             Result = True\r
284         else:\r
285             Result = False\r
286         return Result\r
287 \r
288 class CGenCfgOpt:\r
289     def __init__(self):\r
290         self.Debug          = False\r
291         self.Error          = ''\r
292         self.ReleaseMode    = True\r
293 \r
294         self._GlobalDataDef = """\r
295 GlobalDataDef\r
296     SKUID = 0, "DEFAULT"\r
297 EndGlobalData\r
298 \r
299 """\r
300         self._BuidinOptionTxt = """\r
301 List &EN_DIS\r
302     Selection 0x1 , "Enabled"\r
303     Selection 0x0 , "Disabled"\r
304 EndList\r
305 \r
306 """\r
307 \r
308         self._BsfKeyList    = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
309         self._HdrKeyList    = ['HEADER','STRUCT', 'EMBED', 'COMMENT']\r
310         self._BuidinOption  = {'$EN_DIS' : 'EN_DIS'}\r
311 \r
312         self._MacroDict   = {}\r
313         self._PcdsDict    = {}\r
314         self._CfgBlkDict  = {}\r
315         self._CfgPageDict = {}\r
316         self._CfgItemList = []\r
317         self._DscFile     = ''\r
318         self._FvDir       = ''\r
319         self._MapVer      = 0\r
320 \r
321     def ParseBuildMode (self, OutputStr):\r
322         if "RELEASE_" in OutputStr:\r
323             self.ReleaseMode = True\r
324         if "DEBUG_" in OutputStr:\r
325             self.ReleaseMode = False\r
326         return\r
327 \r
328     def ParseMacros (self, MacroDefStr):\r
329         # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
330         self._MacroDict = {}\r
331         IsExpression = False\r
332         for Macro in MacroDefStr:\r
333             if Macro.startswith('-D'):\r
334                 IsExpression = True\r
335                 if len(Macro) > 2:\r
336                     Macro = Macro[2:]\r
337                 else :\r
338                     continue\r
339             if IsExpression:\r
340                 IsExpression = False\r
341                 Match = re.match("(\w+)=(.+)", Macro)\r
342                 if Match:\r
343                     self._MacroDict[Match.group(1)] = Match.group(2)\r
344                 else:\r
345                     Match = re.match("(\w+)", Macro)\r
346                     if Match:\r
347                         self._MacroDict[Match.group(1)] = ''\r
348         if len(self._MacroDict) == 0:\r
349             Error = 1\r
350         else:\r
351             Error = 0\r
352             if self.Debug:\r
353                 print "INFO : Macro dictionary:"\r
354                 for Each in self._MacroDict:\r
355                     print "       $(%s) = [ %s ]" % (Each , self._MacroDict[Each])\r
356         return Error\r
357 \r
358     def EvaulateIfdef   (self, Macro):\r
359         Result = Macro in self._MacroDict\r
360         if self.Debug:\r
361             print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)\r
362         return  Result\r
363 \r
364     def ExpandMacros (self, Input):\r
365         Line = Input\r
366         Match = re.findall("\$\(\w+\)", Input)\r
367         if Match:\r
368             for Each in Match:\r
369               Variable = Each[2:-1]\r
370               if Variable in self._MacroDict:\r
371                   Line = Line.replace(Each, self._MacroDict[Variable])\r
372               else:\r
373                   if self.Debug:\r
374                       print "WARN : %s is not defined" % Each\r
375                   Line = Line.replace(Each, Each[2:-1])\r
376         return Line\r
377 \r
378     def ExpandPcds (self, Input):\r
379         Line = Input\r
380         Match = re.findall("(\w+\.\w+)", Input)\r
381         if Match:\r
382             for PcdName in Match:\r
383               if PcdName in self._PcdsDict:\r
384                   Line = Line.replace(PcdName, self._PcdsDict[PcdName])\r
385               else:\r
386                   if self.Debug:\r
387                       print "WARN : %s is not defined" % PcdName\r
388         return Line\r
389 \r
390     def EvaluateExpress (self, Expr):\r
391         ExpExpr = self.ExpandPcds(Expr)\r
392         ExpExpr = self.ExpandMacros(ExpExpr)\r
393         LogExpr = CLogicalExpression()\r
394         Result  = LogExpr.evaluateExpress (ExpExpr)\r
395         if self.Debug:\r
396             print "INFO : Eval Express [%s] : %s" % (Expr, Result)\r
397         return Result\r
398 \r
399     def FormatListValue(self, ConfigDict):\r
400         Struct = ConfigDict['struct']\r
401         if Struct not in ['UINT8','UINT16','UINT32','UINT64']:\r
402             return\r
403 \r
404         dataarray = []\r
405         binlist = ConfigDict['value'][1:-1].split(',')\r
406         for each in binlist:\r
407             each = each.strip()\r
408             if each.startswith('0x'):\r
409                 value = int(each, 16)\r
410             else:\r
411                 value = int(each)\r
412             dataarray.append(value)\r
413 \r
414         unit = int(Struct[4:]) / 8\r
415         if int(ConfigDict['length']) != unit * len(dataarray):\r
416             raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])\r
417 \r
418         bytearray = []\r
419         for each in dataarray:\r
420             value = each\r
421             for loop in xrange(unit):\r
422                 bytearray.append("0x%02X" % (value & 0xFF))\r
423                 value = value >> 8\r
424         newvalue  = '{'  + ','.join(bytearray) + '}'\r
425         ConfigDict['value'] = newvalue\r
426         return ""\r
427 \r
428     def ParseDscFile (self, DscFile, FvDir):\r
429         self._CfgItemList = []\r
430         self._CfgPageDict = {}\r
431         self._CfgBlkDict  = {}\r
432         self._DscFile     = DscFile\r
433         self._FvDir       = FvDir\r
434 \r
435         IsDefSect       = False\r
436         IsPcdSect       = False\r
437         IsUpdSect       = False\r
438         IsVpdSect       = False\r
439 \r
440         IfStack         = []\r
441         ElifStack       = []\r
442         Error           = 0\r
443         ConfigDict      = {}\r
444 \r
445         DscFd        = open(DscFile, "r")\r
446         DscLines     = DscFd.readlines()\r
447         DscFd.close()\r
448 \r
449         while len(DscLines):\r
450             DscLine  = DscLines.pop(0).strip()\r
451             Handle   = False\r
452             Match    = re.match("^\[(.+)\]", DscLine)\r
453             if Match is not None:\r
454                 IsDefSect = False\r
455                 IsPcdSect = False\r
456                 IsVpdSect = False\r
457                 IsUpdSect = False\r
458                 if  Match.group(1).lower() == "Defines".lower():\r
459                     IsDefSect = True\r
460                 if  Match.group(1).lower() == "PcdsFeatureFlag".lower():\r
461                     IsPcdSect = True\r
462                 elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
463                     ConfigDict = {}\r
464                     ConfigDict['header']  = 'ON'\r
465                     ConfigDict['region']  = 'UPD'\r
466                     ConfigDict['order']   = -1\r
467                     ConfigDict['page']    = ''\r
468                     ConfigDict['name']    = ''\r
469                     ConfigDict['find']    = ''\r
470                     ConfigDict['struct']  = ''\r
471                     ConfigDict['embed']   = ''\r
472                     ConfigDict['comment'] = ''\r
473                     ConfigDict['subreg']  = []\r
474                     IsUpdSect = True\r
475             else:\r
476                 if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:\r
477                     if re.match("^!else($|\s+#.+)", DscLine):\r
478                         if IfStack:\r
479                             IfStack[-1] = not IfStack[-1]\r
480                         else:\r
481                             print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
482                             raise SystemExit\r
483                     elif re.match("^!endif($|\s+#.+)", DscLine):\r
484                         if IfStack:\r
485                             IfStack.pop()\r
486                             Level = ElifStack.pop()\r
487                             if Level > 0:\r
488                                 del IfStack[-Level:]\r
489                         else:\r
490                             print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
491                             raise SystemExit\r
492                     else:\r
493                         Result = False\r
494                         Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)\r
495                         if Match:\r
496                             Result = self.EvaulateIfdef (Match.group(2))\r
497                             if Match.group(1) == 'ifndef':\r
498                                 Result = not Result\r
499                             IfStack.append(Result)\r
500                             ElifStack.append(0)\r
501                         else:\r
502                             Match  = re.match("!(if|elseif)\s+(.+)", DscLine)\r
503                             if Match:\r
504                                 Result = self.EvaluateExpress(Match.group(2))\r
505                                 if Match.group(1) == "if":\r
506                                     ElifStack.append(0)\r
507                                     IfStack.append(Result)\r
508                                 else:   #elseif\r
509                                     if IfStack:\r
510                                         IfStack[-1] = not IfStack[-1]\r
511                                         IfStack.append(Result)\r
512                                         ElifStack[-1] = ElifStack[-1] + 1\r
513                                     else:\r
514                                         print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
515                                         raise SystemExit\r
516                             else:\r
517                                 if IfStack:\r
518                                     Handle = reduce(lambda x,y: x and y, IfStack)\r
519                                 else:\r
520                                     Handle = True\r
521                                 if Handle:\r
522                                     Match = re.match("!include\s+(.+)", DscLine)\r
523                                     if Match:\r
524                                         IncludeFilePath = Match.group(1)\r
525                                         IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
526                                         try:\r
527                                             IncludeDsc  = open(IncludeFilePath, "r")\r
528                                         except:\r
529                                             print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
530                                             raise SystemExit\r
531                                         NewDscLines = IncludeDsc.readlines()\r
532                                         IncludeDsc.close()\r
533                                         DscLines = NewDscLines + DscLines\r
534                                     else:\r
535                                         if DscLine.startswith('!'):\r
536                                             print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
537                                             raise SystemExit\r
538             if not Handle:\r
539                 continue\r
540 \r
541             if IsDefSect:\r
542                 #DEFINE UPD_TOOL_GUID       = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
543                 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6\r
544                 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385\r
545                 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F\r
546                 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
547                 if Match:\r
548                     self._MacroDict[Match.group(1)] = Match.group(2)\r
549                     if self.Debug:\r
550                         print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))\r
551             elif IsPcdSect:\r
552                 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE\r
553                 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE\r
554                 Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)\r
555                 if Match:\r
556                     self._PcdsDict[Match.group(1)] = Match.group(2)\r
557                     if self.Debug:\r
558                         print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))\r
559             else:\r
560                 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)\r
561                 if Match:\r
562                     Remaining = Match.group(2)\r
563                     if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':\r
564                         Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
565                         if Match:\r
566                             # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
567                             PageList = Match.group(1).split(',')\r
568                             for Page in PageList:\r
569                                 Page  = Page.strip()\r
570                                 Match = re.match("(\w+):\"(.+)\"", Page)\r
571                                 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
572 \r
573                         Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
574                         if Match:\r
575                             self._CfgBlkDict['name'] = Match.group(1)\r
576                             self._CfgBlkDict['ver']  = Match.group(2)\r
577 \r
578                         for Key in self._BsfKeyList:\r
579                             Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
580                             if Match:\r
581                                 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
582                                     ConfigDict[Key.lower()] += Match.group(1)[1:]\r
583                                 else:\r
584                                     ConfigDict[Key.lower()]  = Match.group(1)\r
585                     else:\r
586                         for Key in self._HdrKeyList:\r
587                             Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
588                             if Match:\r
589                                 ConfigDict[Key.lower()]  = Match.group(1)\r
590 \r
591                 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)\r
592                 if Match:\r
593                     ConfigDict['name'] = Match.group(1)\r
594 \r
595                 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)\r
596                 if Match:\r
597                     if Match.group(2).strip() in self._BuidinOption:\r
598                         ConfigDict['option'] = Match.group(2).strip()\r
599                     else:\r
600                         OptionValueList = Match.group(2).split(',')\r
601                         OptionStringList = Match.group(3).split(',')\r
602                         Index = 0\r
603                         for Option in OptionValueList:\r
604                              Option = Option.strip()\r
605                              ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()\r
606                              Index += 1\r
607                              if Index in range(len(OptionValueList)):\r
608                                  ConfigDict['option'] += ', '\r
609                     ConfigDict['type'] = "Combo"\r
610 \r
611                 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
612                 if Match:\r
613                     if "0x" in Match.group(2) or "0x" in Match.group(3):\r
614                        ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
615                     else:\r
616                        ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
617 \r
618                 Match = re.match("^\s*##\s+(.+)", DscLine)\r
619                 if Match:\r
620                     ConfigDict['help'] = Match.group(1)\r
621 \r
622                 # Check VPD/UPD\r
623                 if IsUpdSect:\r
624                     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
625                 else:\r
626                     Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?",  DscLine)\r
627                 if Match:\r
628                     ConfigDict['space']  = Match.group(1)\r
629                     ConfigDict['cname']  = Match.group(2)\r
630                     ConfigDict['offset'] = int (Match.group(3), 16)\r
631                     if ConfigDict['order'] == -1:\r
632                         ConfigDict['order'] = ConfigDict['offset'] << 8\r
633                     else:\r
634                         (Major, Minor) = ConfigDict['order'].split('.')\r
635                         ConfigDict['order'] = (int (Major, 16) << 8 ) +  int (Minor, 16)\r
636                     if IsUpdSect:\r
637                         Value = Match.group(5).strip()\r
638                         if Match.group(4).startswith("0x"):\r
639                             Length  = int (Match.group(4), 16)\r
640                         else :\r
641                             Length  = int (Match.group(4))\r
642                     else:\r
643                         Value = Match.group(4)\r
644                         if Value is None:\r
645                             Value = ''\r
646                         Value = Value.strip()\r
647                         if '|' in Value:\r
648                             Match = re.match("^.+\s*\|\s*(.+)", Value)\r
649                             if Match:\r
650                                 Value = Match.group(1)\r
651                         Length = -1\r
652 \r
653                     ConfigDict['length'] = Length\r
654                     Match = re.match("\$\((\w+)\)", Value)\r
655                     if Match:\r
656                         if Match.group(1) in self._MacroDict:\r
657                             Value = self._MacroDict[Match.group(1)]\r
658 \r
659                     ConfigDict['value']  = Value\r
660                     if (len(Value) > 0)  and (Value[0] == '{'):\r
661                         Value = self.FormatListValue(ConfigDict)\r
662 \r
663                     if ConfigDict['name']  == '':\r
664                         # Clear BSF specific items\r
665                         ConfigDict['bsfname']   = ''\r
666                         ConfigDict['help']   = ''\r
667                         ConfigDict['type']   = ''\r
668                         ConfigDict['option'] = ''\r
669 \r
670                     self._CfgItemList.append(ConfigDict.copy())\r
671                     ConfigDict['name']   = ''\r
672                     ConfigDict['find']   = ''\r
673                     ConfigDict['struct'] = ''\r
674                     ConfigDict['embed']  = ''\r
675                     ConfigDict['comment'] = ''\r
676                     ConfigDict['order']  = -1\r
677                     ConfigDict['subreg'] = []\r
678                     ConfigDict['option'] = ''\r
679                 else:\r
680                     # It could be a virtual item as below\r
681                     # !BSF FIELD:{SerialDebugPortAddress0:1}\r
682                     # or\r
683                     # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
684                     Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)\r
685                     if Match:\r
686                         SubCfgDict = ConfigDict.copy()\r
687                         if (Match.group(4) == None) or (Match.group(4) == 'B'):\r
688                           UnitBitLen = 8\r
689                         elif Match.group(4) == 'b':\r
690                           UnitBitLen = 1\r
691                         else:\r
692                           print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)\r
693                           raise SystemExit\r
694                         SubCfgDict['cname']  = Match.group(2)\r
695                         SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen\r
696                         if SubCfgDict['bitlength'] > 0:\r
697                             LastItem =  self._CfgItemList[-1]\r
698                             if len(LastItem['subreg']) == 0:\r
699                                 SubOffset  = 0\r
700                             else:\r
701                                 SubOffset  = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']\r
702                             SubCfgDict['bitoffset'] = SubOffset\r
703                             LastItem['subreg'].append (SubCfgDict.copy())\r
704                         ConfigDict['name']   = ''\r
705         return Error\r
706 \r
707     def GetBsfBitFields (self, subitem, bytes):\r
708         start = subitem['bitoffset']\r
709         end   = start + subitem['bitlength']\r
710         bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])\r
711         bitsvalue = bitsvalue[::-1]\r
712         bitslen   = len(bitsvalue)\r
713         if start > bitslen or end > bitslen:\r
714             print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name'])\r
715             raise SystemExit\r
716         return hex(int(bitsvalue[start:end][::-1], 2))\r
717 \r
718     def UpdateSubRegionDefaultValue (self):\r
719         Error = 0\r
720         for Item in self._CfgItemList:\r
721             if len(Item['subreg']) == 0:\r
722                 continue\r
723             bytearray = []\r
724             if Item['value'][0] == '{':\r
725                 binlist = Item['value'][1:-1].split(',')\r
726                 for each in binlist:\r
727                     each = each.strip()\r
728                     if each.startswith('0x'):\r
729                         value = int(each, 16)\r
730                     else:\r
731                         value = int(each)\r
732                     bytearray.append(value)\r
733             else:\r
734                 if Item['value'].startswith('0x'):\r
735                     value = int(Item['value'], 16)\r
736                 else:\r
737                     value = int(Item['value'])\r
738                 idx = 0\r
739                 while  idx < Item['length']:\r
740                     bytearray.append(value & 0xFF)\r
741                     value = value >> 8\r
742                     idx = idx + 1\r
743             for SubItem in Item['subreg']:\r
744                 valuestr = self.GetBsfBitFields(SubItem, bytearray)\r
745                 SubItem['value'] = valuestr\r
746         return Error\r
747 \r
748     def CreateSplitUpdTxt (self, UpdTxtFile):\r
749         GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r
750         SignatureList = ['0x545F', '0x4D5F','0x535F']        #  _T, _M, and _S signature for FSPT, FSPM, FSPS\r
751         for Index in range(len(GuidList)):\r
752             UpdTxtFile = ''\r
753             FvDir = self._FvDir\r
754             if GuidList[Index] not in self._MacroDict:\r
755                 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r
756                 return 1\r
757 \r
758             if UpdTxtFile == '':\r
759                 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
760 \r
761             ReCreate = False\r
762             if not os.path.exists(UpdTxtFile):\r
763                 ReCreate = True\r
764             else:\r
765                 DscTime = os.path.getmtime(self._DscFile)\r
766                 TxtTime = os.path.getmtime(UpdTxtFile)\r
767                 if DscTime > TxtTime:\r
768                     ReCreate = True\r
769 \r
770             if not  ReCreate:\r
771                 # DSC has not been modified yet\r
772                 # So don't have to re-generate other files\r
773                 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
774                 return 256\r
775 \r
776             TxtFd = open(UpdTxtFile, "w")\r
777             TxtFd.write("%s\n"   % (__copyright_txt__ % date.today().year))\r
778 \r
779             NextOffset = 0\r
780             SpaceIdx   = 0\r
781             StartAddr  = 0\r
782             EndAddr    = 0\r
783             Default = 'DEFAULT|'\r
784             InRange = False\r
785             for Item in self._CfgItemList:\r
786                 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
787                     StartAddr = Item['offset']\r
788                     NextOffset = StartAddr\r
789                     InRange = True\r
790                 if Item['cname'] == 'UpdTerminator' and InRange == True:\r
791                     EndAddr = Item['offset']\r
792                     InRange = False\r
793             InRange = False\r
794             for Item in self._CfgItemList:\r
795                 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
796                     InRange = True\r
797                 if InRange != True:\r
798                     continue\r
799                 if Item['cname'] == 'UpdTerminator':\r
800                     InRange = False\r
801                 if Item['region'] != 'UPD':\r
802                     continue\r
803                 Offset = Item['offset']\r
804                 if StartAddr > Offset or EndAddr < Offset:\r
805                     continue\r
806                 if NextOffset < Offset:\r
807                     # insert one line\r
808                     TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r
809                     SpaceIdx = SpaceIdx + 1\r
810                 NextOffset = Offset + Item['length']\r
811                 if Item['cname'] == 'PcdSerialIoUartDebugEnable':\r
812                     if self.ReleaseMode == False:\r
813                         Item['value'] = 0x01\r
814                 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r
815             TxtFd.close()\r
816         return 0\r
817 \r
818     def ProcessMultilines (self, String, MaxCharLength):\r
819             Multilines = ''\r
820             StringLength = len(String)\r
821             CurrentStringStart = 0\r
822             StringOffset = 0\r
823             BreakLineDict = []\r
824             if len(String) <= MaxCharLength:\r
825                 while (StringOffset < StringLength):\r
826                     if StringOffset >= 1:\r
827                         if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
828                             BreakLineDict.append (StringOffset + 1)\r
829                     StringOffset += 1\r
830                 if BreakLineDict != []:\r
831                     for Each in BreakLineDict:\r
832                         Multilines += "  %s\n" % String[CurrentStringStart:Each].lstrip()\r
833                         CurrentStringStart = Each\r
834                     if StringLength - CurrentStringStart > 0:\r
835                         Multilines += "  %s\n" % String[CurrentStringStart:].lstrip()\r
836                 else:\r
837                     Multilines = "  %s\n" % String\r
838             else:\r
839                 NewLineStart = 0\r
840                 NewLineCount = 0\r
841                 FoundSpaceChar = False\r
842                 while (StringOffset < StringLength):\r
843                     if StringOffset >= 1:\r
844                         if NewLineCount >= MaxCharLength - 1:\r
845                             if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
846                                 BreakLineDict.append (NewLineStart + NewLineCount)\r
847                                 NewLineStart = NewLineStart + NewLineCount\r
848                                 NewLineCount = 0\r
849                                 FoundSpaceChar = True\r
850                             elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
851                                 BreakLineDict.append (0)\r
852                         if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
853                             BreakLineDict.append (StringOffset + 1)\r
854                             NewLineStart = StringOffset + 1\r
855                             NewLineCount = 0\r
856                     StringOffset += 1\r
857                     NewLineCount += 1\r
858                 if BreakLineDict != []:\r
859                     BreakLineDict.sort ()\r
860                     for Each in BreakLineDict:\r
861                         if Each > 0:\r
862                             Multilines += "  %s\n" % String[CurrentStringStart:Each].lstrip()\r
863                         CurrentStringStart = Each\r
864                     if StringLength - CurrentStringStart > 0:\r
865                         Multilines += "  %s\n" % String[CurrentStringStart:].lstrip()\r
866             return Multilines\r
867 \r
868     def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):\r
869         PosName    = 28\r
870         PosComment = 30\r
871         NameLine=''\r
872         HelpLine=''\r
873         OptionLine=''\r
874 \r
875         IsArray = False\r
876         if Length in [1,2,4,8]:\r
877             Type = "UINT%d" % (Length * 8)\r
878         else:\r
879             IsArray = True\r
880             Type = "UINT8"\r
881 \r
882         if Item and Item['value'].startswith('{'):\r
883             Type = "UINT8"\r
884             IsArray = True\r
885 \r
886         if Struct != '':\r
887             Type = Struct\r
888             if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
889                 IsArray = True\r
890                 Unit = int(Type[4:]) / 8\r
891                 Length = Length / Unit\r
892             else:\r
893                 IsArray = False\r
894 \r
895         if IsArray:\r
896             Name = Name + '[%d]' % Length\r
897 \r
898         if len(Type) < PosName:\r
899             Space1 = PosName - len(Type)\r
900         else:\r
901             Space1 = 1\r
902 \r
903         if BsfName != '':\r
904             NameLine=" - %s\n" % BsfName\r
905         else:\r
906             NameLine="\n"\r
907 \r
908         if Help != '':\r
909             HelpLine = self.ProcessMultilines (Help, 80)\r
910 \r
911         if Option != '':\r
912             OptionLine = self.ProcessMultilines (Option, 80)\r
913 \r
914         if Offset is None:\r
915             OffsetStr = '????'\r
916         else:\r
917             OffsetStr = '0x%04X' % Offset\r
918 \r
919         return "\n/** Offset %s%s%s%s**/\n  %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)\r
920 \r
921     def PostProcessBody (self, TextBody):\r
922         NewTextBody = []\r
923         OldTextBody = []\r
924         IncludeLine = False\r
925         StructName  = ''\r
926         VariableName = ''\r
927         IsUpdHdrDefined = False\r
928         IsUpdHeader = False\r
929         for Line in TextBody:\r
930            SplitToLines = Line.splitlines()\r
931            MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r
932            if MatchComment:\r
933               if MatchComment.group(1) == 'FSP_UPD_HEADER':\r
934                   IsUpdHeader = True\r
935               else:\r
936                   IsUpdHeader = False\r
937               if IsUpdHdrDefined != True or IsUpdHeader != True:\r
938                 CommentLine = " " + MatchComment.group(2) + "\n"\r
939                 NewTextBody.append("/**" + CommentLine + "**/\n")\r
940               Line = Line[(len(SplitToLines[0]) + 1):]\r
941 \r
942            Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
943            if Match:\r
944                Line = Match.group(4)\r
945                if Match.group(1) == 'FSP_UPD_HEADER':\r
946                    IsUpdHeader = True\r
947                else:\r
948                    IsUpdHeader = False\r
949 \r
950            if Match and Match.group(3) == 'START':\r
951                if IsUpdHdrDefined != True or IsUpdHeader != True:\r
952                    NewTextBody.append ('typedef struct {\n')\r
953                StructName   = Match.group(1)\r
954                VariableName = Match.group(2)\r
955                MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
956                if MatchOffset:\r
957                    Offset = int(MatchOffset.group(1), 16)\r
958                else:\r
959                    Offset = None\r
960                Line\r
961                IncludeLine = True\r
962                OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r
963            if IncludeLine:\r
964                if IsUpdHdrDefined != True or IsUpdHeader != True:\r
965                    NewTextBody.append (Line)\r
966            else:\r
967                OldTextBody.append (Line)\r
968 \r
969            if Match and Match.group(3) == 'END':\r
970                if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
971                    print "Unmatched struct name '%s' and '%s' !"  % (StructName, Match.group(1))\r
972                else:\r
973                    if IsUpdHdrDefined != True or IsUpdHeader != True:\r
974                       NewTextBody.append ('} %s;\n\n' %  StructName)\r
975                       IsUpdHdrDefined = True\r
976                IncludeLine = False\r
977         NewTextBody.extend(OldTextBody)\r
978         return NewTextBody\r
979 \r
980     def CreateHeaderFile (self, InputHeaderFile):\r
981         FvDir = self._FvDir\r
982 \r
983         HeaderFileName = 'FspUpd.h'\r
984         HeaderFile = os.path.join(FvDir, HeaderFileName)\r
985 \r
986         # Check if header needs to be recreated\r
987         ReCreate = False\r
988 \r
989         TxtBody = []\r
990         for Item in self._CfgItemList:\r
991            if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
992                Value = int(Item['value'], 16)\r
993                Chars = []\r
994                while Value != 0x0:\r
995                    Chars.append(chr(Value & 0xFF))\r
996                    Value = Value >> 8\r
997                SignatureStr = ''.join(Chars)\r
998                # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly\r
999                if '_T' in SignatureStr[6:6+2]:\r
1000                    TxtBody.append("#define FSPT_UPD_SIGNATURE               %s        /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1001                elif '_M' in SignatureStr[6:6+2]:\r
1002                    TxtBody.append("#define FSPM_UPD_SIGNATURE               %s        /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1003                elif '_S' in SignatureStr[6:6+2]:\r
1004                    TxtBody.append("#define FSPS_UPD_SIGNATURE               %s        /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1005         TxtBody.append("\n")\r
1006 \r
1007         for Region in ['UPD']:\r
1008             UpdOffsetTable = []\r
1009             UpdSignature = ['0x545F', '0x4D5F', '0x535F']   #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS\r
1010             UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r
1011             for Item in self._CfgItemList:\r
1012                 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
1013                     UpdOffsetTable.append (Item["offset"])\r
1014 \r
1015             for UpdIdx in range(len(UpdOffsetTable)):\r
1016                 CommentLine = ""\r
1017                 for Item in self._CfgItemList:\r
1018                     if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r
1019                         MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r
1020                         if MatchComment and MatchComment.group(1) == Region[0]:\r
1021                             CommentLine = " " + MatchComment.group(2) + "\n"\r
1022                             TxtBody.append("/**" + CommentLine + "**/\n")\r
1023                     elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r
1024                         Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r
1025                         if Match:\r
1026                             TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r
1027                 TxtBody.append("typedef struct {\n")\r
1028                 NextOffset  = 0\r
1029                 SpaceIdx    = 0\r
1030                 Offset      = 0\r
1031 \r
1032                 LastVisible = True\r
1033                 ResvOffset  = 0\r
1034                 ResvIdx     = 0\r
1035                 LineBuffer  = []\r
1036                 InRange = False\r
1037                 for Item in self._CfgItemList:\r
1038                     if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r
1039                         InRange = True\r
1040                     if InRange != True:\r
1041                         continue\r
1042                     if Item['cname'] == 'UpdTerminator':\r
1043                         InRange = False\r
1044 \r
1045                     if Item['region'] != Region:\r
1046                         continue\r
1047 \r
1048                     if Item["offset"] < UpdOffsetTable[UpdIdx]:\r
1049                         continue\r
1050 \r
1051                     NextVisible = LastVisible\r
1052 \r
1053                     if LastVisible and (Item['header'] == 'OFF'):\r
1054                         NextVisible = False\r
1055                         ResvOffset  = Item['offset']\r
1056                     elif (not LastVisible) and Item['header'] == 'ON':\r
1057                         NextVisible = True\r
1058                         Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
1059                         ResvIdx = ResvIdx + 1\r
1060                         TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r
1061 \r
1062                     if  Offset < Item["offset"]:\r
1063                         if LastVisible:\r
1064                             Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
1065                             LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r
1066                         SpaceIdx = SpaceIdx + 1\r
1067                         Offset   = Item["offset"]\r
1068 \r
1069                     LastVisible = NextVisible\r
1070 \r
1071                     Offset = Offset + Item["length"]\r
1072                     if LastVisible:\r
1073                         for Each in LineBuffer:\r
1074                             TxtBody.append (Each)\r
1075                         LineBuffer = []\r
1076                         Comment = Item["comment"]\r
1077                         Embed = Item["embed"].upper()\r
1078                         if Embed.endswith(':START') or Embed.endswith(':END'):\r
1079                             if not Comment == '' and Embed.endswith(':START'):\r
1080                                Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r
1081                                Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1082                             else:\r
1083                                Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1084                         else:\r
1085                             if Embed == '':\r
1086                                 Marker = ''\r
1087                             else:\r
1088                                 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1089                                 return 4\r
1090                         Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r
1091                         TxtBody.append(Line)\r
1092                     if Item['cname'] == 'UpdTerminator':\r
1093                         break\r
1094                 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r
1095 \r
1096         # Handle the embedded data structure\r
1097         TxtBody = self.PostProcessBody (TxtBody)\r
1098 \r
1099         HeaderTFileName = 'FsptUpd.h'\r
1100         HeaderMFileName = 'FspmUpd.h'\r
1101         HeaderSFileName = 'FspsUpd.h'\r
1102 \r
1103         UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS']     # FSPX_UPD_REGION\r
1104         UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S']  # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
1105         UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r
1106         ExcludedSpecificUpd = 'FSPM_ARCH_UPD'\r
1107 \r
1108         if InputHeaderFile != '':\r
1109             if not os.path.exists(InputHeaderFile):\r
1110                  self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1111                  return 6\r
1112 \r
1113             InFd         = open(InputHeaderFile, "r")\r
1114             IncLines     = InFd.readlines()\r
1115             InFd.close()\r
1116 \r
1117         for item in range(len(UpdRegionCheck)):\r
1118             if UpdRegionCheck[item] == 'FSPT':\r
1119                 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r
1120                 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r
1121             elif UpdRegionCheck[item] == 'FSPM':\r
1122                 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r
1123                 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r
1124             elif UpdRegionCheck[item] == 'FSPS':\r
1125                 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r
1126                 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r
1127             FileName = FileBase.replace(".", "_").upper()\r
1128             HeaderFd.write("%s\n"   % (__copyright_h__ % date.today().year))\r
1129             HeaderFd.write("#ifndef __%s__\n"   % FileName)\r
1130             HeaderFd.write("#define __%s__\n\n" % FileName)\r
1131             HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r
1132             HeaderFd.write("#pragma pack(push, 1)\n\n")\r
1133 \r
1134             Export = False\r
1135             for Line in IncLines:\r
1136                 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1137                 if Match:\r
1138                     if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r
1139                         Export = True\r
1140                         continue\r
1141                     else:\r
1142                         Export = False\r
1143                         continue\r
1144                 if Export:\r
1145                     HeaderFd.write(Line)\r
1146             HeaderFd.write("\n")\r
1147 \r
1148             Index = 0\r
1149             StartIndex = 0\r
1150             EndIndex = 0\r
1151             StructStart = []\r
1152             StructStartWithComment = []\r
1153             StructEnd = []\r
1154             for Line in TxtBody:\r
1155                 Index += 1\r
1156                 Match = re.match("(typedef struct {)", Line)\r
1157                 if Match:\r
1158                     StartIndex = Index - 1\r
1159                 Match = re.match("}\s([_A-Z0-9]+);", Line)\r
1160                 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):\r
1161                     EndIndex = Index\r
1162                     StructStart.append(StartIndex)\r
1163                     StructEnd.append(EndIndex)\r
1164             Index = 0\r
1165             for Line in TxtBody:\r
1166                 Index += 1\r
1167                 for Item in range(len(StructStart)):\r
1168                     if Index == StructStart[Item]:\r
1169                         Match = re.match("^(/\*\*\s*)", Line)\r
1170                         if Match:\r
1171                             StructStartWithComment.append(StructStart[Item])\r
1172                         else:\r
1173                             StructStartWithComment.append(StructStart[Item] + 1)\r
1174             Index = 0\r
1175             for Line in TxtBody:\r
1176                 Index += 1\r
1177                 for Item in range(len(StructStart)):\r
1178                     if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1179                         HeaderFd.write (Line)\r
1180             HeaderFd.write("#pragma pack(pop)\n\n")\r
1181             HeaderFd.write("#endif\n")\r
1182             HeaderFd.close()\r
1183 \r
1184         HeaderFd = open(HeaderFile, "w")\r
1185         FileBase = os.path.basename(HeaderFile)\r
1186         FileName = FileBase.replace(".", "_").upper()\r
1187         HeaderFd.write("%s\n"   % (__copyright_h__ % date.today().year))\r
1188         HeaderFd.write("#ifndef __%s__\n"   % FileName)\r
1189         HeaderFd.write("#define __%s__\n\n" % FileName)\r
1190         HeaderFd.write("#include <FspEas.h>\n\n")\r
1191         HeaderFd.write("#pragma pack(push, 1)\n\n")\r
1192 \r
1193         for item in range(len(UpdRegionCheck)):\r
1194             Index = 0\r
1195             StartIndex = 0\r
1196             EndIndex = 0\r
1197             StructStart = []\r
1198             StructStartWithComment = []\r
1199             StructEnd = []\r
1200             for Line in TxtBody:\r
1201                 Index += 1\r
1202                 Match = re.match("(typedef struct {)", Line)\r
1203                 if Match:\r
1204                     StartIndex = Index - 1\r
1205                 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r
1206                 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r
1207                     StructStart.append(Index - 1)\r
1208                     StructEnd.append(Index)\r
1209             Index = 0\r
1210             for Line in TxtBody:\r
1211                 Index += 1\r
1212                 for Item in range(len(StructStart)):\r
1213                     if Index == StructStart[Item]:\r
1214                         Match = re.match("^(/\*\*\s*)", Line)\r
1215                         if Match:\r
1216                             StructStartWithComment.append(StructStart[Item])\r
1217                         else:\r
1218                             StructStartWithComment.append(StructStart[Item] + 1)\r
1219             Index = 0\r
1220             for Line in TxtBody:\r
1221                 Index += 1\r
1222                 for Item in range(len(StructStart)):\r
1223                     if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1224                         HeaderFd.write (Line)\r
1225         HeaderFd.write("#pragma pack(pop)\n\n")\r
1226         HeaderFd.write("#endif\n")\r
1227         HeaderFd.close()\r
1228 \r
1229         return 0\r
1230 \r
1231     def WriteBsfStruct  (self, BsfFd, Item):\r
1232         if Item['type'] == "None":\r
1233             Space = "gPlatformFspPkgTokenSpaceGuid"\r
1234         else:\r
1235             Space = Item['space']\r
1236         Line = "    $%s_%s" % (Space, Item['cname'])\r
1237         Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1238         if Match:\r
1239             DefaultValue = Match.group(1).strip()\r
1240         else:\r
1241             DefaultValue = Item['value'].strip()\r
1242         if 'bitlength' in Item:\r
1243             BsfFd.write("    %s%s%4d bits     $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r
1244         else:\r
1245             BsfFd.write("    %s%s%4d bytes    $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
1246         TmpList = []\r
1247         if  Item['type'] == "Combo":\r
1248             if not Item['option'] in self._BuidinOption:\r
1249                 OptList = Item['option'].split(',')\r
1250                 for Option in OptList:\r
1251                     Option = Option.strip()\r
1252                     (OpVal, OpStr) = Option.split(':')\r
1253                     TmpList.append((OpVal, OpStr))\r
1254         return  TmpList\r
1255 \r
1256     def WriteBsfOption  (self, BsfFd, Item):\r
1257         PcdName   = Item['space'] + '_' + Item['cname']\r
1258         WriteHelp = 0\r
1259         if Item['type'] == "Combo":\r
1260             if Item['option'] in self._BuidinOption:\r
1261                 Options = self._BuidinOption[Item['option']]\r
1262             else:\r
1263                 Options = PcdName\r
1264             BsfFd.write('    %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r
1265             WriteHelp = 1\r
1266         elif Item['type'].startswith("EditNum"):\r
1267             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
1268             if Match:\r
1269                 BsfFd.write('    EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r
1270                 WriteHelp = 2\r
1271         elif Item['type'].startswith("EditText"):\r
1272             BsfFd.write('    %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r
1273             WriteHelp = 1\r
1274         elif Item['type'] == "Table":\r
1275             Columns = Item['option'].split(',')\r
1276             if len(Columns) != 0:\r
1277                 BsfFd.write('    %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r
1278                 for Col in Columns:\r
1279                     Fmt = Col.split(':')\r
1280                     if len(Fmt) != 3:\r
1281                         raise Exception("Column format '%s' is invalid !" % Fmt)\r
1282                     try:\r
1283                         Dtype = int(Fmt[1].strip())\r
1284                     except:\r
1285                         raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1286                     BsfFd.write('\n        Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1287                 BsfFd.write(',\n')\r
1288                 WriteHelp = 1\r
1289 \r
1290         if WriteHelp  > 0:\r
1291             HelpLines = Item['help'].split('\\n\\r')\r
1292             FirstLine = True\r
1293             for HelpLine in HelpLines:\r
1294                 if FirstLine:\r
1295                     FirstLine = False\r
1296                     BsfFd.write('        Help "%s"\n' % (HelpLine))\r
1297                 else:\r
1298                     BsfFd.write('             "%s"\n' % (HelpLine))\r
1299             if WriteHelp == 2:\r
1300                     BsfFd.write('             "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r
1301 \r
1302     def GenerateBsfFile (self, BsfFile):\r
1303 \r
1304         if BsfFile == '':\r
1305             self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1306             return 1\r
1307 \r
1308         Error = 0\r
1309         OptionDict = {}\r
1310         BsfFd      = open(BsfFile, "w")\r
1311         BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
1312         BsfFd.write("%s\n" % self._GlobalDataDef)\r
1313         BsfFd.write("StructDef\n")\r
1314         NextOffset = -1\r
1315         for Item in self._CfgItemList:\r
1316             if Item['find'] != '':\r
1317                 BsfFd.write('\n    Find "%s"\n' % Item['find'])\r
1318                 NextOffset = Item['offset'] + Item['length']\r
1319             if Item['name'] != '':\r
1320                 if NextOffset != Item['offset']:\r
1321                     BsfFd.write("        Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1322                 if len(Item['subreg']) > 0:\r
1323                     NextOffset =  Item['offset']\r
1324                     BitsOffset =  NextOffset * 8\r
1325                     for SubItem in Item['subreg']:\r
1326                         BitsOffset += SubItem['bitlength']\r
1327                         if SubItem['name'] == '':\r
1328                             if 'bitlength' in SubItem:\r
1329                                 BsfFd.write("        Skip %d bits\n" % (SubItem['bitlength']))\r
1330                             else:\r
1331                                 BsfFd.write("        Skip %d bytes\n" % (SubItem['length']))\r
1332                         else:\r
1333                             Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1334                             if len(Options) > 0:\r
1335                                 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
1336 \r
1337                     NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
1338                     if NextBitsOffset > BitsOffset:\r
1339                         BitsGap     = NextBitsOffset - BitsOffset\r
1340                         BitsRemain  = BitsGap % 8\r
1341                         if BitsRemain:\r
1342                             BsfFd.write("        Skip %d bits\n" % BitsRemain)\r
1343                             BitsGap -= BitsRemain\r
1344                         BytesRemain = BitsGap / 8\r
1345                         if BytesRemain:\r
1346                             BsfFd.write("        Skip %d bytes\n" % BytesRemain)\r
1347                     NextOffset = Item['offset'] + Item['length']\r
1348                 else:\r
1349                     NextOffset = Item['offset'] + Item['length']\r
1350                     Options = self.WriteBsfStruct(BsfFd, Item)\r
1351                     if len(Options) > 0:\r
1352                         OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1353         BsfFd.write("\nEndStruct\n\n")\r
1354 \r
1355         BsfFd.write("%s" % self._BuidinOptionTxt)\r
1356 \r
1357         for Each in OptionDict:\r
1358             BsfFd.write("List &%s\n" % Each)\r
1359             for Item in OptionDict[Each]:\r
1360                 BsfFd.write('    Selection %s , "%s"\n' % (Item[0], Item[1]))\r
1361             BsfFd.write("EndList\n\n")\r
1362 \r
1363         BsfFd.write("BeginInfoBlock\n")\r
1364         BsfFd.write('    PPVer       "%s"\n' % (self._CfgBlkDict['ver']))\r
1365         BsfFd.write('    Description "%s"\n' % (self._CfgBlkDict['name']))\r
1366         BsfFd.write("EndInfoBlock\n\n")\r
1367 \r
1368         for Each in self._CfgPageDict:\r
1369             BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r
1370             BsfItems = []\r
1371             for Item in self._CfgItemList:\r
1372                 if Item['name'] != '':\r
1373                     if Item['page'] != Each:\r
1374                         continue\r
1375                     if len(Item['subreg']) > 0:\r
1376                         for SubItem in Item['subreg']:\r
1377                             if SubItem['name'] != '':\r
1378                                 BsfItems.append(SubItem)\r
1379                     else:\r
1380                         BsfItems.append(Item)\r
1381 \r
1382             BsfItems.sort(key=lambda x: x['order'])\r
1383 \r
1384             for Item in BsfItems:\r
1385                 self.WriteBsfOption (BsfFd, Item)\r
1386             BsfFd.write("EndPage\n\n")\r
1387 \r
1388         BsfFd.close()\r
1389         return  Error\r
1390 \r
1391 \r
1392 def Usage():\r
1393     print "GenCfgOpt Version 0.52"\r
1394     print "Usage:"\r
1395     print "    GenCfgOpt  UPDTXT  PlatformDscFile BuildFvDir                 [-D Macros]"\r
1396     print "    GenCfgOpt  HEADER  PlatformDscFile BuildFvDir  InputHFile     [-D Macros]"\r
1397     print "    GenCfgOpt  GENBSF  PlatformDscFile BuildFvDir  BsfOutFile     [-D Macros]"\r
1398 \r
1399 def Main():\r
1400     #\r
1401     # Parse the options and args\r
1402     #\r
1403     GenCfgOpt = CGenCfgOpt()\r
1404     argc = len(sys.argv)\r
1405     if argc < 4:\r
1406         Usage()\r
1407         return 1\r
1408     else:\r
1409         DscFile = sys.argv[2]\r
1410         if not os.path.exists(DscFile):\r
1411             print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1412             return 2\r
1413 \r
1414         OutFile = ''\r
1415         if argc > 4:\r
1416             if sys.argv[4][0] == '-':\r
1417                 Start = 4\r
1418             else:\r
1419                 OutFile = sys.argv[4]\r
1420                 Start = 5\r
1421             GenCfgOpt.ParseBuildMode(sys.argv[3])\r
1422             if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
1423                 print "ERROR: Macro parsing failed !"\r
1424                 return 3\r
1425 \r
1426         FvDir = sys.argv[3]\r
1427         if not os.path.exists(FvDir):\r
1428             os.makedirs(FvDir)\r
1429 \r
1430         if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
1431             print "ERROR: %s !" % GenCfgOpt.Error\r
1432             return 5\r
1433 \r
1434         if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1435             print "ERROR: %s !" % GenCfgOpt.Error\r
1436             return 7\r
1437 \r
1438         if sys.argv[1] == "UPDTXT":\r
1439             Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1440             if Ret != 0:\r
1441                 # No change is detected\r
1442                 if Ret == 256:\r
1443                     print "INFO: %s !" % (GenCfgOpt.Error)\r
1444                 else :\r
1445                     print "ERROR: %s !" % (GenCfgOpt.Error)\r
1446             return Ret\r
1447         elif sys.argv[1] == "HEADER":\r
1448             if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
1449                 print "ERROR: %s !" % GenCfgOpt.Error\r
1450                 return 8\r
1451         elif sys.argv[1] == "GENBSF":\r
1452             if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1453                 print "ERROR: %s !" % GenCfgOpt.Error\r
1454                 return 9\r
1455         else:\r
1456             if argc < 5:\r
1457                 Usage()\r
1458                 return 1\r
1459             print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1460             Usage()\r
1461             return 1\r
1462         return 0\r
1463     return 0\r
1464 \r
1465 \r
1466 if __name__ == '__main__':\r
1467     sys.exit(Main())\r