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