]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Tools/GenCfgOpt.py
IntelFsp2Pkg: Align #Pragma in UPD header files to rest of EDK2 Pkgs
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
CommitLineData
cf1d4549
JY
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
14import os\r
15import re\r
16import sys\r
17import struct\r
18from 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
60Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
61\r
62Redistribution and use in source and binary forms, with or without modification,\r
63are 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
91class 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
288class 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
295GlobalDataDef\r
296 SKUID = 0, "DEFAULT"\r
297EndGlobalData\r
298\r
299"""\r
300 self._BuidinOptionTxt = """\r
301List &EN_DIS\r
302 Selection 0x1 , "Enabled"\r
303 Selection 0x0 , "Disabled"\r
304EndList\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
62997d5e 313 self._PcdsDict = {}\r
cf1d4549
JY
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
62997d5e
MM
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
cf1d4549 390 def EvaluateExpress (self, Expr):\r
62997d5e
MM
391 ExpExpr = self.ExpandPcds(Expr)\r
392 ExpExpr = self.ExpandMacros(ExpExpr)\r
cf1d4549
JY
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
62997d5e 428 def ParseDscFile (self, DscFile, FvDir):\r
cf1d4549
JY
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
62997d5e 436 IsPcdSect = False\r
cf1d4549
JY
437 IsUpdSect = False\r
438 IsVpdSect = False\r
cf1d4549
JY
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
62997d5e
MM
454 IsDefSect = False\r
455 IsPcdSect = False\r
456 IsVpdSect = False\r
457 IsUpdSect = False\r
cf1d4549
JY
458 if Match.group(1).lower() == "Defines".lower():\r
459 IsDefSect = True\r
62997d5e
MM
460 if Match.group(1).lower() == "PcdsFeatureFlag".lower():\r
461 IsPcdSect = True\r
cf1d4549
JY
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
cf1d4549 474 IsUpdSect = True\r
cf1d4549 475 else:\r
62997d5e 476 if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:\r
cf1d4549
JY
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
62997d5e 504 Result = self.EvaluateExpress(Match.group(2))\r
cf1d4549
JY
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
62997d5e
MM
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
cf1d4549
JY
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
62997d5e 681 # !BSF FIELD:{SerialDebugPortAddress0:1}\r
cf1d4549 682 # or\r
62997d5e
MM
683 # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
684 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)\r
cf1d4549 685 if Match:\r
62997d5e
MM
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
cf1d4549 694 SubCfgDict['cname'] = Match.group(2)\r
62997d5e
MM
695 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen\r
696 if SubCfgDict['bitlength'] > 0:\r
cf1d4549
JY
697 LastItem = self._CfgItemList[-1]\r
698 if len(LastItem['subreg']) == 0:\r
699 SubOffset = 0\r
700 else:\r
62997d5e
MM
701 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']\r
702 SubCfgDict['bitoffset'] = SubOffset\r
cf1d4549
JY
703 LastItem['subreg'].append (SubCfgDict.copy())\r
704 ConfigDict['name'] = ''\r
705 return Error\r
706\r
62997d5e
MM
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
cf1d4549
JY
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
62997d5e 738 idx = 0\r
cf1d4549
JY
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
62997d5e
MM
744 valuestr = self.GetBsfBitFields(SubItem, bytearray)\r
745 SubItem['value'] = valuestr\r
cf1d4549
JY
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
cd3692b1
SY
878 if Name.startswith("UnusedUpdSpace") and Length != 1:\r
879 IsArray = True\r
880 Type = "UINT8"\r
cf1d4549
JY
881 else:\r
882 IsArray = True\r
883 Type = "UINT8"\r
884\r
885 if Item and Item['value'].startswith('{'):\r
886 Type = "UINT8"\r
887 IsArray = True\r
888\r
889 if Struct != '':\r
890 Type = Struct\r
891 if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
892 IsArray = True\r
893 Unit = int(Type[4:]) / 8\r
894 Length = Length / Unit\r
895 else:\r
896 IsArray = False\r
897\r
898 if IsArray:\r
899 Name = Name + '[%d]' % Length\r
900\r
901 if len(Type) < PosName:\r
902 Space1 = PosName - len(Type)\r
903 else:\r
904 Space1 = 1\r
905\r
906 if BsfName != '':\r
907 NameLine=" - %s\n" % BsfName\r
908 else:\r
909 NameLine="\n"\r
910\r
911 if Help != '':\r
912 HelpLine = self.ProcessMultilines (Help, 80)\r
913\r
914 if Option != '':\r
915 OptionLine = self.ProcessMultilines (Option, 80)\r
916\r
917 if Offset is None:\r
918 OffsetStr = '????'\r
919 else:\r
920 OffsetStr = '0x%04X' % Offset\r
921\r
922 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)\r
923\r
924 def PostProcessBody (self, TextBody):\r
925 NewTextBody = []\r
926 OldTextBody = []\r
927 IncludeLine = False\r
928 StructName = ''\r
929 VariableName = ''\r
930 IsUpdHdrDefined = False\r
931 IsUpdHeader = False\r
932 for Line in TextBody:\r
933 SplitToLines = Line.splitlines()\r
934 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r
935 if MatchComment:\r
936 if MatchComment.group(1) == 'FSP_UPD_HEADER':\r
937 IsUpdHeader = True\r
938 else:\r
939 IsUpdHeader = False\r
940 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
941 CommentLine = " " + MatchComment.group(2) + "\n"\r
942 NewTextBody.append("/**" + CommentLine + "**/\n")\r
943 Line = Line[(len(SplitToLines[0]) + 1):]\r
944\r
945 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
946 if Match:\r
947 Line = Match.group(4)\r
948 if Match.group(1) == 'FSP_UPD_HEADER':\r
949 IsUpdHeader = True\r
950 else:\r
951 IsUpdHeader = False\r
952\r
953 if Match and Match.group(3) == 'START':\r
954 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
955 NewTextBody.append ('typedef struct {\n')\r
956 StructName = Match.group(1)\r
957 VariableName = Match.group(2)\r
958 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
959 if MatchOffset:\r
960 Offset = int(MatchOffset.group(1), 16)\r
961 else:\r
962 Offset = None\r
963 Line\r
964 IncludeLine = True\r
965 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r
966 if IncludeLine:\r
967 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
968 NewTextBody.append (Line)\r
969 else:\r
970 OldTextBody.append (Line)\r
971\r
62997d5e 972 if Match and Match.group(3) == 'END':\r
cf1d4549
JY
973 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
974 print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))\r
975 else:\r
976 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
977 NewTextBody.append ('} %s;\n\n' % StructName)\r
978 IsUpdHdrDefined = True\r
979 IncludeLine = False\r
980 NewTextBody.extend(OldTextBody)\r
981 return NewTextBody\r
982\r
983 def CreateHeaderFile (self, InputHeaderFile):\r
984 FvDir = self._FvDir\r
985\r
986 HeaderFileName = 'FspUpd.h'\r
987 HeaderFile = os.path.join(FvDir, HeaderFileName)\r
988\r
989 # Check if header needs to be recreated\r
990 ReCreate = False\r
991\r
992 TxtBody = []\r
993 for Item in self._CfgItemList:\r
994 if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
995 Value = int(Item['value'], 16)\r
996 Chars = []\r
997 while Value != 0x0:\r
998 Chars.append(chr(Value & 0xFF))\r
999 Value = Value >> 8\r
1000 SignatureStr = ''.join(Chars)\r
1001 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly\r
1002 if '_T' in SignatureStr[6:6+2]:\r
1003 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1004 elif '_M' in SignatureStr[6:6+2]:\r
1005 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1006 elif '_S' in SignatureStr[6:6+2]:\r
1007 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1008 TxtBody.append("\n")\r
1009\r
1010 for Region in ['UPD']:\r
1011 UpdOffsetTable = []\r
1012 UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS\r
1013 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r
1014 for Item in self._CfgItemList:\r
1015 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
1016 UpdOffsetTable.append (Item["offset"])\r
1017\r
1018 for UpdIdx in range(len(UpdOffsetTable)):\r
1019 CommentLine = ""\r
1020 for Item in self._CfgItemList:\r
1021 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r
1022 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r
1023 if MatchComment and MatchComment.group(1) == Region[0]:\r
1024 CommentLine = " " + MatchComment.group(2) + "\n"\r
1025 TxtBody.append("/**" + CommentLine + "**/\n")\r
1026 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r
1027 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r
1028 if Match:\r
1029 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r
1030 TxtBody.append("typedef struct {\n")\r
1031 NextOffset = 0\r
1032 SpaceIdx = 0\r
1033 Offset = 0\r
1034\r
1035 LastVisible = True\r
1036 ResvOffset = 0\r
1037 ResvIdx = 0\r
1038 LineBuffer = []\r
1039 InRange = False\r
1040 for Item in self._CfgItemList:\r
1041 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r
1042 InRange = True\r
1043 if InRange != True:\r
1044 continue\r
1045 if Item['cname'] == 'UpdTerminator':\r
1046 InRange = False\r
1047\r
1048 if Item['region'] != Region:\r
1049 continue\r
1050\r
1051 if Item["offset"] < UpdOffsetTable[UpdIdx]:\r
1052 continue\r
1053\r
1054 NextVisible = LastVisible\r
1055\r
1056 if LastVisible and (Item['header'] == 'OFF'):\r
1057 NextVisible = False\r
1058 ResvOffset = Item['offset']\r
1059 elif (not LastVisible) and Item['header'] == 'ON':\r
1060 NextVisible = True\r
1061 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
1062 ResvIdx = ResvIdx + 1\r
1063 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r
1064\r
1065 if Offset < Item["offset"]:\r
1066 if LastVisible:\r
1067 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
1068 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r
1069 SpaceIdx = SpaceIdx + 1\r
1070 Offset = Item["offset"]\r
1071\r
1072 LastVisible = NextVisible\r
1073\r
1074 Offset = Offset + Item["length"]\r
1075 if LastVisible:\r
1076 for Each in LineBuffer:\r
1077 TxtBody.append (Each)\r
1078 LineBuffer = []\r
1079 Comment = Item["comment"]\r
1080 Embed = Item["embed"].upper()\r
1081 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1082 if not Comment == '' and Embed.endswith(':START'):\r
1083 Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r
1084 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1085 else:\r
1086 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1087 else:\r
1088 if Embed == '':\r
62997d5e 1089 Marker = ''\r
cf1d4549
JY
1090 else:\r
1091 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1092 return 4\r
1093 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r
1094 TxtBody.append(Line)\r
1095 if Item['cname'] == 'UpdTerminator':\r
1096 break\r
1097 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r
62997d5e 1098\r
cf1d4549
JY
1099 # Handle the embedded data structure\r
1100 TxtBody = self.PostProcessBody (TxtBody)\r
1101\r
1102 HeaderTFileName = 'FsptUpd.h'\r
1103 HeaderMFileName = 'FspmUpd.h'\r
1104 HeaderSFileName = 'FspsUpd.h'\r
1105\r
1106 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION\r
1107 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
1108 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r
1109 ExcludedSpecificUpd = 'FSPM_ARCH_UPD'\r
1110\r
1111 if InputHeaderFile != '':\r
1112 if not os.path.exists(InputHeaderFile):\r
1113 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1114 return 6\r
1115\r
1116 InFd = open(InputHeaderFile, "r")\r
1117 IncLines = InFd.readlines()\r
1118 InFd.close()\r
1119\r
1120 for item in range(len(UpdRegionCheck)):\r
1121 if UpdRegionCheck[item] == 'FSPT':\r
1122 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r
1123 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r
1124 elif UpdRegionCheck[item] == 'FSPM':\r
1125 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r
1126 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r
1127 elif UpdRegionCheck[item] == 'FSPS':\r
1128 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r
1129 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r
1130 FileName = FileBase.replace(".", "_").upper()\r
1131 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1132 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1133 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1134 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r
cd3692b1 1135 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1136\r
1137 Export = False\r
1138 for Line in IncLines:\r
1139 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1140 if Match:\r
1141 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r
1142 Export = True\r
1143 continue\r
1144 else:\r
1145 Export = False\r
1146 continue\r
1147 if Export:\r
1148 HeaderFd.write(Line)\r
1149 HeaderFd.write("\n")\r
1150\r
1151 Index = 0\r
1152 StartIndex = 0\r
1153 EndIndex = 0\r
1154 StructStart = []\r
1155 StructStartWithComment = []\r
1156 StructEnd = []\r
1157 for Line in TxtBody:\r
1158 Index += 1\r
1159 Match = re.match("(typedef struct {)", Line)\r
1160 if Match:\r
1161 StartIndex = Index - 1\r
1162 Match = re.match("}\s([_A-Z0-9]+);", Line)\r
1163 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):\r
1164 EndIndex = Index\r
1165 StructStart.append(StartIndex)\r
1166 StructEnd.append(EndIndex)\r
1167 Index = 0\r
1168 for Line in TxtBody:\r
1169 Index += 1\r
1170 for Item in range(len(StructStart)):\r
1171 if Index == StructStart[Item]:\r
1172 Match = re.match("^(/\*\*\s*)", Line)\r
1173 if Match:\r
1174 StructStartWithComment.append(StructStart[Item])\r
1175 else:\r
1176 StructStartWithComment.append(StructStart[Item] + 1)\r
1177 Index = 0\r
1178 for Line in TxtBody:\r
1179 Index += 1\r
1180 for Item in range(len(StructStart)):\r
1181 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1182 HeaderFd.write (Line)\r
cd3692b1 1183 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1184 HeaderFd.write("#endif\n")\r
1185 HeaderFd.close()\r
1186\r
1187 HeaderFd = open(HeaderFile, "w")\r
1188 FileBase = os.path.basename(HeaderFile)\r
1189 FileName = FileBase.replace(".", "_").upper()\r
1190 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1191 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1192 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1193 HeaderFd.write("#include <FspEas.h>\n\n")\r
cd3692b1 1194 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1195\r
1196 for item in range(len(UpdRegionCheck)):\r
1197 Index = 0\r
1198 StartIndex = 0\r
1199 EndIndex = 0\r
1200 StructStart = []\r
1201 StructStartWithComment = []\r
1202 StructEnd = []\r
1203 for Line in TxtBody:\r
1204 Index += 1\r
1205 Match = re.match("(typedef struct {)", Line)\r
1206 if Match:\r
1207 StartIndex = Index - 1\r
1208 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r
1209 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r
1210 StructStart.append(Index - 1)\r
1211 StructEnd.append(Index)\r
1212 Index = 0\r
1213 for Line in TxtBody:\r
1214 Index += 1\r
1215 for Item in range(len(StructStart)):\r
1216 if Index == StructStart[Item]:\r
1217 Match = re.match("^(/\*\*\s*)", Line)\r
1218 if Match:\r
1219 StructStartWithComment.append(StructStart[Item])\r
1220 else:\r
1221 StructStartWithComment.append(StructStart[Item] + 1)\r
1222 Index = 0\r
1223 for Line in TxtBody:\r
1224 Index += 1\r
1225 for Item in range(len(StructStart)):\r
1226 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1227 HeaderFd.write (Line)\r
cd3692b1 1228 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1229 HeaderFd.write("#endif\n")\r
1230 HeaderFd.close()\r
1231\r
1232 return 0\r
1233\r
1234 def WriteBsfStruct (self, BsfFd, Item):\r
1235 if Item['type'] == "None":\r
1236 Space = "gPlatformFspPkgTokenSpaceGuid"\r
1237 else:\r
1238 Space = Item['space']\r
1239 Line = " $%s_%s" % (Space, Item['cname'])\r
1240 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1241 if Match:\r
1242 DefaultValue = Match.group(1).strip()\r
1243 else:\r
1244 DefaultValue = Item['value'].strip()\r
62997d5e
MM
1245 if 'bitlength' in Item:\r
1246 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r
1247 else:\r
1248 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
cf1d4549
JY
1249 TmpList = []\r
1250 if Item['type'] == "Combo":\r
1251 if not Item['option'] in self._BuidinOption:\r
1252 OptList = Item['option'].split(',')\r
1253 for Option in OptList:\r
1254 Option = Option.strip()\r
1255 (OpVal, OpStr) = Option.split(':')\r
1256 TmpList.append((OpVal, OpStr))\r
1257 return TmpList\r
1258\r
1259 def WriteBsfOption (self, BsfFd, Item):\r
1260 PcdName = Item['space'] + '_' + Item['cname']\r
1261 WriteHelp = 0\r
1262 if Item['type'] == "Combo":\r
1263 if Item['option'] in self._BuidinOption:\r
1264 Options = self._BuidinOption[Item['option']]\r
1265 else:\r
1266 Options = PcdName\r
62997d5e 1267 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r
cf1d4549
JY
1268 WriteHelp = 1\r
1269 elif Item['type'].startswith("EditNum"):\r
1270 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
1271 if Match:\r
62997d5e 1272 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r
cf1d4549
JY
1273 WriteHelp = 2\r
1274 elif Item['type'].startswith("EditText"):\r
62997d5e 1275 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1276 WriteHelp = 1\r
1277 elif Item['type'] == "Table":\r
1278 Columns = Item['option'].split(',')\r
1279 if len(Columns) != 0:\r
62997d5e 1280 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1281 for Col in Columns:\r
1282 Fmt = Col.split(':')\r
1283 if len(Fmt) != 3:\r
1284 raise Exception("Column format '%s' is invalid !" % Fmt)\r
1285 try:\r
1286 Dtype = int(Fmt[1].strip())\r
1287 except:\r
1288 raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1289 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1290 BsfFd.write(',\n')\r
1291 WriteHelp = 1\r
62997d5e 1292\r
cf1d4549
JY
1293 if WriteHelp > 0:\r
1294 HelpLines = Item['help'].split('\\n\\r')\r
1295 FirstLine = True\r
1296 for HelpLine in HelpLines:\r
1297 if FirstLine:\r
1298 FirstLine = False\r
62997d5e 1299 BsfFd.write(' Help "%s"\n' % (HelpLine))\r
cf1d4549 1300 else:\r
62997d5e 1301 BsfFd.write(' "%s"\n' % (HelpLine))\r
cf1d4549 1302 if WriteHelp == 2:\r
62997d5e 1303 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r
cf1d4549
JY
1304\r
1305 def GenerateBsfFile (self, BsfFile):\r
1306\r
1307 if BsfFile == '':\r
1308 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1309 return 1\r
1310\r
1311 Error = 0\r
1312 OptionDict = {}\r
1313 BsfFd = open(BsfFile, "w")\r
1314 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
62997d5e 1315 BsfFd.write("%s\n" % self._GlobalDataDef)\r
cf1d4549
JY
1316 BsfFd.write("StructDef\n")\r
1317 NextOffset = -1\r
1318 for Item in self._CfgItemList:\r
1319 if Item['find'] != '':\r
1320 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
1321 NextOffset = Item['offset'] + Item['length']\r
1322 if Item['name'] != '':\r
1323 if NextOffset != Item['offset']:\r
1324 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1325 if len(Item['subreg']) > 0:\r
1326 NextOffset = Item['offset']\r
62997d5e 1327 BitsOffset = NextOffset * 8\r
cf1d4549 1328 for SubItem in Item['subreg']:\r
62997d5e 1329 BitsOffset += SubItem['bitlength']\r
cf1d4549 1330 if SubItem['name'] == '':\r
62997d5e
MM
1331 if 'bitlength' in SubItem:\r
1332 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))\r
1333 else:\r
1334 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
cf1d4549
JY
1335 else:\r
1336 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1337 if len(Options) > 0:\r
1338 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
62997d5e
MM
1339\r
1340 NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
1341 if NextBitsOffset > BitsOffset:\r
1342 BitsGap = NextBitsOffset - BitsOffset\r
1343 BitsRemain = BitsGap % 8\r
1344 if BitsRemain:\r
1345 BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
1346 BitsGap -= BitsRemain\r
1347 BytesRemain = BitsGap / 8\r
1348 if BytesRemain:\r
1349 BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r
1350 NextOffset = Item['offset'] + Item['length']\r
cf1d4549
JY
1351 else:\r
1352 NextOffset = Item['offset'] + Item['length']\r
1353 Options = self.WriteBsfStruct(BsfFd, Item)\r
1354 if len(Options) > 0:\r
1355 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1356 BsfFd.write("\nEndStruct\n\n")\r
1357\r
62997d5e 1358 BsfFd.write("%s" % self._BuidinOptionTxt)\r
cf1d4549
JY
1359\r
1360 for Each in OptionDict:\r
62997d5e 1361 BsfFd.write("List &%s\n" % Each)\r
cf1d4549 1362 for Item in OptionDict[Each]:\r
62997d5e
MM
1363 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))\r
1364 BsfFd.write("EndList\n\n")\r
cf1d4549 1365\r
62997d5e
MM
1366 BsfFd.write("BeginInfoBlock\n")\r
1367 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r
1368 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r
1369 BsfFd.write("EndInfoBlock\n\n")\r
cf1d4549
JY
1370\r
1371 for Each in self._CfgPageDict:\r
62997d5e 1372 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r
cf1d4549
JY
1373 BsfItems = []\r
1374 for Item in self._CfgItemList:\r
1375 if Item['name'] != '':\r
1376 if Item['page'] != Each:\r
1377 continue\r
1378 if len(Item['subreg']) > 0:\r
1379 for SubItem in Item['subreg']:\r
1380 if SubItem['name'] != '':\r
1381 BsfItems.append(SubItem)\r
1382 else:\r
1383 BsfItems.append(Item)\r
1384\r
1385 BsfItems.sort(key=lambda x: x['order'])\r
1386\r
1387 for Item in BsfItems:\r
1388 self.WriteBsfOption (BsfFd, Item)\r
62997d5e 1389 BsfFd.write("EndPage\n\n")\r
cf1d4549
JY
1390\r
1391 BsfFd.close()\r
1392 return Error\r
1393\r
1394\r
1395def Usage():\r
62997d5e 1396 print "GenCfgOpt Version 0.52"\r
cf1d4549 1397 print "Usage:"\r
62997d5e
MM
1398 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]"\r
1399 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]"\r
1400 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r
cf1d4549
JY
1401\r
1402def Main():\r
1403 #\r
1404 # Parse the options and args\r
1405 #\r
1406 GenCfgOpt = CGenCfgOpt()\r
1407 argc = len(sys.argv)\r
1408 if argc < 4:\r
1409 Usage()\r
1410 return 1\r
1411 else:\r
1412 DscFile = sys.argv[2]\r
1413 if not os.path.exists(DscFile):\r
1414 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1415 return 2\r
cf1d4549
JY
1416\r
1417 OutFile = ''\r
1418 if argc > 4:\r
62997d5e 1419 if sys.argv[4][0] == '-':\r
cf1d4549
JY
1420 Start = 4\r
1421 else:\r
62997d5e 1422 OutFile = sys.argv[4]\r
cf1d4549
JY
1423 Start = 5\r
1424 GenCfgOpt.ParseBuildMode(sys.argv[3])\r
1425 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
1426 print "ERROR: Macro parsing failed !"\r
1427 return 3\r
1428\r
1429 FvDir = sys.argv[3]\r
1430 if not os.path.exists(FvDir):\r
1431 os.makedirs(FvDir)\r
1432\r
62997d5e 1433 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
cf1d4549
JY
1434 print "ERROR: %s !" % GenCfgOpt.Error\r
1435 return 5\r
1436\r
1437 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1438 print "ERROR: %s !" % GenCfgOpt.Error\r
1439 return 7\r
1440\r
1441 if sys.argv[1] == "UPDTXT":\r
1442 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1443 if Ret != 0:\r
1444 # No change is detected\r
1445 if Ret == 256:\r
1446 print "INFO: %s !" % (GenCfgOpt.Error)\r
1447 else :\r
1448 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1449 return Ret\r
1450 elif sys.argv[1] == "HEADER":\r
1451 if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
1452 print "ERROR: %s !" % GenCfgOpt.Error\r
1453 return 8\r
1454 elif sys.argv[1] == "GENBSF":\r
1455 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1456 print "ERROR: %s !" % GenCfgOpt.Error\r
1457 return 9\r
1458 else:\r
1459 if argc < 5:\r
1460 Usage()\r
1461 return 1\r
1462 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1463 Usage()\r
1464 return 1\r
1465 return 0\r
1466 return 0\r
1467\r
1468\r
1469if __name__ == '__main__':\r
1470 sys.exit(Main())\r