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