Handle extra module patchable PCD variable in Linux map.
[mirror_edk2.git] / IntelFspPkg / Tools / GenCfgOpt.py
CommitLineData
c8ec22a2
JY
1## @ GenCfgOpt.py\r
2#\r
d5fb1edf 3# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
c8ec22a2
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
b2344187
JY
91def UpdateMemSiUpdInitOffsetValue (DscFile):\r
92 DscFd = open(DscFile, "r")\r
93 DscLines = DscFd.readlines()\r
94 DscFd.close()\r
95\r
96 DscContent = []\r
97 MemUpdInitOffset = 0\r
98 SiUpdInitOffset = 0\r
99 MemUpdInitOffsetValue = 0\r
100 SiUpdInitOffsetValue = 0\r
101\r
102 while len(DscLines):\r
103 DscLine = DscLines.pop(0)\r
104 DscContent.append(DscLine)\r
105 DscLine = DscLine.strip()\r
106 Match = re.match("^([_a-zA-Z0-9]+).(MemoryInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r
107 if Match:\r
108 MemUpdInitOffsetValue = int(Match.group(5), 0)\r
109 Match = re.match("^\s*([_a-zA-Z0-9]+).(SiliconInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r
110 if Match:\r
111 SiUpdInitOffsetValue = int(Match.group(5), 0)\r
112 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*(0x244450554D454D24)",DscLine)\r
113 if Match:\r
114 MemUpdInitOffset = int(Match.group(3), 0)\r
115 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*(0x244450555F495324)",DscLine)\r
116 if Match:\r
117 SiUpdInitOffset = int(Match.group(3), 0)\r
118\r
119 if MemUpdInitOffsetValue != MemUpdInitOffset or SiUpdInitOffsetValue != SiUpdInitOffset:\r
120 MemUpdInitOffsetStr = "0x%08X" % MemUpdInitOffset\r
121 SiUpdInitOffsetStr = "0x%08X" % SiUpdInitOffset\r
122 DscFd = open(DscFile,"w")\r
123 for DscLine in DscContent:\r
124 Match = re.match("^\s*([_a-zA-Z0-9]+).(MemoryInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r
125 if Match:\r
126 DscLine = re.sub(r'(?:[^\s]+\s*$)', MemUpdInitOffsetStr + '\n', DscLine)\r
127 Match = re.match("^\s*([_a-zA-Z0-9]+).(SiliconInitUpdOffset)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)\r
128 if Match:\r
129 DscLine = re.sub(r'(?:[^\s]+\s*$)', SiUpdInitOffsetStr + '\n', line)\r
130 DscFd.writelines(DscLine)\r
131 DscFd.close()\r
132\r
4c9ed23e
MM
133class CLogicalExpression:\r
134 def __init__(self):\r
135 self.index = 0\r
136 self.string = ''\r
137\r
138 def errExit(self, err = ''):\r
139 print "ERROR: Express parsing for:"\r
140 print " %s" % self.string\r
141 print " %s^" % (' ' * self.index)\r
142 if err:\r
143 print "INFO : %s" % err\r
144 raise SystemExit\r
145\r
146 def getNonNumber (self, n1, n2):\r
147 if not n1.isdigit():\r
148 return n1\r
149 if not n2.isdigit():\r
150 return n2\r
151 return None\r
152\r
153 def getCurr(self, lens = 1):\r
154 try:\r
155 if lens == -1:\r
156 return self.string[self.index :]\r
157 else:\r
158 if self.index + lens > len(self.string):\r
159 lens = len(self.string) - self.index\r
160 return self.string[self.index : self.index + lens]\r
161 except Exception:\r
162 return ''\r
163\r
164 def isLast(self):\r
165 return self.index == len(self.string)\r
166\r
167 def moveNext(self, len = 1):\r
168 self.index += len\r
169\r
170 def skipSpace(self):\r
171 while not self.isLast():\r
172 if self.getCurr() in ' \t':\r
173 self.moveNext()\r
174 else:\r
175 return\r
176\r
177 def normNumber (self, val):\r
178 return True if val else False\r
179\r
180 def getNumber(self, var):\r
181 var = var.strip()\r
182 if re.match('^0x[a-fA-F0-9]+$', var):\r
183 value = int(var, 16)\r
184 elif re.match('^[+-]?\d+$', var):\r
185 value = int(var, 10)\r
186 else:\r
187 value = None\r
188 return value\r
189\r
190 def parseValue(self):\r
191 self.skipSpace()\r
192 var = ''\r
193 while not self.isLast():\r
194 char = self.getCurr()\r
195 if re.match('^[\w.]', char):\r
196 var += char\r
197 self.moveNext()\r
198 else:\r
199 break\r
200 val = self.getNumber(var)\r
201 if val is None:\r
202 value = var\r
203 else:\r
204 value = "%d" % val\r
205 return value\r
206\r
207 def parseSingleOp(self):\r
208 self.skipSpace()\r
209 if re.match('^NOT\W', self.getCurr(-1)):\r
210 self.moveNext(3)\r
211 op = self.parseBrace()\r
212 val = self.getNumber (op)\r
213 if val is None:\r
214 self.errExit ("'%s' is not a number" % op)\r
215 return "%d" % (not self.normNumber(int(op)))\r
216 else:\r
217 return self.parseValue()\r
218\r
219 def parseBrace(self):\r
220 self.skipSpace()\r
221 char = self.getCurr()\r
222 if char == '(':\r
223 self.moveNext()\r
224 value = self.parseExpr()\r
225 self.skipSpace()\r
226 if self.getCurr() != ')':\r
227 self.errExit ("Expecting closing brace or operator")\r
228 self.moveNext()\r
229 return value\r
230 else:\r
231 value = self.parseSingleOp()\r
232 return value\r
233\r
234 def parseCompare(self):\r
235 value = self.parseBrace()\r
236 while True:\r
237 self.skipSpace()\r
238 char = self.getCurr()\r
239 if char in ['<', '>']:\r
240 self.moveNext()\r
241 next = self.getCurr()\r
242 if next == '=':\r
243 op = char + next\r
244 self.moveNext()\r
245 else:\r
246 op = char\r
247 result = self.parseBrace()\r
248 test = self.getNonNumber(result, value)\r
249 if test is None:\r
250 value = "%d" % self.normNumber(eval (value + op + result))\r
251 else:\r
252 self.errExit ("'%s' is not a valid number for comparision" % test)\r
253 elif char in ['=', '!']:\r
254 op = self.getCurr(2)\r
255 if op in ['==', '!=']:\r
256 self.moveNext(2)\r
257 result = self.parseBrace()\r
258 test = self.getNonNumber(result, value)\r
259 if test is None:\r
260 value = "%d" % self.normNumber((eval (value + op + result)))\r
261 else:\r
262 value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))\r
263 else:\r
264 break\r
265 else:\r
266 break\r
267 return value\r
268\r
269 def parseAnd(self):\r
270 value = self.parseCompare()\r
271 while True:\r
272 self.skipSpace()\r
273 if re.match('^AND\W', self.getCurr(-1)):\r
274 self.moveNext(3)\r
275 result = self.parseCompare()\r
276 test = self.getNonNumber(result, value)\r
277 if test is None:\r
278 value = "%d" % self.normNumber(int(value) & int(result))\r
279 else:\r
280 self.errExit ("'%s' is not a valid op number for AND" % test)\r
281 else:\r
282 break\r
283 return value\r
284\r
285 def parseOrXor(self):\r
286 value = self.parseAnd()\r
287 op = None\r
288 while True:\r
289 self.skipSpace()\r
290 op = None\r
291 if re.match('^XOR\W', self.getCurr(-1)):\r
292 self.moveNext(3)\r
293 op = '^'\r
294 elif re.match('^OR\W', self.getCurr(-1)):\r
295 self.moveNext(2)\r
296 op = '|'\r
297 else:\r
298 break\r
299 if op:\r
300 result = self.parseAnd()\r
301 test = self.getNonNumber(result, value)\r
302 if test is None:\r
303 value = "%d" % self.normNumber(eval (value + op + result))\r
304 else:\r
305 self.errExit ("'%s' is not a valid op number for XOR/OR" % test)\r
306 return value\r
307\r
308 def parseExpr(self):\r
309 return self.parseOrXor()\r
310\r
311 def getResult(self):\r
312 value = self.parseExpr()\r
313 self.skipSpace()\r
314 if not self.isLast():\r
315 self.errExit ("Unexpected character found '%s'" % self.getCurr())\r
316 test = self.getNumber(value)\r
317 if test is None:\r
318 self.errExit ("Result '%s' is not a number" % value)\r
319 return int(value)\r
320\r
321 def evaluateExpress (self, Expr):\r
322 self.index = 0\r
323 self.string = Expr\r
324 if self.getResult():\r
325 Result = True\r
326 else:\r
327 Result = False\r
328 return Result\r
329\r
c8ec22a2
JY
330class CGenCfgOpt:\r
331 def __init__(self):\r
4c9ed23e 332 self.Debug = False\r
c8ec22a2
JY
333 self.Error = ''\r
334\r
335 self._GlobalDataDef = """\r
336GlobalDataDef\r
337 SKUID = 0, "DEFAULT"\r
338EndGlobalData\r
339\r
340"""\r
341 self._BuidinOptionTxt = """\r
342List &EN_DIS\r
343 Selection 0x1 , "Enabled"\r
344 Selection 0x0 , "Disabled"\r
345EndList\r
346\r
347"""\r
348\r
349 self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
8e5015c2 350 self._HdrKeyList = ['HEADER','STRUCT', 'EMBED']\r
c8ec22a2
JY
351 self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}\r
352\r
353 self._MacroDict = {}\r
354 self._CfgBlkDict = {}\r
355 self._CfgPageDict = {}\r
356 self._CfgItemList = []\r
357 self._DscFile = ''\r
358 self._FvDir = ''\r
359 self._MapVer = 0\r
360\r
361 def ParseMacros (self, MacroDefStr):\r
362 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
363 self._MacroDict = {}\r
364 IsExpression = False\r
365 for Macro in MacroDefStr:\r
366 if Macro.startswith('-D'):\r
367 IsExpression = True\r
368 if len(Macro) > 2:\r
369 Macro = Macro[2:]\r
370 else :\r
371 continue\r
372 if IsExpression:\r
373 IsExpression = False\r
374 Match = re.match("(\w+)=(.+)", Macro)\r
375 if Match:\r
376 self._MacroDict[Match.group(1)] = Match.group(2)\r
377 else:\r
378 Match = re.match("(\w+)", Macro)\r
379 if Match:\r
380 self._MacroDict[Match.group(1)] = ''\r
381 if len(self._MacroDict) == 0:\r
c8ec22a2
JY
382 Error = 1\r
383 else:\r
384 Error = 0\r
4c9ed23e
MM
385 if self.Debug:\r
386 print "INFO : Macro dictionary:"\r
387 for Each in self._MacroDict:\r
388 print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each])\r
c8ec22a2
JY
389 return Error\r
390\r
4c9ed23e
MM
391 def EvaulateIfdef (self, Macro):\r
392 Result = Macro in self._MacroDict\r
393 if self.Debug:\r
394 print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result)\r
395 return Result\r
396\r
397 def ExpandMacros (self, Input):\r
398 Line = Input\r
399 Match = re.findall("\$\(\w+\)", Input)\r
400 if Match:\r
401 for Each in Match:\r
402 Variable = Each[2:-1]\r
403 if Variable in self._MacroDict:\r
404 Line = Line.replace(Each, self._MacroDict[Variable])\r
405 else:\r
406 if self.Debug:\r
407 print "WARN : %s is not defined" % Each\r
408 Line = Line.replace(Each, Each[2:-1])\r
409 return Line\r
410\r
411 def EvaluateExpress (self, Expr):\r
412 ExpExpr = self.ExpandMacros(Expr)\r
413 LogExpr = CLogicalExpression()\r
414 Result = LogExpr.evaluateExpress (ExpExpr)\r
415 if self.Debug:\r
416 print "INFO : Eval Express [%s] : %s" % (Expr, Result)\r
417 return Result\r
418\r
419 def FormatListValue(self, ConfigDict):\r
420 Struct = ConfigDict['struct']\r
421 if Struct not in ['UINT8','UINT16','UINT32','UINT64']:\r
422 return\r
423\r
424 dataarray = []\r
425 binlist = ConfigDict['value'][1:-1].split(',')\r
426 for each in binlist:\r
427 each = each.strip()\r
428 if each.startswith('0x'):\r
429 value = int(each, 16)\r
430 else:\r
431 value = int(each)\r
432 dataarray.append(value)\r
433\r
434 unit = int(Struct[4:]) / 8\r
435 if int(ConfigDict['length']) != unit * len(dataarray):\r
436 raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])\r
437\r
438 bytearray = []\r
439 for each in dataarray:\r
440 value = each\r
441 for loop in xrange(unit):\r
442 bytearray.append("0x%02X" % (value & 0xFF))\r
443 value = value >> 8\r
444 newvalue = '{' + ','.join(bytearray) + '}'\r
445 ConfigDict['value'] = newvalue\r
446 return ""\r
c8ec22a2
JY
447\r
448 def ParseDscFile (self, DscFile, FvDir):\r
449 self._CfgItemList = []\r
450 self._CfgPageDict = {}\r
451 self._CfgBlkDict = {}\r
452 self._DscFile = DscFile\r
453 self._FvDir = FvDir\r
454\r
455 IsDefSect = False\r
456 IsUpdSect = False\r
457 IsVpdSect = False\r
458 Found = False\r
459\r
4c9ed23e 460 IfStack = []\r
c8ec22a2
JY
461 ElifStack = []\r
462 Error = 0\r
4c9ed23e 463 ConfigDict = {}\r
c8ec22a2
JY
464\r
465 DscFd = open(DscFile, "r")\r
466 DscLines = DscFd.readlines()\r
467 DscFd.close()\r
468\r
4c9ed23e 469 while len(DscLines):\r
8e5015c2 470 DscLine = DscLines.pop(0).strip()\r
4c9ed23e
MM
471 Handle = False\r
472 Match = re.match("^\[(.+)\]", DscLine)\r
c8ec22a2
JY
473 if Match is not None:\r
474 if Match.group(1).lower() == "Defines".lower():\r
475 IsDefSect = True\r
476 IsVpdSect = False\r
477 IsUpdSect = False\r
478 elif Match.group(1).lower() == "PcdsDynamicVpd".lower():\r
479 ConfigDict = {}\r
480 ConfigDict['header'] = 'ON'\r
481 ConfigDict['region'] = 'VPD'\r
482 ConfigDict['order'] = -1\r
483 ConfigDict['page'] = ''\r
484 ConfigDict['name'] = ''\r
485 ConfigDict['find'] = ''\r
486 ConfigDict['struct'] = ''\r
8e5015c2 487 ConfigDict['embed'] = ''\r
c8ec22a2
JY
488 ConfigDict['subreg'] = []\r
489 IsDefSect = False\r
490 IsVpdSect = True\r
491 IsUpdSect = False\r
492 elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
493 ConfigDict = {}\r
494 ConfigDict['header'] = 'ON'\r
495 ConfigDict['region'] = 'UPD'\r
496 ConfigDict['order'] = -1\r
497 ConfigDict['page'] = ''\r
498 ConfigDict['name'] = ''\r
499 ConfigDict['find'] = ''\r
500 ConfigDict['struct'] = ''\r
8e5015c2 501 ConfigDict['embed'] = ''\r
c8ec22a2
JY
502 ConfigDict['subreg'] = []\r
503 IsDefSect = False\r
504 IsUpdSect = True\r
505 IsVpdSect = False\r
506 Found = True\r
507 else:\r
508 IsDefSect = False\r
509 IsUpdSect = False\r
510 IsVpdSect = False\r
511 else:\r
512 if IsDefSect or IsUpdSect or IsVpdSect:\r
4c9ed23e
MM
513 if re.match("^!else($|\s+#.+)", DscLine):\r
514 if IfStack:\r
515 IfStack[-1] = not IfStack[-1]\r
516 else:\r
517 print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
518 raise SystemExit\r
519 elif re.match("^!endif($|\s+#.+)", DscLine):\r
520 if IfStack:\r
c8ec22a2 521 IfStack.pop()\r
4c9ed23e
MM
522 Level = ElifStack.pop()\r
523 if Level > 0:\r
524 del IfStack[-Level:]\r
525 else:\r
526 print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
527 raise SystemExit\r
c8ec22a2
JY
528 else:\r
529 Result = False\r
4c9ed23e
MM
530 Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)\r
531 if Match:\r
532 Result = self.EvaulateIfdef (Match.group(2))\r
533 if Match.group(1) == 'ifndef':\r
534 Result = not Result\r
c8ec22a2 535 IfStack.append(Result)\r
4c9ed23e 536 ElifStack.append(0)\r
c8ec22a2 537 else:\r
4c9ed23e
MM
538 Match = re.match("!(if|elseif)\s+(.+)", DscLine)\r
539 if Match:\r
540 Result = self.EvaluateExpress(Match.group(2))\r
c8ec22a2
JY
541 if Match.group(1) == "if":\r
542 ElifStack.append(0)\r
543 IfStack.append(Result)\r
544 else: #elseif\r
4c9ed23e
MM
545 if IfStack:\r
546 IfStack[-1] = not IfStack[-1]\r
547 IfStack.append(Result)\r
548 ElifStack[-1] = ElifStack[-1] + 1\r
549 else:\r
550 print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
551 raise SystemExit\r
c8ec22a2 552 else:\r
4c9ed23e
MM
553 if IfStack:\r
554 Handle = reduce(lambda x,y: x and y, IfStack)\r
c8ec22a2 555 else:\r
4c9ed23e
MM
556 Handle = True\r
557 if Handle:\r
558 Match = re.match("!include\s+(.+)", DscLine)\r
559 if Match:\r
560 IncludeFilePath = Match.group(1)\r
561 IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
562 try:\r
563 IncludeDsc = open(IncludeFilePath, "r")\r
564 except:\r
565 print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
566 raise SystemExit\r
567 NewDscLines = IncludeDsc.readlines()\r
568 IncludeDsc.close()\r
569 DscLines = NewDscLines + DscLines\r
570 else:\r
571 if DscLine.startswith('!'):\r
572 print("ERROR: Unrecoginized directive for line '%s'" % DscLine)\r
573 raise SystemExit\r
c8ec22a2
JY
574 if not Handle:\r
575 continue\r
576\r
577 if IsDefSect:\r
578 #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09\r
4c9ed23e 579 Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
c8ec22a2
JY
580 if Match:\r
581 self._MacroDict[Match.group(1)] = Match.group(2)\r
4c9ed23e
MM
582 if self.Debug:\r
583 print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))\r
c8ec22a2
JY
584 else:\r
585 Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine)\r
586 if Match:\r
587 Remaining = Match.group(2)\r
588 if Match.group(1) == 'BSF':\r
589 Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)\r
590 if Match:\r
591 # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}\r
592 PageList = Match.group(1).split(',')\r
593 for Page in PageList:\r
594 Page = Page.strip()\r
595 Match = re.match("(\w+):\"(.+)\"", Page)\r
596 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
597\r
598 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
599 if Match:\r
600 self._CfgBlkDict['name'] = Match.group(1)\r
601 self._CfgBlkDict['ver'] = Match.group(2)\r
602\r
603 for Key in self._BsfKeyList:\r
604 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
605 if Match:\r
8e5015c2 606 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
c8ec22a2
JY
607 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
608 else:\r
609 ConfigDict[Key.lower()] = Match.group(1)\r
610 else:\r
611 for Key in self._HdrKeyList:\r
612 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
613 if Match:\r
614 ConfigDict[Key.lower()] = Match.group(1)\r
615\r
616 # Check VPD/UPD\r
617 if IsUpdSect:\r
8e5015c2 618 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
c8ec22a2
JY
619 else:\r
620 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
621 if Match:\r
622 ConfigDict['space'] = Match.group(1)\r
623 ConfigDict['cname'] = Match.group(2)\r
624 ConfigDict['offset'] = int (Match.group(3), 16)\r
625 if ConfigDict['order'] == -1:\r
626 ConfigDict['order'] = ConfigDict['offset'] << 8\r
627 else:\r
628 (Major, Minor) = ConfigDict['order'].split('.')\r
629 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
630 if IsUpdSect:\r
631 Value = Match.group(5).strip()\r
632 if Match.group(4).startswith("0x"):\r
633 Length = int (Match.group(4), 16)\r
634 else :\r
635 Length = int (Match.group(4))\r
636 else:\r
637 Value = Match.group(4)\r
638 if Value is None:\r
639 Value = ''\r
640 Value = Value.strip()\r
641 if '|' in Value:\r
642 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
643 if Match:\r
644 Value = Match.group(1)\r
645 Length = -1\r
646\r
647 ConfigDict['length'] = Length\r
648 Match = re.match("\$\((\w+)\)", Value)\r
649 if Match:\r
650 if Match.group(1) in self._MacroDict:\r
651 Value = self._MacroDict[Match.group(1)]\r
4c9ed23e 652\r
c8ec22a2 653 ConfigDict['value'] = Value\r
4c9ed23e
MM
654 if (len(Value) > 0) and (Value[0] == '{'):\r
655 Value = self.FormatListValue(ConfigDict)\r
656\r
c8ec22a2
JY
657 if ConfigDict['name'] == '':\r
658 # Clear BSF specific items\r
8e5015c2 659 ConfigDict['bsfname'] = ''\r
c8ec22a2
JY
660 ConfigDict['help'] = ''\r
661 ConfigDict['type'] = ''\r
662 ConfigDict['option'] = ''\r
663\r
664 self._CfgItemList.append(ConfigDict.copy())\r
665 ConfigDict['name'] = ''\r
666 ConfigDict['find'] = ''\r
667 ConfigDict['struct'] = ''\r
8e5015c2 668 ConfigDict['embed'] = ''\r
c8ec22a2
JY
669 ConfigDict['order'] = -1\r
670 ConfigDict['subreg'] = []\r
671 else:\r
672 # It could be a virtual item as below\r
673 # !BSF FIELD:{1:SerialDebugPortAddress0}\r
674 Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine)\r
675 if Match:\r
676 SubCfgDict = ConfigDict\r
677 SubCfgDict['cname'] = Match.group(1)\r
678 SubCfgDict['length'] = int (Match.group(2))\r
679 if SubCfgDict['length'] > 0:\r
680 LastItem = self._CfgItemList[-1]\r
681 if len(LastItem['subreg']) == 0:\r
682 SubOffset = 0\r
683 else:\r
684 SubOffset += LastItem['subreg'][-1]['length']\r
685 SubCfgDict['offset'] = SubOffset\r
686 LastItem['subreg'].append (SubCfgDict.copy())\r
687 ConfigDict['name'] = ''\r
688 return Error\r
689\r
690 def UpdateSubRegionDefaultValue (self):\r
691 Error = 0\r
692 for Item in self._CfgItemList:\r
693 if len(Item['subreg']) == 0:\r
694 continue\r
695 bytearray = []\r
696 if Item['value'][0] == '{':\r
697 binlist = Item['value'][1:-1].split(',')\r
698 for each in binlist:\r
699 each = each.strip()\r
700 if each.startswith('0x'):\r
701 value = int(each, 16)\r
702 else:\r
703 value = int(each)\r
704 bytearray.append(value)\r
705 else:\r
706 if Item['value'].startswith('0x'):\r
707 value = int(Item['value'], 16)\r
708 else:\r
709 value = int(Item['value'])\r
710 idx = 0;\r
711 while idx < Item['length']:\r
712 bytearray.append(value & 0xFF)\r
713 value = value >> 8\r
714 idx = idx + 1\r
715 for SubItem in Item['subreg']:\r
716 if SubItem['length'] in (1,2,4,8):\r
717 valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]]\r
718 valuelist.reverse()\r
719 valuestr = "".join('%02X' % b for b in valuelist)\r
720 SubItem['value'] = '0x%s' % valuestr\r
721 else:\r
722 valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']])\r
723 SubItem['value'] = '{%s}' % valuestr\r
724 return Error\r
725\r
726 def UpdateVpdSizeField (self):\r
727 FvDir = self._FvDir;\r
728\r
729 if 'VPD_TOOL_GUID' not in self._MacroDict:\r
730 self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
731 return 1\r
732\r
733 VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map')\r
734 if not os.path.exists(VpdMapFile):\r
735 self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile\r
736 return 2\r
737\r
738 MapFd = open(VpdMapFile, "r")\r
739 MapLines = MapFd.readlines()\r
740 MapFd.close()\r
741\r
742 VpdDict = {}\r
743 PcdDict = {}\r
744 for MapLine in MapLines:\r
745 #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346\r
746 #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346\r
747 #gPlatformFspPkgTokenSpaceGuid.PcdTest | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05}\r
748 Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine)\r
749 if Match:\r
750 Space = Match.group(1)\r
751 Name = Match.group(2)\r
752 if (self._MapVer == 0) and (Match.group(3) != None):\r
753 self._MapVer = 1\r
754 Offset = int (Match.group(4), 16)\r
755 if Match.group(5).startswith("0x"):\r
756 Length = int (Match.group(5), 16)\r
757 else :\r
758 Length = int (Match.group(5))\r
759 PcdDict["len"] = Length\r
760 PcdDict["value"] = Match.group(6)\r
761 VpdDict[Space+'.'+Name] = dict(PcdDict)\r
762\r
763 for Item in self._CfgItemList:\r
764 if Item['value'] == '':\r
765 Item['value'] = VpdDict[Item['space']+'.'+Item['cname']]['value']\r
766 if Item['length'] == -1:\r
767 Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len']\r
768 if Item['struct'] != '':\r
769 Type = Item['struct'].strip()\r
770 if Type.endswith('*') and (Item['length'] != 4):\r
771 self.Error = "Struct pointer '%s' has invalid size" % Type\r
772 return 3\r
773\r
774 return 0\r
775\r
776 def CreateUpdTxtFile (self, UpdTxtFile):\r
777 FvDir = self._FvDir\r
778 if 'UPD_TOOL_GUID' not in self._MacroDict:\r
779 self.Error = "UPD_TOOL_GUID definition is missing in DSC file"\r
780 return 1\r
781\r
782 if UpdTxtFile == '':\r
783 UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.txt')\r
784\r
785 ReCreate = False\r
786 if not os.path.exists(UpdTxtFile):\r
787 ReCreate = True\r
788 else:\r
789 DscTime = os.path.getmtime(self._DscFile)\r
790 TxtTime = os.path.getmtime(UpdTxtFile)\r
791 if DscTime > TxtTime:\r
792 ReCreate = True\r
793\r
794 if not ReCreate:\r
795 # DSC has not been modified yet\r
796 # So don't have to re-generate other files\r
797 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
798 return 256\r
799\r
800 TxtFd = open(UpdTxtFile, "w")\r
801 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
802\r
803 NextOffset = 0\r
804 SpaceIdx = 0\r
805 if self._MapVer == 1:\r
806 Default = 'DEFAULT|'\r
807 else:\r
808 Default = ''\r
809 for Item in self._CfgItemList:\r
810 if Item['region'] != 'UPD':\r
811 continue\r
812 Offset = Item['offset']\r
813 if NextOffset < Offset:\r
814 # insert one line\r
815 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset))\r
816 SpaceIdx = SpaceIdx + 1\r
817 NextOffset = Offset + Item['length']\r
818 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value']))\r
819 TxtFd.close()\r
820 return 0\r
821\r
8e5015c2 822 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help):\r
c8ec22a2
JY
823 PosName = 28\r
824 PosComment = 30\r
8e5015c2 825 NameLine=''\r
61267952 826 HelpLine=''\r
c8ec22a2
JY
827\r
828 IsArray = False\r
4c9ed23e
MM
829 if Length in [1,2,4,8]:\r
830 Type = "UINT%d" % (Length * 8)\r
c8ec22a2 831 else:\r
4c9ed23e
MM
832 IsArray = True\r
833 Type = "UINT8"\r
834\r
8e5015c2 835 if Item and Item['value'].startswith('{'):\r
c8ec22a2
JY
836 Type = "UINT8"\r
837 IsArray = True\r
838\r
839 if Struct != '':\r
c8ec22a2 840 Type = Struct\r
4c9ed23e
MM
841 if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
842 IsArray = True\r
843 Unit = int(Type[4:]) / 8\r
844 Length = Length / Unit\r
845 else:\r
846 IsArray = False\r
c8ec22a2
JY
847\r
848 if IsArray:\r
849 Name = Name + '[%d]' % Length\r
850\r
851 if len(Type) < PosName:\r
852 Space1 = PosName - len(Type)\r
853 else:\r
854 Space1 = 1\r
855\r
8e5015c2
MM
856 if BsfName != '':\r
857 NameLine=" %s\n" % BsfName\r
c8ec22a2 858\r
8e5015c2
MM
859 if Help != '':\r
860 HelpLine=" %s\n" % Help\r
c8ec22a2 861\r
8e5015c2
MM
862 if Offset is None:\r
863 OffsetStr = '????'\r
864 else:\r
865 OffsetStr = '0x%04X' % Offset\r
866\r
867 return "/** Offset %s\n%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, Type, ' ' * Space1, Name,)\r
868\r
869 def PostProcessBody (self, TextBody):\r
870 NewTextBody = []\r
871 OldTextBody = []\r
872 IncludeLine = False\r
873 StructName = ''\r
874 VariableName = ''\r
875 for Line in TextBody:\r
876 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
877 if Match:\r
878 Line = Match.group(4)\r
879\r
880 if Match and Match.group(3) == 'START':\r
881 NewTextBody.append ('typedef struct {\n')\r
882 StructName = Match.group(1)\r
883 VariableName = Match.group(2)\r
884 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
885 if MatchOffset:\r
886 Offset = int(MatchOffset.group(1), 16)\r
887 else:\r
888 Offset = None\r
889 Line\r
890 IncludeLine = True\r
891 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', ''))\r
892 if IncludeLine:\r
893 NewTextBody.append (Line)\r
894 else:\r
895 OldTextBody.append (Line)\r
896\r
897 if Match and Match.group(3) == 'END': \r
898 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
899 print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))\r
900 else:\r
901 NewTextBody.append ('} %s;\n\n' % StructName)\r
902 IncludeLine = False\r
903 NewTextBody.extend(OldTextBody)\r
904 return NewTextBody\r
c8ec22a2
JY
905\r
906 def CreateHeaderFile (self, InputHeaderFile, IsInternal):\r
c8ec22a2
JY
907 FvDir = self._FvDir\r
908\r
909 if IsInternal:\r
9774fe6e 910 HeaderFile = os.path.join(FvDir, 'FspUpdVpdInternal.h')\r
c8ec22a2 911 else:\r
9774fe6e 912 HeaderFile = os.path.join(FvDir, 'FspUpdVpd.h')\r
c8ec22a2
JY
913\r
914 # Check if header needs to be recreated\r
915 ReCreate = False\r
916 if IsInternal:\r
917 if not os.path.exists(HeaderFile):\r
918 ReCreate = True\r
919 else:\r
920 DscTime = os.path.getmtime(self._DscFile)\r
921 HeadTime = os.path.getmtime(HeaderFile)\r
922 if not os.path.exists(InputHeaderFile):\r
923 InpTime = HeadTime\r
924 else:\r
925 InpTime = os.path.getmtime(InputHeaderFile)\r
926 if DscTime > HeadTime or InpTime > HeadTime:\r
927 ReCreate = True\r
928\r
929 if not ReCreate:\r
930 self.Error = "No DSC or input header file is changed, skip the header file generating"\r
931 return 256\r
932\r
8e5015c2 933 TxtBody = []\r
b2344187
JY
934 for Item in self._CfgItemList:\r
935 if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
936 Value = int(Item['value'], 16)\r
937 Chars = []\r
938 while Value != 0x0:\r
939 Chars.append(chr(Value & 0xFF))\r
940 Value = Value >> 8\r
941 SignatureStr = ''.join(Chars)\r
942 if int(Item['offset']) == 0:\r
943 TxtBody.append("#define FSP_UPD_SIGNATURE %s /* '%s' */\n" % (Item['value'], SignatureStr))\r
944 elif 'MEM' in SignatureStr:\r
945 TxtBody.append("#define FSP_MEMORY_INIT_UPD_SIGNATURE %s /* '%s' */\n" % (Item['value'], SignatureStr))\r
946 else:\r
947 TxtBody.append("#define FSP_SILICON_INIT_UPD_SIGNATURE %s /* '%s' */\n" % (Item['value'], SignatureStr))\r
948 TxtBody.append("\n")\r
949\r
c8ec22a2
JY
950 for Region in ['UPD', 'VPD']:\r
951\r
952 # Write PcdVpdRegionSign and PcdImageRevision\r
953 if Region[0] == 'V':\r
954 if 'VPD_TOOL_GUID' not in self._MacroDict:\r
955 self.Error = "VPD_TOOL_GUID definition is missing in DSC file"\r
8e5015c2 956 return 1\r
c8ec22a2
JY
957\r
958 BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin")\r
959 if not os.path.exists(BinFile):\r
960 self.Error = "VPD binary file '%s' does not exist" % BinFile\r
8e5015c2 961 return 2\r
c8ec22a2
JY
962\r
963 BinFd = open(BinFile, "rb")\r
964 IdStr = BinFd.read(0x08)\r
63c05743
JY
965 ImageId = struct.unpack('<Q', IdStr)\r
966 ImageRev = struct.unpack('<I', BinFd.read(0x04))\r
c8ec22a2
JY
967 BinFd.close()\r
968\r
8e5015c2
MM
969 TxtBody.append("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (ImageId[0], IdStr))\r
970 TxtBody.append("#define FSP_IMAGE_REV 0x%08X \n\n" % ImageRev[0])\r
c8ec22a2 971\r
8e5015c2 972 TxtBody.append("typedef struct _" + Region[0] + "PD_DATA_REGION {\n")\r
c8ec22a2
JY
973 NextOffset = 0\r
974 SpaceIdx = 0\r
975 Offset = 0\r
976\r
977 LastVisible = True\r
978 ResvOffset = 0\r
979 ResvIdx = 0\r
980 LineBuffer = []\r
981 for Item in self._CfgItemList:\r
982 if Item['region'] != Region:\r
983 continue\r
984\r
985 NextVisible = LastVisible\r
986 if not IsInternal:\r
987 if LastVisible and (Item['header'] == 'OFF'):\r
988 NextVisible = False\r
989 ResvOffset = Item['offset']\r
990 elif (not LastVisible) and Item['header'] == 'ON':\r
991 NextVisible = True\r
992 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
993 ResvIdx = ResvIdx + 1\r
8e5015c2 994 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', ''))\r
c8ec22a2
JY
995\r
996 if Offset < Item["offset"]:\r
997 if IsInternal or LastVisible:\r
998 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
8e5015c2 999 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', ''))\r
c8ec22a2
JY
1000 SpaceIdx = SpaceIdx + 1\r
1001 Offset = Item["offset"]\r
1002\r
1003 if Offset != Item["offset"]:\r
8e5015c2
MM
1004 self.Error = "Unsorted offset 0x%04X\n" % Item["offset"]\r
1005 return 3 \r
c8ec22a2
JY
1006\r
1007 LastVisible = NextVisible\r
1008\r
1009 Offset = Offset + Item["length"]\r
1010 if IsInternal or LastVisible:\r
1011 for Each in LineBuffer:\r
8e5015c2 1012 TxtBody.append (Each)\r
c8ec22a2 1013 LineBuffer = []\r
8e5015c2
MM
1014 Embed = Item["embed"].upper()\r
1015 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1016 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1017 else:\r
1018 if Embed == '':\r
1019 Marker = '';\r
1020 else:\r
1021 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1022 return 4\r
1023 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'])\r
1024 TxtBody.append(Line)\r
1025 \r
1026 TxtBody.append("} " + Region[0] + "PD_DATA_REGION;\n\n")\r
1027 \r
1028 # Handle the embedded data structure\r
1029 TxtBody = self.PostProcessBody (TxtBody)\r
1030\r
1031 HeaderFd = open(HeaderFile, "w")\r
1032 FileBase = os.path.basename(HeaderFile)\r
1033 FileName = FileBase.replace(".", "_").upper()\r
1034 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1035 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1036 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1037 HeaderFd.write("#pragma pack(1)\n\n")\r
c8ec22a2 1038\r
8e5015c2
MM
1039 if InputHeaderFile != '':\r
1040 if not os.path.exists(InputHeaderFile):\r
1041 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1042 return 6\r
1043\r
1044 InFd = open(InputHeaderFile, "r")\r
1045 IncLines = InFd.readlines()\r
1046 InFd.close()\r
1047\r
1048 Export = False\r
1049 for Line in IncLines:\r
1050 Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1051 if Match:\r
1052 if Match.group(1) == "BEGIN":\r
1053 Export = True\r
1054 continue\r
1055 else:\r
1056 Export = False\r
1057 continue\r
1058 if Export:\r
1059 HeaderFd.write(Line)\r
1060 HeaderFd.write("\n\n")\r
1061 \r
1062 for Line in TxtBody:\r
1063 HeaderFd.write (Line)\r
c8ec22a2
JY
1064 HeaderFd.write("#pragma pack()\n\n")\r
1065 HeaderFd.write("#endif\n")\r
1066 HeaderFd.close()\r
1067\r
8e5015c2 1068 return 0\r
c8ec22a2
JY
1069\r
1070 def WriteBsfStruct (self, BsfFd, Item):\r
1071 if Item['type'] == "None":\r
1072 Space = "gPlatformFspPkgTokenSpaceGuid"\r
1073 else:\r
1074 Space = Item['space']\r
1075 Line = " $%s_%s" % (Space, Item['cname'])\r
1076 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1077 if Match:\r
1078 DefaultValue = Match.group(1).strip()\r
1079 else:\r
1080 DefaultValue = Item['value'].strip()\r
1081 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
1082 TmpList = []\r
1083 if Item['type'] == "Combo":\r
1084 if not Item['option'] in self._BuidinOption:\r
1085 OptList = Item['option'].split(',')\r
1086 for Option in OptList:\r
1087 Option = Option.strip()\r
1088 (OpVal, OpStr) = Option.split(':')\r
1089 TmpList.append((OpVal, OpStr))\r
1090 return TmpList\r
1091\r
1092 def WriteBsfOption (self, BsfFd, Item):\r
1093 PcdName = Item['space'] + '_' + Item['cname']\r
1094 WriteHelp = 0\r
1095 if Item['type'] == "Combo":\r
1096 if Item['option'] in self._BuidinOption:\r
1097 Options = self._BuidinOption[Item['option']]\r
1098 else:\r
1099 Options = PcdName\r
1100 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options));\r
1101 WriteHelp = 1\r
1102 elif Item['type'].startswith("EditNum"):\r
1103 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
1104 if Match:\r
1105 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)));\r
1106 WriteHelp = 2\r
1107 elif Item['type'].startswith("EditText"):\r
1108 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']));\r
1109 WriteHelp = 1\r
8e5015c2
MM
1110 elif Item['type'] == "Table":\r
1111 Columns = Item['option'].split(',')\r
1112 if len(Columns) != 0:\r
1113 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']));\r
1114 for Col in Columns:\r
1115 Fmt = Col.split(':')\r
1116 if len(Fmt) != 3:\r
1117 raise Exception("Column format '%s' is invalid !" % Fmt)\r
1118 try:\r
1119 Dtype = int(Fmt[1].strip())\r
1120 except:\r
1121 raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1122 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1123 BsfFd.write(',\n')\r
1124 WriteHelp = 1\r
1125 \r
c8ec22a2
JY
1126 if WriteHelp > 0:\r
1127 HelpLines = Item['help'].split('\\n\\r')\r
1128 FirstLine = True\r
1129 for HelpLine in HelpLines:\r
1130 if FirstLine:\r
1131 FirstLine = False\r
1132 BsfFd.write(' Help "%s"\n' % (HelpLine));\r
1133 else:\r
1134 BsfFd.write(' "%s"\n' % (HelpLine));\r
1135 if WriteHelp == 2:\r
1136 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)));\r
1137\r
1138 def GenerateBsfFile (self, BsfFile):\r
1139\r
1140 if BsfFile == '':\r
1141 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1142 return 1\r
1143\r
1144 Error = 0\r
1145 OptionDict = {}\r
1146 BsfFd = open(BsfFile, "w")\r
1147 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
1148 BsfFd.write("%s\n" % self._GlobalDataDef);\r
1149 BsfFd.write("StructDef\n")\r
1150 NextOffset = -1\r
1151 for Item in self._CfgItemList:\r
1152 if Item['find'] != '':\r
1153 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
1154 NextOffset = Item['offset'] + Item['length']\r
1155 if Item['name'] != '':\r
1156 if NextOffset != Item['offset']:\r
1157 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1158 if len(Item['subreg']) > 0:\r
1159 NextOffset = Item['offset']\r
1160 for SubItem in Item['subreg']:\r
1161 NextOffset += SubItem['length']\r
1162 if SubItem['name'] == '':\r
1163 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
1164 else:\r
1165 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1166 if len(Options) > 0:\r
1167 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
1168 if (Item['offset'] + Item['length']) < NextOffset:\r
1169 self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname'])\r
1170 return 2\r
1171 else:\r
1172 NextOffset = Item['offset'] + Item['length']\r
1173 Options = self.WriteBsfStruct(BsfFd, Item)\r
1174 if len(Options) > 0:\r
1175 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1176 BsfFd.write("\nEndStruct\n\n")\r
1177\r
1178 BsfFd.write("%s" % self._BuidinOptionTxt);\r
1179\r
1180 for Each in OptionDict:\r
1181 BsfFd.write("List &%s\n" % Each);\r
1182 for Item in OptionDict[Each]:\r
1183 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]));\r
1184 BsfFd.write("EndList\n\n");\r
1185\r
1186 BsfFd.write("BeginInfoBlock\n");\r
1187 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']));\r
1188 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']));\r
1189 BsfFd.write("EndInfoBlock\n\n");\r
1190\r
1191 for Each in self._CfgPageDict:\r
1192 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]);\r
1193 BsfItems = []\r
1194 for Item in self._CfgItemList:\r
1195 if Item['name'] != '':\r
1196 if Item['page'] != Each:\r
1197 continue\r
1198 if len(Item['subreg']) > 0:\r
1199 for SubItem in Item['subreg']:\r
1200 if SubItem['name'] != '':\r
1201 BsfItems.append(SubItem)\r
1202 else:\r
1203 BsfItems.append(Item)\r
1204\r
1205 BsfItems.sort(key=lambda x: x['order'])\r
1206\r
1207 for Item in BsfItems:\r
1208 self.WriteBsfOption (BsfFd, Item)\r
1209 BsfFd.write("EndPage\n\n");\r
1210\r
1211 BsfFd.close()\r
1212 return Error\r
1213\r
1214\r
1215def Usage():\r
1216 print "GenCfgOpt Version 0.50"\r
1217 print "Usage:"\r
1218 print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]"\r
1219 print " GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]"\r
1220 print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]"\r
1221\r
1222def Main():\r
1223 #\r
1224 # Parse the options and args\r
1225 #\r
1226 GenCfgOpt = CGenCfgOpt()\r
1227 argc = len(sys.argv)\r
1228 if argc < 4:\r
1229 Usage()\r
1230 return 1\r
1231 else:\r
1232 DscFile = sys.argv[2]\r
1233 if not os.path.exists(DscFile):\r
1234 print "ERROR: Cannot open DSC file '%s' !" % DscFile\r
1235 return 2\r
1236\r
b2344187
JY
1237 UpdateMemSiUpdInitOffsetValue(DscFile)\r
1238\r
c8ec22a2
JY
1239 OutFile = ''\r
1240 if argc > 4:\r
1241 if sys.argv[4][0] == '-':\r
1242 Start = 4\r
1243 else:\r
1244 OutFile = sys.argv[4]\r
1245 Start = 5\r
1246 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
8e5015c2 1247 print "ERROR: Macro parsing failed !"\r
c8ec22a2
JY
1248 return 3\r
1249\r
1250 FvDir = sys.argv[3]\r
1251 if not os.path.isdir(FvDir):\r
1252 print "ERROR: FV folder '%s' is invalid !" % FvDir\r
1253 return 4\r
1254\r
1255 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
1256 print "ERROR: %s !" % GenCfgOpt.Error\r
1257 return 5\r
1258\r
c8ec22a2
JY
1259 if GenCfgOpt.UpdateVpdSizeField() != 0:\r
1260 print "ERROR: %s !" % GenCfgOpt.Error\r
1261 return 6\r
1262\r
1263 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
1264 print "ERROR: %s !" % GenCfgOpt.Error\r
1265 return 7\r
1266\r
1267 if sys.argv[1] == "UPDTXT":\r
1268 Ret = GenCfgOpt.CreateUpdTxtFile(OutFile)\r
1269 if Ret != 0:\r
1270 # No change is detected\r
1271 if Ret == 256:\r
1272 print "INFO: %s !" % (GenCfgOpt.Error)\r
1273 else :\r
1274 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1275 return Ret\r
1276 elif sys.argv[1] == "HEADER":\r
1277 Ret = GenCfgOpt.CreateHeaderFile(OutFile, True)\r
1278 if Ret != 0:\r
1279 # No change is detected\r
1280 if Ret == 256:\r
1281 print "INFO: %s !" % (GenCfgOpt.Error)\r
1282 else :\r
1283 print "ERROR: %s !" % (GenCfgOpt.Error)\r
1284 return Ret\r
1285 if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0:\r
1286 print "ERROR: %s !" % GenCfgOpt.Error\r
1287 return 8\r
1288 elif sys.argv[1] == "GENBSF":\r
1289 if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
1290 print "ERROR: %s !" % GenCfgOpt.Error\r
1291 return 9\r
1292 else:\r
1293 if argc < 5:\r
1294 Usage()\r
1295 return 1\r
1296 print "ERROR: Unknown command '%s' !" % sys.argv[1]\r
1297 Usage()\r
1298 return 1\r
1299 return 0\r
1300 return 0\r
1301\r
1302\r
1303if __name__ == '__main__':\r
1304 sys.exit(Main())\r