Add IntelFsp2Pkg and IntelFsp2WrapperPkg.
[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
313 self._CfgBlkDict = {}\r
314 self._CfgPageDict = {}\r
315 self._CfgItemList = []\r
316 self._DscFile = ''\r
317 self._FvDir = ''\r
318 self._MapVer = 0\r
319\r
320 def ParseBuildMode (self, OutputStr):\r
321 if "RELEASE_" in OutputStr:\r
322 self.ReleaseMode = True\r
323 if "DEBUG_" in OutputStr:\r
324 self.ReleaseMode = False\r
325 return\r
326\r
327 def ParseMacros (self, MacroDefStr):\r
328 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
329 self._MacroDict = {}\r
330 IsExpression = False\r
331 for Macro in MacroDefStr:\r
332 if Macro.startswith('-D'):\r
333 IsExpression = True\r
334 if len(Macro) > 2:\r
335 Macro = Macro[2:]\r
336 else :\r
337 continue\r
338 if IsExpression:\r
339 IsExpression = False\r
340 Match = re.match("(\w+)=(.+)", Macro)\r
341 if Match:\r
342 self._MacroDict[Match.group(1)] = Match.group(2)\r
343 else:\r
344 Match = re.match("(\w+)", Macro)\r
345 if Match:\r
346 self._MacroDict[Match.group(1)] = ''\r
347 if len(self._MacroDict) == 0:\r
348 Error = 1\r
349 else:\r
350 Error = 0\r
351 if self.Debug:\r
352 print "INFO : Macro dictionary:"\r
353 for Each in self._MacroDict:\r
354 print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each])\r
355 return Error\r
356\r
357 def EvaulateIfdef (self, Macro):\r
358 Result = Macro in self._MacroDict\r
359 if self.Debug:\r
360 print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)\r
361 return Result\r
362\r
363 def ExpandMacros (self, Input):\r
364 Line = Input\r
365 Match = re.findall("\$\(\w+\)", Input)\r
366 if Match:\r
367 for Each in Match:\r
368 Variable = Each[2:-1]\r
369 if Variable in self._MacroDict:\r
370 Line = Line.replace(Each, self._MacroDict[Variable])\r
371 else:\r
372 if self.Debug:\r
373 print "WARN : %s is not defined" % Each\r
374 Line = Line.replace(Each, Each[2:-1])\r
375 return Line\r
376\r
377 def EvaluateExpress (self, Expr):\r
378 ExpExpr = self.ExpandMacros(Expr)\r
379 LogExpr = CLogicalExpression()\r
380 Result = LogExpr.evaluateExpress (ExpExpr)\r
381 if self.Debug:\r
382 print "INFO : Eval Express [%s] : %s" % (Expr, Result)\r
383 return Result\r
384\r
385 def FormatListValue(self, ConfigDict):\r
386 Struct = ConfigDict['struct']\r
387 if Struct not in ['UINT8','UINT16','UINT32','UINT64']:\r
388 return\r
389\r
390 dataarray = []\r
391 binlist = ConfigDict['value'][1:-1].split(',')\r
392 for each in binlist:\r
393 each = each.strip()\r
394 if each.startswith('0x'):\r
395 value = int(each, 16)\r
396 else:\r
397 value = int(each)\r
398 dataarray.append(value)\r
399\r
400 unit = int(Struct[4:]) / 8\r
401 if int(ConfigDict['length']) != unit * len(dataarray):\r
402 raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])\r
403\r
404 bytearray = []\r
405 for each in dataarray:\r
406 value = each\r
407 for loop in xrange(unit):\r
408 bytearray.append("0x%02X" % (value & 0xFF))\r
409 value = value >> 8\r
410 newvalue = '{' + ','.join(bytearray) + '}'\r
411 ConfigDict['value'] = newvalue\r
412 return ""\r
413\r
414 def ParseDscFile (self, DscFile, FvDir, ConfigDscFile, ExtConfigDscFile):\r
415 self._CfgItemList = []\r
416 self._CfgPageDict = {}\r
417 self._CfgBlkDict = {}\r
418 self._DscFile = DscFile\r
419 self._FvDir = FvDir\r
420\r
421 IsDefSect = False\r
422 IsUpdSect = False\r
423 IsVpdSect = False\r
424 Found = False\r
425\r
426 IfStack = []\r
427 ElifStack = []\r
428 Error = 0\r
429 ConfigDict = {}\r
430\r
431 DscFd = open(DscFile, "r")\r
432 DscLines = DscFd.readlines()\r
433 DscFd.close()\r
434\r
435 while len(DscLines):\r
436 DscLine = DscLines.pop(0).strip()\r
437 Handle = False\r
438 Match = re.match("^\[(.+)\]", DscLine)\r
439 if Match is not None:\r
440 if Match.group(1).lower() == "Defines".lower():\r
441 IsDefSect = True\r
442 IsVpdSect = False\r
443 IsUpdSect = False\r
444 elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
445 ConfigDict = {}\r
446 ConfigDict['header'] = 'ON'\r
447 ConfigDict['region'] = 'UPD'\r
448 ConfigDict['order'] = -1\r
449 ConfigDict['page'] = ''\r
450 ConfigDict['name'] = ''\r
451 ConfigDict['find'] = ''\r
452 ConfigDict['struct'] = ''\r
453 ConfigDict['embed'] = ''\r
454 ConfigDict['comment'] = ''\r
455 ConfigDict['subreg'] = []\r
456 IsDefSect = False\r
457 IsUpdSect = True\r
458 IsVpdSect = False\r
459 Found = True\r
460 else:\r
461 IsDefSect = False\r
462 IsUpdSect = False\r
463 IsVpdSect = False\r
464 else:\r
465 if IsDefSect or IsUpdSect or IsVpdSect:\r
466 if re.match("^!else($|\s+#.+)", DscLine):\r
467 if IfStack:\r
468 IfStack[-1] = not IfStack[-1]\r
469 else:\r
470 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
471 raise SystemExit\r
472 elif re.match("^!endif($|\s+#.+)", DscLine):\r
473 if IfStack:\r
474 IfStack.pop()\r
475 Level = ElifStack.pop()\r
476 if Level > 0:\r
477 del IfStack[-Level:]\r
478 else:\r
479 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
480 raise SystemExit\r
481 else:\r
482 Result = False\r
483 Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)\r
484 if Match:\r
485 Result = self.EvaulateIfdef (Match.group(2))\r
486 if Match.group(1) == 'ifndef':\r
487 Result = not Result\r
488 IfStack.append(Result)\r
489 ElifStack.append(0)\r
490 else:\r
491 Match = re.match("!(if|elseif)\s+(.+)", DscLine)\r
492 if Match:\r
493 IsFoundInFile = False\r
494 MatchPcdFormat = re.match("^\s*(.+)\.(.+)\s*==\s*(.+)", Match.group(2))\r
495 if MatchPcdFormat:\r
496 ExtConfigDsc = open(ExtConfigDscFile, "r")\r
497 ExtConfigDscLines = ExtConfigDsc.readlines()\r
498 ExtConfigDsc.close()\r
499 \r
500 while len(ExtConfigDscLines):\r
501 ExtConfigDscLine = ExtConfigDscLines.pop(0).strip()\r
502 MatchExtConfigPcd = re.match("^\s*(.+)\s*\|\s*(.+)", ExtConfigDscLine)\r
503 if MatchExtConfigPcd and IsFoundInFile == False:\r
504 PcdFormatStr = str(str(MatchPcdFormat.group(1)) + "." + str(MatchPcdFormat.group(2)))\r
505 ExtConfigPcd = str(MatchExtConfigPcd.group(1))\r
506 Result = False\r
507 if PcdFormatStr.strip() == ExtConfigPcd.strip():\r
508 Result = self.EvaluateExpress(str(str(MatchExtConfigPcd.group(2)) + " == " + str(MatchPcdFormat.group(3))))\r
509 IsFoundInFile = True\r
510 break\r
511 if IsFoundInFile == False:\r
512 ConfigDsc = open(ConfigDscFile, "r")\r
513 ConfigDscLines = ConfigDsc.readlines()\r
514 ConfigDsc.close()\r
515 while len(ConfigDscLines):\r
516 ConfigDscLine = ConfigDscLines.pop(0).strip()\r
517 MatchConfigPcd = re.match("^\s*(.+)\s*\|\s*(.+)", ConfigDscLine)\r
518 if MatchConfigPcd:\r
519 PcdFormatStr = str(str(MatchPcdFormat.group(1)) + "." + str(MatchPcdFormat.group(2)))\r
520 ConfigPcd = str(MatchConfigPcd.group(1))\r
521 Result = False\r
522 if PcdFormatStr.strip() == ConfigPcd.strip():\r
523 Result = self.EvaluateExpress(str(str(MatchConfigPcd.group(2)) + " == " + str(MatchPcdFormat.group(3))))\r
524 IsFoundInFile = True\r
525 break\r
526 else:\r
527 Result = self.EvaluateExpress(Match.group(2))\r
528 if Match.group(1) == "if":\r
529 ElifStack.append(0)\r
530 IfStack.append(Result)\r
531 else: #elseif\r
532 if IfStack:\r
533 IfStack[-1] = not IfStack[-1]\r
534 IfStack.append(Result)\r
535 ElifStack[-1] = ElifStack[-1] + 1\r
536 else:\r
537 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
538 raise SystemExit\r
539 else:\r
540 if IfStack:\r
541 Handle = reduce(lambda x,y: x and y, IfStack)\r
542 else:\r
543 Handle = True\r
544 if Handle:\r
545 Match = re.match("!include\s+(.+)", DscLine)\r
546 if Match:\r
547 IncludeFilePath = Match.group(1)\r
548 IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
549 try:\r
550 IncludeDsc = open(IncludeFilePath, "r")\r
551 except:\r
552 print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
553 raise SystemExit\r
554 NewDscLines = IncludeDsc.readlines()\r
555 IncludeDsc.close()\r
556 DscLines = NewDscLines + DscLines\r
557 else:\r
558 if DscLine.startswith('!'):\r
559 print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
560 raise SystemExit\r
561 if not Handle:\r
562 continue\r
563\r
564 if IsDefSect:\r
565 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
566 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6\r
567 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385\r
568 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F\r
569 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
570 if Match:\r
571 self._MacroDict[Match.group(1)] = Match.group(2)\r
572 if self.Debug:\r
573 print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))\r
574 else:\r
575 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)\r
576 if Match:\r
577 Remaining = Match.group(2)\r
578 if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':\r
579 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
580 if Match:\r
581 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
582 PageList = Match.group(1).split(',')\r
583 for Page in PageList:\r
584 Page = Page.strip()\r
585 Match = re.match("(\w+):\"(.+)\"", Page)\r
586 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
587\r
588 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
589 if Match:\r
590 self._CfgBlkDict['name'] = Match.group(1)\r
591 self._CfgBlkDict['ver'] = Match.group(2)\r
592\r
593 for Key in self._BsfKeyList:\r
594 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
595 if Match:\r
596 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
597 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
598 else:\r
599 ConfigDict[Key.lower()] = Match.group(1)\r
600 else:\r
601 for Key in self._HdrKeyList:\r
602 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
603 if Match:\r
604 ConfigDict[Key.lower()] = Match.group(1)\r
605\r
606 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)\r
607 if Match:\r
608 ConfigDict['name'] = Match.group(1)\r
609\r
610 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)\r
611 if Match:\r
612 if Match.group(2).strip() in self._BuidinOption:\r
613 ConfigDict['option'] = Match.group(2).strip()\r
614 else:\r
615 OptionValueList = Match.group(2).split(',')\r
616 OptionStringList = Match.group(3).split(',')\r
617 Index = 0\r
618 for Option in OptionValueList:\r
619 Option = Option.strip()\r
620 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()\r
621 Index += 1\r
622 if Index in range(len(OptionValueList)):\r
623 ConfigDict['option'] += ', '\r
624 ConfigDict['type'] = "Combo"\r
625\r
626 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
627 if Match:\r
628 if "0x" in Match.group(2) or "0x" in Match.group(3):\r
629 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
630 else:\r
631 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
632\r
633 Match = re.match("^\s*##\s+(.+)", DscLine)\r
634 if Match:\r
635 ConfigDict['help'] = Match.group(1)\r
636\r
637 # Check VPD/UPD\r
638 if IsUpdSect:\r
639 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
640 else:\r
641 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
642 if Match:\r
643 ConfigDict['space'] = Match.group(1)\r
644 ConfigDict['cname'] = Match.group(2)\r
645 ConfigDict['offset'] = int (Match.group(3), 16)\r
646 if ConfigDict['order'] == -1:\r
647 ConfigDict['order'] = ConfigDict['offset'] << 8\r
648 else:\r
649 (Major, Minor) = ConfigDict['order'].split('.')\r
650 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
651 if IsUpdSect:\r
652 Value = Match.group(5).strip()\r
653 if Match.group(4).startswith("0x"):\r
654 Length = int (Match.group(4), 16)\r
655 else :\r
656 Length = int (Match.group(4))\r
657 else:\r
658 Value = Match.group(4)\r
659 if Value is None:\r
660 Value = ''\r
661 Value = Value.strip()\r
662 if '|' in Value:\r
663 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
664 if Match:\r
665 Value = Match.group(1)\r
666 Length = -1\r
667\r
668 ConfigDict['length'] = Length\r
669 Match = re.match("\$\((\w+)\)", Value)\r
670 if Match:\r
671 if Match.group(1) in self._MacroDict:\r
672 Value = self._MacroDict[Match.group(1)]\r
673\r
674 ConfigDict['value'] = Value\r
675 if (len(Value) > 0) and (Value[0] == '{'):\r
676 Value = self.FormatListValue(ConfigDict)\r
677\r
678 if ConfigDict['name'] == '':\r
679 # Clear BSF specific items\r
680 ConfigDict['bsfname'] = ''\r
681 ConfigDict['help'] = ''\r
682 ConfigDict['type'] = ''\r
683 ConfigDict['option'] = ''\r
684\r
685 self._CfgItemList.append(ConfigDict.copy())\r
686 ConfigDict['name'] = ''\r
687 ConfigDict['find'] = ''\r
688 ConfigDict['struct'] = ''\r
689 ConfigDict['embed'] = ''\r
690 ConfigDict['comment'] = ''\r
691 ConfigDict['order'] = -1\r
692 ConfigDict['subreg'] = []\r
693 ConfigDict['option'] = ''\r
694 else:\r
695 # It could be a virtual item as below\r
696 # !BSF FIELD:{1:SerialDebugPortAddress0}\r
697 # or\r
698 # @Bsf FIELD:{1:SerialDebugPortAddress0}\r
699 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)}", DscLine)\r
700 if Match:\r
701 SubCfgDict = ConfigDict\r
702 SubCfgDict['cname'] = Match.group(2)\r
703 SubCfgDict['length'] = int (Match.group(3))\r
704 if SubCfgDict['length'] > 0:\r
705 LastItem = self._CfgItemList[-1]\r
706 if len(LastItem['subreg']) == 0:\r
707 SubOffset = 0\r
708 else:\r
709 SubOffset += LastItem['subreg'][-1]['length']\r
710 SubCfgDict['offset'] = SubOffset\r
711 LastItem['subreg'].append (SubCfgDict.copy())\r
712 ConfigDict['name'] = ''\r
713 return Error\r
714\r
715 def UpdateSubRegionDefaultValue (self):\r
716 Error = 0\r
717 for Item in self._CfgItemList:\r
718 if len(Item['subreg']) == 0:\r
719 continue\r
720 bytearray = []\r
721 if Item['value'][0] == '{':\r
722 binlist = Item['value'][1:-1].split(',')\r
723 for each in binlist:\r
724 each = each.strip()\r
725 if each.startswith('0x'):\r
726 value = int(each, 16)\r
727 else:\r
728 value = int(each)\r
729 bytearray.append(value)\r
730 else:\r
731 if Item['value'].startswith('0x'):\r
732 value = int(Item['value'], 16)\r
733 else:\r
734 value = int(Item['value'])\r
735 idx = 0;\r
736 while idx < Item['length']:\r
737 bytearray.append(value & 0xFF)\r
738 value = value >> 8\r
739 idx = idx + 1\r
740 for SubItem in Item['subreg']:\r
741 if SubItem['length'] in (1,2,4,8):\r
742 valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]\r
743 valuelist.reverse()\r
744 valuestr = "".join('%02X' % b for b in valuelist)\r
745 SubItem['value'] = '0x%s' % valuestr\r
746 else:\r
747 valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])\r
748 SubItem['value'] = '{%s}' % valuestr\r
749 return Error\r
750\r
751 def CreateSplitUpdTxt (self, UpdTxtFile):\r
752 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r
753 SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS\r
754 for Index in range(len(GuidList)):\r
755 UpdTxtFile = ''\r
756 FvDir = self._FvDir\r
757 if GuidList[Index] not in self._MacroDict:\r
758 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r
759 return 1\r
760\r
761 if UpdTxtFile == '':\r
762 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
763\r
764 ReCreate = False\r
765 if not os.path.exists(UpdTxtFile):\r
766 ReCreate = True\r
767 else:\r
768 DscTime = os.path.getmtime(self._DscFile)\r
769 TxtTime = os.path.getmtime(UpdTxtFile)\r
770 if DscTime > TxtTime:\r
771 ReCreate = True\r
772\r
773 if not ReCreate:\r
774 # DSC has not been modified yet\r
775 # So don't have to re-generate other files\r
776 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
777 return 256\r
778\r
779 TxtFd = open(UpdTxtFile, "w")\r
780 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
781\r
782 NextOffset = 0\r
783 SpaceIdx = 0\r
784 StartAddr = 0\r
785 EndAddr = 0\r
786 Default = 'DEFAULT|'\r
787 InRange = False\r
788 for Item in self._CfgItemList:\r
789 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
790 StartAddr = Item['offset']\r
791 NextOffset = StartAddr\r
792 InRange = True\r
793 if Item['cname'] == 'UpdTerminator' and InRange == True:\r
794 EndAddr = Item['offset']\r
795 InRange = False\r
796 InRange = False\r
797 for Item in self._CfgItemList:\r
798 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
799 InRange = True\r
800 if InRange != True:\r
801 continue\r
802 if Item['cname'] == 'UpdTerminator':\r
803 InRange = False\r
804 if Item['region'] != 'UPD':\r
805 continue\r
806 Offset = Item['offset']\r
807 if StartAddr > Offset or EndAddr < Offset:\r
808 continue\r
809 if NextOffset < Offset:\r
810 # insert one line\r
811 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r
812 SpaceIdx = SpaceIdx + 1\r
813 NextOffset = Offset + Item['length']\r
814 if Item['cname'] == 'PcdSerialIoUartDebugEnable':\r
815 if self.ReleaseMode == False:\r
816 Item['value'] = 0x01\r
817 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r
818 TxtFd.close()\r
819 return 0\r
820\r
821 def ProcessMultilines (self, String, MaxCharLength):\r
822 Multilines = ''\r
823 StringLength = len(String)\r
824 CurrentStringStart = 0\r
825 StringOffset = 0\r
826 BreakLineDict = []\r
827 if len(String) <= MaxCharLength:\r
828 while (StringOffset < StringLength):\r
829 if StringOffset >= 1:\r
830 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
831 BreakLineDict.append (StringOffset + 1)\r
832 StringOffset += 1\r
833 if BreakLineDict != []:\r
834 for Each in BreakLineDict:\r
835 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
836 CurrentStringStart = Each\r
837 if StringLength - CurrentStringStart > 0:\r
838 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
839 else:\r
840 Multilines = " %s\n" % String\r
841 else:\r
842 NewLineStart = 0\r
843 NewLineCount = 0\r
844 FoundSpaceChar = False\r
845 while (StringOffset < StringLength):\r
846 if StringOffset >= 1:\r
847 if NewLineCount >= MaxCharLength - 1:\r
848 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
849 BreakLineDict.append (NewLineStart + NewLineCount)\r
850 NewLineStart = NewLineStart + NewLineCount\r
851 NewLineCount = 0\r
852 FoundSpaceChar = True\r
853 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
854 BreakLineDict.append (0)\r
855 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
856 BreakLineDict.append (StringOffset + 1)\r
857 NewLineStart = StringOffset + 1\r
858 NewLineCount = 0\r
859 StringOffset += 1\r
860 NewLineCount += 1\r
861 if BreakLineDict != []:\r
862 BreakLineDict.sort ()\r
863 for Each in BreakLineDict:\r
864 if Each > 0:\r
865 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
866 CurrentStringStart = Each\r
867 if StringLength - CurrentStringStart > 0:\r
868 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
869 return Multilines\r
870\r
871 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):\r
872 PosName = 28\r
873 PosComment = 30\r
874 NameLine=''\r
875 HelpLine=''\r
876 OptionLine=''\r
877\r
878 IsArray = False\r
879 if Length in [1,2,4,8]:\r
880 Type = "UINT%d" % (Length * 8)\r
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
972 if Match and Match.group(3) == 'END': \r
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
1089 Marker = '';\r
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
1098 \r
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
1135 HeaderFd.write("#pragma pack(push, 1)\n\n")\r
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
1183 HeaderFd.write("#pragma pack(pop)\n\n")\r
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
1194 HeaderFd.write("#pragma pack(push, 1)\n\n")\r
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
1228 HeaderFd.write("#pragma pack(pop)\n\n")\r
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
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 for SubItem in Item['subreg']:\r
1325 NextOffset += SubItem['length']\r
1326 if SubItem['name'] == '':\r
1327 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
1328 else:\r
1329 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1330 if len(Options) > 0:\r
1331 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
1332 if (Item['offset'] + Item['length']) < NextOffset:\r
1333 self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])\r
1334 return 2\r
1335 else:\r
1336 NextOffset = Item['offset'] + Item['length']\r
1337 Options = self.WriteBsfStruct(BsfFd, Item)\r
1338 if len(Options) > 0:\r
1339 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1340 BsfFd.write("\nEndStruct\n\n")\r
1341\r
1342 BsfFd.write("%s" % self._BuidinOptionTxt);\r
1343\r
1344 for Each in OptionDict:\r
1345 BsfFd.write("List &%s\n" % Each);\r
1346 for Item in OptionDict[Each]:\r
1347 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]));\r
1348 BsfFd.write("EndList\n\n");\r
1349\r
1350 BsfFd.write("BeginInfoBlock\n");\r
1351 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']));\r
1352 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']));\r
1353 BsfFd.write("EndInfoBlock\n\n");\r
1354\r
1355 for Each in self._CfgPageDict:\r
1356 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);\r
1357 BsfItems = []\r
1358 for Item in self._CfgItemList:\r
1359 if Item['name'] != '':\r
1360 if Item['page'] != Each:\r
1361 continue\r
1362 if len(Item['subreg']) > 0:\r
1363 for SubItem in Item['subreg']:\r
1364 if SubItem['name'] != '':\r
1365 BsfItems.append(SubItem)\r
1366 else:\r
1367 BsfItems.append(Item)\r
1368\r
1369 BsfItems.sort(key=lambda x: x['order'])\r
1370\r
1371 for Item in BsfItems:\r
1372 self.WriteBsfOption (BsfFd, Item)\r
1373 BsfFd.write("EndPage\n\n");\r
1374\r
1375 BsfFd.close()\r
1376 return Error\r
1377\r
1378\r
1379def Usage():\r
1380 print "GenCfgOpt Version 0.51"\r
1381 print "Usage:"\r
1382 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir ConfigDscFile ExtConfigDscFile"\r
1383 print " [-D Macros]"\r
1384 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir ConfigDscFile ExtConfigDscFile"\r
1385 print " InputHFile [-D Macros]"\r
1386 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir ConfigDscFile ExtConfigDscFile"\r
1387 print " BsfOutFile [-D Macros]"\r
1388\r
1389def Main():\r
1390 #\r
1391 # Parse the options and args\r
1392 #\r
1393 GenCfgOpt = CGenCfgOpt()\r
1394 argc = len(sys.argv)\r
1395 if argc < 4:\r
1396 Usage()\r
1397 return 1\r
1398 else:\r
1399 DscFile = sys.argv[2]\r
1400 if not os.path.exists(DscFile):\r
1401 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1402 return 2\r
1403 ConfigDscFile = sys.argv[4]\r
1404 if not os.path.exists(ConfigDscFile):\r
1405 print "ERROR: Cannot open Config DSC file '%s' !" % ConfigDscFile\r
1406 return 2\r
1407 ExtConfigDscFile = sys.argv[5]\r
1408 if not os.path.exists(ExtConfigDscFile):\r
1409 print "ERROR: Cannot open Ext Config DSC file '%s' !" % ExtConfigDscFile\r
1410 return 2\r
1411\r
1412 OutFile = ''\r
1413 if argc > 4:\r
1414 if sys.argv[6][0] == '-':\r
1415 Start = 4\r
1416 else:\r
1417 OutFile = sys.argv[6]\r
1418 Start = 5\r
1419 GenCfgOpt.ParseBuildMode(sys.argv[3])\r
1420 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
1421 print "ERROR: Macro parsing failed !"\r
1422 return 3\r
1423\r
1424 FvDir = sys.argv[3]\r
1425 if not os.path.exists(FvDir):\r
1426 os.makedirs(FvDir)\r
1427\r
1428 if GenCfgOpt.ParseDscFile(DscFile, FvDir, ConfigDscFile, ExtConfigDscFile) != 0:\r
1429 print "ERROR: %s !" % GenCfgOpt.Error\r
1430 return 5\r
1431\r
1432 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1433 print "ERROR: %s !" % GenCfgOpt.Error\r
1434 return 7\r
1435\r
1436 if sys.argv[1] == "UPDTXT":\r
1437 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1438 if Ret != 0:\r
1439 # No change is detected\r
1440 if Ret == 256:\r
1441 print "INFO: %s !" % (GenCfgOpt.Error)\r
1442 else :\r
1443 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1444 return Ret\r
1445 elif sys.argv[1] == "HEADER":\r
1446 if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
1447 print "ERROR: %s !" % GenCfgOpt.Error\r
1448 return 8\r
1449 elif sys.argv[1] == "GENBSF":\r
1450 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1451 print "ERROR: %s !" % GenCfgOpt.Error\r
1452 return 9\r
1453 else:\r
1454 if argc < 5:\r
1455 Usage()\r
1456 return 1\r
1457 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1458 Usage()\r
1459 return 1\r
1460 return 0\r
1461 return 0\r
1462\r
1463\r
1464if __name__ == '__main__':\r
1465 sys.exit(Main())\r