]>
Commit | Line | Data |
---|---|---|
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 | |
8 | import os\r | |
9 | import re\r | |
10 | import sys\r | |
11 | import marshal\r | |
12 | from functools import reduce\r | |
13 | from 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 | |
45 | def Bytes2Val(Bytes):\r | |
46 | return reduce(lambda x, y: (x << 8) | y, Bytes[::-1])\r | |
47 | \r | |
48 | \r | |
49 | def Bytes2Str(Bytes):\r | |
50 | return '{ %s }' % (', '.join('0x%02X' % i for i in Bytes))\r | |
51 | \r | |
52 | \r | |
53 | def 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 | |
60 | def Val2Bytes(Value, Blen):\r | |
61 | return [(Value >> (i * 8) & 0xff) for i in range(Blen)]\r | |
62 | \r | |
63 | \r | |
64 | def 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 | |
85 | def 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 | |
108 | class 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 | |
312 | class 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 | |
588 | class 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 | |
595 | GlobalDataDef\r | |
596 | SKUID = 0, "DEFAULT"\r | |
597 | EndGlobalData\r | |
598 | \r | |
599 | """\r | |
600 | self._BuidinOptionTxt = """\r | |
601 | List &EN_DIS\r | |
602 | Selection 0x1 , "Enabled"\r | |
603 | Selection 0x0 , "Disabled"\r | |
604 | EndList\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 | |
1016 | file '%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 | |
1024 | directive 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 | |
1080 | VER:\"(.+)\"\\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 | |
1119 | parent page '%s'!" % ParentName)\r | |
1120 | self._CfgPageDict[\r | |
1121 | PageName] = Match.group(3)\r | |
1122 | else:\r | |
1123 | raise Exception("Invalid page \\r | |
1124 | definitions '%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 | |
1234 | format '%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 | |
1331 | not 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 | |
1371 | length (%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 | |
1515 | in 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 | |
1902 | format '%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 | |
2001 | and 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 | |
2080 | x64\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 | |
2399 | for 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 | |
2430 | name '%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 | |
2459 | same 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 | |
2476 | is 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 | |
2492 | def Usage():\r | |
2493 | print('\n'.join([\r | |
2494 | "GenCfgData Version 0.01",\r | |
2495 | "Usage:",\r | |
2496 | " GenCfgData GENINC BinFile \\r | |
2497 | IncOutFile [-D Macros]",\r | |
2498 | " GenCfgData GENPKL DscFile \\r | |
2499 | PklOutFile [-D Macros]",\r | |
2500 | " GenCfgData GENINC DscFile[;DltFile] \\r | |
2501 | IncOutFile [-D Macros]",\r | |
2502 | " GenCfgData GENBIN DscFile[;DltFile] \\r | |
2503 | BinOutFile [-D Macros]",\r | |
2504 | " GenCfgData GENBSF DscFile[;DltFile] \\r | |
2505 | BsfOutFile [-D Macros]",\r | |
2506 | " GenCfgData GENDLT DscFile[;AbsfFile] \\r | |
2507 | DltOutFile [-D Macros]",\r | |
2508 | " GenCfgData GENDSC DscFile \\r | |
2509 | DscOutFile [-D Macros]",\r | |
2510 | " GenCfgData GENHDR DscFile[;DltFile] \\r | |
2511 | HdrOutFile[;ComHdrOutFile] [-D Macros]"\r | |
2512 | ]))\r | |
2513 | \r | |
2514 | \r | |
2515 | def 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 | |
2636 | if __name__ == '__main__':\r | |
2637 | sys.exit(Main())\r |