]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Tools/FspGenCfgData.py
DynamicTablesPkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / IntelFsp2Pkg / Tools / FspGenCfgData.py
CommitLineData
580b1120
LTL
1# @ GenCfgData.py\r
2#\r
3# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>\r
4# SPDX-License-Identifier: BSD-2-Clause-Patent\r
5#\r
6##\r
7\r
8import os\r
9import re\r
10import sys\r
11import marshal\r
12from functools import reduce\r
13from datetime import date\r
14\r
15# Generated file copyright header\r
16\r
17__copyright_tmp__ = """/** @file\r
18\r
19 Configuration %s File.\r
20\r
21 Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>\r
22 SPDX-License-Identifier: BSD-2-Clause-Patent\r
23\r
24 This file is automatically generated. Please do NOT modify !!!\r
25\r
26**/\r
27"""\r
28\r
29__copyright_dsc__ = """## @file\r
30#\r
31# Copyright (c) %04d, Intel Corporation. All rights reserved.<BR>\r
32# SPDX-License-Identifier: BSD-2-Clause-Patent\r
33#\r
34##\r
35\r
36[PcdsDynamicVpd.Upd]\r
37 #\r
38 # Global definitions in BSF\r
39 # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"}\r
40 #\r
41\r
42"""\r
43\r
44\r
45def Bytes2Val(Bytes):\r
46 return reduce(lambda x, y: (x << 8) | y, Bytes[::-1])\r
47\r
48\r
49def Bytes2Str(Bytes):\r
50 return '{ %s }' % (', '.join('0x%02X' % i for i in Bytes))\r
51\r
52\r
53def Str2Bytes(Value, Blen):\r
54 Result = bytearray(Value[1:-1], 'utf-8') # Excluding quotes\r
55 if len(Result) < Blen:\r
56 Result.extend(b'\x00' * (Blen - len(Result)))\r
57 return Result\r
58\r
59\r
60def Val2Bytes(Value, Blen):\r
61 return [(Value >> (i * 8) & 0xff) for i in range(Blen)]\r
62\r
63\r
64def Array2Val(ValStr):\r
65 ValStr = ValStr.strip()\r
66 if ValStr.startswith('{'):\r
67 ValStr = ValStr[1:]\r
68 if ValStr.endswith('}'):\r
69 ValStr = ValStr[:-1]\r
70 if ValStr.startswith("'"):\r
71 ValStr = ValStr[1:]\r
72 if ValStr.endswith("'"):\r
73 ValStr = ValStr[:-1]\r
74 Value = 0\r
75 for Each in ValStr.split(',')[::-1]:\r
76 Each = Each.strip()\r
77 if Each.startswith('0x'):\r
78 Base = 16\r
79 else:\r
80 Base = 10\r
81 Value = (Value << 8) | int(Each, Base)\r
82 return Value\r
83\r
84\r
85def GetCopyrightHeader(FileType, AllowModify=False):\r
86 FileDescription = {\r
87 'bsf': 'Boot Setting',\r
88 'dsc': 'Definition',\r
89 'dlt': 'Delta',\r
90 'inc': 'C Binary Blob',\r
91 'h': 'C Struct Header'\r
92 }\r
93 if FileType in ['bsf', 'dsc', 'dlt']:\r
94 CommentChar = '#'\r
95 else:\r
96 CommentChar = ''\r
97 Lines = __copyright_tmp__.split('\n')\r
98\r
99 if AllowModify:\r
100 Lines = [Line for Line in Lines if 'Please do NOT modify' not in Line]\r
101\r
102 CopyrightHdr = '\n'.join('%s%s' % (\r
103 CommentChar, Line) for Line in Lines)[:-1] + '\n'\r
104\r
105 return CopyrightHdr % (FileDescription[FileType], date.today().year)\r
106\r
107\r
108class CLogicalExpression:\r
109 def __init__(self):\r
110 self.index = 0\r
111 self.string = ''\r
112\r
113 def errExit(self, err=''):\r
114 print("ERROR: Express parsing for:")\r
115 print(" %s" % self.string)\r
116 print(" %s^" % (' ' * self.index))\r
117 if err:\r
118 print("INFO : %s" % err)\r
119 raise SystemExit\r
120\r
121 def getNonNumber(self, n1, n2):\r
122 if not n1.isdigit():\r
123 return n1\r
124 if not n2.isdigit():\r
125 return n2\r
126 return None\r
127\r
128 def getCurr(self, lens=1):\r
129 try:\r
130 if lens == -1:\r
131 return self.string[self.index:]\r
132 else:\r
133 if self.index + lens > len(self.string):\r
134 lens = len(self.string) - self.index\r
135 return self.string[self.index: self.index + lens]\r
136 except Exception:\r
137 return ''\r
138\r
139 def isLast(self):\r
140 return self.index == len(self.string)\r
141\r
142 def moveNext(self, len=1):\r
143 self.index += len\r
144\r
145 def skipSpace(self):\r
146 while not self.isLast():\r
147 if self.getCurr() in ' \t':\r
148 self.moveNext()\r
149 else:\r
150 return\r
151\r
152 def normNumber(self, val):\r
153 return True if val else False\r
154\r
155 def getNumber(self, var):\r
156 var = var.strip()\r
157 if re.match('^0x[a-fA-F0-9]+$', var):\r
158 value = int(var, 16)\r
159 elif re.match('^[+-]?\\d+$', var):\r
160 value = int(var, 10)\r
161 else:\r
162 value = None\r
163 return value\r
164\r
165 def parseValue(self):\r
166 self.skipSpace()\r
167 var = ''\r
168 while not self.isLast():\r
169 char = self.getCurr()\r
170 if re.match('^[\\w.]', char):\r
171 var += char\r
172 self.moveNext()\r
173 else:\r
174 break\r
175 val = self.getNumber(var)\r
176 if val is None:\r
177 value = var\r
178 else:\r
179 value = "%d" % val\r
180 return value\r
181\r
182 def parseSingleOp(self):\r
183 self.skipSpace()\r
184 if re.match('^NOT\\W', self.getCurr(-1)):\r
185 self.moveNext(3)\r
186 op = self.parseBrace()\r
187 val = self.getNumber(op)\r
188 if val is None:\r
189 self.errExit("'%s' is not a number" % op)\r
190 return "%d" % (not self.normNumber(int(op)))\r
191 else:\r
192 return self.parseValue()\r
193\r
194 def parseBrace(self):\r
195 self.skipSpace()\r
196 char = self.getCurr()\r
197 if char == '(':\r
198 self.moveNext()\r
199 value = self.parseExpr()\r
200 self.skipSpace()\r
201 if self.getCurr() != ')':\r
202 self.errExit("Expecting closing brace or operator")\r
203 self.moveNext()\r
204 return value\r
205 else:\r
206 value = self.parseSingleOp()\r
207 return value\r
208\r
209 def parseCompare(self):\r
210 value = self.parseBrace()\r
211 while True:\r
212 self.skipSpace()\r
213 char = self.getCurr()\r
214 if char in ['<', '>']:\r
215 self.moveNext()\r
216 next = self.getCurr()\r
217 if next == '=':\r
218 op = char + next\r
219 self.moveNext()\r
220 else:\r
221 op = char\r
222 result = self.parseBrace()\r
223 test = self.getNonNumber(result, value)\r
224 if test is None:\r
225 value = "%d" % self.normNumber(eval(value + op + result))\r
226 else:\r
227 self.errExit("'%s' is not a valid number for comparision"\r
228 % test)\r
229 elif char in ['=', '!']:\r
230 op = self.getCurr(2)\r
231 if op in ['==', '!=']:\r
232 self.moveNext(2)\r
233 result = self.parseBrace()\r
234 test = self.getNonNumber(result, value)\r
235 if test is None:\r
236 value = "%d" % self.normNumber((eval(value + op\r
237 + result)))\r
238 else:\r
239 value = "%d" % self.normNumber(eval("'" + value +\r
240 "'" + op + "'" +\r
241 result + "'"))\r
242 else:\r
243 break\r
244 else:\r
245 break\r
246 return value\r
247\r
248 def parseAnd(self):\r
249 value = self.parseCompare()\r
250 while True:\r
251 self.skipSpace()\r
252 if re.match('^AND\\W', self.getCurr(-1)):\r
253 self.moveNext(3)\r
254 result = self.parseCompare()\r
255 test = self.getNonNumber(result, value)\r
256 if test is None:\r
257 value = "%d" % self.normNumber(int(value) & int(result))\r
258 else:\r
259 self.errExit("'%s' is not a valid op number for AND" %\r
260 test)\r
261 else:\r
262 break\r
263 return value\r
264\r
265 def parseOrXor(self):\r
266 value = self.parseAnd()\r
267 op = None\r
268 while True:\r
269 self.skipSpace()\r
270 op = None\r
271 if re.match('^XOR\\W', self.getCurr(-1)):\r
272 self.moveNext(3)\r
273 op = '^'\r
274 elif re.match('^OR\\W', self.getCurr(-1)):\r
275 self.moveNext(2)\r
276 op = '|'\r
277 else:\r
278 break\r
279 if op:\r
280 result = self.parseAnd()\r
281 test = self.getNonNumber(result, value)\r
282 if test is None:\r
283 value = "%d" % self.normNumber(eval(value + op + result))\r
284 else:\r
285 self.errExit("'%s' is not a valid op number for XOR/OR" %\r
286 test)\r
287 return value\r
288\r
289 def parseExpr(self):\r
290 return self.parseOrXor()\r
291\r
292 def getResult(self):\r
293 value = self.parseExpr()\r
294 self.skipSpace()\r
295 if not self.isLast():\r
296 self.errExit("Unexpected character found '%s'" % self.getCurr())\r
297 test = self.getNumber(value)\r
298 if test is None:\r
299 self.errExit("Result '%s' is not a number" % value)\r
300 return int(value)\r
301\r
302 def evaluateExpress(self, Expr):\r
303 self.index = 0\r
304 self.string = Expr\r
305 if self.getResult():\r
306 Result = True\r
307 else:\r
308 Result = False\r
309 return Result\r
310\r
311\r
312class CFspBsf2Dsc:\r
313\r
314 def __init__(self, bsf_file):\r
315 self.cfg_list = CFspBsf2Dsc.parse_bsf(bsf_file)\r
316\r
317 def get_dsc_lines(self):\r
318 return CFspBsf2Dsc.generate_dsc(self.cfg_list)\r
319\r
320 def save_dsc(self, dsc_file):\r
321 return CFspBsf2Dsc.generate_dsc(self.cfg_list, dsc_file)\r
322\r
323 @staticmethod\r
324 def parse_bsf(bsf_file):\r
325\r
326 fd = open(bsf_file, 'r')\r
327 bsf_txt = fd.read()\r
328 fd.close()\r
329\r
330 find_list = []\r
331 regex = re.compile(r'\s+Find\s+"(.*?)"(.*?)^\s+(\$(.*?)|Skip)\s+',\r
332 re.S | re.MULTILINE)\r
333 for match in regex.finditer(bsf_txt):\r
334 find = match.group(1)\r
335 name = match.group(3)\r
336 line = bsf_txt[:match.end()].count("\n")\r
337 find_list.append((name, find, line))\r
338\r
339 idx = 0\r
340 count = 0\r
341 prefix = ''\r
342 chk_dict = {}\r
343 cfg_list = []\r
344 cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0',\r
345 'type': 'Reserved', 'isbit': False,\r
346 'embed': '', 'page': '', 'option': '', 'instance': 0}\r
347 regex = re.compile(\r
348 r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+(bits|bytes)(\s+\$_DEFAULT_\s'\r
349 r'+=\s+(.+?))?$', re.S |\r
350 re.MULTILINE)\r
351\r
352 for match in regex.finditer(bsf_txt):\r
353 dlen = int(match.group(3))\r
354 if match.group(1) == 'Skip':\r
355 key = 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx\r
356 val = ', '.join(['%02X' % ord(i) for i in '\x00' * dlen])\r
357 idx += 1\r
358 option = '$SKIP'\r
359 else:\r
360 key = match.group(2)\r
361 val = match.group(6)\r
362 option = ''\r
363 is_bit = True if match.group(4) == 'bits' else False\r
364\r
365 cfg_item = dict(cfg_temp)\r
366 line = bsf_txt[:match.end()].count("\n")\r
367 finds = [i for i in find_list if line >= i[2]]\r
368 if len(finds) > 0:\r
369 prefix = finds[0][1]\r
370 cfg_item['embed'] = '%s:TAG_%03X:START' % \\r
371 (prefix, ord(prefix[-1]))\r
372 cfg_item['find'] = prefix\r
373 cfg_item['cname'] = 'Signature'\r
374 cfg_item['length'] = len(finds[0][1])\r
375 str2byte = Str2Bytes("'" + finds[0][1] + "'",\r
376 len(finds[0][1]))\r
377 cfg_item['value'] = '0x%X' % Bytes2Val(str2byte)\r
378\r
379 cfg_list.append(dict(cfg_item))\r
380 cfg_item = dict(cfg_temp)\r
381 find_list.pop(0)\r
382 count = 0\r
383\r
384 cfg_item['cname'] = key\r
385 cfg_item['length'] = dlen\r
386 cfg_item['value'] = val\r
387 cfg_item['option'] = option\r
388 cfg_item['isbit'] = is_bit\r
389\r
390 if key not in chk_dict.keys():\r
391 chk_dict[key] = 0\r
392 else:\r
393 chk_dict[key] += 1\r
394 cfg_item['instance'] = chk_dict[key]\r
395\r
396 cfg_list.append(cfg_item)\r
397 count += 1\r
398\r
399 if prefix:\r
400 cfg_item = dict(cfg_temp)\r
401 cfg_item['cname'] = 'Dummy'\r
402 cfg_item['embed'] = '%s:%03X:END' % (prefix, ord(prefix[-1]))\r
403 cfg_list.append(cfg_item)\r
404\r
405 option_dict = {}\r
406 selreg = re.compile(\r
407 r'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re.S |\r
408 re.MULTILINE)\r
409 regex = re.compile(\r
410 r'^List\s&(.+?)$(.+?)^EndList$', re.S | re.MULTILINE)\r
411 for match in regex.finditer(bsf_txt):\r
412 key = match.group(1)\r
413 option_dict[key] = []\r
414 for select in selreg.finditer(match.group(2)):\r
415 option_dict[key].append(\r
416 (int(select.group(1), 0), select.group(2)))\r
417\r
418 chk_dict = {}\r
419 pagereg = re.compile(\r
420 r'^Page\s"(.*?)"$(.+?)^EndPage$', re.S | re.MULTILINE)\r
421 for match in pagereg.finditer(bsf_txt):\r
422 page = match.group(1)\r
423 for line in match.group(2).splitlines():\r
424 match = re.match(\r
425 r'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line)\r
426 if match:\r
427 cname = match.group(2)\r
428 if cname not in chk_dict.keys():\r
429 chk_dict[cname] = 0\r
430 else:\r
431 chk_dict[cname] += 1\r
432 instance = chk_dict[cname]\r
433 cfg_idxs = [i for i, j in enumerate(cfg_list)\r
434 if j['cname'] == cname and\r
435 j['instance'] == instance]\r
436 if len(cfg_idxs) != 1:\r
437 raise Exception(\r
438 "Multiple CFG item '%s' found !" % cname)\r
439 cfg_item = cfg_list[cfg_idxs[0]]\r
440 cfg_item['page'] = page\r
441 cfg_item['type'] = match.group(1)\r
442 cfg_item['prompt'] = match.group(3)\r
443 cfg_item['range'] = None\r
444 if cfg_item['type'] == 'Combo':\r
445 cfg_item['option'] = option_dict[match.group(4)[1:]]\r
446 elif cfg_item['type'] == 'EditNum':\r
447 cfg_item['option'] = match.group(4)\r
448 match = re.match(r'\s+ Help\s"(.*?)"$', line)\r
449 if match:\r
450 cfg_item['help'] = match.group(1)\r
451\r
452 match = re.match(r'\s+"Valid\srange:\s(.*)"$', line)\r
453 if match:\r
454 parts = match.group(1).split()\r
455 cfg_item['option'] = (\r
456 (int(parts[0], 0), int(parts[2], 0),\r
457 cfg_item['option']))\r
458\r
459 return cfg_list\r
460\r
461 @staticmethod\r
462 def generate_dsc(option_list, dsc_file=None):\r
463 dsc_lines = []\r
464 header = '%s' % (__copyright_dsc__ % date.today().year)\r
465 dsc_lines.extend(header.splitlines())\r
466\r
467 pages = []\r
468 for cfg_item in option_list:\r
469 if cfg_item['page'] and (cfg_item['page'] not in pages):\r
470 pages.append(cfg_item['page'])\r
471\r
472 page_id = 0\r
473 for page in pages:\r
474 dsc_lines.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id, page))\r
475 page_id += 1\r
476 dsc_lines.append('')\r
477\r
478 last_page = ''\r
479\r
480 is_bit = False\r
481 dlen = 0\r
482 dval = 0\r
483 bit_fields = []\r
484 for idx, option in enumerate(option_list):\r
485 if not is_bit and option['isbit']:\r
486 is_bit = True\r
487 dlen = 0\r
488 dval = 0\r
489 idxs = idx\r
490 if is_bit and not option['isbit']:\r
491 is_bit = False\r
492 if dlen % 8 != 0:\r
493 raise Exception("Bit fields are not aligned at "\r
494 "byte boundary !")\r
495 bit_fields.append((idxs, idx, dlen, dval))\r
496 if is_bit:\r
497 blen = option['length']\r
498 bval = int(option['value'], 0)\r
499 dval = dval + ((bval & ((1 << blen) - 1)) << dlen)\r
500 print(dlen, blen, bval, hex(dval))\r
501 dlen += blen\r
502\r
503 struct_idx = 0\r
504 for idx, option in enumerate(option_list):\r
505 dsc_lines.append('')\r
506 default = option['value']\r
507 pos = option['cname'].find('_')\r
508 name = option['cname'][pos + 1:]\r
509\r
510 for start_idx, end_idx, bits_len, bits_val in bit_fields:\r
511 if idx == start_idx:\r
512 val_str = Bytes2Str(Val2Bytes(bits_val, bits_len // 8))\r
513 dsc_lines.append(' # !HDR STRUCT:{BIT_FIELD_DATA_%d}'\r
514 % struct_idx)\r
515 dsc_lines.append(' # !BSF NAME:{BIT_FIELD_STRUCT}')\r
516 dsc_lines.append(' gCfgData.BitFiledStruct%d '\r
517 ' | * | 0x%04X | %s' %\r
518 (struct_idx, bits_len // 8, val_str))\r
519 dsc_lines.append('')\r
520 struct_idx += 1\r
521\r
522 if option['find']:\r
523 dsc_lines.append(' # !BSF FIND:{%s}' % option['find'])\r
524 dsc_lines.append('')\r
525\r
526 if option['instance'] > 0:\r
527 name = name + '_%s' % option['instance']\r
528\r
529 if option['embed']:\r
530 dsc_lines.append(' # !HDR EMBED:{%s}' % option['embed'])\r
531\r
532 if option['type'] == 'Reserved':\r
533 dsc_lines.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}')\r
534 if option['option'] == '$SKIP':\r
535 dsc_lines.append(' # !BSF OPTION:{$SKIP}')\r
536 else:\r
537 prompt = option['prompt']\r
538\r
539 if last_page != option['page']:\r
540 last_page = option['page']\r
541 dsc_lines.append(' # !BSF PAGE:{PG%02X}' %\r
542 (pages.index(option['page'])))\r
543\r
544 if option['type'] == 'Combo':\r
545 dsc_lines.append(' # !BSF NAME:{%s} TYPE:{%s}' %\r
546 (prompt, option['type']))\r
547 ops = []\r
548 for val, text in option['option']:\r
549 ops.append('0x%x:%s' % (val, text))\r
550 dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))\r
551 elif option['type'] == 'EditNum':\r
552 cfg_len = option['length']\r
553 if ',' in default and cfg_len > 8:\r
554 dsc_lines.append(' # !BSF NAME:{%s} TYPE:{Table}' %\r
555 (prompt))\r
556 if cfg_len > 16:\r
557 cfg_len = 16\r
558 ops = []\r
559 for i in range(cfg_len):\r
560 ops.append('%X:1:HEX' % i)\r
561 dsc_lines.append(' # !BSF OPTION:{%s}' %\r
562 (', '.join(ops)))\r
563 else:\r
564 dsc_lines.append(\r
565 ' # !BSF NAME:{%s} TYPE:{%s, %s, (0x%X, 0x%X)}' %\r
566 (prompt, option['type'], option['option'][2],\r
567 option['option'][0], option['option'][1]))\r
568 dsc_lines.append(' # !BSF HELP:{%s}' % option['help'])\r
569\r
570 if ',' in default:\r
571 default = '{%s}' % default\r
572\r
573 if option['isbit']:\r
574 dsc_lines.append(' # !BSF FIELD:{%s:%db}'\r
575 % (name, option['length']))\r
576 else:\r
577 dsc_lines.append(' gCfgData.%-30s | * | 0x%04X | %s' %\r
578 (name, option['length'], default))\r
579\r
580 if dsc_file:\r
581 fd = open(dsc_file, 'w')\r
582 fd.write('\n'.join(dsc_lines))\r
583 fd.close()\r
584\r
585 return dsc_lines\r
586\r
587\r
588class CGenCfgData:\r
589 def __init__(self, Mode=''):\r
590 self.Debug = False\r
591 self.Error = ''\r
592 self.ReleaseMode = True\r
593 self.Mode = Mode\r
594 self._GlobalDataDef = """\r
595GlobalDataDef\r
596 SKUID = 0, "DEFAULT"\r
597EndGlobalData\r
598\r
599"""\r
600 self._BuidinOptionTxt = """\r
601List &EN_DIS\r
602 Selection 0x1 , "Enabled"\r
603 Selection 0x0 , "Disabled"\r
604EndList\r
605\r
606"""\r
607 self._StructType = ['UINT8', 'UINT16', 'UINT32', 'UINT64']\r
608 self._BsfKeyList = ['FIND', 'NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES',\r
609 'BLOCK', 'OPTION', 'CONDITION', 'ORDER', 'MARKER',\r
610 'SUBT']\r
611 self._HdrKeyList = ['HEADER', 'STRUCT', 'EMBED', 'COMMENT']\r
612 self._BuidinOption = {'$EN_DIS': 'EN_DIS'}\r
613\r
614 self._MacroDict = {}\r
615 self._VarDict = {}\r
616 self._PcdsDict = {}\r
617 self._CfgBlkDict = {}\r
618 self._CfgPageDict = {}\r
619 self._CfgOptsDict = {}\r
620 self._BsfTempDict = {}\r
621 self._CfgItemList = []\r
622 self._DscLines = []\r
623 self._DscFile = ''\r
624 self._CfgPageTree = {}\r
625\r
626 self._MapVer = 0\r
627 self._MinCfgTagId = 0x100\r
628\r
629 def ParseMacros(self, MacroDefStr):\r
630 # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
631 self._MacroDict = {}\r
632 IsExpression = False\r
633 for Macro in MacroDefStr:\r
634 if Macro.startswith('-D'):\r
635 IsExpression = True\r
636 if len(Macro) > 2:\r
637 Macro = Macro[2:]\r
638 else:\r
639 continue\r
640 if IsExpression:\r
641 IsExpression = False\r
642 Match = re.match("(\\w+)=(.+)", Macro)\r
643 if Match:\r
644 self._MacroDict[Match.group(1)] = Match.group(2)\r
645 else:\r
646 Match = re.match("(\\w+)", Macro)\r
647 if Match:\r
648 self._MacroDict[Match.group(1)] = ''\r
649 if len(self._MacroDict) == 0:\r
650 Error = 1\r
651 else:\r
652 Error = 0\r
653 if self.Debug:\r
654 print("INFO : Macro dictionary:")\r
655 for Each in self._MacroDict:\r
656 print(" $(%s) = [ %s ]" % (Each,\r
657 self._MacroDict[Each]))\r
658 return Error\r
659\r
660 def EvaulateIfdef(self, Macro):\r
661 Result = Macro in self._MacroDict\r
662 if self.Debug:\r
663 print("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))\r
664 return Result\r
665\r
666 def ExpandMacros(self, Input, Preserve=False):\r
667 Line = Input\r
668 Match = re.findall("\\$\\(\\w+\\)", Input)\r
669 if Match:\r
670 for Each in Match:\r
671 Variable = Each[2:-1]\r
672 if Variable in self._MacroDict:\r
673 Line = Line.replace(Each, self._MacroDict[Variable])\r
674 else:\r
675 if self.Debug:\r
676 print("WARN : %s is not defined" % Each)\r
677 if not Preserve:\r
678 Line = Line.replace(Each, Each[2:-1])\r
679 return Line\r
680\r
681 def ExpandPcds(self, Input):\r
682 Line = Input\r
683 Match = re.findall("(\\w+\\.\\w+)", Input)\r
684 if Match:\r
685 for PcdName in Match:\r
686 if PcdName in self._PcdsDict:\r
687 Line = Line.replace(PcdName, self._PcdsDict[PcdName])\r
688 else:\r
689 if self.Debug:\r
690 print("WARN : %s is not defined" % PcdName)\r
691 return Line\r
692\r
693 def EvaluateExpress(self, Expr):\r
694 ExpExpr = self.ExpandPcds(Expr)\r
695 ExpExpr = self.ExpandMacros(ExpExpr)\r
696 LogExpr = CLogicalExpression()\r
697 Result = LogExpr.evaluateExpress(ExpExpr)\r
698 if self.Debug:\r
699 print("INFO : Eval Express [%s] : %s" % (Expr, Result))\r
700 return Result\r
701\r
702 def ValueToByteArray(self, ValueStr, Length):\r
703 Match = re.match("\\{\\s*FILE:(.+)\\}", ValueStr)\r
704 if Match:\r
705 FileList = Match.group(1).split(',')\r
706 Result = bytearray()\r
707 for File in FileList:\r
708 File = File.strip()\r
709 BinPath = os.path.join(os.path.dirname(self._DscFile), File)\r
710 Result.extend(bytearray(open(BinPath, 'rb').read()))\r
711 else:\r
712 try:\r
713 Result = bytearray(self.ValueToList(ValueStr, Length))\r
714 except ValueError:\r
715 raise Exception("Bytes in '%s' must be in range 0~255 !" %\r
716 ValueStr)\r
717 if len(Result) < Length:\r
718 Result.extend(b'\x00' * (Length - len(Result)))\r
719 elif len(Result) > Length:\r
720 raise Exception("Value '%s' is too big to fit into %d bytes !" %\r
721 (ValueStr, Length))\r
722\r
723 return Result[:Length]\r
724\r
725 def ValueToList(self, ValueStr, Length):\r
726 if ValueStr[0] == '{':\r
727 Result = []\r
728 BinList = ValueStr[1:-1].split(',')\r
729 InBitField = False\r
730 LastInBitField = False\r
731 Value = 0\r
732 BitLen = 0\r
733 for Element in BinList:\r
734 InBitField = False\r
735 Each = Element.strip()\r
736 if len(Each) == 0:\r
737 pass\r
738 else:\r
739 if Each[0] in ['"', "'"]:\r
740 Result.extend(list(bytearray(Each[1:-1], 'utf-8')))\r
741 elif ':' in Each:\r
742 Match = re.match("(.+):(\\d+)b", Each)\r
743 if Match is None:\r
744 raise Exception("Invald value list format '%s' !"\r
745 % Each)\r
746 InBitField = True\r
747 CurrentBitLen = int(Match.group(2))\r
748 CurrentValue = ((self.EvaluateExpress(Match.group(1))\r
749 & (1 << CurrentBitLen) - 1)) << BitLen\r
750 else:\r
751 Result.append(self.EvaluateExpress(Each.strip()))\r
752 if InBitField:\r
753 Value += CurrentValue\r
754 BitLen += CurrentBitLen\r
755 if LastInBitField and ((not InBitField) or (Element ==\r
756 BinList[-1])):\r
757 if BitLen % 8 != 0:\r
758 raise Exception("Invald bit field length!")\r
759 Result.extend(Val2Bytes(Value, BitLen // 8))\r
760 Value = 0\r
761 BitLen = 0\r
762 LastInBitField = InBitField\r
763 elif ValueStr.startswith("'") and ValueStr.endswith("'"):\r
764 Result = Str2Bytes(ValueStr, Length)\r
765 elif ValueStr.startswith('"') and ValueStr.endswith('"'):\r
766 Result = Str2Bytes(ValueStr, Length)\r
767 else:\r
768 Result = Val2Bytes(self.EvaluateExpress(ValueStr), Length)\r
769 return Result\r
770\r
771 def FormatDeltaValue(self, ConfigDict):\r
772 ValStr = ConfigDict['value']\r
773 if ValStr[0] == "'":\r
774 # Remove padding \x00 in the value string\r
775 ValStr = "'%s'" % ValStr[1:-1].rstrip('\x00')\r
776\r
777 Struct = ConfigDict['struct']\r
778 if Struct in self._StructType:\r
779 # Format the array using its struct type\r
780 Unit = int(Struct[4:]) // 8\r
781 Value = Array2Val(ConfigDict['value'])\r
782 Loop = ConfigDict['length'] // Unit\r
783 Values = []\r
784 for Each in range(Loop):\r
785 Values.append(Value & ((1 << (Unit * 8)) - 1))\r
786 Value = Value >> (Unit * 8)\r
787 ValStr = '{ ' + ', '.join([('0x%%0%dX' % (Unit * 2)) %\r
788 x for x in Values]) + ' }'\r
789\r
790 return ValStr\r
791\r
792 def FormatListValue(self, ConfigDict):\r
793 Struct = ConfigDict['struct']\r
794 if Struct not in self._StructType:\r
795 return\r
796\r
797 DataList = self.ValueToList(ConfigDict['value'], ConfigDict['length'])\r
798 Unit = int(Struct[4:]) // 8\r
799 if int(ConfigDict['length']) != Unit * len(DataList):\r
800 # Fallback to byte array\r
801 Unit = 1\r
802 if int(ConfigDict['length']) != len(DataList):\r
803 raise Exception("Array size is not proper for '%s' !" %\r
804 ConfigDict['cname'])\r
805\r
806 ByteArray = []\r
807 for Value in DataList:\r
808 for Loop in range(Unit):\r
809 ByteArray.append("0x%02X" % (Value & 0xFF))\r
810 Value = Value >> 8\r
811 NewValue = '{' + ','.join(ByteArray) + '}'\r
812 ConfigDict['value'] = NewValue\r
813\r
814 return ""\r
815\r
816 def GetOrderNumber(self, Offset, Order, BitOff=0):\r
817 if isinstance(Order, int):\r
818 if Order == -1:\r
819 Order = Offset << 16\r
820 else:\r
821 (Major, Minor) = Order.split('.')\r
822 Order = (int(Major, 16) << 16) + ((int(Minor, 16) & 0xFF) << 8)\r
823 return Order + (BitOff & 0xFF)\r
824\r
825 def SubtituteLine(self, Line, Args):\r
826 Args = Args.strip()\r
827 Vars = Args.split(':')\r
828 Line = self.ExpandMacros(Line, True)\r
829 for Idx in range(len(Vars)-1, 0, -1):\r
830 Line = Line.replace('$(%d)' % Idx, Vars[Idx].strip())\r
831 return Line\r
832\r
833 def CfgDuplicationCheck(self, CfgDict, Name):\r
834 if not self.Debug:\r
835 return\r
836\r
837 if Name == 'Dummy':\r
838 return\r
839\r
840 if Name not in CfgDict:\r
841 CfgDict[Name] = 1\r
842 else:\r
843 print("WARNING: Duplicated item found '%s' !" %\r
844 CfgDict['cname'])\r
845\r
846 def AddBsfChildPage(self, Child, Parent='root'):\r
847 def AddBsfChildPageRecursive(PageTree, Parent, Child):\r
848 Key = next(iter(PageTree))\r
849 if Parent == Key:\r
850 PageTree[Key].append({Child: []})\r
851 return True\r
852 else:\r
853 Result = False\r
854 for Each in PageTree[Key]:\r
855 if AddBsfChildPageRecursive(Each, Parent, Child):\r
856 Result = True\r
857 break\r
858 return Result\r
859\r
860 return AddBsfChildPageRecursive(self._CfgPageTree, Parent, Child)\r
861\r
862 def ParseDscFile(self, DscFile):\r
863 self._DscLines = []\r
864 self._CfgItemList = []\r
865 self._CfgPageDict = {}\r
866 self._CfgBlkDict = {}\r
867 self._BsfTempDict = {}\r
868 self._CfgPageTree = {'root': []}\r
869\r
870 CfgDict = {}\r
871\r
872 SectionNameList = ["Defines".lower(), "PcdsFeatureFlag".lower(),\r
873 "PcdsDynamicVpd.Tmp".lower(),\r
874 "PcdsDynamicVpd.Upd".lower()]\r
875\r
876 IsDefSect = False\r
877 IsPcdSect = False\r
878 IsUpdSect = False\r
879 IsTmpSect = False\r
880\r
881 TemplateName = ''\r
882\r
883 IfStack = []\r
884 ElifStack = []\r
885 Error = 0\r
886 ConfigDict = {}\r
887\r
888 if type(DscFile) is list:\r
889 # it is DSC lines already\r
890 DscLines = DscFile\r
891 self._DscFile = '.'\r
892 else:\r
893 DscFd = open(DscFile, "r")\r
894 DscLines = DscFd.readlines()\r
895 DscFd.close()\r
896 self._DscFile = DscFile\r
897\r
898 BsfRegExp = re.compile("(%s):{(.+?)}(?:$|\\s+)" % '|'.\r
899 join(self._BsfKeyList))\r
900 HdrRegExp = re.compile("(%s):{(.+?)}" % '|'.join(self._HdrKeyList))\r
901 CfgRegExp = re.compile("^([_a-zA-Z0-9]+)\\s*\\|\\s*\\r
902(0x[0-9A-F]+|\\*)\\s*\\|\\s*(\\d+|0x[0-9a-fA-F]+)\\s*\\|\\s*(.+)")\r
903 TksRegExp = re.compile("^(g[_a-zA-Z0-9]+\\.)(.+)")\r
904 SkipLines = 0\r
905 while len(DscLines):\r
906 DscLine = DscLines.pop(0).strip()\r
907 if SkipLines == 0:\r
908 self._DscLines.append(DscLine)\r
909 else:\r
910 SkipLines = SkipLines - 1\r
911 if len(DscLine) == 0:\r
912 continue\r
913\r
914 Handle = False\r
915 Match = re.match("^\\[(.+)\\]", DscLine)\r
916 if Match is not None:\r
917 IsDefSect = False\r
918 IsPcdSect = False\r
919 IsUpdSect = False\r
920 IsTmpSect = False\r
921 SectionName = Match.group(1).lower()\r
922 if SectionName == SectionNameList[0]:\r
923 IsDefSect = True\r
924 if SectionName == SectionNameList[1]:\r
925 IsPcdSect = True\r
926 elif SectionName == SectionNameList[2]:\r
927 IsTmpSect = True\r
928 elif SectionName == SectionNameList[3]:\r
929 ConfigDict = {\r
930 'header': 'ON',\r
931 'page': '',\r
932 'name': '',\r
933 'find': '',\r
934 'struct': '',\r
935 'embed': '',\r
936 'marker': '',\r
937 'option': '',\r
938 'comment': '',\r
939 'condition': '',\r
940 'order': -1,\r
941 'subreg': []\r
942 }\r
943 IsUpdSect = True\r
944 Offset = 0\r
945 else:\r
946 if IsDefSect or IsPcdSect or IsUpdSect or IsTmpSect:\r
947 Match = False if DscLine[0] != '!' else True\r
948 if Match:\r
949 Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif\\r
950|include)\\s*(.+)?$", DscLine.split("#")[0])\r
951 Keyword = Match.group(1) if Match else ''\r
952 Remaining = Match.group(2) if Match else ''\r
953 Remaining = '' if Remaining is None else Remaining.strip()\r
954\r
955 if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'\r
956 ] and not Remaining:\r
957 raise Exception("ERROR: Expression is expected after \\r
958'!if' or !elseif' for line '%s'" % DscLine)\r
959\r
960 if Keyword == 'else':\r
961 if IfStack:\r
962 IfStack[-1] = not IfStack[-1]\r
963 else:\r
964 raise Exception("ERROR: No paired '!if' found for \\r
965'!else' for line '%s'" % DscLine)\r
966 elif Keyword == 'endif':\r
967 if IfStack:\r
968 IfStack.pop()\r
969 Level = ElifStack.pop()\r
970 if Level > 0:\r
971 del IfStack[-Level:]\r
972 else:\r
973 raise Exception("ERROR: No paired '!if' found for \\r
974'!endif' for line '%s'" % DscLine)\r
975 elif Keyword == 'ifdef' or Keyword == 'ifndef':\r
976 Result = self.EvaulateIfdef(Remaining)\r
977 if Keyword == 'ifndef':\r
978 Result = not Result\r
979 IfStack.append(Result)\r
980 ElifStack.append(0)\r
981 elif Keyword == 'if' or Keyword == 'elseif':\r
982 Result = self.EvaluateExpress(Remaining)\r
983 if Keyword == "if":\r
984 ElifStack.append(0)\r
985 IfStack.append(Result)\r
986 else: # elseif\r
987 if IfStack:\r
988 IfStack[-1] = not IfStack[-1]\r
989 IfStack.append(Result)\r
990 ElifStack[-1] = ElifStack[-1] + 1\r
991 else:\r
992 raise Exception("ERROR: No paired '!if' found for \\r
993'!elif' for line '%s'" % DscLine)\r
994 else:\r
995 if IfStack:\r
996 Handle = reduce(lambda x, y: x and y, IfStack)\r
997 else:\r
998 Handle = True\r
999 if Handle:\r
1000 if Keyword == 'include':\r
1001 Remaining = self.ExpandMacros(Remaining)\r
1002 # Relative to DSC filepath\r
1003 IncludeFilePath = os.path.join(\r
1004 os.path.dirname(self._DscFile), Remaining)\r
1005 if not os.path.exists(IncludeFilePath):\r
1006 # Relative to repository to find \\r
1007 # dsc in common platform\r
1008 IncludeFilePath = os.path.join(\r
1009 os.path.dirname(self._DscFile), "..",\r
1010 Remaining)\r
1011\r
1012 try:\r
1013 IncludeDsc = open(IncludeFilePath, "r")\r
1014 except Exception:\r
1015 raise Exception("ERROR: Cannot open \\r
1016file '%s'." % IncludeFilePath)\r
1017 NewDscLines = IncludeDsc.readlines()\r
1018 IncludeDsc.close()\r
1019 DscLines = NewDscLines + DscLines\r
1020 del self._DscLines[-1]\r
1021 else:\r
1022 if DscLine.startswith('!'):\r
1023 raise Exception("ERROR: Unrecoginized \\r
1024directive for line '%s'" % DscLine)\r
1025\r
1026 if not Handle:\r
1027 del self._DscLines[-1]\r
1028 continue\r
1029\r
1030 if IsDefSect:\r
1031 Match = re.match("^\\s*(?:DEFINE\\s+)*(\\w+)\\s*=\\s*(.+)",\r
1032 DscLine)\r
1033 if Match:\r
1034 self._MacroDict[Match.group(1)] = Match.group(2)\r
1035 if self.Debug:\r
1036 print("INFO : DEFINE %s = [ %s ]" % (Match.group(1),\r
1037 Match.group(2)))\r
1038\r
1039 elif IsPcdSect:\r
1040 Match = re.match("^\\s*([\\w\\.]+)\\s*\\|\\s*(\\w+)", DscLine)\r
1041 if Match:\r
1042 self._PcdsDict[Match.group(1)] = Match.group(2)\r
1043 if self.Debug:\r
1044 print("INFO : PCD %s = [ %s ]" % (Match.group(1),\r
1045 Match.group(2)))\r
1046\r
1047 elif IsTmpSect:\r
1048 # !BSF DEFT:{GPIO_TMPL:START}\r
1049 Match = re.match("^\\s*#\\s+(!BSF)\\s+DEFT:{(.+?):\\r
1050(START|END)}", DscLine)\r
1051 if Match:\r
1052 if Match.group(3) == 'START' and not TemplateName:\r
1053 TemplateName = Match.group(2).strip()\r
1054 self._BsfTempDict[TemplateName] = []\r
1055 if Match.group(3) == 'END' and (\r
1056 TemplateName == Match.group(2).strip()\r
1057 ) and TemplateName:\r
1058 TemplateName = ''\r
1059 else:\r
1060 if TemplateName:\r
1061 Match = re.match("^!include\\s*(.+)?$", DscLine)\r
1062 if Match:\r
1063 continue\r
1064 self._BsfTempDict[TemplateName].append(DscLine)\r
1065\r
1066 else:\r
1067 Match = re.match("^\\s*#\\s+(!BSF|!HDR)\\s+(.+)", DscLine)\r
1068 if Match:\r
1069 Remaining = Match.group(2)\r
1070 if Match.group(1) == '!BSF':\r
1071 Result = BsfRegExp.findall(Remaining)\r
1072 if Result:\r
1073 for Each in Result:\r
1074 Key = Each[0]\r
1075 Remaining = Each[1]\r
1076\r
1077 if Key == 'BLOCK':\r
1078 Match = re.match(\r
1079 "NAME:\"(.+)\"\\s*,\\s*\\r
1080VER:\"(.+)\"\\s*", Remaining)\r
1081 if Match:\r
1082 self._CfgBlkDict['name'] = \\r
1083 Match.group(1)\r
1084 self._CfgBlkDict['ver'] = Match.group(2\r
1085 )\r
1086\r
1087 elif Key == 'SUBT':\r
1088 # GPIO_TMPL:1:2:3\r
1089 Remaining = Remaining.strip()\r
1090 Match = re.match("(\\w+)\\s*:", Remaining)\r
1091 if Match:\r
1092 TemplateName = Match.group(1)\r
1093 for Line in self._BsfTempDict[\r
1094 TemplateName][::-1]:\r
1095 NewLine = self.SubtituteLine(\r
1096 Line, Remaining)\r
1097 DscLines.insert(0, NewLine)\r
1098 SkipLines += 1\r
1099\r
1100 elif Key == 'PAGES':\r
1101 # !BSF PAGES:{HSW:"Haswell System Agent", \\r
1102 # LPT:"Lynx Point PCH"}\r
1103 PageList = Remaining.split(',')\r
1104 for Page in PageList:\r
1105 Page = Page.strip()\r
1106 Match = re.match('(\\w+):\\r
1107(\\w*:)?\\"(.+)\\"', Page)\r
1108 if Match:\r
1109 PageName = Match.group(1)\r
1110 ParentName = Match.group(2)\r
1111 if not ParentName or \\r
1112 ParentName == ':':\r
1113 ParentName = 'root'\r
1114 else:\r
1115 ParentName = ParentName[:-1]\r
1116 if not self.AddBsfChildPage(\r
1117 PageName, ParentName):\r
1118 raise Exception("Cannot find \\r
1119parent page '%s'!" % ParentName)\r
1120 self._CfgPageDict[\r
1121 PageName] = Match.group(3)\r
1122 else:\r
1123 raise Exception("Invalid page \\r
1124definitions '%s'!" % Page)\r
1125\r
1126 elif Key in ['NAME', 'HELP', 'OPTION'\r
1127 ] and Remaining.startswith('+'):\r
1128 # Allow certain options to be extended \\r
1129 # to multiple lines\r
1130 ConfigDict[Key.lower()] += Remaining[1:]\r
1131\r
1132 else:\r
1133 if Key == 'NAME':\r
1134 Remaining = Remaining.strip()\r
1135 elif Key == 'CONDITION':\r
1136 Remaining = self.ExpandMacros(\r
1137 Remaining.strip())\r
1138 ConfigDict[Key.lower()] = Remaining\r
1139 else:\r
1140 Match = HdrRegExp.match(Remaining)\r
1141 if Match:\r
1142 Key = Match.group(1)\r
1143 Remaining = Match.group(2)\r
1144 if Key == 'EMBED':\r
1145 Parts = Remaining.split(':')\r
1146 Names = Parts[0].split(',')\r
1147 DummyDict = ConfigDict.copy()\r
1148 if len(Names) > 1:\r
1149 Remaining = Names[0] + ':' + ':'.join(\r
1150 Parts[1:])\r
1151 DummyDict['struct'] = Names[1]\r
1152 else:\r
1153 DummyDict['struct'] = Names[0]\r
1154 DummyDict['cname'] = 'Dummy'\r
1155 DummyDict['name'] = ''\r
1156 DummyDict['embed'] = Remaining\r
1157 DummyDict['offset'] = Offset\r
1158 DummyDict['length'] = 0\r
1159 DummyDict['value'] = '0'\r
1160 DummyDict['type'] = 'Reserved'\r
1161 DummyDict['help'] = ''\r
1162 DummyDict['subreg'] = []\r
1163 self._CfgItemList.append(DummyDict)\r
1164 else:\r
1165 ConfigDict[Key.lower()] = Remaining\r
1166 # Check CFG line\r
1167 # gCfgData.VariableName | * | 0x01 | 0x1\r
1168 Clear = False\r
1169\r
1170 Match = TksRegExp.match(DscLine)\r
1171 if Match:\r
1172 DscLine = 'gCfgData.%s' % Match.group(2)\r
1173\r
1174 if DscLine.startswith('gCfgData.'):\r
1175 Match = CfgRegExp.match(DscLine[9:])\r
1176 else:\r
1177 Match = None\r
1178 if Match:\r
1179 ConfigDict['space'] = 'gCfgData'\r
1180 ConfigDict['cname'] = Match.group(1)\r
1181 if Match.group(2) != '*':\r
1182 Offset = int(Match.group(2), 16)\r
1183 ConfigDict['offset'] = Offset\r
1184 ConfigDict['order'] = self.GetOrderNumber(\r
1185 ConfigDict['offset'], ConfigDict['order'])\r
1186\r
1187 Value = Match.group(4).strip()\r
1188 if Match.group(3).startswith("0x"):\r
1189 Length = int(Match.group(3), 16)\r
1190 else:\r
1191 Length = int(Match.group(3))\r
1192\r
1193 Offset += Length\r
1194\r
1195 ConfigDict['length'] = Length\r
1196 Match = re.match("\\$\\((\\w+)\\)", Value)\r
1197 if Match:\r
1198 if Match.group(1) in self._MacroDict:\r
1199 Value = self._MacroDict[Match.group(1)]\r
1200\r
1201 ConfigDict['value'] = Value\r
1202 if re.match("\\{\\s*FILE:(.+)\\}", Value):\r
1203 # Expand embedded binary file\r
1204 ValArray = self.ValueToByteArray(ConfigDict['value'],\r
1205 ConfigDict['length'])\r
1206 NewValue = Bytes2Str(ValArray)\r
1207 self._DscLines[-1] = re.sub(r'(.*)(\{\s*FILE:.+\})',\r
1208 r'\1 %s' % NewValue,\r
1209 self._DscLines[-1])\r
1210 ConfigDict['value'] = NewValue\r
1211\r
1212 if ConfigDict['name'] == '':\r
1213 # Clear BSF specific items\r
1214 ConfigDict['bsfname'] = ''\r
1215 ConfigDict['help'] = ''\r
1216 ConfigDict['type'] = ''\r
1217 ConfigDict['option'] = ''\r
1218\r
1219 self.CfgDuplicationCheck(CfgDict, ConfigDict['cname'])\r
1220 self._CfgItemList.append(ConfigDict.copy())\r
1221 Clear = True\r
1222\r
1223 else:\r
1224 # It could be a virtual item as below\r
1225 # !BSF FIELD:{SerialDebugPortAddress0:1}\r
1226 # or\r
1227 # @Bsf FIELD:{SerialDebugPortAddress0:1b}\r
1228 Match = re.match(r"^\s*#\s+(!BSF)\s+FIELD:{(.+)}", DscLine)\r
1229 if Match:\r
1230 BitFieldTxt = Match.group(2)\r
1231 Match = re.match("(.+):(\\d+)b([BWDQ])?", BitFieldTxt)\r
1232 if not Match:\r
1233 raise Exception("Incorrect bit field \\r
1234format '%s' !" % BitFieldTxt)\r
1235 UnitBitLen = 1\r
1236 SubCfgDict = ConfigDict.copy()\r
1237 SubCfgDict['cname'] = Match.group(1)\r
1238 SubCfgDict['bitlength'] = int(\r
1239 Match.group(2)) * UnitBitLen\r
1240 if SubCfgDict['bitlength'] > 0:\r
1241 LastItem = self._CfgItemList[-1]\r
1242 if len(LastItem['subreg']) == 0:\r
1243 SubOffset = 0\r
1244 else:\r
1245 SubOffset = \\r
1246 LastItem['subreg'][-1]['bitoffset'] \\r
1247 + LastItem['subreg'][-1]['bitlength']\r
1248 if Match.group(3) == 'B':\r
1249 SubCfgDict['bitunit'] = 1\r
1250 elif Match.group(3) == 'W':\r
1251 SubCfgDict['bitunit'] = 2\r
1252 elif Match.group(3) == 'Q':\r
1253 SubCfgDict['bitunit'] = 8\r
1254 else:\r
1255 SubCfgDict['bitunit'] = 4\r
1256 SubCfgDict['bitoffset'] = SubOffset\r
1257 SubCfgDict['order'] = self.GetOrderNumber(\r
1258 SubCfgDict['offset'], SubCfgDict['order'],\r
1259 SubOffset)\r
1260 SubCfgDict['value'] = ''\r
1261 SubCfgDict['cname'] = '%s_%s' % (LastItem['cname'],\r
1262 Match.group(1))\r
1263 self.CfgDuplicationCheck(CfgDict,\r
1264 SubCfgDict['cname'])\r
1265 LastItem['subreg'].append(SubCfgDict.copy())\r
1266 Clear = True\r
1267\r
1268 if Clear:\r
1269 ConfigDict['name'] = ''\r
1270 ConfigDict['find'] = ''\r
1271 ConfigDict['struct'] = ''\r
1272 ConfigDict['embed'] = ''\r
1273 ConfigDict['marker'] = ''\r
1274 ConfigDict['comment'] = ''\r
1275 ConfigDict['order'] = -1\r
1276 ConfigDict['subreg'] = []\r
1277 ConfigDict['option'] = ''\r
1278 ConfigDict['condition'] = ''\r
1279\r
1280 return Error\r
1281\r
1282 def GetBsfBitFields(self, subitem, bytes):\r
1283 start = subitem['bitoffset']\r
1284 end = start + subitem['bitlength']\r
1285 bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])\r
1286 bitsvalue = bitsvalue[::-1]\r
1287 bitslen = len(bitsvalue)\r
1288 if start > bitslen or end > bitslen:\r
1289 raise Exception("Invalid bits offset [%d,%d] %d for %s" %\r
1290 (start, end, bitslen, subitem['name']))\r
1291 return '0x%X' % (int(bitsvalue[start:end][::-1], 2))\r
1292\r
1293 def UpdateBsfBitFields(self, SubItem, NewValue, ValueArray):\r
1294 Start = SubItem['bitoffset']\r
1295 End = Start + SubItem['bitlength']\r
1296 Blen = len(ValueArray)\r
1297 BitsValue = ''.join('{0:08b}'.format(i) for i in ValueArray[::-1])\r
1298 BitsValue = BitsValue[::-1]\r
1299 BitsLen = len(BitsValue)\r
1300 if Start > BitsLen or End > BitsLen:\r
1301 raise Exception("Invalid bits offset [%d,%d] %d for %s" %\r
1302 (Start, End, BitsLen, SubItem['name']))\r
1303 BitsValue = BitsValue[:Start] + '{0:0{1}b}'.format(\r
1304 NewValue, SubItem['bitlength'])[::-1] + BitsValue[End:]\r
1305 ValueArray[:] = bytearray.fromhex(\r
1306 '{0:0{1}x}'.format(int(BitsValue[::-1], 2), Blen * 2))[::-1]\r
1307\r
1308 def CreateVarDict(self):\r
1309 Error = 0\r
1310 self._VarDict = {}\r
1311 if len(self._CfgItemList) > 0:\r
1312 Item = self._CfgItemList[-1]\r
1313 self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] +\r
1314 Item['length'])\r
1315 for Item in self._CfgItemList:\r
1316 Embed = Item['embed']\r
1317 Match = re.match("^(\\w+):(\\w+):(START|END)", Embed)\r
1318 if Match:\r
1319 StructName = Match.group(1)\r
1320 VarName = '_%s_%s_' % (Match.group(3), StructName)\r
1321 if Match.group(3) == 'END':\r
1322 self._VarDict[VarName] = Item['offset'] + Item['length']\r
1323 self._VarDict['_LENGTH_%s_' % StructName] = \\r
1324 self._VarDict['_END_%s_' % StructName] - \\r
1325 self._VarDict['_START_%s_' % StructName]\r
1326 if Match.group(2).startswith('TAG_'):\r
1327 if (self.Mode != 'FSP') and (self._VarDict\r
1328 ['_LENGTH_%s_' %\r
1329 StructName] % 4):\r
1330 raise Exception("Size of structure '%s' is %d, \\r
1331not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))\r
1332 self._VarDict['_TAG_%s_' % StructName] = int(\r
1333 Match.group(2)[4:], 16) & 0xFFF\r
1334 else:\r
1335 self._VarDict[VarName] = Item['offset']\r
1336 if Item['marker']:\r
1337 self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = \\r
1338 Item['offset']\r
1339 return Error\r
1340\r
1341 def UpdateBsfBitUnit(self, Item):\r
1342 BitTotal = 0\r
1343 BitOffset = 0\r
1344 StartIdx = 0\r
1345 Unit = None\r
1346 UnitDec = {1: 'BYTE', 2: 'WORD', 4: 'DWORD', 8: 'QWORD'}\r
1347 for Idx, SubItem in enumerate(Item['subreg']):\r
1348 if Unit is None:\r
1349 Unit = SubItem['bitunit']\r
1350 BitLength = SubItem['bitlength']\r
1351 BitTotal += BitLength\r
1352 BitOffset += BitLength\r
1353\r
1354 if BitOffset > 64 or BitOffset > Unit * 8:\r
1355 break\r
1356\r
1357 if BitOffset == Unit * 8:\r
1358 for SubIdx in range(StartIdx, Idx + 1):\r
1359 Item['subreg'][SubIdx]['bitunit'] = Unit\r
1360 BitOffset = 0\r
1361 StartIdx = Idx + 1\r
1362 Unit = None\r
1363\r
1364 if BitOffset > 0:\r
1365 raise Exception("Bit fields cannot fit into %s for \\r
1366'%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))\r
1367\r
1368 ExpectedTotal = Item['length'] * 8\r
1369 if Item['length'] * 8 != BitTotal:\r
1370 raise Exception("Bit fields total length (%d) does not match \\r
1371length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))\r
1372\r
1373 def UpdateDefaultValue(self):\r
1374 Error = 0\r
1375 for Idx, Item in enumerate(self._CfgItemList):\r
1376 if len(Item['subreg']) == 0:\r
1377 Value = Item['value']\r
1378 if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or\r
1379 Value[0] == '"'):\r
1380 # {XXX} or 'XXX' strings\r
1381 self.FormatListValue(self._CfgItemList[Idx])\r
1382 else:\r
1383 Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)\r
1384 if not Match:\r
1385 NumValue = self.EvaluateExpress(Value)\r
1386 Item['value'] = '0x%X' % NumValue\r
1387 else:\r
1388 ValArray = self.ValueToByteArray(Item['value'], Item['length'])\r
1389 for SubItem in Item['subreg']:\r
1390 SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)\r
1391 self.UpdateBsfBitUnit(Item)\r
1392 return Error\r
1393\r
1394 @staticmethod\r
1395 def ExpandIncludeFiles(FilePath, CurDir=''):\r
1396 if CurDir == '':\r
1397 CurDir = os.path.dirname(FilePath)\r
1398 FilePath = os.path.basename(FilePath)\r
1399\r
1400 InputFilePath = os.path.join(CurDir, FilePath)\r
1401 File = open(InputFilePath, "r")\r
1402 Lines = File.readlines()\r
1403 File.close()\r
1404\r
1405 NewLines = []\r
1406 for LineNum, Line in enumerate(Lines):\r
1407 Match = re.match("^!include\\s*(.+)?$", Line)\r
1408 if Match:\r
1409 IncPath = Match.group(1)\r
1410 TmpPath = os.path.join(CurDir, IncPath)\r
1411 OrgPath = TmpPath\r
1412 if not os.path.exists(TmpPath):\r
1413 CurDir = os.path.join(os.path.dirname(\r
1414 os.path.realpath(__file__)), "..", "..")\r
1415 TmpPath = os.path.join(CurDir, IncPath)\r
1416 if not os.path.exists(TmpPath):\r
1417 raise Exception("ERROR: Cannot open include file '%s'." %\r
1418 OrgPath)\r
1419 else:\r
1420 NewLines.append(('# Included from file: %s\n' %\r
1421 IncPath, TmpPath, 0))\r
1422 NewLines.append(('# %s\n' % ('=' * 80), TmpPath, 0))\r
1423 NewLines.extend(CGenCfgData.ExpandIncludeFiles\r
1424 (IncPath, CurDir))\r
1425 else:\r
1426 NewLines.append((Line, InputFilePath, LineNum))\r
1427\r
1428 return NewLines\r
1429\r
1430 def OverrideDefaultValue(self, DltFile):\r
1431 Error = 0\r
1432 DltLines = CGenCfgData.ExpandIncludeFiles(DltFile)\r
1433\r
1434 PlatformId = None\r
1435 for Line, FilePath, LineNum in DltLines:\r
1436 Line = Line.strip()\r
1437 if not Line or Line.startswith('#'):\r
1438 continue\r
1439 Match = re.match("\\s*(\\w+)\\.(\\w+)(\\.\\w+)?\\s*\\|\\s*(.+)",\r
1440 Line)\r
1441 if not Match:\r
1442 raise Exception("Unrecognized line '%s' (File:'%s' Line:%d) !"\r
1443 % (Line, FilePath, LineNum + 1))\r
1444\r
1445 Found = False\r
1446 InScope = False\r
1447 for Idx, Item in enumerate(self._CfgItemList):\r
1448 if not InScope:\r
1449 if not (Item['embed'].endswith(':START') and\r
1450 Item['embed'].startswith(Match.group(1))):\r
1451 continue\r
1452 InScope = True\r
1453 if Item['cname'] == Match.group(2):\r
1454 Found = True\r
1455 break\r
1456 if Item['embed'].endswith(':END') and \\r
1457 Item['embed'].startswith(Match.group(1)):\r
1458 break\r
1459 Name = '%s.%s' % (Match.group(1), Match.group(2))\r
1460 if not Found:\r
1461 ErrItem = Match.group(2) if InScope else Match.group(1)\r
1462 raise Exception("Invalid configuration '%s' in '%s' \\r
1463(File:'%s' Line:%d) !" % (ErrItem, Name, FilePath, LineNum + 1))\r
1464\r
1465 ValueStr = Match.group(4).strip()\r
1466 if Match.group(3) is not None:\r
1467 # This is a subregion item\r
1468 BitField = Match.group(3)[1:]\r
1469 Found = False\r
1470 if len(Item['subreg']) > 0:\r
1471 for SubItem in Item['subreg']:\r
1472 if SubItem['cname'] == '%s_%s' % \\r
1473 (Item['cname'], BitField):\r
1474 Found = True\r
1475 break\r
1476 if not Found:\r
1477 raise Exception("Invalid configuration bit field \\r
1478'%s' in '%s.%s' (File:'%s' Line:%d) !" % (BitField, Name, BitField,\r
1479 FilePath, LineNum + 1))\r
1480\r
1481 try:\r
1482 Value = int(ValueStr, 16) if ValueStr.startswith('0x') \\r
1483 else int(ValueStr, 10)\r
1484 except Exception:\r
1485 raise Exception("Invalid value '%s' for bit field '%s.%s' \\r
1486(File:'%s' Line:%d) !" % (ValueStr, Name, BitField, FilePath, LineNum + 1))\r
1487\r
1488 if Value >= 2 ** SubItem['bitlength']:\r
1489 raise Exception("Invalid configuration bit field value \\r
1490'%s' for '%s.%s' (File:'%s' Line:%d) !" % (Value, Name, BitField,\r
1491 FilePath, LineNum + 1))\r
1492\r
1493 ValArray = self.ValueToByteArray(Item['value'], Item['length'])\r
1494 self.UpdateBsfBitFields(SubItem, Value, ValArray)\r
1495\r
1496 if Item['value'].startswith('{'):\r
1497 Item['value'] = '{' + ', '.join('0x%02X' % i\r
1498 for i in ValArray) + '}'\r
1499 else:\r
1500 BitsValue = ''.join('{0:08b}'.format(i)\r
1501 for i in ValArray[::-1])\r
1502 Item['value'] = '0x%X' % (int(BitsValue, 2))\r
1503 else:\r
1504 if Item['value'].startswith('{') and \\r
1505 not ValueStr.startswith('{'):\r
1506 raise Exception("Data array required for '%s' \\r
1507(File:'%s' Line:%d) !" % (Name, FilePath, LineNum + 1))\r
1508 Item['value'] = ValueStr\r
1509\r
1510 if Name == 'PLATFORMID_CFG_DATA.PlatformId':\r
1511 PlatformId = ValueStr\r
1512\r
1513 if (PlatformId is None) and (self.Mode != 'FSP'):\r
1514 raise Exception("PLATFORMID_CFG_DATA.PlatformId is missing \\r
1515in file '%s' !" % (DltFile))\r
1516\r
1517 return Error\r
1518\r
1519 def ProcessMultilines(self, String, MaxCharLength):\r
1520 Multilines = ''\r
1521 StringLength = len(String)\r
1522 CurrentStringStart = 0\r
1523 StringOffset = 0\r
1524 BreakLineDict = []\r
1525 if len(String) <= MaxCharLength:\r
1526 while (StringOffset < StringLength):\r
1527 if StringOffset >= 1:\r
1528 if String[StringOffset - 1] == '\\' and \\r
1529 String[StringOffset] == 'n':\r
1530 BreakLineDict.append(StringOffset + 1)\r
1531 StringOffset += 1\r
1532 if BreakLineDict != []:\r
1533 for Each in BreakLineDict:\r
1534 Multilines += " %s\n" % String[CurrentStringStart:Each].\\r
1535 lstrip()\r
1536 CurrentStringStart = Each\r
1537 if StringLength - CurrentStringStart > 0:\r
1538 Multilines += " %s\n" % String[CurrentStringStart:].\\r
1539 lstrip()\r
1540 else:\r
1541 Multilines = " %s\n" % String\r
1542 else:\r
1543 NewLineStart = 0\r
1544 NewLineCount = 0\r
1545 FoundSpaceChar = False\r
1546 while(StringOffset < StringLength):\r
1547 if StringOffset >= 1:\r
1548 if NewLineCount >= MaxCharLength - 1:\r
1549 if String[StringOffset] == ' ' and \\r
1550 StringLength - StringOffset > 10:\r
1551 BreakLineDict.append(NewLineStart + NewLineCount)\r
1552 NewLineStart = NewLineStart + NewLineCount\r
1553 NewLineCount = 0\r
1554 FoundSpaceChar = True\r
1555 elif StringOffset == StringLength - 1 \\r
1556 and FoundSpaceChar is False:\r
1557 BreakLineDict.append(0)\r
1558 if String[StringOffset - 1] == '\\' and \\r
1559 String[StringOffset] == 'n':\r
1560 BreakLineDict.append(StringOffset + 1)\r
1561 NewLineStart = StringOffset + 1\r
1562 NewLineCount = 0\r
1563 StringOffset += 1\r
1564 NewLineCount += 1\r
1565 if BreakLineDict != []:\r
1566 BreakLineDict.sort()\r
1567 for Each in BreakLineDict:\r
1568 if Each > 0:\r
1569 Multilines += " %s\n" % String[\r
1570 CurrentStringStart:Each].lstrip()\r
1571 CurrentStringStart = Each\r
1572 if StringLength - CurrentStringStart > 0:\r
1573 Multilines += " %s\n" % String[CurrentStringStart:].\\r
1574 lstrip()\r
1575 return Multilines\r
1576\r
1577 def CreateField(self, Item, Name, Length, Offset, Struct,\r
1578 BsfName, Help, Option, BitsLength=None):\r
1579 PosName = 28\r
1580 NameLine = ''\r
1581 HelpLine = ''\r
1582 OptionLine = ''\r
1583\r
1584 if Length == 0 and Name == 'Dummy':\r
1585 return '\n'\r
1586\r
1587 IsArray = False\r
1588 if Length in [1, 2, 4, 8]:\r
1589 Type = "UINT%d" % (Length * 8)\r
1590 else:\r
1591 IsArray = True\r
1592 Type = "UINT8"\r
1593\r
1594 if Item and Item['value'].startswith('{'):\r
1595 Type = "UINT8"\r
1596 IsArray = True\r
1597\r
1598 if Struct != '':\r
1599 Type = Struct\r
1600 if Struct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:\r
1601 IsArray = True\r
1602 Unit = int(Type[4:]) // 8\r
1603 Length = Length / Unit\r
1604 else:\r
1605 IsArray = False\r
1606\r
1607 if IsArray:\r
1608 Name = Name + '[%d]' % Length\r
1609\r
1610 if len(Type) < PosName:\r
1611 Space1 = PosName - len(Type)\r
1612 else:\r
1613 Space1 = 1\r
1614\r
1615 if BsfName != '':\r
1616 NameLine = " %s\n" % BsfName\r
1617 else:\r
1618 NameLine = "\n"\r
1619\r
1620 if Help != '':\r
1621 HelpLine = self.ProcessMultilines(Help, 80)\r
1622\r
1623 if Option != '':\r
1624 OptionLine = self.ProcessMultilines(Option, 80)\r
1625\r
1626 if BitsLength is None:\r
1627 BitsLength = ''\r
1628 else:\r
1629 BitsLength = ' : %d' % BitsLength\r
1630\r
1631 return "\n/** %s%s%s**/\n %s%s%s%s;\n" % \\r
1632 (NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,\r
1633 BitsLength)\r
1634\r
1635 def SplitTextBody(self, TextBody):\r
1636 Marker1 = '{ /* _COMMON_STRUCT_START_ */'\r
1637 Marker2 = '; /* _COMMON_STRUCT_END_ */'\r
1638 ComBody = []\r
1639 TxtBody = []\r
1640 IsCommon = False\r
1641 for Line in TextBody:\r
1642 if Line.strip().endswith(Marker1):\r
1643 Line = Line.replace(Marker1[1:], '')\r
1644 IsCommon = True\r
1645 if Line.strip().endswith(Marker2):\r
1646 Line = Line.replace(Marker2[1:], '')\r
1647 if IsCommon:\r
1648 ComBody.append(Line)\r
1649 IsCommon = False\r
1650 continue\r
1651 if IsCommon:\r
1652 ComBody.append(Line)\r
1653 else:\r
1654 TxtBody.append(Line)\r
1655 return ComBody, TxtBody\r
1656\r
1657 def GetStructArrayInfo(self, Input):\r
1658 ArrayStr = Input.split('[')\r
1659 Name = ArrayStr[0]\r
1660 if len(ArrayStr) > 1:\r
1661 NumStr = ''.join(c for c in ArrayStr[-1] if c.isdigit())\r
1662 NumStr = '1000' if len(NumStr) == 0 else NumStr\r
1663 ArrayNum = int(NumStr)\r
1664 else:\r
1665 ArrayNum = 0\r
1666 return Name, ArrayNum\r
1667\r
1668 def PostProcessBody(self, TextBody, IncludeEmbedOnly=True):\r
1669 NewTextBody = []\r
1670 OldTextBody = []\r
1671 IncTextBody = []\r
1672 StructBody = []\r
1673 IncludeLine = False\r
1674 EmbedFound = False\r
1675 StructName = ''\r
1676 ArrayVarName = ''\r
1677 VariableName = ''\r
1678 Count = 0\r
1679 Level = 0\r
1680 IsCommonStruct = False\r
1681\r
1682 for Line in TextBody:\r
1683 if Line.startswith('#define '):\r
1684 IncTextBody.append(Line)\r
1685 continue\r
1686\r
1687 if not Line.startswith('/* EMBED_STRUCT:'):\r
1688 Match = False\r
1689 else:\r
1690 Match = re.match("^/\\*\\sEMBED_STRUCT:([\\w\\[\\]\\*]+):\\r
1691([\\w\\[\\]\\*]+):(\\w+):(START|END)([\\s\\d]+)\\*/([\\s\\S]*)", Line)\r
1692\r
1693 if Match:\r
1694 ArrayMarker = Match.group(5)\r
1695 if Match.group(4) == 'END':\r
1696 Level -= 1\r
1697 if Level == 0:\r
1698 Line = Match.group(6)\r
1699 else: # 'START'\r
1700 Level += 1\r
1701 if Level == 1:\r
1702 Line = Match.group(6)\r
1703 else:\r
1704 EmbedFound = True\r
1705 TagStr = Match.group(3)\r
1706 if TagStr.startswith('TAG_'):\r
1707 try:\r
1708 TagVal = int(TagStr[4:], 16)\r
1709 except Exception:\r
1710 TagVal = -1\r
1711 if (TagVal >= 0) and (TagVal < self._MinCfgTagId):\r
1712 IsCommonStruct = True\r
1713\r
1714 if Level == 1:\r
1715 if IsCommonStruct:\r
1716 Suffix = ' /* _COMMON_STRUCT_START_ */'\r
1717 else:\r
1718 Suffix = ''\r
1719 StructBody = ['typedef struct {%s' % Suffix]\r
1720 StructName = Match.group(1)\r
1721 StructType = Match.group(2)\r
1722 VariableName = Match.group(3)\r
1723 MatchOffset = re.search('/\\*\\*\\sOffset\\s0x\\r
1724([a-fA-F0-9]+)', Line)\r
1725 if MatchOffset:\r
1726 Offset = int(MatchOffset.group(1), 16)\r
1727 else:\r
1728 Offset = None\r
1729 IncludeLine = True\r
1730\r
1731 ModifiedStructType = StructType.rstrip()\r
1732 if ModifiedStructType.endswith(']'):\r
1733 Idx = ModifiedStructType.index('[')\r
1734 if ArrayMarker != ' ':\r
1735 # Auto array size\r
1736 OldTextBody.append('')\r
1737 ArrayVarName = VariableName\r
1738 if int(ArrayMarker) == 1000:\r
1739 Count = 1\r
1740 else:\r
1741 Count = int(ArrayMarker) + 1000\r
1742 else:\r
1743 if Count < 1000:\r
1744 Count += 1\r
1745\r
1746 VariableTemp = ArrayVarName + '[%d]' % (\r
1747 Count if Count < 1000 else Count - 1000)\r
1748 OldTextBody[-1] = self.CreateField(\r
1749 None, VariableTemp, 0, Offset,\r
1750 ModifiedStructType[:Idx], '',\r
1751 'Structure Array', '')\r
1752 else:\r
1753 ArrayVarName = ''\r
1754 OldTextBody.append(self.CreateField(\r
1755 None, VariableName, 0, Offset,\r
1756 ModifiedStructType, '', '', ''))\r
1757\r
1758 if IncludeLine:\r
1759 StructBody.append(Line)\r
1760 else:\r
1761 OldTextBody.append(Line)\r
1762\r
1763 if Match and Match.group(4) == 'END':\r
1764 if Level == 0:\r
1765 if (StructType != Match.group(2)) or \\r
1766 (VariableName != Match.group(3)):\r
1767 print("Unmatched struct name '%s' and '%s' !" %\r
1768 (StructName, Match.group(2)))\r
1769 else:\r
1770 if IsCommonStruct:\r
1771 Suffix = ' /* _COMMON_STRUCT_END_ */'\r
1772 else:\r
1773 Suffix = ''\r
1774 Line = '} %s;%s\n\n\n' % (StructName, Suffix)\r
1775 StructBody.append(Line)\r
1776 if (Line not in NewTextBody) and \\r
1777 (Line not in OldTextBody):\r
1778 NewTextBody.extend(StructBody)\r
1779 IncludeLine = False\r
1780 IsCommonStruct = False\r
1781\r
1782 if not IncludeEmbedOnly:\r
1783 NewTextBody.extend(OldTextBody)\r
1784\r
1785 if EmbedFound:\r
1786 NewTextBody = self.PostProcessBody(NewTextBody, False)\r
1787\r
1788 NewTextBody = IncTextBody + NewTextBody\r
1789 return NewTextBody\r
1790\r
1791 def WriteHeaderFile(self, TxtBody, FileName, Type='h'):\r
1792 FileNameDef = os.path.basename(FileName).replace('.', '_')\r
1793 FileNameDef = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', FileNameDef)\r
1794 FileNameDef = re.sub('([a-z0-9])([A-Z])', r'\1_\2',\r
1795 FileNameDef).upper()\r
1796\r
1797 Lines = []\r
1798 Lines.append("%s\n" % GetCopyrightHeader(Type))\r
1799 Lines.append("#ifndef __%s__\n" % FileNameDef)\r
1800 Lines.append("#define __%s__\n\n" % FileNameDef)\r
1801 if Type == 'h':\r
1802 Lines.append("#pragma pack(1)\n\n")\r
1803 Lines.extend(TxtBody)\r
1804 if Type == 'h':\r
1805 Lines.append("#pragma pack()\n\n")\r
1806 Lines.append("#endif\n")\r
1807\r
1808 # Don't rewrite if the contents are the same\r
1809 Create = True\r
1810 if os.path.exists(FileName):\r
1811 HdrFile = open(FileName, "r")\r
1812 OrgTxt = HdrFile.read()\r
1813 HdrFile.close()\r
1814\r
1815 NewTxt = ''.join(Lines)\r
1816 if OrgTxt == NewTxt:\r
1817 Create = False\r
1818\r
1819 if Create:\r
1820 HdrFile = open(FileName, "w")\r
1821 HdrFile.write(''.join(Lines))\r
1822 HdrFile.close()\r
1823\r
1824 def CreateHeaderFile(self, HdrFileName, ComHdrFileName=''):\r
1825 LastStruct = ''\r
1826 SpaceIdx = 0\r
1827 Offset = 0\r
1828 FieldIdx = 0\r
1829 LastFieldIdx = 0\r
1830 ResvOffset = 0\r
1831 ResvIdx = 0\r
1832 TxtBody = []\r
1833 LineBuffer = []\r
1834 CfgTags = []\r
1835 LastVisible = True\r
1836\r
1837 TxtBody.append("typedef struct {\n")\r
1838 for Item in self._CfgItemList:\r
1839 # Search for CFGDATA tags\r
1840 Embed = Item["embed"].upper()\r
1841 if Embed.endswith(':START'):\r
1842 Match = re.match(r'(\w+)_CFG_DATA:TAG_([0-9A-F]+):START',\r
1843 Embed)\r
1844 if Match:\r
1845 TagName = Match.group(1)\r
1846 TagId = int(Match.group(2), 16)\r
1847 CfgTags.append((TagId, TagName))\r
1848\r
1849 # Only process visible items\r
1850 NextVisible = LastVisible\r
1851\r
1852 if LastVisible and (Item['header'] == 'OFF'):\r
1853 NextVisible = False\r
1854 ResvOffset = Item['offset']\r
1855 elif (not LastVisible) and Item['header'] == 'ON':\r
1856 NextVisible = True\r
1857 Name = "ReservedUpdSpace%d" % ResvIdx\r
1858 ResvIdx = ResvIdx + 1\r
1859 TxtBody.append(self.CreateField(\r
1860 Item, Name, Item["offset"] - ResvOffset,\r
1861 ResvOffset, '', '', '', ''))\r
1862 FieldIdx += 1\r
1863\r
1864 if Offset < Item["offset"]:\r
1865 if LastVisible:\r
1866 Name = "UnusedUpdSpace%d" % SpaceIdx\r
1867 LineBuffer.append(self.CreateField\r
1868 (Item, Name, Item["offset"] -\r
1869 Offset, Offset, '', '', '', ''))\r
1870 FieldIdx += 1\r
1871 SpaceIdx = SpaceIdx + 1\r
1872 Offset = Item["offset"]\r
1873\r
1874 LastVisible = NextVisible\r
1875\r
1876 Offset = Offset + Item["length"]\r
1877 if LastVisible:\r
1878 for Each in LineBuffer:\r
1879 TxtBody.append(Each)\r
1880 LineBuffer = []\r
1881 Embed = Item["embed"].upper()\r
1882 if Embed.endswith(':START') or Embed.endswith(':END'):\r
1883 # EMBED_STRUCT: StructName : \\r
1884 # ItemName : VariableName : START|END\r
1885 Name, ArrayNum = self.GetStructArrayInfo(Item["struct"])\r
1886 Remaining = Item["embed"]\r
1887 if (LastFieldIdx + 1 == FieldIdx) and (LastStruct == Name):\r
1888 ArrayMarker = ' '\r
1889 else:\r
1890 ArrayMarker = '%d' % ArrayNum\r
1891 LastFieldIdx = FieldIdx\r
1892 LastStruct = Name\r
1893 Marker = '/* EMBED_STRUCT:%s:%s%s*/ ' % (Name, Remaining,\r
1894 ArrayMarker)\r
1895 # if Embed.endswith(':START') and Comment != '':\r
1896 # Marker = '/* COMMENT:%s */ \n' % Item["comment"] + Marker\r
1897 else:\r
1898 if Embed == '':\r
1899 Marker = ''\r
1900 else:\r
1901 self.Error = "Invalid embedded structure \\r
1902format '%s'!\n" % Item["embed"]\r
1903 return 4\r
1904\r
1905 # Generate bit fields for structure\r
1906 if len(Item['subreg']) > 0 and Item["struct"]:\r
1907 StructType = Item["struct"]\r
1908 StructName, ArrayNum = self.GetStructArrayInfo(StructType)\r
1909 if (LastFieldIdx + 1 == FieldIdx) and \\r
1910 (LastStruct == Item["struct"]):\r
1911 ArrayMarker = ' '\r
1912 else:\r
1913 ArrayMarker = '%d' % ArrayNum\r
1914 TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:START%s*/\n' %\r
1915 (StructName, StructType, Item["cname"],\r
1916 ArrayMarker))\r
1917 for SubItem in Item['subreg']:\r
1918 Name = SubItem["cname"]\r
1919 if Name.startswith(Item["cname"]):\r
1920 Name = Name[len(Item["cname"]) + 1:]\r
1921 Line = self.CreateField(\r
1922 SubItem, Name, SubItem["bitunit"],\r
1923 SubItem["offset"], SubItem['struct'],\r
1924 SubItem['name'], SubItem['help'],\r
1925 SubItem['option'], SubItem['bitlength'])\r
1926 TxtBody.append(Line)\r
1927 TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:END%s*/\n' %\r
1928 (StructName, StructType, Item["cname"],\r
1929 ArrayMarker))\r
1930 LastFieldIdx = FieldIdx\r
1931 LastStruct = Item["struct"]\r
1932 FieldIdx += 1\r
1933 else:\r
1934 FieldIdx += 1\r
1935 Line = Marker + self.CreateField(\r
1936 Item, Item["cname"], Item["length"], Item["offset"],\r
1937 Item['struct'], Item['name'], Item['help'],\r
1938 Item['option'])\r
1939 TxtBody.append(Line)\r
1940\r
1941 TxtBody.append("}\n\n")\r
1942\r
1943 # Handle the embedded data structure\r
1944 TxtBody = self.PostProcessBody(TxtBody)\r
1945 ComBody, TxtBody = self.SplitTextBody(TxtBody)\r
1946\r
1947 # Prepare TAG defines\r
1948 PltTagDefTxt = ['\n']\r
1949 ComTagDefTxt = ['\n']\r
1950 for TagId, TagName in sorted(CfgTags):\r
1951 TagLine = '#define %-30s 0x%03X\n' % ('CDATA_%s_TAG' %\r
1952 TagName, TagId)\r
1953 if TagId < self._MinCfgTagId:\r
1954 # TAG ID < 0x100, it is a generic TAG\r
1955 ComTagDefTxt.append(TagLine)\r
1956 else:\r
1957 PltTagDefTxt.append(TagLine)\r
1958 PltTagDefTxt.append('\n\n')\r
1959 ComTagDefTxt.append('\n\n')\r
1960\r
1961 # Write file back\r
1962 self.WriteHeaderFile(PltTagDefTxt + TxtBody, HdrFileName)\r
1963 if ComHdrFileName:\r
1964 self.WriteHeaderFile(ComTagDefTxt + ComBody, ComHdrFileName)\r
1965\r
1966 return 0\r
1967\r
1968 def UpdateConfigItemValue(self, Item, ValueStr):\r
1969 IsArray = True if Item['value'].startswith('{') else False\r
1970 IsString = True if Item['value'].startswith("'") else False\r
1971 Bytes = self.ValueToByteArray(ValueStr, Item['length'])\r
1972 if IsString:\r
1973 NewValue = "'%s'" % Bytes.decode("utf-8")\r
1974 elif IsArray:\r
1975 NewValue = Bytes2Str(Bytes)\r
1976 else:\r
1977 Fmt = '0x%X' if Item['value'].startswith('0x') else '%d'\r
1978 NewValue = Fmt % Bytes2Val(Bytes)\r
1979 Item['value'] = NewValue\r
1980\r
1981 def LoadDefaultFromBinaryArray(self, BinDat, IgnoreFind=False):\r
1982 FindOff = 0\r
1983 StartOff = 0\r
1984 for Item in self._CfgItemList:\r
1985 if Item['length'] == 0:\r
1986 continue\r
1987 if not IgnoreFind and Item['find']:\r
1988 FindBin = Item['find'].encode()\r
1989 Offset = BinDat.find(FindBin)\r
1990 if Offset >= 0:\r
1991 TestOff = BinDat[Offset+len(FindBin):].find(FindBin)\r
1992 if TestOff >= 0:\r
1993 raise Exception('Multiple match found for "%s" !' %\r
1994 Item['find'])\r
1995 FindOff = Offset + len(FindBin)\r
1996 StartOff = Item['offset']\r
1997 else:\r
1998 raise Exception('Could not find "%s" !' % Item['find'])\r
1999 if Item['offset'] + Item['length'] > len(BinDat):\r
2000 raise Exception('Mismatching format between DSC \\r
2001and BIN files !')\r
2002 Offset = FindOff + (Item['offset'] - StartOff)\r
2003 ValStr = Bytes2Str(BinDat[Offset: Offset + Item['length']])\r
2004 self.UpdateConfigItemValue(Item, ValStr)\r
2005\r
2006 self.UpdateDefaultValue()\r
2007\r
2008 def PatchBinaryArray(self, BinDat):\r
2009 FileOff = 0\r
2010 Offset = 0\r
2011 FindOff = 0\r
2012\r
2013 PatchList = []\r
2014 CfgBin = bytearray()\r
2015 for Item in self._CfgItemList:\r
2016 if Item['length'] == 0:\r
2017 continue\r
2018\r
2019 if Item['find']:\r
2020 if len(CfgBin) > 0:\r
2021 PatchList.append((FileOff, CfgBin))\r
2022 FindBin = Item['find'].encode()\r
2023 FileOff = BinDat.find(FindBin)\r
2024 if FileOff < 0:\r
2025 raise Exception('Could not find "%s" !' % Item['find'])\r
2026 else:\r
2027 TestOff = BinDat[FileOff+len(FindBin):].find(FindBin)\r
2028 if TestOff >= 0:\r
2029 raise Exception('Multiple match found for "%s" !' %\r
2030 Item['find'])\r
2031 FileOff += len(FindBin)\r
2032 Offset = Item['offset']\r
2033 FindOff = Offset\r
2034 CfgBin = bytearray()\r
2035\r
2036 if Item['offset'] > Offset:\r
2037 Gap = Item['offset'] - Offset\r
2038 CfgBin.extend(b'\x00' * Gap)\r
2039\r
2040 if Item['type'] == 'Reserved' and Item['option'] == '$SKIP':\r
2041 # keep old data\r
2042 NewOff = FileOff + (Offset - FindOff)\r
2043 FileData = bytearray(BinDat[NewOff: NewOff + Item['length']])\r
2044 CfgBin.extend(FileData)\r
2045 else:\r
2046 CfgBin.extend(self.ValueToByteArray(Item['value'],\r
2047 Item['length']))\r
2048 Offset = Item['offset'] + Item['length']\r
2049\r
2050 if len(CfgBin) > 0:\r
2051 PatchList.append((FileOff, CfgBin))\r
2052\r
2053 for FileOff, CfgBin in PatchList:\r
2054 Length = len(CfgBin)\r
2055 if FileOff + Length < len(BinDat):\r
2056 BinDat[FileOff:FileOff+Length] = CfgBin[:]\r
2057\r
2058 return BinDat\r
2059\r
2060 def GenerateBinaryArray(self):\r
2061 Offset = 0\r
2062 BinDat = bytearray()\r
2063 for Item in self._CfgItemList:\r
2064 if Item['offset'] > Offset:\r
2065 Gap = Item['offset'] - Offset\r
2066 BinDat.extend(b'\x00' * Gap)\r
2067 BinDat.extend(self.ValueToByteArray(Item['value'], Item['length']))\r
2068 Offset = Item['offset'] + Item['length']\r
2069 return BinDat\r
2070\r
2071 def GenerateBinary(self, BinFileName):\r
2072 BinFile = open(BinFileName, "wb")\r
2073 BinFile.write(self.GenerateBinaryArray())\r
2074 BinFile.close()\r
2075 return 0\r
2076\r
2077 def GenerateDataIncFile(self, DatIncFileName, BinFile=None):\r
2078 # Put a prefix GUID before CFGDATA so that it can be located later on\r
2079 Prefix = b'\xa7\xbd\x7f\x73\x20\x1e\x46\xd6\xbe\x8f\\r
2080x64\x12\x05\x8d\x0a\xa8'\r
2081 if BinFile:\r
2082 Fin = open(BinFile, 'rb')\r
2083 BinDat = Prefix + bytearray(Fin.read())\r
2084 Fin.close()\r
2085 else:\r
2086 BinDat = Prefix + self.GenerateBinaryArray()\r
2087\r
2088 FileName = os.path.basename(DatIncFileName).upper()\r
2089 FileName = FileName.replace('.', '_')\r
2090\r
2091 TxtLines = []\r
2092\r
2093 TxtLines.append("UINT8 mConfigDataBlob[%d] = {\n" % len(BinDat))\r
2094 Count = 0\r
2095 Line = [' ']\r
2096 for Each in BinDat:\r
2097 Line.append('0x%02X, ' % Each)\r
2098 Count = Count + 1\r
2099 if (Count & 0x0F) == 0:\r
2100 Line.append('\n')\r
2101 TxtLines.append(''.join(Line))\r
2102 Line = [' ']\r
2103 if len(Line) > 1:\r
2104 TxtLines.append(''.join(Line) + '\n')\r
2105\r
2106 TxtLines.append("};\n\n")\r
2107\r
2108 self.WriteHeaderFile(TxtLines, DatIncFileName, 'inc')\r
2109\r
2110 return 0\r
2111\r
2112 def CheckCfgData(self):\r
2113 # Check if CfgData contains any duplicated name\r
2114 def AddItem(Item, ChkList):\r
2115 Name = Item['cname']\r
2116 if Name in ChkList:\r
2117 return Item\r
2118 if Name not in ['Dummy', 'Reserved', 'CfgHeader', 'CondValue']:\r
2119 ChkList.append(Name)\r
2120 return None\r
2121\r
2122 Duplicate = None\r
2123 ChkList = []\r
2124 for Item in self._CfgItemList:\r
2125 Duplicate = AddItem(Item, ChkList)\r
2126 if not Duplicate:\r
2127 for SubItem in Item['subreg']:\r
2128 Duplicate = AddItem(SubItem, ChkList)\r
2129 if Duplicate:\r
2130 break\r
2131 if Duplicate:\r
2132 break\r
2133 if Duplicate:\r
2134 self.Error = "Duplicated CFGDATA '%s' found !\n" % \\r
2135 Duplicate['cname']\r
2136 return -1\r
2137 return 0\r
2138\r
2139 def PrintData(self):\r
2140 for Item in self._CfgItemList:\r
2141 if not Item['length']:\r
2142 continue\r
2143 print("%-10s @Offset:0x%04X Len:%3d Val:%s" %\r
2144 (Item['cname'], Item['offset'], Item['length'],\r
2145 Item['value']))\r
2146 for SubItem in Item['subreg']:\r
2147 print(" %-20s BitOff:0x%04X BitLen:%-3d Val:%s" %\r
2148 (SubItem['cname'], SubItem['bitoffset'],\r
2149 SubItem['bitlength'], SubItem['value']))\r
2150\r
2151 def FormatArrayValue(self, Input, Length):\r
2152 Dat = self.ValueToByteArray(Input, Length)\r
2153 return ','.join('0x%02X' % Each for Each in Dat)\r
2154\r
2155 def GetItemOptionList(self, Item):\r
2156 TmpList = []\r
2157 if Item['type'] == "Combo":\r
2158 if not Item['option'] in self._BuidinOption:\r
2159 OptList = Item['option'].split(',')\r
2160 for Option in OptList:\r
2161 Option = Option.strip()\r
2162 try:\r
2163 (OpVal, OpStr) = Option.split(':')\r
2164 except Exception:\r
2165 raise Exception("Invalide option format '%s' !" %\r
2166 Option)\r
2167 TmpList.append((OpVal, OpStr))\r
2168 return TmpList\r
2169\r
2170 def WriteBsfStruct(self, BsfFd, Item):\r
2171 if Item['type'] == "None":\r
2172 Space = "gPlatformFspPkgTokenSpaceGuid"\r
2173 else:\r
2174 Space = Item['space']\r
2175 Line = " $%s_%s" % (Space, Item['cname'])\r
2176 Match = re.match("\\s*(\\{.+\\})\\s*", Item['value'])\r
2177 if Match:\r
2178 DefaultValue = self.FormatArrayValue(Match.group(1).strip(),\r
2179 Item['length'])\r
2180 else:\r
2181 DefaultValue = Item['value'].strip()\r
2182 if 'bitlength' in Item:\r
2183 if Item['bitlength']:\r
2184 BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" %\r
2185 (Line, ' ' * (64 - len(Line)), Item['bitlength'],\r
2186 DefaultValue))\r
2187 else:\r
2188 if Item['length']:\r
2189 BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" %\r
2190 (Line, ' ' * (64 - len(Line)), Item['length'],\r
2191 DefaultValue))\r
2192\r
2193 return self.GetItemOptionList(Item)\r
2194\r
2195 def GetBsfOption(self, OptionName):\r
2196 if OptionName in self._CfgOptsDict:\r
2197 return self._CfgOptsDict[OptionName]\r
2198 else:\r
2199 return OptionName\r
2200\r
2201 def WriteBsfOption(self, BsfFd, Item):\r
2202 PcdName = Item['space'] + '_' + Item['cname']\r
2203 WriteHelp = 0\r
2204 BsfLines = []\r
2205 if Item['type'] == "Combo":\r
2206 if Item['option'] in self._BuidinOption:\r
2207 Options = self._BuidinOption[Item['option']]\r
2208 else:\r
2209 Options = self.GetBsfOption(PcdName)\r
2210 BsfLines.append(' %s $%s, "%s", &%s,\n' % (\r
2211 Item['type'], PcdName, Item['name'], Options))\r
2212 WriteHelp = 1\r
2213 elif Item['type'].startswith("EditNum"):\r
2214 Match = re.match("EditNum\\s*,\\s*(HEX|DEC)\\s*,\\s*\\(\\r
2215(\\d+|0x[0-9A-Fa-f]+)\\s*,\\s*(\\d+|0x[0-9A-Fa-f]+)\\)", Item['type'])\r
2216 if Match:\r
2217 BsfLines.append(' EditNum $%s, "%s", %s,\n' % (\r
2218 PcdName, Item['name'], Match.group(1)))\r
2219 WriteHelp = 2\r
2220 elif Item['type'].startswith("EditText"):\r
2221 BsfLines.append(' %s $%s, "%s",\n' % (Item['type'], PcdName,\r
2222 Item['name']))\r
2223 WriteHelp = 1\r
2224 elif Item['type'] == "Table":\r
2225 Columns = Item['option'].split(',')\r
2226 if len(Columns) != 0:\r
2227 BsfLines.append(' %s $%s "%s",' % (Item['type'], PcdName,\r
2228 Item['name']))\r
2229 for Col in Columns:\r
2230 Fmt = Col.split(':')\r
2231 if len(Fmt) != 3:\r
2232 raise Exception("Column format '%s' is invalid !" %\r
2233 Fmt)\r
2234 try:\r
2235 Dtype = int(Fmt[1].strip())\r
2236 except Exception:\r
2237 raise Exception("Column size '%s' is invalid !" %\r
2238 Fmt[1])\r
2239 BsfLines.append('\n Column "%s", %d bytes, %s' %\r
2240 (Fmt[0].strip(), Dtype, Fmt[2].strip()))\r
2241 BsfLines.append(',\n')\r
2242 WriteHelp = 1\r
2243\r
2244 if WriteHelp > 0:\r
2245 HelpLines = Item['help'].split('\\n\\r')\r
2246 FirstLine = True\r
2247 for HelpLine in HelpLines:\r
2248 if FirstLine:\r
2249 FirstLine = False\r
2250 BsfLines.append(' Help "%s"\n' % (HelpLine))\r
2251 else:\r
2252 BsfLines.append(' "%s"\n' % (HelpLine))\r
2253 if WriteHelp == 2:\r
2254 BsfLines.append(' "Valid range: %s ~ %s"\n' %\r
2255 (Match.group(2), Match.group(3)))\r
2256\r
2257 if len(Item['condition']) > 4:\r
2258 CondList = Item['condition'].split(',')\r
2259 Idx = 0\r
2260 for Cond in CondList:\r
2261 Cond = Cond.strip()\r
2262 if Cond.startswith('#'):\r
2263 BsfLines.insert(Idx, Cond + '\n')\r
2264 Idx += 1\r
2265 elif Cond.startswith('@#'):\r
2266 BsfLines.append(Cond[1:] + '\n')\r
2267\r
2268 for Line in BsfLines:\r
2269 BsfFd.write(Line)\r
2270\r
2271 def WriteBsfPages(self, PageTree, BsfFd):\r
2272 BsfFd.write('\n')\r
2273 Key = next(iter(PageTree))\r
2274 for Page in PageTree[Key]:\r
2275 PageName = next(iter(Page))\r
2276 BsfFd.write('Page "%s"\n' % self._CfgPageDict[PageName])\r
2277 if len(PageTree[Key]):\r
2278 self.WriteBsfPages(Page, BsfFd)\r
2279\r
2280 BsfItems = []\r
2281 for Item in self._CfgItemList:\r
2282 if Item['name'] != '':\r
2283 if Item['page'] != PageName:\r
2284 continue\r
2285 if len(Item['subreg']) > 0:\r
2286 for SubItem in Item['subreg']:\r
2287 if SubItem['name'] != '':\r
2288 BsfItems.append(SubItem)\r
2289 else:\r
2290 BsfItems.append(Item)\r
2291\r
2292 BsfItems.sort(key=lambda x: x['order'])\r
2293\r
2294 for Item in BsfItems:\r
2295 self.WriteBsfOption(BsfFd, Item)\r
2296 BsfFd.write("EndPage\n\n")\r
2297\r
2298 def GenerateBsfFile(self, BsfFile):\r
2299\r
2300 if BsfFile == '':\r
2301 self.Error = "BSF output file '%s' is invalid" % BsfFile\r
2302 return 1\r
2303\r
2304 Error = 0\r
2305 OptionDict = {}\r
2306 BsfFd = open(BsfFile, "w")\r
2307 BsfFd.write("%s\n" % GetCopyrightHeader('bsf'))\r
2308 BsfFd.write("%s\n" % self._GlobalDataDef)\r
2309 BsfFd.write("StructDef\n")\r
2310 NextOffset = -1\r
2311 for Item in self._CfgItemList:\r
2312 if Item['find'] != '':\r
2313 BsfFd.write('\n Find "%s"\n' % Item['find'])\r
2314 NextOffset = Item['offset'] + Item['length']\r
2315 if Item['name'] != '':\r
2316 if NextOffset != Item['offset']:\r
2317 BsfFd.write(" Skip %d bytes\n" %\r
2318 (Item['offset'] - NextOffset))\r
2319 if len(Item['subreg']) > 0:\r
2320 NextOffset = Item['offset']\r
2321 BitsOffset = NextOffset * 8\r
2322 for SubItem in Item['subreg']:\r
2323 BitsOffset += SubItem['bitlength']\r
2324 if SubItem['name'] == '':\r
2325 if 'bitlength' in SubItem:\r
2326 BsfFd.write(" Skip %d bits\n" %\r
2327 (SubItem['bitlength']))\r
2328 else:\r
2329 BsfFd.write(" Skip %d bytes\n" %\r
2330 (SubItem['length']))\r
2331 else:\r
2332 Options = self.WriteBsfStruct(BsfFd, SubItem)\r
2333 if len(Options) > 0:\r
2334 OptionDict[SubItem\r
2335 ['space']+'_'+SubItem\r
2336 ['cname']] = Options\r
2337\r
2338 NextBitsOffset = (Item['offset'] + Item['length']) * 8\r
2339 if NextBitsOffset > BitsOffset:\r
2340 BitsGap = NextBitsOffset - BitsOffset\r
2341 BitsRemain = BitsGap % 8\r
2342 if BitsRemain:\r
2343 BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
2344 BitsGap -= BitsRemain\r
2345 BytesRemain = BitsGap // 8\r
2346 if BytesRemain:\r
2347 BsfFd.write(" Skip %d bytes\n" %\r
2348 BytesRemain)\r
2349 NextOffset = Item['offset'] + Item['length']\r
2350 else:\r
2351 NextOffset = Item['offset'] + Item['length']\r
2352 Options = self.WriteBsfStruct(BsfFd, Item)\r
2353 if len(Options) > 0:\r
2354 OptionDict[Item['space']+'_'+Item['cname']] = Options\r
2355 BsfFd.write("\nEndStruct\n\n")\r
2356\r
2357 BsfFd.write("%s" % self._BuidinOptionTxt)\r
2358\r
2359 NameList = []\r
2360 OptionList = []\r
2361 for Each in sorted(OptionDict):\r
2362 if OptionDict[Each] not in OptionList:\r
2363 NameList.append(Each)\r
2364 OptionList.append(OptionDict[Each])\r
2365 BsfFd.write("List &%s\n" % Each)\r
2366 for Item in OptionDict[Each]:\r
2367 BsfFd.write(' Selection %s , "%s"\n' %\r
2368 (self.EvaluateExpress(Item[0]), Item[1]))\r
2369 BsfFd.write("EndList\n\n")\r
2370 else:\r
2371 # Item has idential options as other item\r
2372 # Try to reuse the previous options instead\r
2373 Idx = OptionList.index(OptionDict[Each])\r
2374 self._CfgOptsDict[Each] = NameList[Idx]\r
2375\r
2376 BsfFd.write("BeginInfoBlock\n")\r
2377 BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))\r
2378 BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))\r
2379 BsfFd.write("EndInfoBlock\n\n")\r
2380\r
2381 self.WriteBsfPages(self._CfgPageTree, BsfFd)\r
2382\r
2383 BsfFd.close()\r
2384 return Error\r
2385\r
2386 def WriteDeltaLine(self, OutLines, Name, ValStr, IsArray):\r
2387 if IsArray:\r
2388 Output = '%s | { %s }' % (Name, ValStr)\r
2389 else:\r
2390 Output = '%s | 0x%X' % (Name, Array2Val(ValStr))\r
2391 OutLines.append(Output)\r
2392\r
2393 def WriteDeltaFile(self, OutFile, PlatformId, OutLines):\r
2394 DltFd = open(OutFile, "w")\r
2395 DltFd.write("%s\n" % GetCopyrightHeader('dlt', True))\r
2396 if PlatformId is not None:\r
2397 DltFd.write('#\n')\r
2398 DltFd.write('# Delta configuration values \\r
2399for platform ID 0x%04X\n' % PlatformId)\r
2400 DltFd.write('#\n\n')\r
2401 for Line in OutLines:\r
2402 DltFd.write('%s\n' % Line)\r
2403 DltFd.close()\r
2404\r
2405 def GenerateDeltaFile(self, OutFile, AbsfFile):\r
2406 # Parse ABSF Build in dict\r
2407 if not os.path.exists(AbsfFile):\r
2408 Lines = []\r
2409 else:\r
2410 with open(AbsfFile) as Fin:\r
2411 Lines = Fin.readlines()\r
2412\r
2413 AbsfBuiltValDict = {}\r
2414 Process = False\r
2415 for Line in Lines:\r
2416 Line = Line.strip()\r
2417 if Line.startswith('StructDef'):\r
2418 Process = True\r
2419 if Line.startswith('EndStruct'):\r
2420 break\r
2421 if not Process:\r
2422 continue\r
2423 Match = re.match('\\s*\\$gCfgData_(\\w+)\\s+\\r
2424(\\d+)\\s+(bits|bytes)\\s+\\$_AS_BUILT_\\s+=\\s+(.+)\\$', Line)\r
2425 if Match:\r
2426 if Match.group(1) not in AbsfBuiltValDict:\r
2427 AbsfBuiltValDict[Match.group(1)] = Match.group(4).strip()\r
2428 else:\r
2429 raise Exception("Duplicated configuration \\r
2430name '%s' found !", Match.group(1))\r
2431\r
2432 # Match config item in DSC\r
2433 PlatformId = None\r
2434 OutLines = []\r
2435 TagName = ''\r
2436 Level = 0\r
2437 for Item in self._CfgItemList:\r
2438 Name = None\r
2439 if Level == 0 and Item['embed'].endswith(':START'):\r
2440 TagName = Item['embed'].split(':')[0]\r
2441 Level += 1\r
2442 if Item['cname'] in AbsfBuiltValDict:\r
2443 ValStr = AbsfBuiltValDict[Item['cname']]\r
2444 Name = '%s.%s' % (TagName, Item['cname'])\r
2445 if not Item['subreg'] and Item['value'].startswith('{'):\r
2446 Value = Array2Val(Item['value'])\r
2447 IsArray = True\r
2448 else:\r
2449 Value = int(Item['value'], 16)\r
2450 IsArray = False\r
2451 AbsfVal = Array2Val(ValStr)\r
2452 if AbsfVal != Value:\r
2453 if 'PLATFORMID_CFG_DATA.PlatformId' == Name:\r
2454 PlatformId = AbsfVal\r
2455 self.WriteDeltaLine(OutLines, Name, ValStr, IsArray)\r
2456 else:\r
2457 if 'PLATFORMID_CFG_DATA.PlatformId' == Name:\r
2458 raise Exception("'PlatformId' has the \\r
2459same value as DSC default !")\r
2460\r
2461 if Item['subreg']:\r
2462 for SubItem in Item['subreg']:\r
2463 if SubItem['cname'] in AbsfBuiltValDict:\r
2464 ValStr = AbsfBuiltValDict[SubItem['cname']]\r
2465 if Array2Val(ValStr) == int(SubItem['value'], 16):\r
2466 continue\r
2467 Name = '%s.%s.%s' % (TagName, Item['cname'],\r
2468 SubItem['cname'])\r
2469 self.WriteDeltaLine(OutLines, Name, ValStr, False)\r
2470\r
2471 if Item['embed'].endswith(':END'):\r
2472 Level -= 1\r
2473\r
2474 if PlatformId is None and Lines:\r
2475 raise Exception("'PlatformId' configuration \\r
2476is missing in ABSF file!")\r
2477 else:\r
2478 PlatformId = 0\r
2479\r
2480 self.WriteDeltaFile(OutFile, PlatformId, Lines)\r
2481\r
2482 return 0\r
2483\r
2484 def GenerateDscFile(self, OutFile):\r
2485 DscFd = open(OutFile, "w")\r
2486 for Line in self._DscLines:\r
2487 DscFd.write(Line + '\n')\r
2488 DscFd.close()\r
2489 return 0\r
2490\r
2491\r
2492def Usage():\r
2493 print('\n'.join([\r
2494 "GenCfgData Version 0.01",\r
2495 "Usage:",\r
2496 " GenCfgData GENINC BinFile \\r
2497IncOutFile [-D Macros]",\r
2498 " GenCfgData GENPKL DscFile \\r
2499PklOutFile [-D Macros]",\r
2500 " GenCfgData GENINC DscFile[;DltFile] \\r
2501IncOutFile [-D Macros]",\r
2502 " GenCfgData GENBIN DscFile[;DltFile] \\r
2503BinOutFile [-D Macros]",\r
2504 " GenCfgData GENBSF DscFile[;DltFile] \\r
2505BsfOutFile [-D Macros]",\r
2506 " GenCfgData GENDLT DscFile[;AbsfFile] \\r
2507DltOutFile [-D Macros]",\r
2508 " GenCfgData GENDSC DscFile \\r
2509DscOutFile [-D Macros]",\r
2510 " GenCfgData GENHDR DscFile[;DltFile] \\r
2511HdrOutFile[;ComHdrOutFile] [-D Macros]"\r
2512 ]))\r
2513\r
2514\r
2515def Main():\r
2516 #\r
2517 # Parse the options and args\r
2518 #\r
2519 argc = len(sys.argv)\r
2520 if argc < 4:\r
2521 Usage()\r
2522 return 1\r
2523\r
2524 GenCfgData = CGenCfgData()\r
2525 Command = sys.argv[1].upper()\r
2526 OutFile = sys.argv[3]\r
2527\r
2528 if argc > 5 and GenCfgData.ParseMacros(sys.argv[4:]) != 0:\r
2529 raise Exception("ERROR: Macro parsing failed !")\r
2530\r
2531 FileList = sys.argv[2].split(';')\r
2532 if len(FileList) == 2:\r
2533 DscFile = FileList[0]\r
2534 DltFile = FileList[1]\r
2535 elif len(FileList) == 1:\r
2536 DscFile = FileList[0]\r
2537 DltFile = ''\r
2538 else:\r
2539 raise Exception("ERROR: Invalid parameter '%s' !" % sys.argv[2])\r
2540\r
2541 if Command == "GENDLT" and DscFile.endswith('.dlt'):\r
2542 # It needs to expand an existing DLT file\r
2543 DltFile = DscFile\r
2544 Lines = CGenCfgData.ExpandIncludeFiles(DltFile)\r
2545 OutTxt = ''.join([x[0] for x in Lines])\r
2546 OutFile = open(OutFile, "w")\r
2547 OutFile.write(OutTxt)\r
2548 OutFile.close()\r
2549 return 0\r
2550\r
2551 if not os.path.exists(DscFile):\r
2552 raise Exception("ERROR: Cannot open file '%s' !" % DscFile)\r
2553\r
2554 CfgBinFile = ''\r
2555 if DltFile:\r
2556 if not os.path.exists(DltFile):\r
2557 raise Exception("ERROR: Cannot open file '%s' !" % DltFile)\r
2558 if Command == "GENDLT":\r
2559 CfgBinFile = DltFile\r
2560 DltFile = ''\r
2561\r
2562 BinFile = ''\r
2563 if (DscFile.lower().endswith('.bin')) and (Command == "GENINC"):\r
2564 # It is binary file\r
2565 BinFile = DscFile\r
2566 DscFile = ''\r
2567\r
2568 if BinFile:\r
2569 if GenCfgData.GenerateDataIncFile(OutFile, BinFile) != 0:\r
2570 raise Exception(GenCfgData.Error)\r
2571 return 0\r
2572\r
2573 if DscFile.lower().endswith('.pkl'):\r
2574 with open(DscFile, "rb") as PklFile:\r
2575 GenCfgData.__dict__ = marshal.load(PklFile)\r
2576 else:\r
2577 if GenCfgData.ParseDscFile(DscFile) != 0:\r
2578 raise Exception(GenCfgData.Error)\r
2579\r
2580 # if GenCfgData.CheckCfgData() != 0:\r
2581 # raise Exception(GenCfgData.Error)\r
2582\r
2583 if GenCfgData.CreateVarDict() != 0:\r
2584 raise Exception(GenCfgData.Error)\r
2585\r
2586 if Command == 'GENPKL':\r
2587 with open(OutFile, "wb") as PklFile:\r
2588 marshal.dump(GenCfgData.__dict__, PklFile)\r
2589 return 0\r
2590\r
2591 if DltFile and Command in ['GENHDR', 'GENBIN', 'GENINC', 'GENBSF']:\r
2592 if GenCfgData.OverrideDefaultValue(DltFile) != 0:\r
2593 raise Exception(GenCfgData.Error)\r
2594\r
2595 if GenCfgData.UpdateDefaultValue() != 0:\r
2596 raise Exception(GenCfgData.Error)\r
2597\r
2598 # GenCfgData.PrintData ()\r
2599\r
2600 if sys.argv[1] == "GENBIN":\r
2601 if GenCfgData.GenerateBinary(OutFile) != 0:\r
2602 raise Exception(GenCfgData.Error)\r
2603\r
2604 elif sys.argv[1] == "GENHDR":\r
2605 OutFiles = OutFile.split(';')\r
2606 BrdOutFile = OutFiles[0].strip()\r
2607 if len(OutFiles) > 1:\r
2608 ComOutFile = OutFiles[1].strip()\r
2609 else:\r
2610 ComOutFile = ''\r
2611 if GenCfgData.CreateHeaderFile(BrdOutFile, ComOutFile) != 0:\r
2612 raise Exception(GenCfgData.Error)\r
2613\r
2614 elif sys.argv[1] == "GENBSF":\r
2615 if GenCfgData.GenerateBsfFile(OutFile) != 0:\r
2616 raise Exception(GenCfgData.Error)\r
2617\r
2618 elif sys.argv[1] == "GENINC":\r
2619 if GenCfgData.GenerateDataIncFile(OutFile) != 0:\r
2620 raise Exception(GenCfgData.Error)\r
2621\r
2622 elif sys.argv[1] == "GENDLT":\r
2623 if GenCfgData.GenerateDeltaFile(OutFile, CfgBinFile) != 0:\r
2624 raise Exception(GenCfgData.Error)\r
2625\r
2626 elif sys.argv[1] == "GENDSC":\r
2627 if GenCfgData.GenerateDscFile(OutFile) != 0:\r
2628 raise Exception(GenCfgData.Error)\r
2629\r
2630 else:\r
2631 raise Exception("Unsuported command '%s' !" % Command)\r
2632\r
2633 return 0\r
2634\r
2635\r
2636if __name__ == '__main__':\r
2637 sys.exit(Main())\r