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