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