]>
Commit | Line | Data |
---|---|---|
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 | |
8 | import os\r | |
9 | import re\r | |
10 | import sys\r | |
11 | import struct\r | |
12 | from datetime import date\r | |
c3f0829b | 13 | from 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 | |
55 | Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r | |
56 | \r | |
57 | Redistribution and use in source and binary forms, with or without modification,\r | |
58 | are 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 |
86 | BuildOptionPcd = []\r |
87 | \r | |
cf1d4549 JY |
88 | class 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 | |
285 | class 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 |
291 | GlobalDataDef\r | |
292 | SKUID = 0, "DEFAULT"\r | |
293 | EndGlobalData\r | |
294 | \r | |
295 | """\r | |
296 | self._BuidinOptionTxt = """\r | |
297 | List &EN_DIS\r | |
298 | Selection 0x1 , "Enabled"\r | |
299 | Selection 0x0 , "Disabled"\r | |
300 | EndList\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 JY |
955 | def CreateSplitUpdTxt (self, UpdTxtFile):\r |
956 | GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r | |
957 | SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS\r | |
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 | |
962 | self.Error = "%s definition is missing in DSC file" % (GuidList[Index])\r | |
963 | return 1\r | |
964 | \r | |
965 | if UpdTxtFile == '':\r | |
966 | UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r | |
967 | \r | |
cc942105 | 968 | if (self.NoDscFileChange (UpdTxtFile)):\r |
cf1d4549 JY |
969 | # DSC has not been modified yet\r |
970 | # So don't have to re-generate other files\r | |
971 | self.Error = 'No DSC file change, skip to create UPD TXT file'\r | |
972 | return 256\r | |
973 | \r | |
974 | TxtFd = open(UpdTxtFile, "w")\r | |
975 | TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))\r | |
976 | \r | |
977 | NextOffset = 0\r | |
978 | SpaceIdx = 0\r | |
979 | StartAddr = 0\r | |
980 | EndAddr = 0\r | |
981 | Default = 'DEFAULT|'\r | |
982 | InRange = False\r | |
983 | for Item in self._CfgItemList:\r | |
984 | if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r | |
985 | StartAddr = Item['offset']\r | |
986 | NextOffset = StartAddr\r | |
987 | InRange = True\r | |
988 | if Item['cname'] == 'UpdTerminator' and InRange == True:\r | |
989 | EndAddr = Item['offset']\r | |
990 | InRange = False\r | |
991 | InRange = False\r | |
992 | for Item in self._CfgItemList:\r | |
993 | if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:\r | |
994 | InRange = True\r | |
995 | if InRange != True:\r | |
996 | continue\r | |
997 | if Item['cname'] == 'UpdTerminator':\r | |
998 | InRange = False\r | |
999 | if Item['region'] != 'UPD':\r | |
1000 | continue\r | |
1001 | Offset = Item['offset']\r | |
1002 | if StartAddr > Offset or EndAddr < Offset:\r | |
1003 | continue\r | |
1004 | if NextOffset < Offset:\r | |
1005 | # insert one line\r | |
1006 | TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))\r | |
1007 | SpaceIdx = SpaceIdx + 1\r | |
1008 | NextOffset = Offset + Item['length']\r | |
cf1d4549 JY |
1009 | TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))\r |
1010 | TxtFd.close()\r | |
1011 | return 0\r | |
1012 | \r | |
27326112 LTL |
1013 | def CreateVarDict (self):\r |
1014 | Error = 0\r | |
1015 | self._VarDict = {}\r | |
1016 | if len(self._CfgItemList) > 0:\r | |
1017 | Item = self._CfgItemList[-1]\r | |
1018 | self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])\r | |
1019 | for Item in self._CfgItemList:\r | |
1020 | Embed = Item['embed']\r | |
1021 | Match = re.match("^(\w+):(\w+):(START|END)", Embed)\r | |
1022 | if Match:\r | |
1023 | StructName = Match.group(1)\r | |
1024 | VarName = '_%s_%s_' % (Match.group(3), StructName)\r | |
1025 | if Match.group(3) == 'END':\r | |
1026 | self._VarDict[VarName] = Item['offset'] + Item['length']\r | |
1027 | self._VarDict['_LENGTH_%s_' % StructName] = \\r | |
1028 | self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]\r | |
1029 | if Match.group(2).startswith('TAG_'):\r | |
1030 | if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):\r | |
1031 | raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))\r | |
1032 | self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF\r | |
cf1d4549 | 1033 | else:\r |
27326112 LTL |
1034 | self._VarDict[VarName] = Item['offset']\r |
1035 | if Item['marker']:\r | |
1036 | self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']\r | |
1037 | return Error\r | |
1038 | \r | |
1039 | def UpdateBsfBitUnit (self, Item):\r | |
1040 | BitTotal = 0\r | |
1041 | BitOffset = 0\r | |
1042 | StartIdx = 0\r | |
1043 | Unit = None\r | |
1044 | UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}\r | |
1045 | for Idx, SubItem in enumerate(Item['subreg']):\r | |
1046 | if Unit is None:\r | |
1047 | Unit = SubItem['bitunit']\r | |
1048 | BitLength = SubItem['bitlength']\r | |
1049 | BitTotal += BitLength\r | |
1050 | BitOffset += BitLength\r | |
1051 | \r | |
1052 | if BitOffset > 64 or BitOffset > Unit * 8:\r | |
1053 | break\r | |
1054 | \r | |
1055 | if BitOffset == Unit * 8:\r | |
1056 | for SubIdx in range (StartIdx, Idx + 1):\r | |
1057 | Item['subreg'][SubIdx]['bitunit'] = Unit\r | |
1058 | BitOffset = 0\r | |
1059 | StartIdx = Idx + 1\r | |
1060 | Unit = None\r | |
1061 | \r | |
1062 | if BitOffset > 0:\r | |
1063 | raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))\r | |
1064 | \r | |
1065 | ExpectedTotal = Item['length'] * 8\r | |
1066 | if Item['length'] * 8 != BitTotal:\r | |
1067 | raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))\r | |
1068 | \r | |
1069 | def UpdateDefaultValue (self):\r | |
1070 | Error = 0\r | |
1071 | for Idx, Item in enumerate(self._CfgItemList):\r | |
1072 | if len(Item['subreg']) == 0:\r | |
1073 | Value = Item['value']\r | |
1074 | if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):\r | |
1075 | # {XXX} or 'XXX' strings\r | |
1076 | self.FormatListValue(self._CfgItemList[Idx])\r | |
1077 | else:\r | |
1078 | Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)\r | |
1079 | if not Match:\r | |
1080 | NumValue = self.EvaluateExpress (Value)\r | |
1081 | Item['value'] = '0x%X' % NumValue\r | |
cf1d4549 | 1082 | else:\r |
27326112 LTL |
1083 | ValArray = self.ValueToByteArray (Item['value'], Item['length'])\r |
1084 | for SubItem in Item['subreg']:\r | |
1085 | SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)\r | |
1086 | self.UpdateBsfBitUnit (Item)\r | |
1087 | return Error\r | |
1088 | \r | |
1089 | def ProcessMultilines (self, String, MaxCharLength):\r | |
1090 | Multilines = ''\r | |
1091 | StringLength = len(String)\r | |
1092 | CurrentStringStart = 0\r | |
1093 | StringOffset = 0\r | |
1094 | BreakLineDict = []\r | |
1095 | if len(String) <= MaxCharLength:\r | |
1096 | while (StringOffset < StringLength):\r | |
1097 | if StringOffset >= 1:\r | |
1098 | if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r | |
1099 | BreakLineDict.append (StringOffset + 1)\r | |
1100 | StringOffset += 1\r | |
1101 | if BreakLineDict != []:\r | |
1102 | for Each in BreakLineDict:\r | |
1103 | Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r | |
1104 | CurrentStringStart = Each\r | |
1105 | if StringLength - CurrentStringStart > 0:\r | |
1106 | Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r | |
1107 | else:\r | |
1108 | Multilines = " %s\n" % String\r | |
1109 | else:\r | |
1110 | NewLineStart = 0\r | |
1111 | NewLineCount = 0\r | |
1112 | FoundSpaceChar = False\r | |
1113 | while (StringOffset < StringLength):\r | |
1114 | if StringOffset >= 1:\r | |
1115 | if NewLineCount >= MaxCharLength - 1:\r | |
1116 | if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r | |
1117 | BreakLineDict.append (NewLineStart + NewLineCount)\r | |
1118 | NewLineStart = NewLineStart + NewLineCount\r | |
cf1d4549 | 1119 | NewLineCount = 0\r |
27326112 LTL |
1120 | FoundSpaceChar = True\r |
1121 | elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r | |
1122 | BreakLineDict.append (0)\r | |
1123 | if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r | |
1124 | BreakLineDict.append (StringOffset + 1)\r | |
1125 | NewLineStart = StringOffset + 1\r | |
1126 | NewLineCount = 0\r | |
1127 | StringOffset += 1\r | |
1128 | NewLineCount += 1\r | |
1129 | if BreakLineDict != []:\r | |
1130 | BreakLineDict.sort ()\r | |
1131 | for Each in BreakLineDict:\r | |
1132 | if Each > 0:\r | |
1133 | Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r | |
1134 | CurrentStringStart = Each\r | |
1135 | if StringLength - CurrentStringStart > 0:\r | |
1136 | Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r | |
1137 | return Multilines\r | |
1138 | \r | |
1139 | def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):\r | |
cf1d4549 JY |
1140 | PosName = 28\r |
1141 | PosComment = 30\r | |
1142 | NameLine=''\r | |
1143 | HelpLine=''\r | |
1144 | OptionLine=''\r | |
1145 | \r | |
27326112 LTL |
1146 | if Length == 0 and Name == 'Dummy':\r |
1147 | return '\n'\r | |
1148 | \r | |
cf1d4549 JY |
1149 | IsArray = False\r |
1150 | if Length in [1,2,4,8]:\r | |
1151 | Type = "UINT%d" % (Length * 8)\r | |
cd3692b1 SY |
1152 | if Name.startswith("UnusedUpdSpace") and Length != 1:\r |
1153 | IsArray = True\r | |
1154 | Type = "UINT8"\r | |
cf1d4549 JY |
1155 | else:\r |
1156 | IsArray = True\r | |
1157 | Type = "UINT8"\r | |
1158 | \r | |
1159 | if Item and Item['value'].startswith('{'):\r | |
1160 | Type = "UINT8"\r | |
1161 | IsArray = True\r | |
1162 | \r | |
1163 | if Struct != '':\r | |
1164 | Type = Struct\r | |
1165 | if Struct in ['UINT8','UINT16','UINT32','UINT64']:\r | |
1166 | IsArray = True\r | |
1167 | Unit = int(Type[4:]) / 8\r | |
1168 | Length = Length / Unit\r | |
1169 | else:\r | |
1170 | IsArray = False\r | |
1171 | \r | |
1172 | if IsArray:\r | |
1173 | Name = Name + '[%d]' % Length\r | |
1174 | \r | |
1175 | if len(Type) < PosName:\r | |
1176 | Space1 = PosName - len(Type)\r | |
1177 | else:\r | |
1178 | Space1 = 1\r | |
1179 | \r | |
1180 | if BsfName != '':\r | |
1181 | NameLine=" - %s\n" % BsfName\r | |
1182 | else:\r | |
1183 | NameLine="\n"\r | |
1184 | \r | |
1185 | if Help != '':\r | |
1186 | HelpLine = self.ProcessMultilines (Help, 80)\r | |
1187 | \r | |
1188 | if Option != '':\r | |
1189 | OptionLine = self.ProcessMultilines (Option, 80)\r | |
1190 | \r | |
1191 | if Offset is None:\r | |
1192 | OffsetStr = '????'\r | |
1193 | else:\r | |
1194 | OffsetStr = '0x%04X' % Offset\r | |
1195 | \r | |
27326112 LTL |
1196 | if BitsLength is None:\r |
1197 | BitsLength = ''\r | |
1198 | else:\r | |
1199 | BitsLength = ' : %d' % BitsLength\r | |
1200 | \r | |
1201 | return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)\r | |
cf1d4549 JY |
1202 | \r |
1203 | def PostProcessBody (self, TextBody):\r | |
1204 | NewTextBody = []\r | |
1205 | OldTextBody = []\r | |
1206 | IncludeLine = False\r | |
1207 | StructName = ''\r | |
1208 | VariableName = ''\r | |
1209 | IsUpdHdrDefined = False\r | |
1210 | IsUpdHeader = False\r | |
1211 | for Line in TextBody:\r | |
1212 | SplitToLines = Line.splitlines()\r | |
1213 | MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])\r | |
1214 | if MatchComment:\r | |
1215 | if MatchComment.group(1) == 'FSP_UPD_HEADER':\r | |
1216 | IsUpdHeader = True\r | |
1217 | else:\r | |
1218 | IsUpdHeader = False\r | |
1219 | if IsUpdHdrDefined != True or IsUpdHeader != True:\r | |
1220 | CommentLine = " " + MatchComment.group(2) + "\n"\r | |
1221 | NewTextBody.append("/**" + CommentLine + "**/\n")\r | |
1222 | Line = Line[(len(SplitToLines[0]) + 1):]\r | |
1223 | \r | |
1224 | Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)\r | |
1225 | if Match:\r | |
1226 | Line = Match.group(4)\r | |
1227 | if Match.group(1) == 'FSP_UPD_HEADER':\r | |
1228 | IsUpdHeader = True\r | |
1229 | else:\r | |
1230 | IsUpdHeader = False\r | |
1231 | \r | |
1232 | if Match and Match.group(3) == 'START':\r | |
1233 | if IsUpdHdrDefined != True or IsUpdHeader != True:\r | |
1234 | NewTextBody.append ('typedef struct {\n')\r | |
1235 | StructName = Match.group(1)\r | |
1236 | VariableName = Match.group(2)\r | |
1237 | MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)\r | |
1238 | if MatchOffset:\r | |
1239 | Offset = int(MatchOffset.group(1), 16)\r | |
1240 | else:\r | |
1241 | Offset = None\r | |
1242 | Line\r | |
1243 | IncludeLine = True\r | |
1244 | OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))\r | |
1245 | if IncludeLine:\r | |
1246 | if IsUpdHdrDefined != True or IsUpdHeader != True:\r | |
1247 | NewTextBody.append (Line)\r | |
1248 | else:\r | |
1249 | OldTextBody.append (Line)\r | |
1250 | \r | |
62997d5e | 1251 | if Match and Match.group(3) == 'END':\r |
cf1d4549 | 1252 | if (StructName != Match.group(1)) or (VariableName != Match.group(2)):\r |
c3f0829b | 1253 | print ("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)))\r |
cf1d4549 JY |
1254 | else:\r |
1255 | if IsUpdHdrDefined != True or IsUpdHeader != True:\r | |
1256 | NewTextBody.append ('} %s;\n\n' % StructName)\r | |
1257 | IsUpdHdrDefined = True\r | |
1258 | IncludeLine = False\r | |
1259 | NewTextBody.extend(OldTextBody)\r | |
1260 | return NewTextBody\r | |
1261 | \r | |
d75c07bc CC |
1262 | def WriteLinesWithoutTailingSpace (self, HeaderFd, Line):\r |
1263 | TxtBody2 = Line.splitlines(True)\r | |
1264 | for Line2 in TxtBody2:\r | |
1265 | Line2 = Line2.rstrip()\r | |
1266 | Line2 += '\n'\r | |
1267 | HeaderFd.write (Line2)\r | |
1268 | return 0\r | |
cf1d4549 JY |
1269 | def CreateHeaderFile (self, InputHeaderFile):\r |
1270 | FvDir = self._FvDir\r | |
1271 | \r | |
1272 | HeaderFileName = 'FspUpd.h'\r | |
1273 | HeaderFile = os.path.join(FvDir, HeaderFileName)\r | |
1274 | \r | |
1275 | # Check if header needs to be recreated\r | |
cc942105 CC |
1276 | if (self.NoDscFileChange (HeaderFile)):\r |
1277 | # DSC has not been modified yet\r | |
1278 | # So don't have to re-generate other files\r | |
1279 | self.Error = 'No DSC file change, skip to create UPD header file'\r | |
1280 | return 256\r | |
cf1d4549 JY |
1281 | \r |
1282 | TxtBody = []\r | |
1283 | for Item in self._CfgItemList:\r | |
1284 | if str(Item['cname']) == 'Signature' and Item['length'] == 8:\r | |
1285 | Value = int(Item['value'], 16)\r | |
1286 | Chars = []\r | |
1287 | while Value != 0x0:\r | |
1288 | Chars.append(chr(Value & 0xFF))\r | |
1289 | Value = Value >> 8\r | |
1290 | SignatureStr = ''.join(Chars)\r | |
1291 | # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly\r | |
1292 | if '_T' in SignatureStr[6:6+2]:\r | |
1293 | TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r | |
1294 | elif '_M' in SignatureStr[6:6+2]:\r | |
1295 | TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r | |
1296 | elif '_S' in SignatureStr[6:6+2]:\r | |
1297 | TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))\r | |
1298 | TxtBody.append("\n")\r | |
1299 | \r | |
1300 | for Region in ['UPD']:\r | |
1301 | UpdOffsetTable = []\r | |
1302 | UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS\r | |
1303 | UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r | |
1304 | for Item in self._CfgItemList:\r | |
1305 | if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r | |
27326112 | 1306 | Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting\r |
cf1d4549 JY |
1307 | UpdOffsetTable.append (Item["offset"])\r |
1308 | \r | |
1309 | for UpdIdx in range(len(UpdOffsetTable)):\r | |
1310 | CommentLine = ""\r | |
1311 | for Item in self._CfgItemList:\r | |
1312 | if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:\r | |
1313 | MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])\r | |
1314 | if MatchComment and MatchComment.group(1) == Region[0]:\r | |
1315 | CommentLine = " " + MatchComment.group(2) + "\n"\r | |
1316 | TxtBody.append("/**" + CommentLine + "**/\n")\r | |
1317 | elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':\r | |
1318 | Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])\r | |
1319 | if Match:\r | |
1320 | TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")\r | |
1321 | TxtBody.append("typedef struct {\n")\r | |
1322 | NextOffset = 0\r | |
1323 | SpaceIdx = 0\r | |
1324 | Offset = 0\r | |
1325 | \r | |
1326 | LastVisible = True\r | |
1327 | ResvOffset = 0\r | |
1328 | ResvIdx = 0\r | |
1329 | LineBuffer = []\r | |
1330 | InRange = False\r | |
1331 | for Item in self._CfgItemList:\r | |
1332 | if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':\r | |
1333 | InRange = True\r | |
1334 | if InRange != True:\r | |
1335 | continue\r | |
1336 | if Item['cname'] == 'UpdTerminator':\r | |
1337 | InRange = False\r | |
1338 | \r | |
1339 | if Item['region'] != Region:\r | |
1340 | continue\r | |
1341 | \r | |
1342 | if Item["offset"] < UpdOffsetTable[UpdIdx]:\r | |
1343 | continue\r | |
1344 | \r | |
1345 | NextVisible = LastVisible\r | |
1346 | \r | |
1347 | if LastVisible and (Item['header'] == 'OFF'):\r | |
1348 | NextVisible = False\r | |
1349 | ResvOffset = Item['offset']\r | |
1350 | elif (not LastVisible) and Item['header'] == 'ON':\r | |
1351 | NextVisible = True\r | |
1352 | Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx\r | |
1353 | ResvIdx = ResvIdx + 1\r | |
1354 | TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))\r | |
1355 | \r | |
1356 | if Offset < Item["offset"]:\r | |
1357 | if LastVisible:\r | |
1358 | Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx\r | |
1359 | LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))\r | |
1360 | SpaceIdx = SpaceIdx + 1\r | |
1361 | Offset = Item["offset"]\r | |
1362 | \r | |
1363 | LastVisible = NextVisible\r | |
1364 | \r | |
1365 | Offset = Offset + Item["length"]\r | |
1366 | if LastVisible:\r | |
1367 | for Each in LineBuffer:\r | |
1368 | TxtBody.append (Each)\r | |
1369 | LineBuffer = []\r | |
1370 | Comment = Item["comment"]\r | |
1371 | Embed = Item["embed"].upper()\r | |
1372 | if Embed.endswith(':START') or Embed.endswith(':END'):\r | |
1373 | if not Comment == '' and Embed.endswith(':START'):\r | |
1374 | Marker = '/* COMMENT:%s */ \n' % Item["comment"]\r | |
1375 | Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r | |
1376 | else:\r | |
1377 | Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]\r | |
1378 | else:\r | |
1379 | if Embed == '':\r | |
62997d5e | 1380 | Marker = ''\r |
cf1d4549 JY |
1381 | else:\r |
1382 | self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]\r | |
1383 | return 4\r | |
1384 | Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])\r | |
1385 | TxtBody.append(Line)\r | |
1386 | if Item['cname'] == 'UpdTerminator':\r | |
1387 | break\r | |
1388 | TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")\r | |
62997d5e | 1389 | \r |
cf1d4549 JY |
1390 | # Handle the embedded data structure\r |
1391 | TxtBody = self.PostProcessBody (TxtBody)\r | |
1392 | \r | |
1393 | HeaderTFileName = 'FsptUpd.h'\r | |
1394 | HeaderMFileName = 'FspmUpd.h'\r | |
1395 | HeaderSFileName = 'FspsUpd.h'\r | |
1396 | \r | |
1397 | UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION\r | |
1398 | UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r | |
1399 | UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r | |
89f569ae | 1400 | ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']\r |
6f219bef | 1401 | ExcludedSpecificUpd1 = ['FSPT_ARCH2_UPD', 'FSPM_ARCH2_UPD', 'FSPS_ARCH2_UPD']\r |
cf1d4549 | 1402 | \r |
1d058c3e | 1403 | IncLines = []\r |
cf1d4549 JY |
1404 | if InputHeaderFile != '':\r |
1405 | if not os.path.exists(InputHeaderFile):\r | |
1406 | self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r | |
1407 | return 6\r | |
1408 | \r | |
1409 | InFd = open(InputHeaderFile, "r")\r | |
1410 | IncLines = InFd.readlines()\r | |
1411 | InFd.close()\r | |
1412 | \r | |
1413 | for item in range(len(UpdRegionCheck)):\r | |
1414 | if UpdRegionCheck[item] == 'FSPT':\r | |
1415 | HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")\r | |
1416 | FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))\r | |
1417 | elif UpdRegionCheck[item] == 'FSPM':\r | |
1418 | HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")\r | |
1419 | FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))\r | |
1420 | elif UpdRegionCheck[item] == 'FSPS':\r | |
1421 | HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")\r | |
1422 | FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))\r | |
1423 | FileName = FileBase.replace(".", "_").upper()\r | |
1424 | HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r | |
1425 | HeaderFd.write("#ifndef __%s__\n" % FileName)\r | |
1426 | HeaderFd.write("#define __%s__\n\n" % FileName)\r | |
1427 | HeaderFd.write("#include <%s>\n\n" % HeaderFileName)\r | |
cd3692b1 | 1428 | HeaderFd.write("#pragma pack(1)\n\n")\r |
cf1d4549 JY |
1429 | \r |
1430 | Export = False\r | |
1431 | for Line in IncLines:\r | |
1432 | Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)\r | |
1433 | if Match:\r | |
1434 | if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:\r | |
1435 | Export = True\r | |
1436 | continue\r | |
1437 | else:\r | |
1438 | Export = False\r | |
1439 | continue\r | |
1440 | if Export:\r | |
1441 | HeaderFd.write(Line)\r | |
1442 | HeaderFd.write("\n")\r | |
1443 | \r | |
1444 | Index = 0\r | |
1445 | StartIndex = 0\r | |
1446 | EndIndex = 0\r | |
1447 | StructStart = []\r | |
1448 | StructStartWithComment = []\r | |
1449 | StructEnd = []\r | |
1450 | for Line in TxtBody:\r | |
1451 | Index += 1\r | |
1452 | Match = re.match("(typedef struct {)", Line)\r | |
1453 | if Match:\r | |
1454 | StartIndex = Index - 1\r | |
1455 | Match = re.match("}\s([_A-Z0-9]+);", Line)\r | |
6f219bef | 1456 | 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 |
1457 | EndIndex = Index\r |
1458 | StructStart.append(StartIndex)\r | |
1459 | StructEnd.append(EndIndex)\r | |
1460 | Index = 0\r | |
1461 | for Line in TxtBody:\r | |
1462 | Index += 1\r | |
1463 | for Item in range(len(StructStart)):\r | |
1464 | if Index == StructStart[Item]:\r | |
1465 | Match = re.match("^(/\*\*\s*)", Line)\r | |
1466 | if Match:\r | |
1467 | StructStartWithComment.append(StructStart[Item])\r | |
1468 | else:\r | |
1469 | StructStartWithComment.append(StructStart[Item] + 1)\r | |
1470 | Index = 0\r | |
1471 | for Line in TxtBody:\r | |
1472 | Index += 1\r | |
1473 | for Item in range(len(StructStart)):\r | |
1474 | if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r | |
d75c07bc | 1475 | self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r |
cd3692b1 | 1476 | HeaderFd.write("#pragma pack()\n\n")\r |
cf1d4549 JY |
1477 | HeaderFd.write("#endif\n")\r |
1478 | HeaderFd.close()\r | |
1479 | \r | |
1480 | HeaderFd = open(HeaderFile, "w")\r | |
1481 | FileBase = os.path.basename(HeaderFile)\r | |
1482 | FileName = FileBase.replace(".", "_").upper()\r | |
1483 | HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))\r | |
1484 | HeaderFd.write("#ifndef __%s__\n" % FileName)\r | |
1485 | HeaderFd.write("#define __%s__\n\n" % FileName)\r | |
1486 | HeaderFd.write("#include <FspEas.h>\n\n")\r | |
cd3692b1 | 1487 | HeaderFd.write("#pragma pack(1)\n\n")\r |
cf1d4549 JY |
1488 | \r |
1489 | for item in range(len(UpdRegionCheck)):\r | |
1490 | Index = 0\r | |
1491 | StartIndex = 0\r | |
1492 | EndIndex = 0\r | |
1493 | StructStart = []\r | |
1494 | StructStartWithComment = []\r | |
1495 | StructEnd = []\r | |
1496 | for Line in TxtBody:\r | |
1497 | Index += 1\r | |
1498 | Match = re.match("(typedef struct {)", Line)\r | |
1499 | if Match:\r | |
1500 | StartIndex = Index - 1\r | |
1501 | Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)\r | |
1502 | if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):\r | |
1503 | StructStart.append(Index - 1)\r | |
1504 | StructEnd.append(Index)\r | |
1505 | Index = 0\r | |
1506 | for Line in TxtBody:\r | |
1507 | Index += 1\r | |
1508 | for Item in range(len(StructStart)):\r | |
1509 | if Index == StructStart[Item]:\r | |
1510 | Match = re.match("^(/\*\*\s*)", Line)\r | |
1511 | if Match:\r | |
1512 | StructStartWithComment.append(StructStart[Item])\r | |
1513 | else:\r | |
1514 | StructStartWithComment.append(StructStart[Item] + 1)\r | |
1515 | Index = 0\r | |
1516 | for Line in TxtBody:\r | |
1517 | Index += 1\r | |
1518 | for Item in range(len(StructStart)):\r | |
1519 | if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:\r | |
d75c07bc | 1520 | self.WriteLinesWithoutTailingSpace(HeaderFd, Line)\r |
cd3692b1 | 1521 | HeaderFd.write("#pragma pack()\n\n")\r |
cf1d4549 JY |
1522 | HeaderFd.write("#endif\n")\r |
1523 | HeaderFd.close()\r | |
1524 | \r | |
1525 | return 0\r | |
1526 | \r | |
1527 | def WriteBsfStruct (self, BsfFd, Item):\r | |
ba8ea427 | 1528 | LogExpr = CLogicalExpression()\r |
cf1d4549 JY |
1529 | if Item['type'] == "None":\r |
1530 | Space = "gPlatformFspPkgTokenSpaceGuid"\r | |
1531 | else:\r | |
1532 | Space = Item['space']\r | |
1533 | Line = " $%s_%s" % (Space, Item['cname'])\r | |
1534 | Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])\r | |
1535 | if Match:\r | |
1536 | DefaultValue = Match.group(1).strip()\r | |
1537 | else:\r | |
1538 | DefaultValue = Item['value'].strip()\r | |
62997d5e MM |
1539 | if 'bitlength' in Item:\r |
1540 | BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))\r | |
1541 | else:\r | |
1542 | BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))\r | |
cf1d4549 JY |
1543 | TmpList = []\r |
1544 | if Item['type'] == "Combo":\r | |
1545 | if not Item['option'] in self._BuidinOption:\r | |
1546 | OptList = Item['option'].split(',')\r | |
1547 | for Option in OptList:\r | |
1548 | Option = Option.strip()\r | |
1549 | (OpVal, OpStr) = Option.split(':')\r | |
ba8ea427 TRM |
1550 | test = LogExpr.getNumber (OpVal)\r |
1551 | if test is None:\r | |
1552 | raise Exception("Selection Index '%s' is not a number" % OpVal)\r | |
cf1d4549 JY |
1553 | TmpList.append((OpVal, OpStr))\r |
1554 | return TmpList\r | |
1555 | \r | |
1556 | def WriteBsfOption (self, BsfFd, Item):\r | |
1557 | PcdName = Item['space'] + '_' + Item['cname']\r | |
1558 | WriteHelp = 0\r | |
1559 | if Item['type'] == "Combo":\r | |
1560 | if Item['option'] in self._BuidinOption:\r | |
1561 | Options = self._BuidinOption[Item['option']]\r | |
1562 | else:\r | |
1563 | Options = PcdName\r | |
62997d5e | 1564 | BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))\r |
cf1d4549 JY |
1565 | WriteHelp = 1\r |
1566 | elif Item['type'].startswith("EditNum"):\r | |
1567 | 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 | |
1568 | if Match:\r | |
62997d5e | 1569 | BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))\r |
cf1d4549 JY |
1570 | WriteHelp = 2\r |
1571 | elif Item['type'].startswith("EditText"):\r | |
62997d5e | 1572 | BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))\r |
cf1d4549 JY |
1573 | WriteHelp = 1\r |
1574 | elif Item['type'] == "Table":\r | |
1575 | Columns = Item['option'].split(',')\r | |
1576 | if len(Columns) != 0:\r | |
62997d5e | 1577 | BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))\r |
cf1d4549 JY |
1578 | for Col in Columns:\r |
1579 | Fmt = Col.split(':')\r | |
1580 | if len(Fmt) != 3:\r | |
1581 | raise Exception("Column format '%s' is invalid !" % Fmt)\r | |
1582 | try:\r | |
1583 | Dtype = int(Fmt[1].strip())\r | |
1584 | except:\r | |
1585 | raise Exception("Column size '%s' is invalid !" % Fmt[1])\r | |
1586 | BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r | |
1587 | BsfFd.write(',\n')\r | |
1588 | WriteHelp = 1\r | |
62997d5e | 1589 | \r |
cf1d4549 JY |
1590 | if WriteHelp > 0:\r |
1591 | HelpLines = Item['help'].split('\\n\\r')\r | |
1592 | FirstLine = True\r | |
1593 | for HelpLine in HelpLines:\r | |
1594 | if FirstLine:\r | |
1595 | FirstLine = False\r | |
62997d5e | 1596 | BsfFd.write(' Help "%s"\n' % (HelpLine))\r |
cf1d4549 | 1597 | else:\r |
62997d5e | 1598 | BsfFd.write(' "%s"\n' % (HelpLine))\r |
cf1d4549 | 1599 | if WriteHelp == 2:\r |
62997d5e | 1600 | BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))\r |
cf1d4549 JY |
1601 | \r |
1602 | def GenerateBsfFile (self, BsfFile):\r | |
1603 | \r | |
1604 | if BsfFile == '':\r | |
1605 | self.Error = "BSF output file '%s' is invalid" % BsfFile\r | |
1606 | return 1\r | |
1607 | \r | |
cc942105 CC |
1608 | if (self.NoDscFileChange (BsfFile)):\r |
1609 | # DSC has not been modified yet\r | |
1610 | # So don't have to re-generate other files\r | |
1611 | self.Error = 'No DSC file change, skip to create UPD BSF file'\r | |
1612 | return 256\r | |
1613 | \r | |
cf1d4549 JY |
1614 | Error = 0\r |
1615 | OptionDict = {}\r | |
1616 | BsfFd = open(BsfFile, "w")\r | |
1617 | BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))\r | |
62997d5e | 1618 | BsfFd.write("%s\n" % self._GlobalDataDef)\r |
cf1d4549 JY |
1619 | BsfFd.write("StructDef\n")\r |
1620 | NextOffset = -1\r | |
1621 | for Item in self._CfgItemList:\r | |
1622 | if Item['find'] != '':\r | |
1623 | BsfFd.write('\n Find "%s"\n' % Item['find'])\r | |
1624 | NextOffset = Item['offset'] + Item['length']\r | |
1625 | if Item['name'] != '':\r | |
1626 | if NextOffset != Item['offset']:\r | |
1627 | BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))\r | |
1628 | if len(Item['subreg']) > 0:\r | |
1629 | NextOffset = Item['offset']\r | |
62997d5e | 1630 | BitsOffset = NextOffset * 8\r |
cf1d4549 | 1631 | for SubItem in Item['subreg']:\r |
62997d5e | 1632 | BitsOffset += SubItem['bitlength']\r |
cf1d4549 | 1633 | if SubItem['name'] == '':\r |
62997d5e MM |
1634 | if 'bitlength' in SubItem:\r |
1635 | BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))\r | |
1636 | else:\r | |
1637 | BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))\r | |
cf1d4549 JY |
1638 | else:\r |
1639 | Options = self.WriteBsfStruct(BsfFd, SubItem)\r | |
1640 | if len(Options) > 0:\r | |
1641 | OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options\r | |
62997d5e MM |
1642 | \r |
1643 | NextBitsOffset = (Item['offset'] + Item['length']) * 8\r | |
1644 | if NextBitsOffset > BitsOffset:\r | |
1645 | BitsGap = NextBitsOffset - BitsOffset\r | |
1646 | BitsRemain = BitsGap % 8\r | |
1647 | if BitsRemain:\r | |
1648 | BsfFd.write(" Skip %d bits\n" % BitsRemain)\r | |
1649 | BitsGap -= BitsRemain\r | |
5e4ebd9e | 1650 | BytesRemain = int(BitsGap / 8)\r |
62997d5e MM |
1651 | if BytesRemain:\r |
1652 | BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r | |
1653 | NextOffset = Item['offset'] + Item['length']\r | |
cf1d4549 JY |
1654 | else:\r |
1655 | NextOffset = Item['offset'] + Item['length']\r | |
1656 | Options = self.WriteBsfStruct(BsfFd, Item)\r | |
1657 | if len(Options) > 0:\r | |
1658 | OptionDict[Item['space']+'_'+Item['cname']] = Options\r | |
1659 | BsfFd.write("\nEndStruct\n\n")\r | |
1660 | \r | |
62997d5e | 1661 | BsfFd.write("%s" % self._BuidinOptionTxt)\r |
cf1d4549 JY |
1662 | \r |
1663 | for Each in OptionDict:\r | |
62997d5e | 1664 | BsfFd.write("List &%s\n" % Each)\r |
cf1d4549 | 1665 | for Item in OptionDict[Each]:\r |
62997d5e MM |
1666 | BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))\r |
1667 | BsfFd.write("EndList\n\n")\r | |
cf1d4549 | 1668 | \r |
62997d5e MM |
1669 | BsfFd.write("BeginInfoBlock\n")\r |
1670 | BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r | |
1671 | BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r | |
1672 | BsfFd.write("EndInfoBlock\n\n")\r | |
cf1d4549 JY |
1673 | \r |
1674 | for Each in self._CfgPageDict:\r | |
62997d5e | 1675 | BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])\r |
cf1d4549 JY |
1676 | BsfItems = []\r |
1677 | for Item in self._CfgItemList:\r | |
1678 | if Item['name'] != '':\r | |
1679 | if Item['page'] != Each:\r | |
1680 | continue\r | |
1681 | if len(Item['subreg']) > 0:\r | |
1682 | for SubItem in Item['subreg']:\r | |
1683 | if SubItem['name'] != '':\r | |
1684 | BsfItems.append(SubItem)\r | |
1685 | else:\r | |
1686 | BsfItems.append(Item)\r | |
1687 | \r | |
1688 | BsfItems.sort(key=lambda x: x['order'])\r | |
1689 | \r | |
1690 | for Item in BsfItems:\r | |
1691 | self.WriteBsfOption (BsfFd, Item)\r | |
62997d5e | 1692 | BsfFd.write("EndPage\n\n")\r |
cf1d4549 JY |
1693 | \r |
1694 | BsfFd.close()\r | |
1695 | return Error\r | |
1696 | \r | |
1697 | \r | |
1698 | def Usage():\r | |
6f219bef | 1699 | print ("GenCfgOpt Version 0.57")\r |
c3f0829b CC |
1700 | print ("Usage:")\r |
1701 | print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")\r | |
1702 | print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")\r | |
1703 | print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")\r | |
cf1d4549 JY |
1704 | \r |
1705 | def Main():\r | |
1706 | #\r | |
1707 | # Parse the options and args\r | |
1708 | #\r | |
b9c055f7 CC |
1709 | i = 1\r |
1710 | \r | |
cf1d4549 | 1711 | GenCfgOpt = CGenCfgOpt()\r |
b9c055f7 CC |
1712 | while i < len(sys.argv):\r |
1713 | if sys.argv[i].strip().lower() == "--pcd":\r | |
1714 | BuildOptionPcd.append(sys.argv[i+1])\r | |
1715 | i += 1\r | |
1716 | i += 1\r | |
cf1d4549 JY |
1717 | argc = len(sys.argv)\r |
1718 | if argc < 4:\r | |
1719 | Usage()\r | |
1720 | return 1\r | |
1721 | else:\r | |
1722 | DscFile = sys.argv[2]\r | |
1723 | if not os.path.exists(DscFile):\r | |
c3f0829b | 1724 | print ("ERROR: Cannot open DSC file '%s' !" % DscFile)\r |
cf1d4549 | 1725 | return 2\r |
cf1d4549 JY |
1726 | \r |
1727 | OutFile = ''\r | |
1728 | if argc > 4:\r | |
62997d5e | 1729 | if sys.argv[4][0] == '-':\r |
cf1d4549 JY |
1730 | Start = 4\r |
1731 | else:\r | |
62997d5e | 1732 | OutFile = sys.argv[4]\r |
cf1d4549 | 1733 | Start = 5\r |
e4408576 OBO |
1734 | if argc > Start:\r |
1735 | if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:\r | |
c3f0829b | 1736 | print ("ERROR: Macro parsing failed !")\r |
e4408576 | 1737 | return 3\r |
cf1d4549 JY |
1738 | \r |
1739 | FvDir = sys.argv[3]\r | |
1740 | if not os.path.exists(FvDir):\r | |
1741 | os.makedirs(FvDir)\r | |
1742 | \r | |
62997d5e | 1743 | if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:\r |
c3f0829b | 1744 | print ("ERROR: %s !" % GenCfgOpt.Error)\r |
cf1d4549 JY |
1745 | return 5\r |
1746 | \r | |
1747 | if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:\r | |
c3f0829b | 1748 | print ("ERROR: %s !" % GenCfgOpt.Error)\r |
cf1d4549 JY |
1749 | return 7\r |
1750 | \r | |
1751 | if sys.argv[1] == "UPDTXT":\r | |
1752 | Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)\r | |
1753 | if Ret != 0:\r | |
1754 | # No change is detected\r | |
1755 | if Ret == 256:\r | |
c3f0829b | 1756 | print ("INFO: %s !" % (GenCfgOpt.Error))\r |
cf1d4549 | 1757 | else :\r |
c3f0829b | 1758 | print ("ERROR: %s !" % (GenCfgOpt.Error))\r |
cf1d4549 JY |
1759 | return Ret\r |
1760 | elif sys.argv[1] == "HEADER":\r | |
cc942105 CC |
1761 | Ret = GenCfgOpt.CreateHeaderFile(OutFile)\r |
1762 | if Ret != 0:\r | |
1763 | # No change is detected\r | |
1764 | if Ret == 256:\r | |
1765 | print ("INFO: %s !" % (GenCfgOpt.Error))\r | |
1766 | else :\r | |
1767 | print ("ERROR: %s !" % (GenCfgOpt.Error))\r | |
1768 | return 8\r | |
1769 | return Ret\r | |
cf1d4549 | 1770 | elif sys.argv[1] == "GENBSF":\r |
cc942105 CC |
1771 | Ret = GenCfgOpt.GenerateBsfFile(OutFile)\r |
1772 | if Ret != 0:\r | |
1773 | # No change is detected\r | |
1774 | if Ret == 256:\r | |
1775 | print ("INFO: %s !" % (GenCfgOpt.Error))\r | |
1776 | else :\r | |
1777 | print ("ERROR: %s !" % (GenCfgOpt.Error))\r | |
1778 | return 9\r | |
1779 | return Ret\r | |
cf1d4549 JY |
1780 | else:\r |
1781 | if argc < 5:\r | |
1782 | Usage()\r | |
1783 | return 1\r | |
c3f0829b | 1784 | print ("ERROR: Unknown command '%s' !" % sys.argv[1])\r |
cf1d4549 JY |
1785 | Usage()\r |
1786 | return 1\r | |
1787 | return 0\r | |
1788 | return 0\r | |
1789 | \r | |
1790 | \r | |
1791 | if __name__ == '__main__':\r | |
1792 | sys.exit(Main())\r |