]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Tools/GenCfgOpt.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / IntelFsp2Pkg / Tools / GenCfgOpt.py
CommitLineData
cf1d4549
JY
1## @ GenCfgOpt.py\r
2#\r
6f219bef 3# Copyright (c) 2014 - 2022, 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
1fbf5e30
LTL
711 if Match != None:\r
712 self._CfgPageDict[Match.group(1)] = Match.group(2)\r
cf1d4549
JY
713\r
714 Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
715 if Match:\r
716 self._CfgBlkDict['name'] = Match.group(1)\r
717 self._CfgBlkDict['ver'] = Match.group(2)\r
718\r
719 for Key in self._BsfKeyList:\r
720 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
721 if Match:\r
722 if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):\r
723 ConfigDict[Key.lower()] += Match.group(1)[1:]\r
724 else:\r
725 ConfigDict[Key.lower()] = Match.group(1)\r
726 else:\r
727 for Key in self._HdrKeyList:\r
728 Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)\r
729 if Match:\r
730 ConfigDict[Key.lower()] = Match.group(1)\r
731\r
732 Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)\r
733 if Match:\r
734 ConfigDict['name'] = Match.group(1)\r
735\r
736 Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)\r
737 if Match:\r
738 if Match.group(2).strip() in self._BuidinOption:\r
739 ConfigDict['option'] = Match.group(2).strip()\r
740 else:\r
741 OptionValueList = Match.group(2).split(',')\r
742 OptionStringList = Match.group(3).split(',')\r
743 Index = 0\r
744 for Option in OptionValueList:\r
745 Option = Option.strip()\r
746 ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()\r
747 Index += 1\r
748 if Index in range(len(OptionValueList)):\r
749 ConfigDict['option'] += ', '\r
750 ConfigDict['type'] = "Combo"\r
751\r
752 Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
753 if Match:\r
754 if "0x" in Match.group(2) or "0x" in Match.group(3):\r
27326112 755 ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
cf1d4549 756 else:\r
27326112 757 ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
cf1d4549
JY
758\r
759 Match = re.match("^\s*##\s+(.+)", DscLine)\r
760 if Match:\r
761 ConfigDict['help'] = Match.group(1)\r
762\r
763 # Check VPD/UPD\r
764 if IsUpdSect:\r
1d7eed41 765 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
766 else:\r
767 Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)\r
768 if Match:\r
769 ConfigDict['space'] = Match.group(1)\r
770 ConfigDict['cname'] = Match.group(2)\r
1d7eed41
CC
771 if Match.group(3) != '*':\r
772 Hardcode = True\r
773 Offset = int (Match.group(3), 16)\r
774 else:\r
775 AutoAlign = True\r
776\r
777 if Hardcode and AutoAlign:\r
778 print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")\r
779 raise SystemExit\r
780 ConfigDict['offset'] = Offset\r
cf1d4549
JY
781 if ConfigDict['order'] == -1:\r
782 ConfigDict['order'] = ConfigDict['offset'] << 8\r
783 else:\r
784 (Major, Minor) = ConfigDict['order'].split('.')\r
785 ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)\r
786 if IsUpdSect:\r
787 Value = Match.group(5).strip()\r
788 if Match.group(4).startswith("0x"):\r
789 Length = int (Match.group(4), 16)\r
790 else :\r
791 Length = int (Match.group(4))\r
1d7eed41 792 Offset += Length\r
cf1d4549
JY
793 else:\r
794 Value = Match.group(4)\r
795 if Value is None:\r
796 Value = ''\r
797 Value = Value.strip()\r
798 if '|' in Value:\r
799 Match = re.match("^.+\s*\|\s*(.+)", Value)\r
800 if Match:\r
801 Value = Match.group(1)\r
802 Length = -1\r
803\r
804 ConfigDict['length'] = Length\r
805 Match = re.match("\$\((\w+)\)", Value)\r
806 if Match:\r
807 if Match.group(1) in self._MacroDict:\r
808 Value = self._MacroDict[Match.group(1)]\r
809\r
810 ConfigDict['value'] = Value\r
811 if (len(Value) > 0) and (Value[0] == '{'):\r
812 Value = self.FormatListValue(ConfigDict)\r
813\r
814 if ConfigDict['name'] == '':\r
815 # Clear BSF specific items\r
816 ConfigDict['bsfname'] = ''\r
817 ConfigDict['help'] = ''\r
818 ConfigDict['type'] = ''\r
819 ConfigDict['option'] = ''\r
1d7eed41
CC
820 if IsUpdSect and AutoAlign:\r
821 ItemLength = int(ConfigDict['length'])\r
822 ItemOffset = int(ConfigDict['offset'])\r
823 ItemStruct = ConfigDict['struct']\r
824 Unit = 1\r
825 if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):\r
826 Unit = ItemLength\r
827 # If there are 64 bit unit, align to 64\r
828 if Unit == 8:\r
829 MaxAlign = 64\r
830 SizeAlign = 8\r
831 if ItemStruct != '':\r
832 UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}\r
833 if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:\r
834 Unit = UnitDict[ItemStruct]\r
835 # If there are 64 bit unit, align to 64\r
836 if Unit == 8:\r
837 MaxAlign = 64\r
838 SizeAlign = max(SizeAlign, Unit)\r
839 if (ConfigDict['embed'].find(':START') != -1):\r
840 Base = ItemOffset\r
841 SubOffset = ItemOffset - Base\r
842 SubRemainder = SubOffset % Unit\r
843 if SubRemainder:\r
844 Diff = Unit - SubRemainder\r
845 Offset = Offset + Diff\r
846 ItemOffset = ItemOffset + Diff\r
847\r
848 if (ConfigDict['embed'].find(':END') != -1):\r
849 Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64\r
850 if Remainder:\r
5e4ebd9e 851 Diff = int((MaxAlign/8) - Remainder)\r
1d7eed41
CC
852 Offset = Offset + Diff\r
853 ItemOffset = ItemOffset + Diff\r
854 MaxAlign = 32 # Reset to default 32 align when struct end\r
855 if (ConfigDict['cname'] == 'UpdTerminator'):\r
856 # ItemLength is the size of UpdTerminator\r
857 # Itemlength might be 16, 32, or 64\r
858 # Struct align to 64 if UpdTerminator\r
859 # or struct size is 64 bit, else align to 32\r
860 Remainder = Offset % max(ItemLength/8, 4, SizeAlign)\r
861 Offset = Offset + ItemLength\r
862 if Remainder:\r
5e4ebd9e 863 Diff = int(max(ItemLength/8, 4, SizeAlign) - Remainder)\r
1d7eed41
CC
864 ItemOffset = ItemOffset + Diff\r
865 ConfigDict['offset'] = ItemOffset\r
cf1d4549
JY
866\r
867 self._CfgItemList.append(ConfigDict.copy())\r
868 ConfigDict['name'] = ''\r
869 ConfigDict['find'] = ''\r
870 ConfigDict['struct'] = ''\r
871 ConfigDict['embed'] = ''\r
872 ConfigDict['comment'] = ''\r
27326112 873 ConfigDict['marker'] = ''\r
cf1d4549
JY
874 ConfigDict['order'] = -1\r
875 ConfigDict['subreg'] = []\r
876 ConfigDict['option'] = ''\r
877 else:\r
878 # It could be a virtual item as below\r
62997d5e 879 # !BSF FIELD:{SerialDebugPortAddress0:1}\r
cf1d4549 880 # or\r
62997d5e
MM
881 # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
882 Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)\r
cf1d4549 883 if Match:\r
62997d5e
MM
884 SubCfgDict = ConfigDict.copy()\r
885 if (Match.group(4) == None) or (Match.group(4) == 'B'):\r
886 UnitBitLen = 8\r
887 elif Match.group(4) == 'b':\r
888 UnitBitLen = 1\r
889 else:\r
890 print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)\r
891 raise SystemExit\r
cf1d4549 892 SubCfgDict['cname'] = Match.group(2)\r
62997d5e
MM
893 SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen\r
894 if SubCfgDict['bitlength'] > 0:\r
cf1d4549
JY
895 LastItem = self._CfgItemList[-1]\r
896 if len(LastItem['subreg']) == 0:\r
897 SubOffset = 0\r
898 else:\r
62997d5e
MM
899 SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']\r
900 SubCfgDict['bitoffset'] = SubOffset\r
cf1d4549
JY
901 LastItem['subreg'].append (SubCfgDict.copy())\r
902 ConfigDict['name'] = ''\r
903 return Error\r
904\r
62997d5e
MM
905 def GetBsfBitFields (self, subitem, bytes):\r
906 start = subitem['bitoffset']\r
907 end = start + subitem['bitlength']\r
908 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])\r
909 bitsvalue = bitsvalue[::-1]\r
910 bitslen = len(bitsvalue)\r
911 if start > bitslen or end > bitslen:\r
27326112
LTL
912 raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))\r
913 return '0x%X' % (int(bitsvalue[start:end][::-1], 2))\r
62997d5e 914\r
cf1d4549
JY
915 def UpdateSubRegionDefaultValue (self):\r
916 Error = 0\r
917 for Item in self._CfgItemList:\r
918 if len(Item['subreg']) == 0:\r
919 continue\r
920 bytearray = []\r
921 if Item['value'][0] == '{':\r
922 binlist = Item['value'][1:-1].split(',')\r
923 for each in binlist:\r
924 each = each.strip()\r
925 if each.startswith('0x'):\r
926 value = int(each, 16)\r
927 else:\r
928 value = int(each)\r
929 bytearray.append(value)\r
930 else:\r
931 if Item['value'].startswith('0x'):\r
932 value = int(Item['value'], 16)\r
933 else:\r
934 value = int(Item['value'])\r
62997d5e 935 idx = 0\r
cf1d4549
JY
936 while idx < Item['length']:\r
937 bytearray.append(value & 0xFF)\r
938 value = value >> 8\r
939 idx = idx + 1\r
940 for SubItem in Item['subreg']:\r
62997d5e
MM
941 valuestr = self.GetBsfBitFields(SubItem, bytearray)\r
942 SubItem['value'] = valuestr\r
cf1d4549
JY
943 return Error\r
944\r
cc942105
CC
945 def NoDscFileChange (self, OutPutFile):\r
946 NoFileChange = True\r
947 if not os.path.exists(OutPutFile):\r
948 NoFileChange = False\r
949 else:\r
cc942105 950 OutputTime = os.path.getmtime(OutPutFile)\r
f95e80d8 951 if self._DscTime > OutputTime:\r
cc942105
CC
952 NoFileChange = False\r
953 return NoFileChange\r
954\r
cf1d4549 955 def CreateSplitUpdTxt (self, UpdTxtFile):\r
48249243
HZ
956 GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID','FSP_I_UPD_TOOL_GUID']\r
957 SignatureList = ['0x545F', '0x4D5F','0x535F','0x495F'] # _T, _M, _S and _I signature for FSPT, FSPM, FSPS, FSPI\r
cf1d4549
JY
958 for Index in range(len(GuidList)):\r
959 UpdTxtFile = ''\r
960 FvDir = self._FvDir\r
961 if GuidList[Index] not in self._MacroDict:\r
3eca64f1
CC
962 NoFSPI = False\r
963 if GuidList[Index] == 'FSP_I_UPD_TOOL_GUID':\r
964 NoFSPI = True\r
965 continue\r
966 else:\r
967 self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r
968 return 1\r
cf1d4549
JY
969\r
970 if UpdTxtFile == '':\r
971 UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
972\r
cc942105 973 if (self.NoDscFileChange (UpdTxtFile)):\r
cf1d4549
JY
974 # DSC has not been modified yet\r
975 # So don't have to re-generate other files\r
976 self.Error = 'No DSC file change, skip to create UPD TXT file'\r
977 return 256\r
978\r
979 TxtFd = open(UpdTxtFile, "w")\r
980 TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r
981\r
982 NextOffset = 0\r
983 SpaceIdx = 0\r
984 StartAddr = 0\r
985 EndAddr = 0\r
986 Default = 'DEFAULT|'\r
987 InRange = False\r
988 for Item in self._CfgItemList:\r
989 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
990 StartAddr = Item['offset']\r
991 NextOffset = StartAddr\r
992 InRange = True\r
993 if Item['cname'] == 'UpdTerminator' and InRange == True:\r
994 EndAddr = Item['offset']\r
995 InRange = False\r
996 InRange = False\r
997 for Item in self._CfgItemList:\r
998 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r
999 InRange = True\r
1000 if InRange != True:\r
1001 continue\r
1002 if Item['cname'] == 'UpdTerminator':\r
1003 InRange = False\r
1004 if Item['region'] != 'UPD':\r
1005 continue\r
1006 Offset = Item['offset']\r
1007 if StartAddr > Offset or EndAddr < Offset:\r
1008 continue\r
1009 if NextOffset < Offset:\r
1010 # insert one line\r
1011 TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r
1012 SpaceIdx = SpaceIdx + 1\r
1013 NextOffset = Offset + Item['length']\r
cf1d4549
JY
1014 TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r
1015 TxtFd.close()\r
1016 return 0\r
1017\r
27326112
LTL
1018 def CreateVarDict (self):\r
1019 Error = 0\r
1020 self._VarDict = {}\r
1021 if len(self._CfgItemList) > 0:\r
1022 Item = self._CfgItemList[-1]\r
1023 self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])\r
1024 for Item in self._CfgItemList:\r
1025 Embed = Item['embed']\r
1026 Match = re.match("^(\w+):(\w+):(START|END)", Embed)\r
1027 if Match:\r
1028 StructName = Match.group(1)\r
1029 VarName = '_%s_%s_' % (Match.group(3), StructName)\r
1030 if Match.group(3) == 'END':\r
1031 self._VarDict[VarName] = Item['offset'] + Item['length']\r
1032 self._VarDict['_LENGTH_%s_' % StructName] = \\r
1033 self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]\r
1034 if Match.group(2).startswith('TAG_'):\r
1035 if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):\r
1036 raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))\r
1037 self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF\r
cf1d4549 1038 else:\r
27326112
LTL
1039 self._VarDict[VarName] = Item['offset']\r
1040 if Item['marker']:\r
1041 self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']\r
1042 return Error\r
1043\r
1044 def UpdateBsfBitUnit (self, Item):\r
1045 BitTotal = 0\r
1046 BitOffset = 0\r
1047 StartIdx = 0\r
1048 Unit = None\r
1049 UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}\r
1050 for Idx, SubItem in enumerate(Item['subreg']):\r
1051 if Unit is None:\r
1052 Unit = SubItem['bitunit']\r
1053 BitLength = SubItem['bitlength']\r
1054 BitTotal += BitLength\r
1055 BitOffset += BitLength\r
1056\r
1057 if BitOffset > 64 or BitOffset > Unit * 8:\r
1058 break\r
1059\r
1060 if BitOffset == Unit * 8:\r
1061 for SubIdx in range (StartIdx, Idx + 1):\r
1062 Item['subreg'][SubIdx]['bitunit'] = Unit\r
1063 BitOffset = 0\r
1064 StartIdx = Idx + 1\r
1065 Unit = None\r
1066\r
1067 if BitOffset > 0:\r
1068 raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))\r
1069\r
1070 ExpectedTotal = Item['length'] * 8\r
1071 if Item['length'] * 8 != BitTotal:\r
1072 raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))\r
1073\r
1074 def UpdateDefaultValue (self):\r
1075 Error = 0\r
1076 for Idx, Item in enumerate(self._CfgItemList):\r
1077 if len(Item['subreg']) == 0:\r
1078 Value = Item['value']\r
1079 if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):\r
1080 # {XXX} or 'XXX' strings\r
1081 self.FormatListValue(self._CfgItemList[Idx])\r
1082 else:\r
1083 Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)\r
1084 if not Match:\r
1085 NumValue = self.EvaluateExpress (Value)\r
1086 Item['value'] = '0x%X' % NumValue\r
cf1d4549 1087 else:\r
27326112
LTL
1088 ValArray = self.ValueToByteArray (Item['value'], Item['length'])\r
1089 for SubItem in Item['subreg']:\r
1090 SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)\r
1091 self.UpdateBsfBitUnit (Item)\r
1092 return Error\r
1093\r
1094 def ProcessMultilines (self, String, MaxCharLength):\r
1095 Multilines = ''\r
1096 StringLength = len(String)\r
1097 CurrentStringStart = 0\r
1098 StringOffset = 0\r
1099 BreakLineDict = []\r
1100 if len(String) <= MaxCharLength:\r
1101 while (StringOffset < StringLength):\r
1102 if StringOffset >= 1:\r
1103 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
1104 BreakLineDict.append (StringOffset + 1)\r
1105 StringOffset += 1\r
1106 if BreakLineDict != []:\r
1107 for Each in BreakLineDict:\r
1108 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
1109 CurrentStringStart = Each\r
1110 if StringLength - CurrentStringStart > 0:\r
1111 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
1112 else:\r
1113 Multilines = " %s\n" % String\r
1114 else:\r
1115 NewLineStart = 0\r
1116 NewLineCount = 0\r
1117 FoundSpaceChar = False\r
1118 while (StringOffset < StringLength):\r
1119 if StringOffset >= 1:\r
1120 if NewLineCount >= MaxCharLength - 1:\r
1121 if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
1122 BreakLineDict.append (NewLineStart + NewLineCount)\r
1123 NewLineStart = NewLineStart + NewLineCount\r
cf1d4549 1124 NewLineCount = 0\r
27326112
LTL
1125 FoundSpaceChar = True\r
1126 elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
1127 BreakLineDict.append (0)\r
1128 if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
1129 BreakLineDict.append (StringOffset + 1)\r
1130 NewLineStart = StringOffset + 1\r
1131 NewLineCount = 0\r
1132 StringOffset += 1\r
1133 NewLineCount += 1\r
1134 if BreakLineDict != []:\r
1135 BreakLineDict.sort ()\r
1136 for Each in BreakLineDict:\r
1137 if Each > 0:\r
1138 Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
1139 CurrentStringStart = Each\r
1140 if StringLength - CurrentStringStart > 0:\r
1141 Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
1142 return Multilines\r
1143\r
1144 def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):\r
cf1d4549
JY
1145 PosName = 28\r
1146 PosComment = 30\r
1147 NameLine=''\r
1148 HelpLine=''\r
1149 OptionLine=''\r
1150\r
27326112
LTL
1151 if Length == 0 and Name == 'Dummy':\r
1152 return '\n'\r
1153\r
cf1d4549
JY
1154 IsArray = False\r
1155 if Length in [1,2,4,8]:\r
1156 Type = "UINT%d" % (Length * 8)\r
cd3692b1
SY
1157 if Name.startswith("UnusedUpdSpace") and Length != 1:\r
1158 IsArray = True\r
1159 Type = "UINT8"\r
cf1d4549
JY
1160 else:\r
1161 IsArray = True\r
1162 Type = "UINT8"\r
1163\r
1164 if Item and Item['value'].startswith('{'):\r
1165 Type = "UINT8"\r
1166 IsArray = True\r
1167\r
1168 if Struct != '':\r
1169 Type = Struct\r
1170 if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r
1171 IsArray = True\r
1172 Unit = int(Type[4:]) / 8\r
1173 Length = Length / Unit\r
1174 else:\r
1175 IsArray = False\r
1176\r
1177 if IsArray:\r
1178 Name = Name + '[%d]' % Length\r
1179\r
1180 if len(Type) < PosName:\r
1181 Space1 = PosName - len(Type)\r
1182 else:\r
1183 Space1 = 1\r
1184\r
1185 if BsfName != '':\r
1186 NameLine=" - %s\n" % BsfName\r
1187 else:\r
1188 NameLine="\n"\r
1189\r
1190 if Help != '':\r
1191 HelpLine = self.ProcessMultilines (Help, 80)\r
1192\r
1193 if Option != '':\r
1194 OptionLine = self.ProcessMultilines (Option, 80)\r
1195\r
1196 if Offset is None:\r
1197 OffsetStr = '????'\r
1198 else:\r
1199 OffsetStr = '0x%04X' % Offset\r
1200\r
27326112
LTL
1201 if BitsLength is None:\r
1202 BitsLength = ''\r
1203 else:\r
1204 BitsLength = ' : %d' % BitsLength\r
1205\r
1206 return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)\r
cf1d4549
JY
1207\r
1208 def PostProcessBody (self, TextBody):\r
1209 NewTextBody = []\r
1210 OldTextBody = []\r
1211 IncludeLine = False\r
1212 StructName = ''\r
1213 VariableName = ''\r
1214 IsUpdHdrDefined = False\r
1215 IsUpdHeader = False\r
1216 for Line in TextBody:\r
1217 SplitToLines = Line.splitlines()\r
1218 MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r
1219 if MatchComment:\r
1220 if MatchComment.group(1) == 'FSP_UPD_HEADER':\r
1221 IsUpdHeader = True\r
1222 else:\r
1223 IsUpdHeader = False\r
1224 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1225 CommentLine = " " + MatchComment.group(2) + "\n"\r
1226 NewTextBody.append("/**" + CommentLine + "**/\n")\r
1227 Line = Line[(len(SplitToLines[0]) + 1):]\r
1228\r
1229 Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r
1230 if Match:\r
1231 Line = Match.group(4)\r
1232 if Match.group(1) == 'FSP_UPD_HEADER':\r
1233 IsUpdHeader = True\r
1234 else:\r
1235 IsUpdHeader = False\r
1236\r
1237 if Match and Match.group(3) == 'START':\r
1238 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1239 NewTextBody.append ('typedef struct {\n')\r
1240 StructName = Match.group(1)\r
1241 VariableName = Match.group(2)\r
1242 MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r
1243 if MatchOffset:\r
1244 Offset = int(MatchOffset.group(1), 16)\r
1245 else:\r
1246 Offset = None\r
1247 Line\r
1248 IncludeLine = True\r
1249 OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r
1250 if IncludeLine:\r
1251 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1252 NewTextBody.append (Line)\r
1253 else:\r
1254 OldTextBody.append (Line)\r
1255\r
62997d5e 1256 if Match and Match.group(3) == 'END':\r
cf1d4549 1257 if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r
c3f0829b 1258 print ("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)))\r
cf1d4549
JY
1259 else:\r
1260 if IsUpdHdrDefined != True or IsUpdHeader != True:\r
1261 NewTextBody.append ('} %s;\n\n' % StructName)\r
1262 IsUpdHdrDefined = True\r
1263 IncludeLine = False\r
1264 NewTextBody.extend(OldTextBody)\r
1265 return NewTextBody\r
1266\r
d75c07bc
CC
1267 def WriteLinesWithoutTailingSpace (self, HeaderFd, Line):\r
1268 TxtBody2 = Line.splitlines(True)\r
1269 for Line2 in TxtBody2:\r
1270 Line2 = Line2.rstrip()\r
1271 Line2 += '\n'\r
1272 HeaderFd.write (Line2)\r
1273 return 0\r
cf1d4549
JY
1274 def CreateHeaderFile (self, InputHeaderFile):\r
1275 FvDir = self._FvDir\r
1276\r
1277 HeaderFileName = 'FspUpd.h'\r
1278 HeaderFile = os.path.join(FvDir, HeaderFileName)\r
1279\r
1280 # Check if header needs to be recreated\r
cc942105
CC
1281 if (self.NoDscFileChange (HeaderFile)):\r
1282 # DSC has not been modified yet\r
1283 # So don't have to re-generate other files\r
1284 self.Error = 'No DSC file change, skip to create UPD header file'\r
1285 return 256\r
cf1d4549
JY
1286\r
1287 TxtBody = []\r
1288 for Item in self._CfgItemList:\r
1289 if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r
1290 Value = int(Item['value'], 16)\r
1291 Chars = []\r
1292 while Value != 0x0:\r
1293 Chars.append(chr(Value & 0xFF))\r
1294 Value = Value >> 8\r
1295 SignatureStr = ''.join(Chars)\r
48249243 1296 # Signature will be _T / _M / _S / _I for FSPT / FSPM / FSPS /FSPI accordingly\r
cf1d4549
JY
1297 if '_T' in SignatureStr[6:6+2]:\r
1298 TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1299 elif '_M' in SignatureStr[6:6+2]:\r
1300 TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
1301 elif '_S' in SignatureStr[6:6+2]:\r
1302 TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
48249243 1303 elif '_I' in SignatureStr[6:6+2]:\r
0d0bfcb4 1304 if NoFSPI == False:\r
3eca64f1 1305 TxtBody.append("#define FSPI_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r
cf1d4549
JY
1306 TxtBody.append("\n")\r
1307\r
1308 for Region in ['UPD']:\r
1309 UpdOffsetTable = []\r
48249243
HZ
1310 UpdSignature = ['0x545F', '0x4D5F', '0x535F', '0x495F'] #['_T', '_M', '_S', '_I'] signature for FSPT, FSPM, FSPS, FSPI\r
1311 UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD', 'FSPI_UPD']\r
cf1d4549
JY
1312 for Item in self._CfgItemList:\r
1313 if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
27326112 1314 Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting\r
cf1d4549
JY
1315 UpdOffsetTable.append (Item["offset"])\r
1316\r
1317 for UpdIdx in range(len(UpdOffsetTable)):\r
1318 CommentLine = ""\r
1319 for Item in self._CfgItemList:\r
1320 if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r
1321 MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r
1322 if MatchComment and MatchComment.group(1) == Region[0]:\r
1323 CommentLine = " " + MatchComment.group(2) + "\n"\r
1324 TxtBody.append("/**" + CommentLine + "**/\n")\r
1325 elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r
1326 Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r
1327 if Match:\r
1328 TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r
1329 TxtBody.append("typedef struct {\n")\r
1330 NextOffset = 0\r
1331 SpaceIdx = 0\r
1332 Offset = 0\r
1333\r
1334 LastVisible = True\r
1335 ResvOffset = 0\r
1336 ResvIdx = 0\r
1337 LineBuffer = []\r
1338 InRange = False\r
1339 for Item in self._CfgItemList:\r
1340 if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r
1341 InRange = True\r
1342 if InRange != True:\r
1343 continue\r
1344 if Item['cname'] == 'UpdTerminator':\r
1345 InRange = False\r
1346\r
1347 if Item['region'] != Region:\r
1348 continue\r
1349\r
1350 if Item["offset"] < UpdOffsetTable[UpdIdx]:\r
1351 continue\r
1352\r
1353 NextVisible = LastVisible\r
1354\r
1355 if LastVisible and (Item['header'] == 'OFF'):\r
1356 NextVisible = False\r
1357 ResvOffset = Item['offset']\r
1358 elif (not LastVisible) and Item['header'] == 'ON':\r
1359 NextVisible = True\r
1360 Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r
1361 ResvIdx = ResvIdx + 1\r
1362 TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r
1363\r
1364 if Offset < Item["offset"]:\r
1365 if LastVisible:\r
1366 Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r
1367 LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r
1368 SpaceIdx = SpaceIdx + 1\r
1369 Offset = Item["offset"]\r
1370\r
1371 LastVisible = NextVisible\r
1372\r
1373 Offset = Offset + Item["length"]\r
1374 if LastVisible:\r
1375 for Each in LineBuffer:\r
1376 TxtBody.append (Each)\r
1377 LineBuffer = []\r
1378 Comment = Item["comment"]\r
1379 Embed = Item["embed"].upper()\r
1380 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1381 if not Comment == '' and Embed.endswith(':START'):\r
1382 Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r
1383 Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1384 else:\r
1385 Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r
1386 else:\r
1387 if Embed == '':\r
62997d5e 1388 Marker = ''\r
cf1d4549
JY
1389 else:\r
1390 self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r
1391 return 4\r
1392 Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r
1393 TxtBody.append(Line)\r
1394 if Item['cname'] == 'UpdTerminator':\r
1395 break\r
1396 TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r
62997d5e 1397\r
cf1d4549
JY
1398 # Handle the embedded data structure\r
1399 TxtBody = self.PostProcessBody (TxtBody)\r
1400\r
1401 HeaderTFileName = 'FsptUpd.h'\r
1402 HeaderMFileName = 'FspmUpd.h'\r
1403 HeaderSFileName = 'FspsUpd.h'\r
48249243 1404 HeaderIFileName = 'FspiUpd.h'\r
cf1d4549 1405\r
48249243
HZ
1406 UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS', 'FSPI'] # FSPX_UPD_REGION\r
1407 UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S', 'FSP_I'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
1408 UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE', 'FSPI_UPD_SIGNATURE']\r
1409 ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD', 'FSPI_ARCH_UPD']\r
6f219bef 1410 ExcludedSpecificUpd1 = ['FSPT_ARCH2_UPD', 'FSPM_ARCH2_UPD', 'FSPS_ARCH2_UPD']\r
cf1d4549 1411\r
1d058c3e 1412 IncLines = []\r
cf1d4549
JY
1413 if InputHeaderFile != '':\r
1414 if not os.path.exists(InputHeaderFile):\r
1415 self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
1416 return 6\r
1417\r
1418 InFd = open(InputHeaderFile, "r")\r
1419 IncLines = InFd.readlines()\r
1420 InFd.close()\r
1421\r
1422 for item in range(len(UpdRegionCheck)):\r
1423 if UpdRegionCheck[item] == 'FSPT':\r
1424 HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r
1425 FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r
1426 elif UpdRegionCheck[item] == 'FSPM':\r
1427 HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r
1428 FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r
1429 elif UpdRegionCheck[item] == 'FSPS':\r
1430 HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r
1431 FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r
48249243
HZ
1432 elif UpdRegionCheck[item] == 'FSPI':\r
1433 HeaderFd = open(os.path.join(FvDir, HeaderIFileName), "w")\r
1434 FileBase = os.path.basename(os.path.join(FvDir, HeaderIFileName))\r
cf1d4549
JY
1435 FileName = FileBase.replace(".", "_").upper()\r
1436 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1437 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1438 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1439 HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r
cd3692b1 1440 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1441\r
1442 Export = False\r
1443 for Line in IncLines:\r
1444 Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r
1445 if Match:\r
1446 if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r
1447 Export = True\r
1448 continue\r
1449 else:\r
1450 Export = False\r
1451 continue\r
1452 if Export:\r
1453 HeaderFd.write(Line)\r
1454 HeaderFd.write("\n")\r
1455\r
1456 Index = 0\r
1457 StartIndex = 0\r
1458 EndIndex = 0\r
1459 StructStart = []\r
1460 StructStartWithComment = []\r
1461 StructEnd = []\r
1462 for Line in TxtBody:\r
1463 Index += 1\r
1464 Match = re.match("(typedef struct {)", Line)\r
1465 if Match:\r
1466 StartIndex = Index - 1\r
1467 Match = re.match("}\s([_A-Z0-9]+);", Line)\r
6f219bef 1468 if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd[item] not in Match.group(1)) and (ExcludedSpecificUpd1[item] not in Match.group(1)):\r
cf1d4549
JY
1469 EndIndex = Index\r
1470 StructStart.append(StartIndex)\r
1471 StructEnd.append(EndIndex)\r
1472 Index = 0\r
1473 for Line in TxtBody:\r
1474 Index += 1\r
1475 for Item in range(len(StructStart)):\r
1476 if Index == StructStart[Item]:\r
1477 Match = re.match("^(/\*\*\s*)", Line)\r
1478 if Match:\r
1479 StructStartWithComment.append(StructStart[Item])\r
1480 else:\r
1481 StructStartWithComment.append(StructStart[Item] + 1)\r
1482 Index = 0\r
1483 for Line in TxtBody:\r
1484 Index += 1\r
1485 for Item in range(len(StructStart)):\r
1486 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
d75c07bc 1487 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r
cd3692b1 1488 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1489 HeaderFd.write("#endif\n")\r
1490 HeaderFd.close()\r
1491\r
1492 HeaderFd = open(HeaderFile, "w")\r
1493 FileBase = os.path.basename(HeaderFile)\r
1494 FileName = FileBase.replace(".", "_").upper()\r
1495 HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r
1496 HeaderFd.write("#ifndef __%s__\n" % FileName)\r
1497 HeaderFd.write("#define __%s__\n\n" % FileName)\r
1498 HeaderFd.write("#include <FspEas.h>\n\n")\r
cd3692b1 1499 HeaderFd.write("#pragma pack(1)\n\n")\r
cf1d4549
JY
1500\r
1501 for item in range(len(UpdRegionCheck)):\r
1502 Index = 0\r
1503 StartIndex = 0\r
1504 EndIndex = 0\r
1505 StructStart = []\r
1506 StructStartWithComment = []\r
1507 StructEnd = []\r
1508 for Line in TxtBody:\r
1509 Index += 1\r
1510 Match = re.match("(typedef struct {)", Line)\r
1511 if Match:\r
1512 StartIndex = Index - 1\r
1513 Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r
1514 if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r
1515 StructStart.append(Index - 1)\r
1516 StructEnd.append(Index)\r
1517 Index = 0\r
1518 for Line in TxtBody:\r
1519 Index += 1\r
1520 for Item in range(len(StructStart)):\r
1521 if Index == StructStart[Item]:\r
1522 Match = re.match("^(/\*\*\s*)", Line)\r
1523 if Match:\r
1524 StructStartWithComment.append(StructStart[Item])\r
1525 else:\r
1526 StructStartWithComment.append(StructStart[Item] + 1)\r
1527 Index = 0\r
1528 for Line in TxtBody:\r
1529 Index += 1\r
1530 for Item in range(len(StructStart)):\r
1531 if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r
d75c07bc 1532 self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r
cd3692b1 1533 HeaderFd.write("#pragma pack()\n\n")\r
cf1d4549
JY
1534 HeaderFd.write("#endif\n")\r
1535 HeaderFd.close()\r
1536\r
1537 return 0\r
1538\r
1539 def WriteBsfStruct (self, BsfFd, Item):\r
ba8ea427 1540 LogExpr = CLogicalExpression()\r
cf1d4549
JY
1541 if Item['type'] == "None":\r
1542 Space = "gPlatformFspPkgTokenSpaceGuid"\r
1543 else:\r
1544 Space = Item['space']\r
1545 Line = " $%s_%s" % (Space, Item['cname'])\r
1546 Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r
1547 if Match:\r
1548 DefaultValue = Match.group(1).strip()\r
1549 else:\r
1550 DefaultValue = Item['value'].strip()\r
62997d5e
MM
1551 if 'bitlength' in Item:\r
1552 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r
1553 else:\r
1554 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r
cf1d4549
JY
1555 TmpList = []\r
1556 if Item['type'] == "Combo":\r
1557 if not Item['option'] in self._BuidinOption:\r
1558 OptList = Item['option'].split(',')\r
1559 for Option in OptList:\r
1560 Option = Option.strip()\r
1561 (OpVal, OpStr) = Option.split(':')\r
ba8ea427
TRM
1562 test = LogExpr.getNumber (OpVal)\r
1563 if test is None:\r
1564 raise Exception("Selection Index '%s' is not a number" % OpVal)\r
cf1d4549
JY
1565 TmpList.append((OpVal, OpStr))\r
1566 return TmpList\r
1567\r
1568 def WriteBsfOption (self, BsfFd, Item):\r
1569 PcdName = Item['space'] + '_' + Item['cname']\r
1570 WriteHelp = 0\r
1571 if Item['type'] == "Combo":\r
1572 if Item['option'] in self._BuidinOption:\r
1573 Options = self._BuidinOption[Item['option']]\r
1574 else:\r
1575 Options = PcdName\r
62997d5e 1576 BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r
cf1d4549
JY
1577 WriteHelp = 1\r
1578 elif Item['type'].startswith("EditNum"):\r
1579 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
1580 if Match:\r
62997d5e 1581 BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r
cf1d4549
JY
1582 WriteHelp = 2\r
1583 elif Item['type'].startswith("EditText"):\r
62997d5e 1584 BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1585 WriteHelp = 1\r
1586 elif Item['type'] == "Table":\r
1587 Columns = Item['option'].split(',')\r
1588 if len(Columns) != 0:\r
62997d5e 1589 BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r
cf1d4549
JY
1590 for Col in Columns:\r
1591 Fmt = Col.split(':')\r
1592 if len(Fmt) != 3:\r
1593 raise Exception("Column format '%s' is invalid !" % Fmt)\r
1594 try:\r
1595 Dtype = int(Fmt[1].strip())\r
1596 except:\r
1597 raise Exception("Column size '%s' is invalid !" % Fmt[1])\r
1598 BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
1599 BsfFd.write(',\n')\r
1600 WriteHelp = 1\r
62997d5e 1601\r
cf1d4549
JY
1602 if WriteHelp > 0:\r
1603 HelpLines = Item['help'].split('\\n\\r')\r
1604 FirstLine = True\r
1605 for HelpLine in HelpLines:\r
1606 if FirstLine:\r
1607 FirstLine = False\r
62997d5e 1608 BsfFd.write(' Help "%s"\n' % (HelpLine))\r
cf1d4549 1609 else:\r
62997d5e 1610 BsfFd.write(' "%s"\n' % (HelpLine))\r
cf1d4549 1611 if WriteHelp == 2:\r
62997d5e 1612 BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r
cf1d4549
JY
1613\r
1614 def GenerateBsfFile (self, BsfFile):\r
1615\r
1616 if BsfFile == '':\r
1617 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
1618 return 1\r
1619\r
cc942105
CC
1620 if (self.NoDscFileChange (BsfFile)):\r
1621 # DSC has not been modified yet\r
1622 # So don't have to re-generate other files\r
1623 self.Error = 'No DSC file change, skip to create UPD BSF file'\r
1624 return 256\r
1625\r
cf1d4549
JY
1626 Error = 0\r
1627 OptionDict = {}\r
1628 BsfFd = open(BsfFile, "w")\r
1629 BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r
62997d5e 1630 BsfFd.write("%s\n" % self._GlobalDataDef)\r
cf1d4549
JY
1631 BsfFd.write("StructDef\n")\r
1632 NextOffset = -1\r
1633 for Item in self._CfgItemList:\r
1634 if Item['find'] != '':\r
1635 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
1636 NextOffset = Item['offset'] + Item['length']\r
1637 if Item['name'] != '':\r
1638 if NextOffset != Item['offset']:\r
1639 BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r
1640 if len(Item['subreg']) > 0:\r
1641 NextOffset = Item['offset']\r
62997d5e 1642 BitsOffset = NextOffset * 8\r
cf1d4549 1643 for SubItem in Item['subreg']:\r
62997d5e 1644 BitsOffset += SubItem['bitlength']\r
cf1d4549 1645 if SubItem['name'] == '':\r
62997d5e
MM
1646 if 'bitlength' in SubItem:\r
1647 BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))\r
1648 else:\r
1649 BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r
cf1d4549
JY
1650 else:\r
1651 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
1652 if len(Options) > 0:\r
1653 OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r
62997d5e
MM
1654\r
1655 NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
1656 if NextBitsOffset > BitsOffset:\r
1657 BitsGap = NextBitsOffset - BitsOffset\r
1658 BitsRemain = BitsGap % 8\r
1659 if BitsRemain:\r
1660 BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
1661 BitsGap -= BitsRemain\r
5e4ebd9e 1662 BytesRemain = int(BitsGap / 8)\r
62997d5e
MM
1663 if BytesRemain:\r
1664 BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r
1665 NextOffset = Item['offset'] + Item['length']\r
cf1d4549
JY
1666 else:\r
1667 NextOffset = Item['offset'] + Item['length']\r
1668 Options = self.WriteBsfStruct(BsfFd, Item)\r
1669 if len(Options) > 0:\r
1670 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
1671 BsfFd.write("\nEndStruct\n\n")\r
1672\r
62997d5e 1673 BsfFd.write("%s" % self._BuidinOptionTxt)\r
cf1d4549
JY
1674\r
1675 for Each in OptionDict:\r
62997d5e 1676 BsfFd.write("List &%s\n" % Each)\r
cf1d4549 1677 for Item in OptionDict[Each]:\r
62997d5e
MM
1678 BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))\r
1679 BsfFd.write("EndList\n\n")\r
cf1d4549 1680\r
62997d5e
MM
1681 BsfFd.write("BeginInfoBlock\n")\r
1682 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r
1683 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r
1684 BsfFd.write("EndInfoBlock\n\n")\r
cf1d4549
JY
1685\r
1686 for Each in self._CfgPageDict:\r
62997d5e 1687 BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r
cf1d4549
JY
1688 BsfItems = []\r
1689 for Item in self._CfgItemList:\r
1690 if Item['name'] != '':\r
1691 if Item['page'] != Each:\r
1692 continue\r
1693 if len(Item['subreg']) > 0:\r
1694 for SubItem in Item['subreg']:\r
1695 if SubItem['name'] != '':\r
1696 BsfItems.append(SubItem)\r
1697 else:\r
1698 BsfItems.append(Item)\r
1699\r
1700 BsfItems.sort(key=lambda x: x['order'])\r
1701\r
1702 for Item in BsfItems:\r
1703 self.WriteBsfOption (BsfFd, Item)\r
62997d5e 1704 BsfFd.write("EndPage\n\n")\r
cf1d4549
JY
1705\r
1706 BsfFd.close()\r
1707 return Error\r
1708\r
1709\r
1710def Usage():\r
3eca64f1 1711 print ("GenCfgOpt Version 0.59")\r
c3f0829b
CC
1712 print ("Usage:")\r
1713 print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")\r
1714 print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")\r
1715 print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")\r
cf1d4549
JY
1716\r
1717def Main():\r
1718 #\r
1719 # Parse the options and args\r
1720 #\r
b9c055f7
CC
1721 i = 1\r
1722\r
cf1d4549 1723 GenCfgOpt = CGenCfgOpt()\r
b9c055f7
CC
1724 while i < len(sys.argv):\r
1725 if sys.argv[i].strip().lower() == "--pcd":\r
1726 BuildOptionPcd.append(sys.argv[i+1])\r
1727 i += 1\r
1728 i += 1\r
cf1d4549
JY
1729 argc = len(sys.argv)\r
1730 if argc < 4:\r
1731 Usage()\r
1732 return 1\r
1733 else:\r
1734 DscFile = sys.argv[2]\r
1735 if not os.path.exists(DscFile):\r
c3f0829b 1736 print ("ERROR: Cannot open DSC file '%s' !" % DscFile)\r
cf1d4549 1737 return 2\r
cf1d4549
JY
1738\r
1739 OutFile = ''\r
1740 if argc > 4:\r
62997d5e 1741 if sys.argv[4][0] == '-':\r
cf1d4549
JY
1742 Start = 4\r
1743 else:\r
62997d5e 1744 OutFile = sys.argv[4]\r
cf1d4549 1745 Start = 5\r
e4408576
OBO
1746 if argc > Start:\r
1747 if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r
c3f0829b 1748 print ("ERROR: Macro parsing failed !")\r
e4408576 1749 return 3\r
cf1d4549
JY
1750\r
1751 FvDir = sys.argv[3]\r
1752 if not os.path.exists(FvDir):\r
1753 os.makedirs(FvDir)\r
1754\r
62997d5e 1755 if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r
c3f0829b 1756 print ("ERROR: %s !" % GenCfgOpt.Error)\r
cf1d4549
JY
1757 return 5\r
1758\r
1759 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r
c3f0829b 1760 print ("ERROR: %s !" % GenCfgOpt.Error)\r
cf1d4549
JY
1761 return 7\r
1762\r
1763 if sys.argv[1] == "UPDTXT":\r
1764 Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r
1765 if Ret != 0:\r
1766 # No change is detected\r
1767 if Ret == 256:\r
c3f0829b 1768 print ("INFO: %s !" % (GenCfgOpt.Error))\r
cf1d4549 1769 else :\r
c3f0829b 1770 print ("ERROR: %s !" % (GenCfgOpt.Error))\r
cf1d4549
JY
1771 return Ret\r
1772 elif sys.argv[1] == "HEADER":\r
cc942105
CC
1773 Ret = GenCfgOpt.CreateHeaderFile(OutFile)\r
1774 if Ret != 0:\r
1775 # No change is detected\r
1776 if Ret == 256:\r
1777 print ("INFO: %s !" % (GenCfgOpt.Error))\r
1778 else :\r
1779 print ("ERROR: %s !" % (GenCfgOpt.Error))\r
1780 return 8\r
1781 return Ret\r
cf1d4549 1782 elif sys.argv[1] == "GENBSF":\r
cc942105
CC
1783 Ret = GenCfgOpt.GenerateBsfFile(OutFile)\r
1784 if Ret != 0:\r
1785 # No change is detected\r
1786 if Ret == 256:\r
1787 print ("INFO: %s !" % (GenCfgOpt.Error))\r
1788 else :\r
1789 print ("ERROR: %s !" % (GenCfgOpt.Error))\r
1790 return 9\r
1791 return Ret\r
cf1d4549
JY
1792 else:\r
1793 if argc < 5:\r
1794 Usage()\r
1795 return 1\r
c3f0829b 1796 print ("ERROR: Unknown command '%s' !" % sys.argv[1])\r
cf1d4549
JY
1797 Usage()\r
1798 return 1\r
1799 return 0\r
1800 return 0\r
1801\r
1802\r
1803if __name__ == '__main__':\r
1804 sys.exit(Main())\r