]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Tools/GenCfgOpt.py
GenCfgOpt.py: remove tailing space from output file
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
CommitLineData
cf1d4549
JY
1## @ GenCfgOpt.py\r
2#\r
bb88882b 3# Copyright (c) 2014 - 2018, 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
cf1d4549
JY
292\r
293 self._GlobalDataDef = """\r
294GlobalDataDef\r
295 SKUID = 0, "DEFAULT"\r
296EndGlobalData\r
297\r
298"""\r
299 self._BuidinOptionTxt = """\r
300List &EN_DIS\r
301 Selection 0x1 , "Enabled"\r
302 Selection 0x0 , "Disabled"\r
303EndList\r
304\r
305"""\r
306\r
307 self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
308 self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']\r
309 self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}\r
310\r
311 self._MacroDict = {}\r
62997d5e 312 self._PcdsDict = {}\r
cf1d4549
JY
313 self._CfgBlkDict = {}\r
314 self._CfgPageDict = {}\r
315 self._CfgItemList = []\r
316 self._DscFile = ''\r
317 self._FvDir = ''\r
318 self._MapVer = 0\r
319\r
cf1d4549
JY
320 def ParseMacros (self, MacroDefStr):\r
321 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
322 self._MacroDict = {}\r
323 IsExpression = False\r
324 for Macro in MacroDefStr:\r
325 if Macro.startswith('-D'):\r
326 IsExpression = True\r
327 if len(Macro) > 2:\r
328 Macro = Macro[2:]\r
329 else :\r
330 continue\r
331 if IsExpression:\r
332 IsExpression = False\r
333 Match = re.match("(\w+)=(.+)", Macro)\r
334 if Match:\r
335 self._MacroDict[Match.group(1)] = Match.group(2)\r
336 else:\r
337 Match = re.match("(\w+)", Macro)\r
338 if Match:\r
339 self._MacroDict[Match.group(1)] = ''\r
340 if len(self._MacroDict) == 0:\r
341 Error = 1\r
342 else:\r
343 Error = 0\r
344 if self.Debug:\r
345 print "INFO : Macro dictionary:"\r
346 for Each in self._MacroDict:\r
347 print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each])\r
348 return Error\r
349\r
350 def EvaulateIfdef (self, Macro):\r
351 Result = Macro in self._MacroDict\r
352 if self.Debug:\r
353 print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)\r
354 return Result\r
355\r
356 def ExpandMacros (self, Input):\r
357 Line = Input\r
358 Match = re.findall("\$\(\w+\)", Input)\r
359 if Match:\r
360 for Each in Match:\r
361 Variable = Each[2:-1]\r
362 if Variable in self._MacroDict:\r
363 Line = Line.replace(Each, self._MacroDict[Variable])\r
364 else:\r
365 if self.Debug:\r
366 print "WARN : %s is not defined" % Each\r
367 Line = Line.replace(Each, Each[2:-1])\r
368 return Line\r
369\r
62997d5e
MM
370 def ExpandPcds (self, Input):\r
371 Line = Input\r
372 Match = re.findall("(\w+\.\w+)", Input)\r
373 if Match:\r
374 for PcdName in Match:\r
375 if PcdName in self._PcdsDict:\r
376 Line = Line.replace(PcdName, self._PcdsDict[PcdName])\r
377 else:\r
378 if self.Debug:\r
379 print "WARN : %s is not defined" % PcdName\r
380 return Line\r
381\r
cf1d4549 382 def EvaluateExpress (self, Expr):\r
62997d5e
MM
383 ExpExpr = self.ExpandPcds(Expr)\r
384 ExpExpr = self.ExpandMacros(ExpExpr)\r
cf1d4549
JY
385 LogExpr = CLogicalExpression()\r
386 Result = LogExpr.evaluateExpress (ExpExpr)\r
387 if self.Debug:\r
388 print "INFO : Eval Express [%s] : %s" % (Expr, Result)\r
389 return Result\r
390\r
391 def FormatListValue(self, ConfigDict):\r
392 Struct = ConfigDict['struct']\r
393 if Struct not in ['UINT8','UINT16','UINT32','UINT64']:\r
394 return\r
395\r
396 dataarray = []\r
397 binlist = ConfigDict['value'][1:-1].split(',')\r
398 for each in binlist:\r
399 each = each.strip()\r
400 if each.startswith('0x'):\r
401 value = int(each, 16)\r
402 else:\r
403 value = int(each)\r
404 dataarray.append(value)\r
405\r
406 unit = int(Struct[4:]) / 8\r
407 if int(ConfigDict['length']) != unit * len(dataarray):\r
408 raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])\r
409\r
410 bytearray = []\r
411 for each in dataarray:\r
412 value = each\r
413 for loop in xrange(unit):\r
414 bytearray.append("0x%02X" % (value & 0xFF))\r
415 value = value >> 8\r
416 newvalue = '{' + ','.join(bytearray) + '}'\r
417 ConfigDict['value'] = newvalue\r
418 return ""\r
419\r
62997d5e 420 def ParseDscFile (self, DscFile, FvDir):\r
29933058
CC
421 Hardcode = False\r
422 AutoAlign = False\r
cf1d4549
JY
423 self._CfgItemList = []\r
424 self._CfgPageDict = {}\r
425 self._CfgBlkDict = {}\r
426 self._DscFile = DscFile\r
427 self._FvDir = FvDir\r
428\r
429 IsDefSect = False\r
62997d5e 430 IsPcdSect = False\r
cf1d4549
JY
431 IsUpdSect = False\r
432 IsVpdSect = False\r
cf1d4549
JY
433\r
434 IfStack = []\r
435 ElifStack = []\r
436 Error = 0\r
437 ConfigDict = {}\r
438\r
439 DscFd = open(DscFile, "r")\r
440 DscLines = DscFd.readlines()\r
441 DscFd.close()\r
442\r
29933058
CC
443 MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64\r
444 SizeAlign = 0 #record the struct max align\r
cf1d4549
JY
445 while len(DscLines):\r
446 DscLine = DscLines.pop(0).strip()\r
447 Handle = False\r
448 Match = re.match("^\[(.+)\]", DscLine)\r
449 if Match is not None:\r
62997d5e
MM
450 IsDefSect = False\r
451 IsPcdSect = False\r
452 IsVpdSect = False\r
453 IsUpdSect = False\r
cf1d4549
JY
454 if Match.group(1).lower() == "Defines".lower():\r
455 IsDefSect = True\r
bb88882b 456 if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()):\r
62997d5e 457 IsPcdSect = True\r
cf1d4549
JY
458 elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
459 ConfigDict = {}\r
460 ConfigDict['header'] = 'ON'\r
461 ConfigDict['region'] = 'UPD'\r
462 ConfigDict['order'] = -1\r
463 ConfigDict['page'] = ''\r
464 ConfigDict['name'] = ''\r
465 ConfigDict['find'] = ''\r
466 ConfigDict['struct'] = ''\r
467 ConfigDict['embed'] = ''\r
468 ConfigDict['comment'] = ''\r
469 ConfigDict['subreg'] = []\r
cf1d4549 470 IsUpdSect = True\r
29933058 471 Offset = 0\r
cf1d4549 472 else:\r
62997d5e 473 if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:\r
cf1d4549
JY
474 if re.match("^!else($|\s+#.+)", DscLine):\r
475 if IfStack:\r
476 IfStack[-1] = not IfStack[-1]\r
477 else:\r
478 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
479 raise SystemExit\r
480 elif re.match("^!endif($|\s+#.+)", DscLine):\r
481 if IfStack:\r
482 IfStack.pop()\r
483 Level = ElifStack.pop()\r
484 if Level > 0:\r
485 del IfStack[-Level:]\r
486 else:\r
487 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
488 raise SystemExit\r
489 else:\r
490 Result = False\r
491 Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)\r
492 if Match:\r
493 Result = self.EvaulateIfdef (Match.group(2))\r
494 if Match.group(1) == 'ifndef':\r
495 Result = not Result\r
496 IfStack.append(Result)\r
497 ElifStack.append(0)\r
498 else:\r
bb88882b 499 Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0])\r
cf1d4549 500 if Match:\r
62997d5e 501 Result = self.EvaluateExpress(Match.group(2))\r
cf1d4549
JY
502 if Match.group(1) == "if":\r
503 ElifStack.append(0)\r
504 IfStack.append(Result)\r
505 else: #elseif\r
506 if IfStack:\r
507 IfStack[-1] = not IfStack[-1]\r
508 IfStack.append(Result)\r
509 ElifStack[-1] = ElifStack[-1] + 1\r
510 else:\r
511 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
512 raise SystemExit\r
513 else:\r
514 if IfStack:\r
515 Handle = reduce(lambda x,y: x and y, IfStack)\r
516 else:\r
517 Handle = True\r
518 if Handle:\r
519 Match = re.match("!include\s+(.+)", DscLine)\r
520 if Match:\r
521 IncludeFilePath = Match.group(1)\r
522 IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
41d739e4 523 PackagesPath = os.getenv("PACKAGES_PATH")\r
60131098
SZ
524 if PackagesPath:\r
525 for PackagePath in PackagesPath.split(os.pathsep):\r
526 IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))\r
527 if os.path.exists(IncludeFilePathAbs):\r
528 IncludeDsc = open(IncludeFilePathAbs, "r")\r
529 break\r
530 else:\r
531 IncludeDsc = open(IncludeFilePath, "r")\r
41d739e4 532 if IncludeDsc == None:\r
cf1d4549
JY
533 print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
534 raise SystemExit\r
535 NewDscLines = IncludeDsc.readlines()\r
536 IncludeDsc.close()\r
537 DscLines = NewDscLines + DscLines\r
29933058 538 Offset = 0\r
cf1d4549
JY
539 else:\r
540 if DscLine.startswith('!'):\r
541 print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
542 raise SystemExit\r
543 if not Handle:\r
544 continue\r
545\r
546 if IsDefSect:\r
547 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
548 #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6\r
549 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385\r
550 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F\r
551 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
552 if Match:\r
553 self._MacroDict[Match.group(1)] = Match.group(2)\r
554 if self.Debug:\r
555 print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))\r
62997d5e
MM
556 elif IsPcdSect:\r
557 #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE\r
558 #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE\r
559 Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)\r
560 if Match:\r
561 self._PcdsDict[Match.group(1)] = Match.group(2)\r
562 if self.Debug:\r
563 print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))\r
cf1d4549
JY
564 else:\r
565 Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)\r
566 if Match:\r
567 Remaining = Match.group(2)\r
568 if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':\r
569 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
570 if Match:\r
571 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
572 PageList = Match.group(1).split(',')\r
573 for Page in PageList:\r
574 Page = Page.strip()\r
575 Match = re.match("(\w+):\"(.+)\"", Page)\r
576 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
577\r
578 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
579 if Match:\r
580 self._CfgBlkDict['name'] = Match.group(1)\r
581 self._CfgBlkDict['ver'] = Match.group(2)\r
582\r
583 for Key in self._BsfKeyList:\r
584 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
585 if Match:\r
586 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
587 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
588 else:\r
589 ConfigDict[Key.lower()] = Match.group(1)\r
590 else:\r
591 for Key in self._HdrKeyList:\r
592 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
593 if Match:\r
594 ConfigDict[Key.lower()] = Match.group(1)\r
595\r
596 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)\r
597 if Match:\r
598 ConfigDict['name'] = Match.group(1)\r
599\r
600 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)\r
601 if Match:\r
602 if Match.group(2).strip() in self._BuidinOption:\r
603 ConfigDict['option'] = Match.group(2).strip()\r
604 else:\r
605 OptionValueList = Match.group(2).split(',')\r
606 OptionStringList = Match.group(3).split(',')\r
607 Index = 0\r
608 for Option in OptionValueList:\r
609 Option = Option.strip()\r
610 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()\r
611 Index += 1\r
612 if Index in range(len(OptionValueList)):\r
613 ConfigDict['option'] += ', '\r
614 ConfigDict['type'] = "Combo"\r
615\r
616 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
617 if Match:\r
618 if "0x" in Match.group(2) or "0x" in Match.group(3):\r
619 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
620 else:\r
621 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
622\r
623 Match = re.match("^\s*##\s+(.+)", DscLine)\r
624 if Match:\r
625 ConfigDict['help'] = Match.group(1)\r
626\r
627 # Check VPD/UPD\r
628 if IsUpdSect:\r
29933058 629 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
630 else:\r
631 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
632 if Match:\r
633 ConfigDict['space'] = Match.group(1)\r
634 ConfigDict['cname'] = Match.group(2)\r
29933058
CC
635 if Match.group(3) != '*':\r
636 Hardcode = True\r
637 Offset = int (Match.group(3), 16)\r
638 else:\r
639 AutoAlign = True\r
640\r
641 if Hardcode and AutoAlign:\r
642 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")\r
643 raise SystemExit\r
644 ConfigDict['offset'] = Offset\r
cf1d4549
JY
645 if ConfigDict['order'] == -1:\r
646 ConfigDict['order'] = ConfigDict['offset'] << 8\r
647 else:\r
648 (Major, Minor) = ConfigDict['order'].split('.')\r
649 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
650 if IsUpdSect:\r
651 Value = Match.group(5).strip()\r
652 if Match.group(4).startswith("0x"):\r
653 Length = int (Match.group(4), 16)\r
654 else :\r
655 Length = int (Match.group(4))\r
29933058 656 Offset += Length\r
cf1d4549
JY
657 else:\r
658 Value = Match.group(4)\r
659 if Value is None:\r
660 Value = ''\r
661 Value = Value.strip()\r
662 if '|' in Value:\r
663 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
664 if Match:\r
665 Value = Match.group(1)\r
666 Length = -1\r
667\r
668 ConfigDict['length'] = Length\r
669 Match = re.match("\$\((\w+)\)", Value)\r
670 if Match:\r
671 if Match.group(1) in self._MacroDict:\r
672 Value = self._MacroDict[Match.group(1)]\r
673\r
674 ConfigDict['value'] = Value\r
675 if (len(Value) > 0) and (Value[0] == '{'):\r
676 Value = self.FormatListValue(ConfigDict)\r
677\r
678 if ConfigDict['name'] == '':\r
679 # Clear BSF specific items\r
680 ConfigDict['bsfname'] = ''\r
681 ConfigDict['help'] = ''\r
682 ConfigDict['type'] = ''\r
683 ConfigDict['option'] = ''\r
29933058
CC
684 if IsUpdSect and AutoAlign:\r
685 ItemLength = int(ConfigDict['length'])\r
686 ItemOffset = int(ConfigDict['offset'])\r
687 ItemStruct = ConfigDict['struct']\r
688 Unit = 1\r
689 if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):\r
690 Unit = ItemLength\r
691 # If there are 64 bit unit, align to 64\r
692 if Unit == 8:\r
693 MaxAlign = 64\r
694 SizeAlign = 8\r
695 if ItemStruct != '':\r
696 UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}\r
697 if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:\r
698 Unit = UnitDict[ItemStruct]\r
699 # If there are 64 bit unit, align to 64\r
700 if Unit == 8:\r
701 MaxAlign = 64\r
702 SizeAlign = max(SizeAlign, Unit)\r
703 if (ConfigDict['embed'].find(':START') != -1):\r
704 Base = ItemOffset\r
705 SubOffset = ItemOffset - Base\r
706 SubRemainder = SubOffset % Unit\r
707 if SubRemainder:\r
708 Diff = Unit - SubRemainder\r
709 Offset = Offset + Diff\r
710 ItemOffset = ItemOffset + Diff\r
711\r
712 if (ConfigDict['embed'].find(':END') != -1):\r
713 Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64\r
714 if Remainder:\r
715 Diff = (MaxAlign/8) - Remainder\r
716 Offset = Offset + Diff\r
717 ItemOffset = ItemOffset + Diff\r
718 MaxAlign = 32 # Reset to default 32 align when struct end\r
719 if (ConfigDict['cname'] == 'UpdTerminator'):\r
720 # ItemLength is the size of UpdTerminator\r
721 # Itemlength might be 16, 32, or 64\r
722 # Struct align to 64 if UpdTerminator\r
723 # or struct size is 64 bit, else align to 32\r
724 Remainder = Offset % max(ItemLength/8, 4, SizeAlign)\r
725 Offset = Offset + ItemLength\r
726 if Remainder:\r
727 Diff = max(ItemLength/8, 4, SizeAlign) - Remainder\r
728 ItemOffset = ItemOffset + Diff\r
729 ConfigDict['offset'] = ItemOffset\r
cf1d4549
JY
730\r
731 self._CfgItemList.append(ConfigDict.copy())\r
732 ConfigDict['name'] = ''\r
733 ConfigDict['find'] = ''\r
734 ConfigDict['struct'] = ''\r
735 ConfigDict['embed'] = ''\r
736 ConfigDict['comment'] = ''\r
737 ConfigDict['order'] = -1\r
738 ConfigDict['subreg'] = []\r
739 ConfigDict['option'] = ''\r
740 else:\r
741 # It could be a virtual item as below\r
62997d5e 742 # !BSF FIELD:{SerialDebugPortAddress0:1}\r
cf1d4549 743 # or\r
62997d5e
MM
744 # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
745 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)\r
cf1d4549 746 if Match:\r
62997d5e
MM
747 SubCfgDict = ConfigDict.copy()\r
748 if (Match.group(4) == None) or (Match.group(4) == 'B'):\r
749 UnitBitLen = 8\r
750 elif Match.group(4) == 'b':\r
751 UnitBitLen = 1\r
752 else:\r
753 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)\r
754 raise SystemExit\r
cf1d4549 755 SubCfgDict['cname'] = Match.group(2)\r
62997d5e
MM
756 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen\r
757 if SubCfgDict['bitlength'] > 0:\r
cf1d4549
JY
758 LastItem = self._CfgItemList[-1]\r
759 if len(LastItem['subreg']) == 0:\r
760 SubOffset = 0\r
761 else:\r
62997d5e
MM
762 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']\r
763 SubCfgDict['bitoffset'] = SubOffset\r
cf1d4549
JY
764 LastItem['subreg'].append (SubCfgDict.copy())\r
765 ConfigDict['name'] = ''\r
766 return Error\r
767\r
62997d5e
MM
768 def GetBsfBitFields (self, subitem, bytes):\r
769 start = subitem['bitoffset']\r
770 end = start + subitem['bitlength']\r
771 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])\r
772 bitsvalue = bitsvalue[::-1]\r
773 bitslen = len(bitsvalue)\r
774 if start > bitslen or end > bitslen:\r
775 print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name'])\r
776 raise SystemExit\r
777 return hex(int(bitsvalue[start:end][::-1], 2))\r
778\r
cf1d4549
JY
779 def UpdateSubRegionDefaultValue (self):\r
780 Error = 0\r
781 for Item in self._CfgItemList:\r
782 if len(Item['subreg']) == 0:\r
783 continue\r
784 bytearray = []\r
785 if Item['value'][0] == '{':\r
786 binlist = Item['value'][1:-1].split(',')\r
787 for each in binlist:\r
788 each = each.strip()\r
789 if each.startswith('0x'):\r
790 value = int(each, 16)\r
791 else:\r
792 value = int(each)\r
793 bytearray.append(value)\r
794 else:\r
795 if Item['value'].startswith('0x'):\r
796 value = int(Item['value'], 16)\r
797 else:\r
798 value = int(Item['value'])\r
62997d5e 799 idx = 0\r
cf1d4549
JY
800 while idx < Item['length']:\r
801 bytearray.append(value & 0xFF)\r
802 value = value >> 8\r
803 idx = idx + 1\r
804 for SubItem in Item['subreg']:\r
62997d5e
MM
805 valuestr = self.GetBsfBitFields(SubItem, bytearray)\r
806 SubItem['value'] = valuestr\r
cf1d4549
JY
807 return Error\r
808\r
809 def CreateSplitUpdTxt (self, UpdTxtFile):\r
810 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r
811 SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS\r
812 for Index in range(len(GuidList)):\r
813 UpdTxtFile = ''\r
814 FvDir = self._FvDir\r
815 if GuidList[Index] not in self._MacroDict:\r
816 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r
817 return 1\r
818\r
819 if UpdTxtFile == '':\r
820 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
821\r
822 ReCreate = False\r
823 if not os.path.exists(UpdTxtFile):\r
824 ReCreate = True\r
825 else:\r
826 DscTime = os.path.getmtime(self._DscFile)\r
827 TxtTime = os.path.getmtime(UpdTxtFile)\r
828 if DscTime > TxtTime:\r
829 ReCreate = True\r
830\r
831 if not ReCreate:\r
832 # DSC has not been modified yet\r
833 # So don't have to re-generate other files\r
834 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
835 return 256\r
836\r
837 TxtFd = open(UpdTxtFile, "w")\r
838 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
839\r
840 NextOffset = 0\r
841 SpaceIdx = 0\r
842 StartAddr = 0\r
843 EndAddr = 0\r
844 Default = 'DEFAULT|'\r
845 InRange = False\r
846 for Item in self._CfgItemList:\r
847 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
848 StartAddr = Item['offset']\r
849 NextOffset = StartAddr\r
850 InRange = True\r
851 if Item['cname'] == 'UpdTerminator' and InRange == True:\r
852 EndAddr = Item['offset']\r
853 InRange = False\r
854 InRange = False\r
855 for Item in self._CfgItemList:\r
856 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
857 InRange = True\r
858 if InRange != True:\r
859 continue\r
860 if Item['cname'] == 'UpdTerminator':\r
861 InRange = False\r
862 if Item['region'] != 'UPD':\r
863 continue\r
864 Offset = Item['offset']\r
865 if StartAddr > Offset or EndAddr < Offset:\r
866 continue\r
867 if NextOffset < Offset:\r
868 # insert one line\r
869 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r
870 SpaceIdx = SpaceIdx + 1\r
871 NextOffset = Offset + Item['length']\r
cf1d4549
JY
872 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r
873 TxtFd.close()\r
874 return 0\r
875\r
876 def ProcessMultilines (self, String, MaxCharLength):\r
877 Multilines = ''\r
878 StringLength = len(String)\r
879 CurrentStringStart = 0\r
880 StringOffset = 0\r
881 BreakLineDict = []\r
882 if len(String) <= MaxCharLength:\r
883 while (StringOffset < StringLength):\r
884 if StringOffset >= 1:\r
885 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
886 BreakLineDict.append (StringOffset + 1)\r
887 StringOffset += 1\r
888 if BreakLineDict != []:\r
889 for Each in BreakLineDict:\r
890 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
891 CurrentStringStart = Each\r
892 if StringLength - CurrentStringStart > 0:\r
893 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
894 else:\r
895 Multilines = " %s\n" % String\r
896 else:\r
897 NewLineStart = 0\r
898 NewLineCount = 0\r
899 FoundSpaceChar = False\r
900 while (StringOffset < StringLength):\r
901 if StringOffset >= 1:\r
902 if NewLineCount >= MaxCharLength - 1:\r
903 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
904 BreakLineDict.append (NewLineStart + NewLineCount)\r
905 NewLineStart = NewLineStart + NewLineCount\r
906 NewLineCount = 0\r
907 FoundSpaceChar = True\r
908 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
909 BreakLineDict.append (0)\r
910 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
911 BreakLineDict.append (StringOffset + 1)\r
912 NewLineStart = StringOffset + 1\r
913 NewLineCount = 0\r
914 StringOffset += 1\r
915 NewLineCount += 1\r
916 if BreakLineDict != []:\r
917 BreakLineDict.sort ()\r
918 for Each in BreakLineDict:\r
919 if Each > 0:\r
920 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
921 CurrentStringStart = Each\r
922 if StringLength - CurrentStringStart > 0:\r
923 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
924 return Multilines\r
925\r
926 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):\r
927 PosName = 28\r
928 PosComment = 30\r
929 NameLine=''\r
930 HelpLine=''\r
931 OptionLine=''\r
932\r
933 IsArray = False\r
934 if Length in [1,2,4,8]:\r
935 Type = "UINT%d" % (Length * 8)\r
cd3692b1
SY
936 if Name.startswith("UnusedUpdSpace") and Length != 1:\r
937 IsArray = True\r
938 Type = "UINT8"\r
cf1d4549
JY
939 else:\r
940 IsArray = True\r
941 Type = "UINT8"\r
942\r
943 if Item and Item['value'].startswith('{'):\r
944 Type = "UINT8"\r
945 IsArray = True\r
946\r
947 if Struct != '':\r
948 Type = Struct\r
949 if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
950 IsArray = True\r
951 Unit = int(Type[4:]) / 8\r
952 Length = Length / Unit\r
953 else:\r
954 IsArray = False\r
955\r
956 if IsArray:\r
957 Name = Name + '[%d]' % Length\r
958\r
959 if len(Type) < PosName:\r
960 Space1 = PosName - len(Type)\r
961 else:\r
962 Space1 = 1\r
963\r
964 if BsfName != '':\r
965 NameLine=" - %s\n" % BsfName\r
966 else:\r
967 NameLine="\n"\r
968\r
969 if Help != '':\r
970 HelpLine = self.ProcessMultilines (Help, 80)\r
971\r
972 if Option != '':\r
973 OptionLine = self.ProcessMultilines (Option, 80)\r
974\r
975 if Offset is None:\r
976 OffsetStr = '????'\r
977 else:\r
978 OffsetStr = '0x%04X' % Offset\r
979\r
980 return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)\r
981\r
982 def PostProcessBody (self, TextBody):\r
983 NewTextBody = []\r
984 OldTextBody = []\r
985 IncludeLine = False\r
986 StructName = ''\r
987 VariableName = ''\r
988 IsUpdHdrDefined = False\r
989 IsUpdHeader = False\r
990 for Line in TextBody:\r
991 SplitToLines = Line.splitlines()\r
992 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r
993 if MatchComment:\r
994 if MatchComment.group(1) == 'FSP_UPD_HEADER':\r
995 IsUpdHeader = True\r
996 else:\r
997 IsUpdHeader = False\r
998 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
999 CommentLine = " " + MatchComment.group(2) + "\n"\r
1000 NewTextBody.append("/**" + CommentLine + "**/\n")\r
1001 Line = Line[(len(SplitToLines[0]) + 1):]\r
1002\r
1003 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
1004 if Match:\r
1005 Line = Match.group(4)\r
1006 if Match.group(1) == 'FSP_UPD_HEADER':\r
1007 IsUpdHeader = True\r
1008 else:\r
1009 IsUpdHeader = False\r
1010\r
1011 if Match and Match.group(3) == 'START':\r
1012 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1013 NewTextBody.append ('typedef struct {\n')\r
1014 StructName = Match.group(1)\r
1015 VariableName = Match.group(2)\r
1016 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
1017 if MatchOffset:\r
1018 Offset = int(MatchOffset.group(1), 16)\r
1019 else:\r
1020 Offset = None\r
1021 Line\r
1022 IncludeLine = True\r
1023 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r
1024 if IncludeLine:\r
1025 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1026 NewTextBody.append (Line)\r
1027 else:\r
1028 OldTextBody.append (Line)\r
1029\r
62997d5e 1030 if Match and Match.group(3) == 'END':\r
cf1d4549
JY
1031 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
1032 print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))\r
1033 else:\r
1034 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1035 NewTextBody.append ('} %s;\n\n' % StructName)\r
1036 IsUpdHdrDefined = True\r
1037 IncludeLine = False\r
1038 NewTextBody.extend(OldTextBody)\r
1039 return NewTextBody\r
1040\r
737f812b
CC
1041 def WriteLinesWithoutTailingSpace (self, HeaderFd, Line):\r
1042 TxtBody2 = Line.splitlines(True)\r
1043 for Line2 in TxtBody2:\r
1044 Line2 = Line2.rstrip()\r
1045 Line2 += '\n'\r
1046 HeaderFd.write (Line2)\r
1047 return 0\r
cf1d4549
JY
1048 def CreateHeaderFile (self, InputHeaderFile):\r
1049 FvDir = self._FvDir\r
1050\r
1051 HeaderFileName = 'FspUpd.h'\r
1052 HeaderFile = os.path.join(FvDir, HeaderFileName)\r
1053\r
1054 # Check if header needs to be recreated\r
1055 ReCreate = False\r
1056\r
1057 TxtBody = []\r
1058 for Item in self._CfgItemList:\r
1059 if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
1060 Value = int(Item['value'], 16)\r
1061 Chars = []\r
1062 while Value != 0x0:\r
1063 Chars.append(chr(Value & 0xFF))\r
1064 Value = Value >> 8\r
1065 SignatureStr = ''.join(Chars)\r
1066 # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly\r
1067 if '_T' in SignatureStr[6:6+2]:\r
1068 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1069 elif '_M' in SignatureStr[6:6+2]:\r
1070 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1071 elif '_S' in SignatureStr[6:6+2]:\r
1072 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1073 TxtBody.append("\n")\r
1074\r
1075 for Region in ['UPD']:\r
1076 UpdOffsetTable = []\r
1077 UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS\r
1078 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r
1079 for Item in self._CfgItemList:\r
1080 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
1081 UpdOffsetTable.append (Item["offset"])\r
1082\r
1083 for UpdIdx in range(len(UpdOffsetTable)):\r
1084 CommentLine = ""\r
1085 for Item in self._CfgItemList:\r
1086 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r
1087 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r
1088 if MatchComment and MatchComment.group(1) == Region[0]:\r
1089 CommentLine = " " + MatchComment.group(2) + "\n"\r
1090 TxtBody.append("/**" + CommentLine + "**/\n")\r
1091 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r
1092 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r
1093 if Match:\r
1094 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r
1095 TxtBody.append("typedef struct {\n")\r
1096 NextOffset = 0\r
1097 SpaceIdx = 0\r
1098 Offset = 0\r
1099\r
1100 LastVisible = True\r
1101 ResvOffset = 0\r
1102 ResvIdx = 0\r
1103 LineBuffer = []\r
1104 InRange = False\r
1105 for Item in self._CfgItemList:\r
1106 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r
1107 InRange = True\r
1108 if InRange != True:\r
1109 continue\r
1110 if Item['cname'] == 'UpdTerminator':\r
1111 InRange = False\r
1112\r
1113 if Item['region'] != Region:\r
1114 continue\r
1115\r
1116 if Item["offset"] < UpdOffsetTable[UpdIdx]:\r
1117 continue\r
1118\r
1119 NextVisible = LastVisible\r
1120\r
1121 if LastVisible and (Item['header'] == 'OFF'):\r
1122 NextVisible = False\r
1123 ResvOffset = Item['offset']\r
1124 elif (not LastVisible) and Item['header'] == 'ON':\r
1125 NextVisible = True\r
1126 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
1127 ResvIdx = ResvIdx + 1\r
1128 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r
1129\r
1130 if Offset < Item["offset"]:\r
1131 if LastVisible:\r
1132 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
1133 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r
1134 SpaceIdx = SpaceIdx + 1\r
1135 Offset = Item["offset"]\r
1136\r
1137 LastVisible = NextVisible\r
1138\r
1139 Offset = Offset + Item["length"]\r
1140 if LastVisible:\r
1141 for Each in LineBuffer:\r
1142 TxtBody.append (Each)\r
1143 LineBuffer = []\r
1144 Comment = Item["comment"]\r
1145 Embed = Item["embed"].upper()\r
1146 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1147 if not Comment == '' and Embed.endswith(':START'):\r
1148 Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r
1149 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1150 else:\r
1151 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1152 else:\r
1153 if Embed == '':\r
62997d5e 1154 Marker = ''\r
cf1d4549
JY
1155 else:\r
1156 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1157 return 4\r
1158 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r
1159 TxtBody.append(Line)\r
1160 if Item['cname'] == 'UpdTerminator':\r
1161 break\r
1162 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r
62997d5e 1163\r
cf1d4549
JY
1164 # Handle the embedded data structure\r
1165 TxtBody = self.PostProcessBody (TxtBody)\r
1166\r
1167 HeaderTFileName = 'FsptUpd.h'\r
1168 HeaderMFileName = 'FspmUpd.h'\r
1169 HeaderSFileName = 'FspsUpd.h'\r
1170\r
1171 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION\r
1172 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
1173 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r
1174 ExcludedSpecificUpd = 'FSPM_ARCH_UPD'\r
1175\r
1176 if InputHeaderFile != '':\r
1177 if not os.path.exists(InputHeaderFile):\r
1178 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1179 return 6\r
1180\r
1181 InFd = open(InputHeaderFile, "r")\r
1182 IncLines = InFd.readlines()\r
1183 InFd.close()\r
1184\r
1185 for item in range(len(UpdRegionCheck)):\r
1186 if UpdRegionCheck[item] == 'FSPT':\r
1187 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r
1188 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r
1189 elif UpdRegionCheck[item] == 'FSPM':\r
1190 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r
1191 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r
1192 elif UpdRegionCheck[item] == 'FSPS':\r
1193 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r
1194 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r
1195 FileName = FileBase.replace(".", "_").upper()\r
1196 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1197 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1198 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1199 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r
cd3692b1 1200 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1201\r
1202 Export = False\r
1203 for Line in IncLines:\r
1204 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1205 if Match:\r
1206 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r
1207 Export = True\r
1208 continue\r
1209 else:\r
1210 Export = False\r
1211 continue\r
1212 if Export:\r
1213 HeaderFd.write(Line)\r
1214 HeaderFd.write("\n")\r
1215\r
1216 Index = 0\r
1217 StartIndex = 0\r
1218 EndIndex = 0\r
1219 StructStart = []\r
1220 StructStartWithComment = []\r
1221 StructEnd = []\r
1222 for Line in TxtBody:\r
1223 Index += 1\r
1224 Match = re.match("(typedef struct {)", Line)\r
1225 if Match:\r
1226 StartIndex = Index - 1\r
1227 Match = re.match("}\s([_A-Z0-9]+);", Line)\r
1228 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):\r
1229 EndIndex = Index\r
1230 StructStart.append(StartIndex)\r
1231 StructEnd.append(EndIndex)\r
1232 Index = 0\r
1233 for Line in TxtBody:\r
1234 Index += 1\r
1235 for Item in range(len(StructStart)):\r
1236 if Index == StructStart[Item]:\r
1237 Match = re.match("^(/\*\*\s*)", Line)\r
1238 if Match:\r
1239 StructStartWithComment.append(StructStart[Item])\r
1240 else:\r
1241 StructStartWithComment.append(StructStart[Item] + 1)\r
1242 Index = 0\r
1243 for Line in TxtBody:\r
1244 Index += 1\r
1245 for Item in range(len(StructStart)):\r
1246 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
737f812b 1247 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r
cd3692b1 1248 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1249 HeaderFd.write("#endif\n")\r
1250 HeaderFd.close()\r
1251\r
1252 HeaderFd = open(HeaderFile, "w")\r
1253 FileBase = os.path.basename(HeaderFile)\r
1254 FileName = FileBase.replace(".", "_").upper()\r
1255 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1256 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1257 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1258 HeaderFd.write("#include <FspEas.h>\n\n")\r
cd3692b1 1259 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1260\r
1261 for item in range(len(UpdRegionCheck)):\r
1262 Index = 0\r
1263 StartIndex = 0\r
1264 EndIndex = 0\r
1265 StructStart = []\r
1266 StructStartWithComment = []\r
1267 StructEnd = []\r
1268 for Line in TxtBody:\r
1269 Index += 1\r
1270 Match = re.match("(typedef struct {)", Line)\r
1271 if Match:\r
1272 StartIndex = Index - 1\r
1273 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r
1274 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r
1275 StructStart.append(Index - 1)\r
1276 StructEnd.append(Index)\r
1277 Index = 0\r
1278 for Line in TxtBody:\r
1279 Index += 1\r
1280 for Item in range(len(StructStart)):\r
1281 if Index == StructStart[Item]:\r
1282 Match = re.match("^(/\*\*\s*)", Line)\r
1283 if Match:\r
1284 StructStartWithComment.append(StructStart[Item])\r
1285 else:\r
1286 StructStartWithComment.append(StructStart[Item] + 1)\r
1287 Index = 0\r
1288 for Line in TxtBody:\r
1289 Index += 1\r
1290 for Item in range(len(StructStart)):\r
1291 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
737f812b 1292 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r
cd3692b1 1293 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1294 HeaderFd.write("#endif\n")\r
1295 HeaderFd.close()\r
1296\r
1297 return 0\r
1298\r
1299 def WriteBsfStruct (self, BsfFd, Item):\r
ba8ea427 1300 LogExpr = CLogicalExpression()\r
cf1d4549
JY
1301 if Item['type'] == "None":\r
1302 Space = "gPlatformFspPkgTokenSpaceGuid"\r
1303 else:\r
1304 Space = Item['space']\r
1305 Line = " $%s_%s" % (Space, Item['cname'])\r
1306 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1307 if Match:\r
1308 DefaultValue = Match.group(1).strip()\r
1309 else:\r
1310 DefaultValue = Item['value'].strip()\r
62997d5e
MM
1311 if 'bitlength' in Item:\r
1312 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r
1313 else:\r
1314 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
cf1d4549
JY
1315 TmpList = []\r
1316 if Item['type'] == "Combo":\r
1317 if not Item['option'] in self._BuidinOption:\r
1318 OptList = Item['option'].split(',')\r
1319 for Option in OptList:\r
1320 Option = Option.strip()\r
1321 (OpVal, OpStr) = Option.split(':')\r
ba8ea427
TRM
1322 test = LogExpr.getNumber (OpVal)\r
1323 if test is None:\r
1324 raise Exception("Selection Index '%s' is not a number" % OpVal)\r
cf1d4549
JY
1325 TmpList.append((OpVal, OpStr))\r
1326 return TmpList\r
1327\r
1328 def WriteBsfOption (self, BsfFd, Item):\r
1329 PcdName = Item['space'] + '_' + Item['cname']\r
1330 WriteHelp = 0\r
1331 if Item['type'] == "Combo":\r
1332 if Item['option'] in self._BuidinOption:\r
1333 Options = self._BuidinOption[Item['option']]\r
1334 else:\r
1335 Options = PcdName\r
62997d5e 1336 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r
cf1d4549
JY
1337 WriteHelp = 1\r
1338 elif Item['type'].startswith("EditNum"):\r
1339 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
1340 if Match:\r
62997d5e 1341 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r
cf1d4549
JY
1342 WriteHelp = 2\r
1343 elif Item['type'].startswith("EditText"):\r
62997d5e 1344 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1345 WriteHelp = 1\r
1346 elif Item['type'] == "Table":\r
1347 Columns = Item['option'].split(',')\r
1348 if len(Columns) != 0:\r
62997d5e 1349 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1350 for Col in Columns:\r
1351 Fmt = Col.split(':')\r
1352 if len(Fmt) != 3:\r
1353 raise Exception("Column format '%s' is invalid !" % Fmt)\r
1354 try:\r
1355 Dtype = int(Fmt[1].strip())\r
1356 except:\r
1357 raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1358 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1359 BsfFd.write(',\n')\r
1360 WriteHelp = 1\r
62997d5e 1361\r
cf1d4549
JY
1362 if WriteHelp > 0:\r
1363 HelpLines = Item['help'].split('\\n\\r')\r
1364 FirstLine = True\r
1365 for HelpLine in HelpLines:\r
1366 if FirstLine:\r
1367 FirstLine = False\r
62997d5e 1368 BsfFd.write(' Help "%s"\n' % (HelpLine))\r
cf1d4549 1369 else:\r
62997d5e 1370 BsfFd.write(' "%s"\n' % (HelpLine))\r
cf1d4549 1371 if WriteHelp == 2:\r
62997d5e 1372 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r
cf1d4549
JY
1373\r
1374 def GenerateBsfFile (self, BsfFile):\r
1375\r
1376 if BsfFile == '':\r
1377 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1378 return 1\r
1379\r
1380 Error = 0\r
1381 OptionDict = {}\r
1382 BsfFd = open(BsfFile, "w")\r
1383 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
62997d5e 1384 BsfFd.write("%s\n" % self._GlobalDataDef)\r
cf1d4549
JY
1385 BsfFd.write("StructDef\n")\r
1386 NextOffset = -1\r
1387 for Item in self._CfgItemList:\r
1388 if Item['find'] != '':\r
1389 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
1390 NextOffset = Item['offset'] + Item['length']\r
1391 if Item['name'] != '':\r
1392 if NextOffset != Item['offset']:\r
1393 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1394 if len(Item['subreg']) > 0:\r
1395 NextOffset = Item['offset']\r
62997d5e 1396 BitsOffset = NextOffset * 8\r
cf1d4549 1397 for SubItem in Item['subreg']:\r
62997d5e 1398 BitsOffset += SubItem['bitlength']\r
cf1d4549 1399 if SubItem['name'] == '':\r
62997d5e
MM
1400 if 'bitlength' in SubItem:\r
1401 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))\r
1402 else:\r
1403 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
cf1d4549
JY
1404 else:\r
1405 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1406 if len(Options) > 0:\r
1407 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
62997d5e
MM
1408\r
1409 NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
1410 if NextBitsOffset > BitsOffset:\r
1411 BitsGap = NextBitsOffset - BitsOffset\r
1412 BitsRemain = BitsGap % 8\r
1413 if BitsRemain:\r
1414 BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
1415 BitsGap -= BitsRemain\r
1416 BytesRemain = BitsGap / 8\r
1417 if BytesRemain:\r
1418 BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r
1419 NextOffset = Item['offset'] + Item['length']\r
cf1d4549
JY
1420 else:\r
1421 NextOffset = Item['offset'] + Item['length']\r
1422 Options = self.WriteBsfStruct(BsfFd, Item)\r
1423 if len(Options) > 0:\r
1424 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1425 BsfFd.write("\nEndStruct\n\n")\r
1426\r
62997d5e 1427 BsfFd.write("%s" % self._BuidinOptionTxt)\r
cf1d4549
JY
1428\r
1429 for Each in OptionDict:\r
62997d5e 1430 BsfFd.write("List &%s\n" % Each)\r
cf1d4549 1431 for Item in OptionDict[Each]:\r
62997d5e
MM
1432 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))\r
1433 BsfFd.write("EndList\n\n")\r
cf1d4549 1434\r
62997d5e
MM
1435 BsfFd.write("BeginInfoBlock\n")\r
1436 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r
1437 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r
1438 BsfFd.write("EndInfoBlock\n\n")\r
cf1d4549
JY
1439\r
1440 for Each in self._CfgPageDict:\r
62997d5e 1441 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r
cf1d4549
JY
1442 BsfItems = []\r
1443 for Item in self._CfgItemList:\r
1444 if Item['name'] != '':\r
1445 if Item['page'] != Each:\r
1446 continue\r
1447 if len(Item['subreg']) > 0:\r
1448 for SubItem in Item['subreg']:\r
1449 if SubItem['name'] != '':\r
1450 BsfItems.append(SubItem)\r
1451 else:\r
1452 BsfItems.append(Item)\r
1453\r
1454 BsfItems.sort(key=lambda x: x['order'])\r
1455\r
1456 for Item in BsfItems:\r
1457 self.WriteBsfOption (BsfFd, Item)\r
62997d5e 1458 BsfFd.write("EndPage\n\n")\r
cf1d4549
JY
1459\r
1460 BsfFd.close()\r
1461 return Error\r
1462\r
1463\r
1464def Usage():\r
62997d5e 1465 print "GenCfgOpt Version 0.52"\r
cf1d4549 1466 print "Usage:"\r
62997d5e
MM
1467 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]"\r
1468 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]"\r
1469 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r
cf1d4549
JY
1470\r
1471def Main():\r
1472 #\r
1473 # Parse the options and args\r
1474 #\r
1475 GenCfgOpt = CGenCfgOpt()\r
1476 argc = len(sys.argv)\r
1477 if argc < 4:\r
1478 Usage()\r
1479 return 1\r
1480 else:\r
1481 DscFile = sys.argv[2]\r
1482 if not os.path.exists(DscFile):\r
1483 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1484 return 2\r
cf1d4549
JY
1485\r
1486 OutFile = ''\r
1487 if argc > 4:\r
62997d5e 1488 if sys.argv[4][0] == '-':\r
cf1d4549
JY
1489 Start = 4\r
1490 else:\r
62997d5e 1491 OutFile = sys.argv[4]\r
cf1d4549 1492 Start = 5\r
e4408576
OBO
1493 if argc > Start:\r
1494 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
1495 print "ERROR: Macro parsing failed !"\r
1496 return 3\r
cf1d4549
JY
1497\r
1498 FvDir = sys.argv[3]\r
1499 if not os.path.exists(FvDir):\r
1500 os.makedirs(FvDir)\r
1501\r
62997d5e 1502 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
cf1d4549
JY
1503 print "ERROR: %s !" % GenCfgOpt.Error\r
1504 return 5\r
1505\r
1506 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1507 print "ERROR: %s !" % GenCfgOpt.Error\r
1508 return 7\r
1509\r
1510 if sys.argv[1] == "UPDTXT":\r
1511 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1512 if Ret != 0:\r
1513 # No change is detected\r
1514 if Ret == 256:\r
1515 print "INFO: %s !" % (GenCfgOpt.Error)\r
1516 else :\r
1517 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1518 return Ret\r
1519 elif sys.argv[1] == "HEADER":\r
1520 if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
1521 print "ERROR: %s !" % GenCfgOpt.Error\r
1522 return 8\r
1523 elif sys.argv[1] == "GENBSF":\r
1524 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1525 print "ERROR: %s !" % GenCfgOpt.Error\r
1526 return 9\r
1527 else:\r
1528 if argc < 5:\r
1529 Usage()\r
1530 return 1\r
1531 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1532 Usage()\r
1533 return 1\r
1534 return 0\r
1535 return 0\r
1536\r
1537\r
1538if __name__ == '__main__':\r
1539 sys.exit(Main())\r