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