]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Tools/GenCfgOpt.py
BaseTools/VolInfo: Fix printf issue using '%ls' in format string
[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
41d739e4
TRM
526 PackagesPath = os.getenv("PACKAGES_PATH")\r
527 for PackagePath in PackagesPath.split(os.pathsep):\r
528 IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))\r
529 if os.path.exists(IncludeFilePathAbs):\r
530 IncludeDsc = open(IncludeFilePathAbs, "r")\r
531 break\r
532 if IncludeDsc == None:\r
cf1d4549
JY
533 print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
534 raise SystemExit\r
535 NewDscLines = IncludeDsc.readlines()\r
536 IncludeDsc.close()\r
537 DscLines = NewDscLines + DscLines\r
538 else:\r
539 if DscLine.startswith('!'):\r
540 print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
541 raise SystemExit\r
542 if not Handle:\r
543 continue\r
544\r
545 if IsDefSect:\r
546 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
547 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6\r
548 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385\r
549 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F\r
550 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
551 if Match:\r
552 self._MacroDict[Match.group(1)] = Match.group(2)\r
553 if self.Debug:\r
554 print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))\r
62997d5e
MM
555 elif IsPcdSect:\r
556 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE\r
557 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE\r
558 Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)\r
559 if Match:\r
560 self._PcdsDict[Match.group(1)] = Match.group(2)\r
561 if self.Debug:\r
562 print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))\r
cf1d4549
JY
563 else:\r
564 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)\r
565 if Match:\r
566 Remaining = Match.group(2)\r
567 if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':\r
568 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
569 if Match:\r
570 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
571 PageList = Match.group(1).split(',')\r
572 for Page in PageList:\r
573 Page = Page.strip()\r
574 Match = re.match("(\w+):\"(.+)\"", Page)\r
575 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
576\r
577 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
578 if Match:\r
579 self._CfgBlkDict['name'] = Match.group(1)\r
580 self._CfgBlkDict['ver'] = Match.group(2)\r
581\r
582 for Key in self._BsfKeyList:\r
583 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
584 if Match:\r
585 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
586 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
587 else:\r
588 ConfigDict[Key.lower()] = Match.group(1)\r
589 else:\r
590 for Key in self._HdrKeyList:\r
591 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
592 if Match:\r
593 ConfigDict[Key.lower()] = Match.group(1)\r
594\r
595 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)\r
596 if Match:\r
597 ConfigDict['name'] = Match.group(1)\r
598\r
599 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)\r
600 if Match:\r
601 if Match.group(2).strip() in self._BuidinOption:\r
602 ConfigDict['option'] = Match.group(2).strip()\r
603 else:\r
604 OptionValueList = Match.group(2).split(',')\r
605 OptionStringList = Match.group(3).split(',')\r
606 Index = 0\r
607 for Option in OptionValueList:\r
608 Option = Option.strip()\r
609 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()\r
610 Index += 1\r
611 if Index in range(len(OptionValueList)):\r
612 ConfigDict['option'] += ', '\r
613 ConfigDict['type'] = "Combo"\r
614\r
615 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
616 if Match:\r
617 if "0x" in Match.group(2) or "0x" in Match.group(3):\r
618 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
619 else:\r
620 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
621\r
622 Match = re.match("^\s*##\s+(.+)", DscLine)\r
623 if Match:\r
624 ConfigDict['help'] = Match.group(1)\r
625\r
626 # Check VPD/UPD\r
627 if IsUpdSect:\r
628 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
629 else:\r
630 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
631 if Match:\r
632 ConfigDict['space'] = Match.group(1)\r
633 ConfigDict['cname'] = Match.group(2)\r
634 ConfigDict['offset'] = int (Match.group(3), 16)\r
635 if ConfigDict['order'] == -1:\r
636 ConfigDict['order'] = ConfigDict['offset'] << 8\r
637 else:\r
638 (Major, Minor) = ConfigDict['order'].split('.')\r
639 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
640 if IsUpdSect:\r
641 Value = Match.group(5).strip()\r
642 if Match.group(4).startswith("0x"):\r
643 Length = int (Match.group(4), 16)\r
644 else :\r
645 Length = int (Match.group(4))\r
646 else:\r
647 Value = Match.group(4)\r
648 if Value is None:\r
649 Value = ''\r
650 Value = Value.strip()\r
651 if '|' in Value:\r
652 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
653 if Match:\r
654 Value = Match.group(1)\r
655 Length = -1\r
656\r
657 ConfigDict['length'] = Length\r
658 Match = re.match("\$\((\w+)\)", Value)\r
659 if Match:\r
660 if Match.group(1) in self._MacroDict:\r
661 Value = self._MacroDict[Match.group(1)]\r
662\r
663 ConfigDict['value'] = Value\r
664 if (len(Value) > 0) and (Value[0] == '{'):\r
665 Value = self.FormatListValue(ConfigDict)\r
666\r
667 if ConfigDict['name'] == '':\r
668 # Clear BSF specific items\r
669 ConfigDict['bsfname'] = ''\r
670 ConfigDict['help'] = ''\r
671 ConfigDict['type'] = ''\r
672 ConfigDict['option'] = ''\r
673\r
674 self._CfgItemList.append(ConfigDict.copy())\r
675 ConfigDict['name'] = ''\r
676 ConfigDict['find'] = ''\r
677 ConfigDict['struct'] = ''\r
678 ConfigDict['embed'] = ''\r
679 ConfigDict['comment'] = ''\r
680 ConfigDict['order'] = -1\r
681 ConfigDict['subreg'] = []\r
682 ConfigDict['option'] = ''\r
683 else:\r
684 # It could be a virtual item as below\r
62997d5e 685 # !BSF FIELD:{SerialDebugPortAddress0:1}\r
cf1d4549 686 # or\r
62997d5e
MM
687 # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
688 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)\r
cf1d4549 689 if Match:\r
62997d5e
MM
690 SubCfgDict = ConfigDict.copy()\r
691 if (Match.group(4) == None) or (Match.group(4) == 'B'):\r
692 UnitBitLen = 8\r
693 elif Match.group(4) == 'b':\r
694 UnitBitLen = 1\r
695 else:\r
696 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)\r
697 raise SystemExit\r
cf1d4549 698 SubCfgDict['cname'] = Match.group(2)\r
62997d5e
MM
699 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen\r
700 if SubCfgDict['bitlength'] > 0:\r
cf1d4549
JY
701 LastItem = self._CfgItemList[-1]\r
702 if len(LastItem['subreg']) == 0:\r
703 SubOffset = 0\r
704 else:\r
62997d5e
MM
705 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']\r
706 SubCfgDict['bitoffset'] = SubOffset\r
cf1d4549
JY
707 LastItem['subreg'].append (SubCfgDict.copy())\r
708 ConfigDict['name'] = ''\r
709 return Error\r
710\r
62997d5e
MM
711 def GetBsfBitFields (self, subitem, bytes):\r
712 start = subitem['bitoffset']\r
713 end = start + subitem['bitlength']\r
714 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])\r
715 bitsvalue = bitsvalue[::-1]\r
716 bitslen = len(bitsvalue)\r
717 if start > bitslen or end > bitslen:\r
718 print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name'])\r
719 raise SystemExit\r
720 return hex(int(bitsvalue[start:end][::-1], 2))\r
721\r
cf1d4549
JY
722 def UpdateSubRegionDefaultValue (self):\r
723 Error = 0\r
724 for Item in self._CfgItemList:\r
725 if len(Item['subreg']) == 0:\r
726 continue\r
727 bytearray = []\r
728 if Item['value'][0] == '{':\r
729 binlist = Item['value'][1:-1].split(',')\r
730 for each in binlist:\r
731 each = each.strip()\r
732 if each.startswith('0x'):\r
733 value = int(each, 16)\r
734 else:\r
735 value = int(each)\r
736 bytearray.append(value)\r
737 else:\r
738 if Item['value'].startswith('0x'):\r
739 value = int(Item['value'], 16)\r
740 else:\r
741 value = int(Item['value'])\r
62997d5e 742 idx = 0\r
cf1d4549
JY
743 while idx < Item['length']:\r
744 bytearray.append(value & 0xFF)\r
745 value = value >> 8\r
746 idx = idx + 1\r
747 for SubItem in Item['subreg']:\r
62997d5e
MM
748 valuestr = self.GetBsfBitFields(SubItem, bytearray)\r
749 SubItem['value'] = valuestr\r
cf1d4549
JY
750 return Error\r
751\r
752 def CreateSplitUpdTxt (self, UpdTxtFile):\r
753 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r
754 SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS\r
755 for Index in range(len(GuidList)):\r
756 UpdTxtFile = ''\r
757 FvDir = self._FvDir\r
758 if GuidList[Index] not in self._MacroDict:\r
759 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r
760 return 1\r
761\r
762 if UpdTxtFile == '':\r
763 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
764\r
765 ReCreate = False\r
766 if not os.path.exists(UpdTxtFile):\r
767 ReCreate = True\r
768 else:\r
769 DscTime = os.path.getmtime(self._DscFile)\r
770 TxtTime = os.path.getmtime(UpdTxtFile)\r
771 if DscTime > TxtTime:\r
772 ReCreate = True\r
773\r
774 if not ReCreate:\r
775 # DSC has not been modified yet\r
776 # So don't have to re-generate other files\r
777 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
778 return 256\r
779\r
780 TxtFd = open(UpdTxtFile, "w")\r
781 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
782\r
783 NextOffset = 0\r
784 SpaceIdx = 0\r
785 StartAddr = 0\r
786 EndAddr = 0\r
787 Default = 'DEFAULT|'\r
788 InRange = False\r
789 for Item in self._CfgItemList:\r
790 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
791 StartAddr = Item['offset']\r
792 NextOffset = StartAddr\r
793 InRange = True\r
794 if Item['cname'] == 'UpdTerminator' and InRange == True:\r
795 EndAddr = Item['offset']\r
796 InRange = False\r
797 InRange = False\r
798 for Item in self._CfgItemList:\r
799 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
800 InRange = True\r
801 if InRange != True:\r
802 continue\r
803 if Item['cname'] == 'UpdTerminator':\r
804 InRange = False\r
805 if Item['region'] != 'UPD':\r
806 continue\r
807 Offset = Item['offset']\r
808 if StartAddr > Offset or EndAddr < Offset:\r
809 continue\r
810 if NextOffset < Offset:\r
811 # insert one line\r
812 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r
813 SpaceIdx = SpaceIdx + 1\r
814 NextOffset = Offset + Item['length']\r
815 if Item['cname'] == 'PcdSerialIoUartDebugEnable':\r
816 if self.ReleaseMode == False:\r
817 Item['value'] = 0x01\r
818 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r
819 TxtFd.close()\r
820 return 0\r
821\r
822 def ProcessMultilines (self, String, MaxCharLength):\r
823 Multilines = ''\r
824 StringLength = len(String)\r
825 CurrentStringStart = 0\r
826 StringOffset = 0\r
827 BreakLineDict = []\r
828 if len(String) <= MaxCharLength:\r
829 while (StringOffset < StringLength):\r
830 if StringOffset >= 1:\r
831 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
832 BreakLineDict.append (StringOffset + 1)\r
833 StringOffset += 1\r
834 if BreakLineDict != []:\r
835 for Each in BreakLineDict:\r
836 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
837 CurrentStringStart = Each\r
838 if StringLength - CurrentStringStart > 0:\r
839 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
840 else:\r
841 Multilines = " %s\n" % String\r
842 else:\r
843 NewLineStart = 0\r
844 NewLineCount = 0\r
845 FoundSpaceChar = False\r
846 while (StringOffset < StringLength):\r
847 if StringOffset >= 1:\r
848 if NewLineCount >= MaxCharLength - 1:\r
849 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
850 BreakLineDict.append (NewLineStart + NewLineCount)\r
851 NewLineStart = NewLineStart + NewLineCount\r
852 NewLineCount = 0\r
853 FoundSpaceChar = True\r
854 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
855 BreakLineDict.append (0)\r
856 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
857 BreakLineDict.append (StringOffset + 1)\r
858 NewLineStart = StringOffset + 1\r
859 NewLineCount = 0\r
860 StringOffset += 1\r
861 NewLineCount += 1\r
862 if BreakLineDict != []:\r
863 BreakLineDict.sort ()\r
864 for Each in BreakLineDict:\r
865 if Each > 0:\r
866 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
867 CurrentStringStart = Each\r
868 if StringLength - CurrentStringStart > 0:\r
869 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
870 return Multilines\r
871\r
872 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):\r
873 PosName = 28\r
874 PosComment = 30\r
875 NameLine=''\r
876 HelpLine=''\r
877 OptionLine=''\r
878\r
879 IsArray = False\r
880 if Length in [1,2,4,8]:\r
881 Type = "UINT%d" % (Length * 8)\r
cd3692b1
SY
882 if Name.startswith("UnusedUpdSpace") and Length != 1:\r
883 IsArray = True\r
884 Type = "UINT8"\r
cf1d4549
JY
885 else:\r
886 IsArray = True\r
887 Type = "UINT8"\r
888\r
889 if Item and Item['value'].startswith('{'):\r
890 Type = "UINT8"\r
891 IsArray = True\r
892\r
893 if Struct != '':\r
894 Type = Struct\r
895 if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
896 IsArray = True\r
897 Unit = int(Type[4:]) / 8\r
898 Length = Length / Unit\r
899 else:\r
900 IsArray = False\r
901\r
902 if IsArray:\r
903 Name = Name + '[%d]' % Length\r
904\r
905 if len(Type) < PosName:\r
906 Space1 = PosName - len(Type)\r
907 else:\r
908 Space1 = 1\r
909\r
910 if BsfName != '':\r
911 NameLine=" - %s\n" % BsfName\r
912 else:\r
913 NameLine="\n"\r
914\r
915 if Help != '':\r
916 HelpLine = self.ProcessMultilines (Help, 80)\r
917\r
918 if Option != '':\r
919 OptionLine = self.ProcessMultilines (Option, 80)\r
920\r
921 if Offset is None:\r
922 OffsetStr = '????'\r
923 else:\r
924 OffsetStr = '0x%04X' % Offset\r
925\r
926 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)\r
927\r
928 def PostProcessBody (self, TextBody):\r
929 NewTextBody = []\r
930 OldTextBody = []\r
931 IncludeLine = False\r
932 StructName = ''\r
933 VariableName = ''\r
934 IsUpdHdrDefined = False\r
935 IsUpdHeader = False\r
936 for Line in TextBody:\r
937 SplitToLines = Line.splitlines()\r
938 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r
939 if MatchComment:\r
940 if MatchComment.group(1) == 'FSP_UPD_HEADER':\r
941 IsUpdHeader = True\r
942 else:\r
943 IsUpdHeader = False\r
944 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
945 CommentLine = " " + MatchComment.group(2) + "\n"\r
946 NewTextBody.append("/**" + CommentLine + "**/\n")\r
947 Line = Line[(len(SplitToLines[0]) + 1):]\r
948\r
949 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
950 if Match:\r
951 Line = Match.group(4)\r
952 if Match.group(1) == 'FSP_UPD_HEADER':\r
953 IsUpdHeader = True\r
954 else:\r
955 IsUpdHeader = False\r
956\r
957 if Match and Match.group(3) == 'START':\r
958 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
959 NewTextBody.append ('typedef struct {\n')\r
960 StructName = Match.group(1)\r
961 VariableName = Match.group(2)\r
962 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
963 if MatchOffset:\r
964 Offset = int(MatchOffset.group(1), 16)\r
965 else:\r
966 Offset = None\r
967 Line\r
968 IncludeLine = True\r
969 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r
970 if IncludeLine:\r
971 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
972 NewTextBody.append (Line)\r
973 else:\r
974 OldTextBody.append (Line)\r
975\r
62997d5e 976 if Match and Match.group(3) == 'END':\r
cf1d4549
JY
977 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
978 print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))\r
979 else:\r
980 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
981 NewTextBody.append ('} %s;\n\n' % StructName)\r
982 IsUpdHdrDefined = True\r
983 IncludeLine = False\r
984 NewTextBody.extend(OldTextBody)\r
985 return NewTextBody\r
986\r
987 def CreateHeaderFile (self, InputHeaderFile):\r
988 FvDir = self._FvDir\r
989\r
990 HeaderFileName = 'FspUpd.h'\r
991 HeaderFile = os.path.join(FvDir, HeaderFileName)\r
992\r
993 # Check if header needs to be recreated\r
994 ReCreate = False\r
995\r
996 TxtBody = []\r
997 for Item in self._CfgItemList:\r
998 if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
999 Value = int(Item['value'], 16)\r
1000 Chars = []\r
1001 while Value != 0x0:\r
1002 Chars.append(chr(Value & 0xFF))\r
1003 Value = Value >> 8\r
1004 SignatureStr = ''.join(Chars)\r
1005 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly\r
1006 if '_T' in SignatureStr[6:6+2]:\r
1007 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1008 elif '_M' in SignatureStr[6:6+2]:\r
1009 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1010 elif '_S' in SignatureStr[6:6+2]:\r
1011 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1012 TxtBody.append("\n")\r
1013\r
1014 for Region in ['UPD']:\r
1015 UpdOffsetTable = []\r
1016 UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS\r
1017 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r
1018 for Item in self._CfgItemList:\r
1019 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
1020 UpdOffsetTable.append (Item["offset"])\r
1021\r
1022 for UpdIdx in range(len(UpdOffsetTable)):\r
1023 CommentLine = ""\r
1024 for Item in self._CfgItemList:\r
1025 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r
1026 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r
1027 if MatchComment and MatchComment.group(1) == Region[0]:\r
1028 CommentLine = " " + MatchComment.group(2) + "\n"\r
1029 TxtBody.append("/**" + CommentLine + "**/\n")\r
1030 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r
1031 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r
1032 if Match:\r
1033 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r
1034 TxtBody.append("typedef struct {\n")\r
1035 NextOffset = 0\r
1036 SpaceIdx = 0\r
1037 Offset = 0\r
1038\r
1039 LastVisible = True\r
1040 ResvOffset = 0\r
1041 ResvIdx = 0\r
1042 LineBuffer = []\r
1043 InRange = False\r
1044 for Item in self._CfgItemList:\r
1045 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r
1046 InRange = True\r
1047 if InRange != True:\r
1048 continue\r
1049 if Item['cname'] == 'UpdTerminator':\r
1050 InRange = False\r
1051\r
1052 if Item['region'] != Region:\r
1053 continue\r
1054\r
1055 if Item["offset"] < UpdOffsetTable[UpdIdx]:\r
1056 continue\r
1057\r
1058 NextVisible = LastVisible\r
1059\r
1060 if LastVisible and (Item['header'] == 'OFF'):\r
1061 NextVisible = False\r
1062 ResvOffset = Item['offset']\r
1063 elif (not LastVisible) and Item['header'] == 'ON':\r
1064 NextVisible = True\r
1065 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
1066 ResvIdx = ResvIdx + 1\r
1067 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r
1068\r
1069 if Offset < Item["offset"]:\r
1070 if LastVisible:\r
1071 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
1072 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r
1073 SpaceIdx = SpaceIdx + 1\r
1074 Offset = Item["offset"]\r
1075\r
1076 LastVisible = NextVisible\r
1077\r
1078 Offset = Offset + Item["length"]\r
1079 if LastVisible:\r
1080 for Each in LineBuffer:\r
1081 TxtBody.append (Each)\r
1082 LineBuffer = []\r
1083 Comment = Item["comment"]\r
1084 Embed = Item["embed"].upper()\r
1085 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1086 if not Comment == '' and Embed.endswith(':START'):\r
1087 Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r
1088 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1089 else:\r
1090 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1091 else:\r
1092 if Embed == '':\r
62997d5e 1093 Marker = ''\r
cf1d4549
JY
1094 else:\r
1095 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1096 return 4\r
1097 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r
1098 TxtBody.append(Line)\r
1099 if Item['cname'] == 'UpdTerminator':\r
1100 break\r
1101 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r
62997d5e 1102\r
cf1d4549
JY
1103 # Handle the embedded data structure\r
1104 TxtBody = self.PostProcessBody (TxtBody)\r
1105\r
1106 HeaderTFileName = 'FsptUpd.h'\r
1107 HeaderMFileName = 'FspmUpd.h'\r
1108 HeaderSFileName = 'FspsUpd.h'\r
1109\r
1110 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION\r
1111 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
1112 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r
1113 ExcludedSpecificUpd = 'FSPM_ARCH_UPD'\r
1114\r
1115 if InputHeaderFile != '':\r
1116 if not os.path.exists(InputHeaderFile):\r
1117 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1118 return 6\r
1119\r
1120 InFd = open(InputHeaderFile, "r")\r
1121 IncLines = InFd.readlines()\r
1122 InFd.close()\r
1123\r
1124 for item in range(len(UpdRegionCheck)):\r
1125 if UpdRegionCheck[item] == 'FSPT':\r
1126 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r
1127 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r
1128 elif UpdRegionCheck[item] == 'FSPM':\r
1129 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r
1130 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r
1131 elif UpdRegionCheck[item] == 'FSPS':\r
1132 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r
1133 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r
1134 FileName = FileBase.replace(".", "_").upper()\r
1135 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1136 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1137 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1138 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r
cd3692b1 1139 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1140\r
1141 Export = False\r
1142 for Line in IncLines:\r
1143 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1144 if Match:\r
1145 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r
1146 Export = True\r
1147 continue\r
1148 else:\r
1149 Export = False\r
1150 continue\r
1151 if Export:\r
1152 HeaderFd.write(Line)\r
1153 HeaderFd.write("\n")\r
1154\r
1155 Index = 0\r
1156 StartIndex = 0\r
1157 EndIndex = 0\r
1158 StructStart = []\r
1159 StructStartWithComment = []\r
1160 StructEnd = []\r
1161 for Line in TxtBody:\r
1162 Index += 1\r
1163 Match = re.match("(typedef struct {)", Line)\r
1164 if Match:\r
1165 StartIndex = Index - 1\r
1166 Match = re.match("}\s([_A-Z0-9]+);", Line)\r
1167 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):\r
1168 EndIndex = Index\r
1169 StructStart.append(StartIndex)\r
1170 StructEnd.append(EndIndex)\r
1171 Index = 0\r
1172 for Line in TxtBody:\r
1173 Index += 1\r
1174 for Item in range(len(StructStart)):\r
1175 if Index == StructStart[Item]:\r
1176 Match = re.match("^(/\*\*\s*)", Line)\r
1177 if Match:\r
1178 StructStartWithComment.append(StructStart[Item])\r
1179 else:\r
1180 StructStartWithComment.append(StructStart[Item] + 1)\r
1181 Index = 0\r
1182 for Line in TxtBody:\r
1183 Index += 1\r
1184 for Item in range(len(StructStart)):\r
1185 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1186 HeaderFd.write (Line)\r
cd3692b1 1187 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1188 HeaderFd.write("#endif\n")\r
1189 HeaderFd.close()\r
1190\r
1191 HeaderFd = open(HeaderFile, "w")\r
1192 FileBase = os.path.basename(HeaderFile)\r
1193 FileName = FileBase.replace(".", "_").upper()\r
1194 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1195 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1196 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1197 HeaderFd.write("#include <FspEas.h>\n\n")\r
cd3692b1 1198 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1199\r
1200 for item in range(len(UpdRegionCheck)):\r
1201 Index = 0\r
1202 StartIndex = 0\r
1203 EndIndex = 0\r
1204 StructStart = []\r
1205 StructStartWithComment = []\r
1206 StructEnd = []\r
1207 for Line in TxtBody:\r
1208 Index += 1\r
1209 Match = re.match("(typedef struct {)", Line)\r
1210 if Match:\r
1211 StartIndex = Index - 1\r
1212 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r
1213 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r
1214 StructStart.append(Index - 1)\r
1215 StructEnd.append(Index)\r
1216 Index = 0\r
1217 for Line in TxtBody:\r
1218 Index += 1\r
1219 for Item in range(len(StructStart)):\r
1220 if Index == StructStart[Item]:\r
1221 Match = re.match("^(/\*\*\s*)", Line)\r
1222 if Match:\r
1223 StructStartWithComment.append(StructStart[Item])\r
1224 else:\r
1225 StructStartWithComment.append(StructStart[Item] + 1)\r
1226 Index = 0\r
1227 for Line in TxtBody:\r
1228 Index += 1\r
1229 for Item in range(len(StructStart)):\r
1230 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
1231 HeaderFd.write (Line)\r
cd3692b1 1232 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1233 HeaderFd.write("#endif\n")\r
1234 HeaderFd.close()\r
1235\r
1236 return 0\r
1237\r
1238 def WriteBsfStruct (self, BsfFd, Item):\r
1239 if Item['type'] == "None":\r
1240 Space = "gPlatformFspPkgTokenSpaceGuid"\r
1241 else:\r
1242 Space = Item['space']\r
1243 Line = " $%s_%s" % (Space, Item['cname'])\r
1244 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1245 if Match:\r
1246 DefaultValue = Match.group(1).strip()\r
1247 else:\r
1248 DefaultValue = Item['value'].strip()\r
62997d5e
MM
1249 if 'bitlength' in Item:\r
1250 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r
1251 else:\r
1252 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
cf1d4549
JY
1253 TmpList = []\r
1254 if Item['type'] == "Combo":\r
1255 if not Item['option'] in self._BuidinOption:\r
1256 OptList = Item['option'].split(',')\r
1257 for Option in OptList:\r
1258 Option = Option.strip()\r
1259 (OpVal, OpStr) = Option.split(':')\r
1260 TmpList.append((OpVal, OpStr))\r
1261 return TmpList\r
1262\r
1263 def WriteBsfOption (self, BsfFd, Item):\r
1264 PcdName = Item['space'] + '_' + Item['cname']\r
1265 WriteHelp = 0\r
1266 if Item['type'] == "Combo":\r
1267 if Item['option'] in self._BuidinOption:\r
1268 Options = self._BuidinOption[Item['option']]\r
1269 else:\r
1270 Options = PcdName\r
62997d5e 1271 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r
cf1d4549
JY
1272 WriteHelp = 1\r
1273 elif Item['type'].startswith("EditNum"):\r
1274 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
1275 if Match:\r
62997d5e 1276 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r
cf1d4549
JY
1277 WriteHelp = 2\r
1278 elif Item['type'].startswith("EditText"):\r
62997d5e 1279 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1280 WriteHelp = 1\r
1281 elif Item['type'] == "Table":\r
1282 Columns = Item['option'].split(',')\r
1283 if len(Columns) != 0:\r
62997d5e 1284 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1285 for Col in Columns:\r
1286 Fmt = Col.split(':')\r
1287 if len(Fmt) != 3:\r
1288 raise Exception("Column format '%s' is invalid !" % Fmt)\r
1289 try:\r
1290 Dtype = int(Fmt[1].strip())\r
1291 except:\r
1292 raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1293 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1294 BsfFd.write(',\n')\r
1295 WriteHelp = 1\r
62997d5e 1296\r
cf1d4549
JY
1297 if WriteHelp > 0:\r
1298 HelpLines = Item['help'].split('\\n\\r')\r
1299 FirstLine = True\r
1300 for HelpLine in HelpLines:\r
1301 if FirstLine:\r
1302 FirstLine = False\r
62997d5e 1303 BsfFd.write(' Help "%s"\n' % (HelpLine))\r
cf1d4549 1304 else:\r
62997d5e 1305 BsfFd.write(' "%s"\n' % (HelpLine))\r
cf1d4549 1306 if WriteHelp == 2:\r
62997d5e 1307 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r
cf1d4549
JY
1308\r
1309 def GenerateBsfFile (self, BsfFile):\r
1310\r
1311 if BsfFile == '':\r
1312 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1313 return 1\r
1314\r
1315 Error = 0\r
1316 OptionDict = {}\r
1317 BsfFd = open(BsfFile, "w")\r
1318 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
62997d5e 1319 BsfFd.write("%s\n" % self._GlobalDataDef)\r
cf1d4549
JY
1320 BsfFd.write("StructDef\n")\r
1321 NextOffset = -1\r
1322 for Item in self._CfgItemList:\r
1323 if Item['find'] != '':\r
1324 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
1325 NextOffset = Item['offset'] + Item['length']\r
1326 if Item['name'] != '':\r
1327 if NextOffset != Item['offset']:\r
1328 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1329 if len(Item['subreg']) > 0:\r
1330 NextOffset = Item['offset']\r
62997d5e 1331 BitsOffset = NextOffset * 8\r
cf1d4549 1332 for SubItem in Item['subreg']:\r
62997d5e 1333 BitsOffset += SubItem['bitlength']\r
cf1d4549 1334 if SubItem['name'] == '':\r
62997d5e
MM
1335 if 'bitlength' in SubItem:\r
1336 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))\r
1337 else:\r
1338 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
cf1d4549
JY
1339 else:\r
1340 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1341 if len(Options) > 0:\r
1342 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
62997d5e
MM
1343\r
1344 NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
1345 if NextBitsOffset > BitsOffset:\r
1346 BitsGap = NextBitsOffset - BitsOffset\r
1347 BitsRemain = BitsGap % 8\r
1348 if BitsRemain:\r
1349 BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
1350 BitsGap -= BitsRemain\r
1351 BytesRemain = BitsGap / 8\r
1352 if BytesRemain:\r
1353 BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r
1354 NextOffset = Item['offset'] + Item['length']\r
cf1d4549
JY
1355 else:\r
1356 NextOffset = Item['offset'] + Item['length']\r
1357 Options = self.WriteBsfStruct(BsfFd, Item)\r
1358 if len(Options) > 0:\r
1359 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1360 BsfFd.write("\nEndStruct\n\n")\r
1361\r
62997d5e 1362 BsfFd.write("%s" % self._BuidinOptionTxt)\r
cf1d4549
JY
1363\r
1364 for Each in OptionDict:\r
62997d5e 1365 BsfFd.write("List &%s\n" % Each)\r
cf1d4549 1366 for Item in OptionDict[Each]:\r
62997d5e
MM
1367 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))\r
1368 BsfFd.write("EndList\n\n")\r
cf1d4549 1369\r
62997d5e
MM
1370 BsfFd.write("BeginInfoBlock\n")\r
1371 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r
1372 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r
1373 BsfFd.write("EndInfoBlock\n\n")\r
cf1d4549
JY
1374\r
1375 for Each in self._CfgPageDict:\r
62997d5e 1376 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r
cf1d4549
JY
1377 BsfItems = []\r
1378 for Item in self._CfgItemList:\r
1379 if Item['name'] != '':\r
1380 if Item['page'] != Each:\r
1381 continue\r
1382 if len(Item['subreg']) > 0:\r
1383 for SubItem in Item['subreg']:\r
1384 if SubItem['name'] != '':\r
1385 BsfItems.append(SubItem)\r
1386 else:\r
1387 BsfItems.append(Item)\r
1388\r
1389 BsfItems.sort(key=lambda x: x['order'])\r
1390\r
1391 for Item in BsfItems:\r
1392 self.WriteBsfOption (BsfFd, Item)\r
62997d5e 1393 BsfFd.write("EndPage\n\n")\r
cf1d4549
JY
1394\r
1395 BsfFd.close()\r
1396 return Error\r
1397\r
1398\r
1399def Usage():\r
62997d5e 1400 print "GenCfgOpt Version 0.52"\r
cf1d4549 1401 print "Usage:"\r
62997d5e
MM
1402 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]"\r
1403 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]"\r
1404 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r
cf1d4549
JY
1405\r
1406def Main():\r
1407 #\r
1408 # Parse the options and args\r
1409 #\r
1410 GenCfgOpt = CGenCfgOpt()\r
1411 argc = len(sys.argv)\r
1412 if argc < 4:\r
1413 Usage()\r
1414 return 1\r
1415 else:\r
1416 DscFile = sys.argv[2]\r
1417 if not os.path.exists(DscFile):\r
1418 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1419 return 2\r
cf1d4549
JY
1420\r
1421 OutFile = ''\r
1422 if argc > 4:\r
62997d5e 1423 if sys.argv[4][0] == '-':\r
cf1d4549
JY
1424 Start = 4\r
1425 else:\r
62997d5e 1426 OutFile = sys.argv[4]\r
cf1d4549
JY
1427 Start = 5\r
1428 GenCfgOpt.ParseBuildMode(sys.argv[3])\r
1429 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
1430 print "ERROR: Macro parsing failed !"\r
1431 return 3\r
1432\r
1433 FvDir = sys.argv[3]\r
1434 if not os.path.exists(FvDir):\r
1435 os.makedirs(FvDir)\r
1436\r
62997d5e 1437 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
cf1d4549
JY
1438 print "ERROR: %s !" % GenCfgOpt.Error\r
1439 return 5\r
1440\r
1441 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1442 print "ERROR: %s !" % GenCfgOpt.Error\r
1443 return 7\r
1444\r
1445 if sys.argv[1] == "UPDTXT":\r
1446 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1447 if Ret != 0:\r
1448 # No change is detected\r
1449 if Ret == 256:\r
1450 print "INFO: %s !" % (GenCfgOpt.Error)\r
1451 else :\r
1452 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1453 return Ret\r
1454 elif sys.argv[1] == "HEADER":\r
1455 if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
1456 print "ERROR: %s !" % GenCfgOpt.Error\r
1457 return 8\r
1458 elif sys.argv[1] == "GENBSF":\r
1459 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1460 print "ERROR: %s !" % GenCfgOpt.Error\r
1461 return 9\r
1462 else:\r
1463 if argc < 5:\r
1464 Usage()\r
1465 return 1\r
1466 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1467 Usage()\r
1468 return 1\r
1469 return 0\r
1470 return 0\r
1471\r
1472\r
1473if __name__ == '__main__':\r
1474 sys.exit(Main())\r