# @ GenCfgData.py # # Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## import os import re import sys import marshal from functools import reduce from datetime import date # Generated file copyright header __copyright_tmp__ = """/** @file Configuration %s File. Copyright (c) %4d, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent This file is automatically generated. Please do NOT modify !!! **/ """ __copyright_dsc__ = """## @file # # Copyright (c) %04d, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## [PcdsDynamicVpd.Upd] # # Global definitions in BSF # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"} # """ def Bytes2Val(Bytes): return reduce(lambda x, y: (x << 8) | y, Bytes[::-1]) def Bytes2Str(Bytes): return '{ %s }' % (', '.join('0x%02X' % i for i in Bytes)) def Str2Bytes(Value, Blen): Result = bytearray(Value[1:-1], 'utf-8') # Excluding quotes if len(Result) < Blen: Result.extend(b'\x00' * (Blen - len(Result))) return Result def Val2Bytes(Value, Blen): return [(Value >> (i * 8) & 0xff) for i in range(Blen)] def Array2Val(ValStr): ValStr = ValStr.strip() if ValStr.startswith('{'): ValStr = ValStr[1:] if ValStr.endswith('}'): ValStr = ValStr[:-1] if ValStr.startswith("'"): ValStr = ValStr[1:] if ValStr.endswith("'"): ValStr = ValStr[:-1] Value = 0 for Each in ValStr.split(',')[::-1]: Each = Each.strip() if Each.startswith('0x'): Base = 16 else: Base = 10 Value = (Value << 8) | int(Each, Base) return Value def GetCopyrightHeader(FileType, AllowModify=False): FileDescription = { 'bsf': 'Boot Setting', 'dsc': 'Definition', 'dlt': 'Delta', 'inc': 'C Binary Blob', 'h': 'C Struct Header' } if FileType in ['bsf', 'dsc', 'dlt']: CommentChar = '#' else: CommentChar = '' Lines = __copyright_tmp__.split('\n') if AllowModify: Lines = [Line for Line in Lines if 'Please do NOT modify' not in Line] CopyrightHdr = '\n'.join('%s%s' % ( CommentChar, Line) for Line in Lines)[:-1] + '\n' return CopyrightHdr % (FileDescription[FileType], date.today().year) class CLogicalExpression: def __init__(self): self.index = 0 self.string = '' def errExit(self, err=''): print("ERROR: Express parsing for:") print(" %s" % self.string) print(" %s^" % (' ' * self.index)) if err: print("INFO : %s" % err) raise SystemExit def getNonNumber(self, n1, n2): if not n1.isdigit(): return n1 if not n2.isdigit(): return n2 return None def getCurr(self, lens=1): try: if lens == -1: return self.string[self.index:] else: if self.index + lens > len(self.string): lens = len(self.string) - self.index return self.string[self.index: self.index + lens] except Exception: return '' def isLast(self): return self.index == len(self.string) def moveNext(self, len=1): self.index += len def skipSpace(self): while not self.isLast(): if self.getCurr() in ' \t': self.moveNext() else: return def normNumber(self, val): return True if val else False def getNumber(self, var): var = var.strip() if re.match('^0x[a-fA-F0-9]+$', var): value = int(var, 16) elif re.match('^[+-]?\\d+$', var): value = int(var, 10) else: value = None return value def parseValue(self): self.skipSpace() var = '' while not self.isLast(): char = self.getCurr() if re.match('^[\\w.]', char): var += char self.moveNext() else: break val = self.getNumber(var) if val is None: value = var else: value = "%d" % val return value def parseSingleOp(self): self.skipSpace() if re.match('^NOT\\W', self.getCurr(-1)): self.moveNext(3) op = self.parseBrace() val = self.getNumber(op) if val is None: self.errExit("'%s' is not a number" % op) return "%d" % (not self.normNumber(int(op))) else: return self.parseValue() def parseBrace(self): self.skipSpace() char = self.getCurr() if char == '(': self.moveNext() value = self.parseExpr() self.skipSpace() if self.getCurr() != ')': self.errExit("Expecting closing brace or operator") self.moveNext() return value else: value = self.parseSingleOp() return value def parseCompare(self): value = self.parseBrace() while True: self.skipSpace() char = self.getCurr() if char in ['<', '>']: self.moveNext() next = self.getCurr() if next == '=': op = char + next self.moveNext() else: op = char result = self.parseBrace() test = self.getNonNumber(result, value) if test is None: value = "%d" % self.normNumber(eval(value + op + result)) else: self.errExit("'%s' is not a valid number for comparision" % test) elif char in ['=', '!']: op = self.getCurr(2) if op in ['==', '!=']: self.moveNext(2) result = self.parseBrace() test = self.getNonNumber(result, value) if test is None: value = "%d" % self.normNumber((eval(value + op + result))) else: value = "%d" % self.normNumber(eval("'" + value + "'" + op + "'" + result + "'")) else: break else: break return value def parseAnd(self): value = self.parseCompare() while True: self.skipSpace() if re.match('^AND\\W', self.getCurr(-1)): self.moveNext(3) result = self.parseCompare() test = self.getNonNumber(result, value) if test is None: value = "%d" % self.normNumber(int(value) & int(result)) else: self.errExit("'%s' is not a valid op number for AND" % test) else: break return value def parseOrXor(self): value = self.parseAnd() op = None while True: self.skipSpace() op = None if re.match('^XOR\\W', self.getCurr(-1)): self.moveNext(3) op = '^' elif re.match('^OR\\W', self.getCurr(-1)): self.moveNext(2) op = '|' else: break if op: result = self.parseAnd() test = self.getNonNumber(result, value) if test is None: value = "%d" % self.normNumber(eval(value + op + result)) else: self.errExit("'%s' is not a valid op number for XOR/OR" % test) return value def parseExpr(self): return self.parseOrXor() def getResult(self): value = self.parseExpr() self.skipSpace() if not self.isLast(): self.errExit("Unexpected character found '%s'" % self.getCurr()) test = self.getNumber(value) if test is None: self.errExit("Result '%s' is not a number" % value) return int(value) def evaluateExpress(self, Expr): self.index = 0 self.string = Expr if self.getResult(): Result = True else: Result = False return Result class CFspBsf2Dsc: def __init__(self, bsf_file): self.cfg_list = CFspBsf2Dsc.parse_bsf(bsf_file) def get_dsc_lines(self): return CFspBsf2Dsc.generate_dsc(self.cfg_list) def save_dsc(self, dsc_file): return CFspBsf2Dsc.generate_dsc(self.cfg_list, dsc_file) @staticmethod def parse_bsf(bsf_file): fd = open(bsf_file, 'r') bsf_txt = fd.read() fd.close() find_list = [] regex = re.compile(r'\s+Find\s+"(.*?)"(.*?)^\s+(\$(.*?)|Skip)\s+', re.S | re.MULTILINE) for match in regex.finditer(bsf_txt): find = match.group(1) name = match.group(3) line = bsf_txt[:match.end()].count("\n") find_list.append((name, find, line)) idx = 0 count = 0 prefix = '' chk_dict = {} cfg_list = [] cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0', 'type': 'Reserved', 'isbit': False, 'embed': '', 'page': '', 'option': '', 'instance': 0} regex = re.compile( r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+(bits|bytes)(\s+\$_DEFAULT_\s' r'+=\s+(.+?))?$', re.S | re.MULTILINE) for match in regex.finditer(bsf_txt): dlen = int(match.group(3)) if match.group(1) == 'Skip': key = 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx val = ', '.join(['%02X' % ord(i) for i in '\x00' * dlen]) idx += 1 option = '$SKIP' else: key = match.group(2) val = match.group(6) option = '' is_bit = True if match.group(4) == 'bits' else False cfg_item = dict(cfg_temp) line = bsf_txt[:match.end()].count("\n") finds = [i for i in find_list if line >= i[2]] if len(finds) > 0: prefix = finds[0][1] cfg_item['embed'] = '%s:TAG_%03X:START' % \ (prefix, ord(prefix[-1])) cfg_item['find'] = prefix cfg_item['cname'] = 'Signature' cfg_item['length'] = len(finds[0][1]) str2byte = Str2Bytes("'" + finds[0][1] + "'", len(finds[0][1])) cfg_item['value'] = '0x%X' % Bytes2Val(str2byte) cfg_list.append(dict(cfg_item)) cfg_item = dict(cfg_temp) find_list.pop(0) count = 0 cfg_item['cname'] = key cfg_item['length'] = dlen cfg_item['value'] = val cfg_item['option'] = option cfg_item['isbit'] = is_bit if key not in chk_dict.keys(): chk_dict[key] = 0 else: chk_dict[key] += 1 cfg_item['instance'] = chk_dict[key] cfg_list.append(cfg_item) count += 1 if prefix: cfg_item = dict(cfg_temp) cfg_item['cname'] = 'Dummy' cfg_item['embed'] = '%s:%03X:END' % (prefix, ord(prefix[-1])) cfg_list.append(cfg_item) option_dict = {} selreg = re.compile( r'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re.S | re.MULTILINE) regex = re.compile( r'^List\s&(.+?)$(.+?)^EndList$', re.S | re.MULTILINE) for match in regex.finditer(bsf_txt): key = match.group(1) option_dict[key] = [] for select in selreg.finditer(match.group(2)): option_dict[key].append( (int(select.group(1), 0), select.group(2))) chk_dict = {} pagereg = re.compile( r'^Page\s"(.*?)"$(.+?)^EndPage$', re.S | re.MULTILINE) for match in pagereg.finditer(bsf_txt): page = match.group(1) for line in match.group(2).splitlines(): match = re.match( r'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line) if match: cname = match.group(2) if cname not in chk_dict.keys(): chk_dict[cname] = 0 else: chk_dict[cname] += 1 instance = chk_dict[cname] cfg_idxs = [i for i, j in enumerate(cfg_list) if j['cname'] == cname and j['instance'] == instance] if len(cfg_idxs) != 1: raise Exception( "Multiple CFG item '%s' found !" % cname) cfg_item = cfg_list[cfg_idxs[0]] cfg_item['page'] = page cfg_item['type'] = match.group(1) cfg_item['prompt'] = match.group(3) cfg_item['range'] = None if cfg_item['type'] == 'Combo': cfg_item['option'] = option_dict[match.group(4)[1:]] elif cfg_item['type'] == 'EditNum': cfg_item['option'] = match.group(4) match = re.match(r'\s+ Help\s"(.*?)"$', line) if match: cfg_item['help'] = match.group(1) match = re.match(r'\s+"Valid\srange:\s(.*)"$', line) if match: parts = match.group(1).split() cfg_item['option'] = ( (int(parts[0], 0), int(parts[2], 0), cfg_item['option'])) return cfg_list @staticmethod def generate_dsc(option_list, dsc_file=None): dsc_lines = [] header = '%s' % (__copyright_dsc__ % date.today().year) dsc_lines.extend(header.splitlines()) pages = [] for cfg_item in option_list: if cfg_item['page'] and (cfg_item['page'] not in pages): pages.append(cfg_item['page']) page_id = 0 for page in pages: dsc_lines.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id, page)) page_id += 1 dsc_lines.append('') last_page = '' is_bit = False dlen = 0 dval = 0 bit_fields = [] for idx, option in enumerate(option_list): if not is_bit and option['isbit']: is_bit = True dlen = 0 dval = 0 idxs = idx if is_bit and not option['isbit']: is_bit = False if dlen % 8 != 0: raise Exception("Bit fields are not aligned at " "byte boundary !") bit_fields.append((idxs, idx, dlen, dval)) if is_bit: blen = option['length'] bval = int(option['value'], 0) dval = dval + ((bval & ((1 << blen) - 1)) << dlen) print(dlen, blen, bval, hex(dval)) dlen += blen struct_idx = 0 for idx, option in enumerate(option_list): dsc_lines.append('') default = option['value'] pos = option['cname'].find('_') name = option['cname'][pos + 1:] for start_idx, end_idx, bits_len, bits_val in bit_fields: if idx == start_idx: val_str = Bytes2Str(Val2Bytes(bits_val, bits_len // 8)) dsc_lines.append(' # !HDR STRUCT:{BIT_FIELD_DATA_%d}' % struct_idx) dsc_lines.append(' # !BSF NAME:{BIT_FIELD_STRUCT}') dsc_lines.append(' gCfgData.BitFiledStruct%d ' ' | * | 0x%04X | %s' % (struct_idx, bits_len // 8, val_str)) dsc_lines.append('') struct_idx += 1 if option['find']: dsc_lines.append(' # !BSF FIND:{%s}' % option['find']) dsc_lines.append('') if option['instance'] > 0: name = name + '_%s' % option['instance'] if option['embed']: dsc_lines.append(' # !HDR EMBED:{%s}' % option['embed']) if option['type'] == 'Reserved': dsc_lines.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}') if option['option'] == '$SKIP': dsc_lines.append(' # !BSF OPTION:{$SKIP}') else: prompt = option['prompt'] if last_page != option['page']: last_page = option['page'] dsc_lines.append(' # !BSF PAGE:{PG%02X}' % (pages.index(option['page']))) if option['type'] == 'Combo': dsc_lines.append(' # !BSF NAME:{%s} TYPE:{%s}' % (prompt, option['type'])) ops = [] for val, text in option['option']: ops.append('0x%x:%s' % (val, text)) dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops))) elif option['type'] == 'EditNum': cfg_len = option['length'] if ',' in default and cfg_len > 8: dsc_lines.append(' # !BSF NAME:{%s} TYPE:{Table}' % (prompt)) if cfg_len > 16: cfg_len = 16 ops = [] for i in range(cfg_len): ops.append('%X:1:HEX' % i) dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops))) else: dsc_lines.append( ' # !BSF NAME:{%s} TYPE:{%s, %s, (0x%X, 0x%X)}' % (prompt, option['type'], option['option'][2], option['option'][0], option['option'][1])) dsc_lines.append(' # !BSF HELP:{%s}' % option['help']) if ',' in default: default = '{%s}' % default if option['isbit']: dsc_lines.append(' # !BSF FIELD:{%s:%db}' % (name, option['length'])) else: dsc_lines.append(' gCfgData.%-30s | * | 0x%04X | %s' % (name, option['length'], default)) if dsc_file: fd = open(dsc_file, 'w') fd.write('\n'.join(dsc_lines)) fd.close() return dsc_lines class CGenCfgData: def __init__(self, Mode=''): self.Debug = False self.Error = '' self.ReleaseMode = True self.Mode = Mode self._GlobalDataDef = """ GlobalDataDef SKUID = 0, "DEFAULT" EndGlobalData """ self._BuidinOptionTxt = """ List &EN_DIS Selection 0x1 , "Enabled" Selection 0x0 , "Disabled" EndList """ self._StructType = ['UINT8', 'UINT16', 'UINT32', 'UINT64'] self._BsfKeyList = ['FIND', 'NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES', 'BLOCK', 'OPTION', 'CONDITION', 'ORDER', 'MARKER', 'SUBT'] self._HdrKeyList = ['HEADER', 'STRUCT', 'EMBED', 'COMMENT'] self._BuidinOption = {'$EN_DIS': 'EN_DIS'} self._MacroDict = {} self._VarDict = {} self._PcdsDict = {} self._CfgBlkDict = {} self._CfgPageDict = {} self._CfgOptsDict = {} self._BsfTempDict = {} self._CfgItemList = [] self._DscLines = [] self._DscFile = '' self._CfgPageTree = {} self._MapVer = 0 self._MinCfgTagId = 0x100 def ParseMacros(self, MacroDefStr): # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build'] self._MacroDict = {} IsExpression = False for Macro in MacroDefStr: if Macro.startswith('-D'): IsExpression = True if len(Macro) > 2: Macro = Macro[2:] else: continue if IsExpression: IsExpression = False Match = re.match("(\\w+)=(.+)", Macro) if Match: self._MacroDict[Match.group(1)] = Match.group(2) else: Match = re.match("(\\w+)", Macro) if Match: self._MacroDict[Match.group(1)] = '' if len(self._MacroDict) == 0: Error = 1 else: Error = 0 if self.Debug: print("INFO : Macro dictionary:") for Each in self._MacroDict: print(" $(%s) = [ %s ]" % (Each, self._MacroDict[Each])) return Error def EvaulateIfdef(self, Macro): Result = Macro in self._MacroDict if self.Debug: print("INFO : Eval Ifdef [%s] : %s" % (Macro, Result)) return Result def ExpandMacros(self, Input, Preserve=False): Line = Input Match = re.findall("\\$\\(\\w+\\)", Input) if Match: for Each in Match: Variable = Each[2:-1] if Variable in self._MacroDict: Line = Line.replace(Each, self._MacroDict[Variable]) else: if self.Debug: print("WARN : %s is not defined" % Each) if not Preserve: Line = Line.replace(Each, Each[2:-1]) return Line def ExpandPcds(self, Input): Line = Input Match = re.findall("(\\w+\\.\\w+)", Input) if Match: for PcdName in Match: if PcdName in self._PcdsDict: Line = Line.replace(PcdName, self._PcdsDict[PcdName]) else: if self.Debug: print("WARN : %s is not defined" % PcdName) return Line def EvaluateExpress(self, Expr): ExpExpr = self.ExpandPcds(Expr) ExpExpr = self.ExpandMacros(ExpExpr) LogExpr = CLogicalExpression() Result = LogExpr.evaluateExpress(ExpExpr) if self.Debug: print("INFO : Eval Express [%s] : %s" % (Expr, Result)) return Result def ValueToByteArray(self, ValueStr, Length): Match = re.match("\\{\\s*FILE:(.+)\\}", ValueStr) if Match: FileList = Match.group(1).split(',') Result = bytearray() for File in FileList: File = File.strip() BinPath = os.path.join(os.path.dirname(self._DscFile), File) Result.extend(bytearray(open(BinPath, 'rb').read())) else: try: Result = bytearray(self.ValueToList(ValueStr, Length)) except ValueError: raise Exception("Bytes in '%s' must be in range 0~255 !" % ValueStr) if len(Result) < Length: Result.extend(b'\x00' * (Length - len(Result))) elif len(Result) > Length: raise Exception("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length)) return Result[:Length] def ValueToList(self, ValueStr, Length): if ValueStr[0] == '{': Result = [] BinList = ValueStr[1:-1].split(',') InBitField = False LastInBitField = False Value = 0 BitLen = 0 for Element in BinList: InBitField = False Each = Element.strip() if len(Each) == 0: pass else: if Each[0] in ['"', "'"]: Result.extend(list(bytearray(Each[1:-1], 'utf-8'))) elif ':' in Each: Match = re.match("(.+):(\\d+)b", Each) if Match is None: raise Exception("Invald value list format '%s' !" % Each) InBitField = True CurrentBitLen = int(Match.group(2)) CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1 << CurrentBitLen) - 1)) << BitLen else: Result.append(self.EvaluateExpress(Each.strip())) if InBitField: Value += CurrentValue BitLen += CurrentBitLen if LastInBitField and ((not InBitField) or (Element == BinList[-1])): if BitLen % 8 != 0: raise Exception("Invald bit field length!") Result.extend(Val2Bytes(Value, BitLen // 8)) Value = 0 BitLen = 0 LastInBitField = InBitField elif ValueStr.startswith("'") and ValueStr.endswith("'"): Result = Str2Bytes(ValueStr, Length) elif ValueStr.startswith('"') and ValueStr.endswith('"'): Result = Str2Bytes(ValueStr, Length) else: Result = Val2Bytes(self.EvaluateExpress(ValueStr), Length) return Result def FormatDeltaValue(self, ConfigDict): ValStr = ConfigDict['value'] if ValStr[0] == "'": # Remove padding \x00 in the value string ValStr = "'%s'" % ValStr[1:-1].rstrip('\x00') Struct = ConfigDict['struct'] if Struct in self._StructType: # Format the array using its struct type Unit = int(Struct[4:]) // 8 Value = Array2Val(ConfigDict['value']) Loop = ConfigDict['length'] // Unit Values = [] for Each in range(Loop): Values.append(Value & ((1 << (Unit * 8)) - 1)) Value = Value >> (Unit * 8) ValStr = '{ ' + ', '.join([('0x%%0%dX' % (Unit * 2)) % x for x in Values]) + ' }' return ValStr def FormatListValue(self, ConfigDict): Struct = ConfigDict['struct'] if Struct not in self._StructType: return DataList = self.ValueToList(ConfigDict['value'], ConfigDict['length']) Unit = int(Struct[4:]) // 8 if int(ConfigDict['length']) != Unit * len(DataList): # Fallback to byte array Unit = 1 if int(ConfigDict['length']) != len(DataList): raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname']) ByteArray = [] for Value in DataList: for Loop in range(Unit): ByteArray.append("0x%02X" % (Value & 0xFF)) Value = Value >> 8 NewValue = '{' + ','.join(ByteArray) + '}' ConfigDict['value'] = NewValue return "" def GetOrderNumber(self, Offset, Order, BitOff=0): if isinstance(Order, int): if Order == -1: Order = Offset << 16 else: (Major, Minor) = Order.split('.') Order = (int(Major, 16) << 16) + ((int(Minor, 16) & 0xFF) << 8) return Order + (BitOff & 0xFF) def SubtituteLine(self, Line, Args): Args = Args.strip() Vars = Args.split(':') Line = self.ExpandMacros(Line, True) for Idx in range(len(Vars)-1, 0, -1): Line = Line.replace('$(%d)' % Idx, Vars[Idx].strip()) return Line def CfgDuplicationCheck(self, CfgDict, Name): if not self.Debug: return if Name == 'Dummy': return if Name not in CfgDict: CfgDict[Name] = 1 else: print("WARNING: Duplicated item found '%s' !" % CfgDict['cname']) def AddBsfChildPage(self, Child, Parent='root'): def AddBsfChildPageRecursive(PageTree, Parent, Child): Key = next(iter(PageTree)) if Parent == Key: PageTree[Key].append({Child: []}) return True else: Result = False for Each in PageTree[Key]: if AddBsfChildPageRecursive(Each, Parent, Child): Result = True break return Result return AddBsfChildPageRecursive(self._CfgPageTree, Parent, Child) def ParseDscFile(self, DscFile): self._DscLines = [] self._CfgItemList = [] self._CfgPageDict = {} self._CfgBlkDict = {} self._BsfTempDict = {} self._CfgPageTree = {'root': []} CfgDict = {} SectionNameList = ["Defines".lower(), "PcdsFeatureFlag".lower(), "PcdsDynamicVpd.Tmp".lower(), "PcdsDynamicVpd.Upd".lower()] IsDefSect = False IsPcdSect = False IsUpdSect = False IsTmpSect = False TemplateName = '' IfStack = [] ElifStack = [] Error = 0 ConfigDict = {} if type(DscFile) is list: # it is DSC lines already DscLines = DscFile self._DscFile = '.' else: DscFd = open(DscFile, "r") DscLines = DscFd.readlines() DscFd.close() self._DscFile = DscFile BsfRegExp = re.compile("(%s):{(.+?)}(?:$|\\s+)" % '|'. join(self._BsfKeyList)) HdrRegExp = re.compile("(%s):{(.+?)}" % '|'.join(self._HdrKeyList)) CfgRegExp = re.compile("^([_a-zA-Z0-9]+)\\s*\\|\\s*\ (0x[0-9A-F]+|\\*)\\s*\\|\\s*(\\d+|0x[0-9a-fA-F]+)\\s*\\|\\s*(.+)") TksRegExp = re.compile("^(g[_a-zA-Z0-9]+\\.)(.+)") SkipLines = 0 while len(DscLines): DscLine = DscLines.pop(0).strip() if SkipLines == 0: self._DscLines.append(DscLine) else: SkipLines = SkipLines - 1 if len(DscLine) == 0: continue Handle = False Match = re.match("^\\[(.+)\\]", DscLine) if Match is not None: IsDefSect = False IsPcdSect = False IsUpdSect = False IsTmpSect = False SectionName = Match.group(1).lower() if SectionName == SectionNameList[0]: IsDefSect = True if SectionName == SectionNameList[1]: IsPcdSect = True elif SectionName == SectionNameList[2]: IsTmpSect = True elif SectionName == SectionNameList[3]: ConfigDict = { 'header': 'ON', 'page': '', 'name': '', 'find': '', 'struct': '', 'embed': '', 'marker': '', 'option': '', 'comment': '', 'condition': '', 'order': -1, 'subreg': [] } IsUpdSect = True Offset = 0 else: if IsDefSect or IsPcdSect or IsUpdSect or IsTmpSect: Match = False if DscLine[0] != '!' else True if Match: Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif\ |include)\\s*(.+)?$", DscLine.split("#")[0]) Keyword = Match.group(1) if Match else '' Remaining = Match.group(2) if Match else '' Remaining = '' if Remaining is None else Remaining.strip() if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include' ] and not Remaining: raise Exception("ERROR: Expression is expected after \ '!if' or !elseif' for line '%s'" % DscLine) if Keyword == 'else': if IfStack: IfStack[-1] = not IfStack[-1] else: raise Exception("ERROR: No paired '!if' found for \ '!else' for line '%s'" % DscLine) elif Keyword == 'endif': if IfStack: IfStack.pop() Level = ElifStack.pop() if Level > 0: del IfStack[-Level:] else: raise Exception("ERROR: No paired '!if' found for \ '!endif' for line '%s'" % DscLine) elif Keyword == 'ifdef' or Keyword == 'ifndef': Result = self.EvaulateIfdef(Remaining) if Keyword == 'ifndef': Result = not Result IfStack.append(Result) ElifStack.append(0) elif Keyword == 'if' or Keyword == 'elseif': Result = self.EvaluateExpress(Remaining) if Keyword == "if": ElifStack.append(0) IfStack.append(Result) else: # elseif if IfStack: IfStack[-1] = not IfStack[-1] IfStack.append(Result) ElifStack[-1] = ElifStack[-1] + 1 else: raise Exception("ERROR: No paired '!if' found for \ '!elif' for line '%s'" % DscLine) else: if IfStack: Handle = reduce(lambda x, y: x and y, IfStack) else: Handle = True if Handle: if Keyword == 'include': Remaining = self.ExpandMacros(Remaining) # Relative to DSC filepath IncludeFilePath = os.path.join( os.path.dirname(self._DscFile), Remaining) if not os.path.exists(IncludeFilePath): # Relative to repository to find \ # dsc in common platform IncludeFilePath = os.path.join( os.path.dirname(self._DscFile), "..", Remaining) try: IncludeDsc = open(IncludeFilePath, "r") except Exception: raise Exception("ERROR: Cannot open \ file '%s'." % IncludeFilePath) NewDscLines = IncludeDsc.readlines() IncludeDsc.close() DscLines = NewDscLines + DscLines del self._DscLines[-1] else: if DscLine.startswith('!'): raise Exception("ERROR: Unrecoginized \ directive for line '%s'" % DscLine) if not Handle: del self._DscLines[-1] continue if IsDefSect: Match = re.match("^\\s*(?:DEFINE\\s+)*(\\w+)\\s*=\\s*(.+)", DscLine) if Match: self._MacroDict[Match.group(1)] = Match.group(2) if self.Debug: print("INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2))) elif IsPcdSect: Match = re.match("^\\s*([\\w\\.]+)\\s*\\|\\s*(\\w+)", DscLine) if Match: self._PcdsDict[Match.group(1)] = Match.group(2) if self.Debug: print("INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))) elif IsTmpSect: # !BSF DEFT:{GPIO_TMPL:START} Match = re.match("^\\s*#\\s+(!BSF)\\s+DEFT:{(.+?):\ (START|END)}", DscLine) if Match: if Match.group(3) == 'START' and not TemplateName: TemplateName = Match.group(2).strip() self._BsfTempDict[TemplateName] = [] if Match.group(3) == 'END' and ( TemplateName == Match.group(2).strip() ) and TemplateName: TemplateName = '' else: if TemplateName: Match = re.match("^!include\\s*(.+)?$", DscLine) if Match: continue self._BsfTempDict[TemplateName].append(DscLine) else: Match = re.match("^\\s*#\\s+(!BSF|!HDR)\\s+(.+)", DscLine) if Match: Remaining = Match.group(2) if Match.group(1) == '!BSF': Result = BsfRegExp.findall(Remaining) if Result: for Each in Result: Key = Each[0] Remaining = Each[1] if Key == 'BLOCK': Match = re.match( "NAME:\"(.+)\"\\s*,\\s*\ VER:\"(.+)\"\\s*", Remaining) if Match: self._CfgBlkDict['name'] = \ Match.group(1) self._CfgBlkDict['ver'] = Match.group(2 ) elif Key == 'SUBT': # GPIO_TMPL:1:2:3 Remaining = Remaining.strip() Match = re.match("(\\w+)\\s*:", Remaining) if Match: TemplateName = Match.group(1) for Line in self._BsfTempDict[ TemplateName][::-1]: NewLine = self.SubtituteLine( Line, Remaining) DscLines.insert(0, NewLine) SkipLines += 1 elif Key == 'PAGES': # !BSF PAGES:{HSW:"Haswell System Agent", \ # LPT:"Lynx Point PCH"} PageList = Remaining.split(',') for Page in PageList: Page = Page.strip() Match = re.match('(\\w+):\ (\\w*:)?\\"(.+)\\"', Page) if Match: PageName = Match.group(1) ParentName = Match.group(2) if not ParentName or \ ParentName == ':': ParentName = 'root' else: ParentName = ParentName[:-1] if not self.AddBsfChildPage( PageName, ParentName): raise Exception("Cannot find \ parent page '%s'!" % ParentName) self._CfgPageDict[ PageName] = Match.group(3) else: raise Exception("Invalid page \ definitions '%s'!" % Page) elif Key in ['NAME', 'HELP', 'OPTION' ] and Remaining.startswith('+'): # Allow certain options to be extended \ # to multiple lines ConfigDict[Key.lower()] += Remaining[1:] else: if Key == 'NAME': Remaining = Remaining.strip() elif Key == 'CONDITION': Remaining = self.ExpandMacros( Remaining.strip()) ConfigDict[Key.lower()] = Remaining else: Match = HdrRegExp.match(Remaining) if Match: Key = Match.group(1) Remaining = Match.group(2) if Key == 'EMBED': Parts = Remaining.split(':') Names = Parts[0].split(',') DummyDict = ConfigDict.copy() if len(Names) > 1: Remaining = Names[0] + ':' + ':'.join( Parts[1:]) DummyDict['struct'] = Names[1] else: DummyDict['struct'] = Names[0] DummyDict['cname'] = 'Dummy' DummyDict['name'] = '' DummyDict['embed'] = Remaining DummyDict['offset'] = Offset DummyDict['length'] = 0 DummyDict['value'] = '0' DummyDict['type'] = 'Reserved' DummyDict['help'] = '' DummyDict['subreg'] = [] self._CfgItemList.append(DummyDict) else: ConfigDict[Key.lower()] = Remaining # Check CFG line # gCfgData.VariableName | * | 0x01 | 0x1 Clear = False Match = TksRegExp.match(DscLine) if Match: DscLine = 'gCfgData.%s' % Match.group(2) if DscLine.startswith('gCfgData.'): Match = CfgRegExp.match(DscLine[9:]) else: Match = None if Match: ConfigDict['space'] = 'gCfgData' ConfigDict['cname'] = Match.group(1) if Match.group(2) != '*': Offset = int(Match.group(2), 16) ConfigDict['offset'] = Offset ConfigDict['order'] = self.GetOrderNumber( ConfigDict['offset'], ConfigDict['order']) Value = Match.group(4).strip() if Match.group(3).startswith("0x"): Length = int(Match.group(3), 16) else: Length = int(Match.group(3)) Offset += Length ConfigDict['length'] = Length Match = re.match("\\$\\((\\w+)\\)", Value) if Match: if Match.group(1) in self._MacroDict: Value = self._MacroDict[Match.group(1)] ConfigDict['value'] = Value if re.match("\\{\\s*FILE:(.+)\\}", Value): # Expand embedded binary file ValArray = self.ValueToByteArray(ConfigDict['value'], ConfigDict['length']) NewValue = Bytes2Str(ValArray) self._DscLines[-1] = re.sub(r'(.*)(\{\s*FILE:.+\})', r'\1 %s' % NewValue, self._DscLines[-1]) ConfigDict['value'] = NewValue if ConfigDict['name'] == '': # Clear BSF specific items ConfigDict['bsfname'] = '' ConfigDict['help'] = '' ConfigDict['type'] = '' ConfigDict['option'] = '' self.CfgDuplicationCheck(CfgDict, ConfigDict['cname']) self._CfgItemList.append(ConfigDict.copy()) Clear = True else: # It could be a virtual item as below # !BSF FIELD:{SerialDebugPortAddress0:1} # or # @Bsf FIELD:{SerialDebugPortAddress0:1b} Match = re.match(r"^\s*#\s+(!BSF)\s+FIELD:{(.+)}", DscLine) if Match: BitFieldTxt = Match.group(2) Match = re.match("(.+):(\\d+)b([BWDQ])?", BitFieldTxt) if not Match: raise Exception("Incorrect bit field \ format '%s' !" % BitFieldTxt) UnitBitLen = 1 SubCfgDict = ConfigDict.copy() SubCfgDict['cname'] = Match.group(1) SubCfgDict['bitlength'] = int( Match.group(2)) * UnitBitLen if SubCfgDict['bitlength'] > 0: LastItem = self._CfgItemList[-1] if len(LastItem['subreg']) == 0: SubOffset = 0 else: SubOffset = \ LastItem['subreg'][-1]['bitoffset'] \ + LastItem['subreg'][-1]['bitlength'] if Match.group(3) == 'B': SubCfgDict['bitunit'] = 1 elif Match.group(3) == 'W': SubCfgDict['bitunit'] = 2 elif Match.group(3) == 'Q': SubCfgDict['bitunit'] = 8 else: SubCfgDict['bitunit'] = 4 SubCfgDict['bitoffset'] = SubOffset SubCfgDict['order'] = self.GetOrderNumber( SubCfgDict['offset'], SubCfgDict['order'], SubOffset) SubCfgDict['value'] = '' SubCfgDict['cname'] = '%s_%s' % (LastItem['cname'], Match.group(1)) self.CfgDuplicationCheck(CfgDict, SubCfgDict['cname']) LastItem['subreg'].append(SubCfgDict.copy()) Clear = True if Clear: ConfigDict['name'] = '' ConfigDict['find'] = '' ConfigDict['struct'] = '' ConfigDict['embed'] = '' ConfigDict['marker'] = '' ConfigDict['comment'] = '' ConfigDict['order'] = -1 ConfigDict['subreg'] = [] ConfigDict['option'] = '' ConfigDict['condition'] = '' return Error def GetBsfBitFields(self, subitem, bytes): start = subitem['bitoffset'] end = start + subitem['bitlength'] bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1]) bitsvalue = bitsvalue[::-1] bitslen = len(bitsvalue) if start > bitslen or end > bitslen: raise Exception("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name'])) return '0x%X' % (int(bitsvalue[start:end][::-1], 2)) def UpdateBsfBitFields(self, SubItem, NewValue, ValueArray): Start = SubItem['bitoffset'] End = Start + SubItem['bitlength'] Blen = len(ValueArray) BitsValue = ''.join('{0:08b}'.format(i) for i in ValueArray[::-1]) BitsValue = BitsValue[::-1] BitsLen = len(BitsValue) if Start > BitsLen or End > BitsLen: raise Exception("Invalid bits offset [%d,%d] %d for %s" % (Start, End, BitsLen, SubItem['name'])) BitsValue = BitsValue[:Start] + '{0:0{1}b}'.format( NewValue, SubItem['bitlength'])[::-1] + BitsValue[End:] ValueArray[:] = bytearray.fromhex( '{0:0{1}x}'.format(int(BitsValue[::-1], 2), Blen * 2))[::-1] def CreateVarDict(self): Error = 0 self._VarDict = {} if len(self._CfgItemList) > 0: Item = self._CfgItemList[-1] self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length']) for Item in self._CfgItemList: Embed = Item['embed'] Match = re.match("^(\\w+):(\\w+):(START|END)", Embed) if Match: StructName = Match.group(1) VarName = '_%s_%s_' % (Match.group(3), StructName) if Match.group(3) == 'END': self._VarDict[VarName] = Item['offset'] + Item['length'] self._VarDict['_LENGTH_%s_' % StructName] = \ self._VarDict['_END_%s_' % StructName] - \ self._VarDict['_START_%s_' % StructName] if Match.group(2).startswith('TAG_'): if (self.Mode != 'FSP') and (self._VarDict ['_LENGTH_%s_' % StructName] % 4): raise Exception("Size of structure '%s' is %d, \ not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName])) self._VarDict['_TAG_%s_' % StructName] = int( Match.group(2)[4:], 16) & 0xFFF else: self._VarDict[VarName] = Item['offset'] if Item['marker']: self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = \ Item['offset'] return Error def UpdateBsfBitUnit(self, Item): BitTotal = 0 BitOffset = 0 StartIdx = 0 Unit = None UnitDec = {1: 'BYTE', 2: 'WORD', 4: 'DWORD', 8: 'QWORD'} for Idx, SubItem in enumerate(Item['subreg']): if Unit is None: Unit = SubItem['bitunit'] BitLength = SubItem['bitlength'] BitTotal += BitLength BitOffset += BitLength if BitOffset > 64 or BitOffset > Unit * 8: break if BitOffset == Unit * 8: for SubIdx in range(StartIdx, Idx + 1): Item['subreg'][SubIdx]['bitunit'] = Unit BitOffset = 0 StartIdx = Idx + 1 Unit = None if BitOffset > 0: raise Exception("Bit fields cannot fit into %s for \ '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname'])) ExpectedTotal = Item['length'] * 8 if Item['length'] * 8 != BitTotal: raise Exception("Bit fields total length (%d) does not match \ length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname'])) def UpdateDefaultValue(self): Error = 0 for Idx, Item in enumerate(self._CfgItemList): if len(Item['subreg']) == 0: Value = Item['value'] if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'): # {XXX} or 'XXX' strings self.FormatListValue(self._CfgItemList[Idx]) else: Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value) if not Match: NumValue = self.EvaluateExpress(Value) Item['value'] = '0x%X' % NumValue else: ValArray = self.ValueToByteArray(Item['value'], Item['length']) for SubItem in Item['subreg']: SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray) self.UpdateBsfBitUnit(Item) return Error @staticmethod def ExpandIncludeFiles(FilePath, CurDir=''): if CurDir == '': CurDir = os.path.dirname(FilePath) FilePath = os.path.basename(FilePath) InputFilePath = os.path.join(CurDir, FilePath) File = open(InputFilePath, "r") Lines = File.readlines() File.close() NewLines = [] for LineNum, Line in enumerate(Lines): Match = re.match("^!include\\s*(.+)?$", Line) if Match: IncPath = Match.group(1) TmpPath = os.path.join(CurDir, IncPath) OrgPath = TmpPath if not os.path.exists(TmpPath): CurDir = os.path.join(os.path.dirname( os.path.realpath(__file__)), "..", "..") TmpPath = os.path.join(CurDir, IncPath) if not os.path.exists(TmpPath): raise Exception("ERROR: Cannot open include file '%s'." % OrgPath) else: NewLines.append(('# Included from file: %s\n' % IncPath, TmpPath, 0)) NewLines.append(('# %s\n' % ('=' * 80), TmpPath, 0)) NewLines.extend(CGenCfgData.ExpandIncludeFiles (IncPath, CurDir)) else: NewLines.append((Line, InputFilePath, LineNum)) return NewLines def OverrideDefaultValue(self, DltFile): Error = 0 DltLines = CGenCfgData.ExpandIncludeFiles(DltFile) PlatformId = None for Line, FilePath, LineNum in DltLines: Line = Line.strip() if not Line or Line.startswith('#'): continue Match = re.match("\\s*(\\w+)\\.(\\w+)(\\.\\w+)?\\s*\\|\\s*(.+)", Line) if not Match: raise Exception("Unrecognized line '%s' (File:'%s' Line:%d) !" % (Line, FilePath, LineNum + 1)) Found = False InScope = False for Idx, Item in enumerate(self._CfgItemList): if not InScope: if not (Item['embed'].endswith(':START') and Item['embed'].startswith(Match.group(1))): continue InScope = True if Item['cname'] == Match.group(2): Found = True break if Item['embed'].endswith(':END') and \ Item['embed'].startswith(Match.group(1)): break Name = '%s.%s' % (Match.group(1), Match.group(2)) if not Found: ErrItem = Match.group(2) if InScope else Match.group(1) raise Exception("Invalid configuration '%s' in '%s' \ (File:'%s' Line:%d) !" % (ErrItem, Name, FilePath, LineNum + 1)) ValueStr = Match.group(4).strip() if Match.group(3) is not None: # This is a subregion item BitField = Match.group(3)[1:] Found = False if len(Item['subreg']) > 0: for SubItem in Item['subreg']: if SubItem['cname'] == '%s_%s' % \ (Item['cname'], BitField): Found = True break if not Found: raise Exception("Invalid configuration bit field \ '%s' in '%s.%s' (File:'%s' Line:%d) !" % (BitField, Name, BitField, FilePath, LineNum + 1)) try: Value = int(ValueStr, 16) if ValueStr.startswith('0x') \ else int(ValueStr, 10) except Exception: raise Exception("Invalid value '%s' for bit field '%s.%s' \ (File:'%s' Line:%d) !" % (ValueStr, Name, BitField, FilePath, LineNum + 1)) if Value >= 2 ** SubItem['bitlength']: raise Exception("Invalid configuration bit field value \ '%s' for '%s.%s' (File:'%s' Line:%d) !" % (Value, Name, BitField, FilePath, LineNum + 1)) ValArray = self.ValueToByteArray(Item['value'], Item['length']) self.UpdateBsfBitFields(SubItem, Value, ValArray) if Item['value'].startswith('{'): Item['value'] = '{' + ', '.join('0x%02X' % i for i in ValArray) + '}' else: BitsValue = ''.join('{0:08b}'.format(i) for i in ValArray[::-1]) Item['value'] = '0x%X' % (int(BitsValue, 2)) else: if Item['value'].startswith('{') and \ not ValueStr.startswith('{'): raise Exception("Data array required for '%s' \ (File:'%s' Line:%d) !" % (Name, FilePath, LineNum + 1)) Item['value'] = ValueStr if Name == 'PLATFORMID_CFG_DATA.PlatformId': PlatformId = ValueStr if (PlatformId is None) and (self.Mode != 'FSP'): raise Exception("PLATFORMID_CFG_DATA.PlatformId is missing \ in file '%s' !" % (DltFile)) return Error def ProcessMultilines(self, String, MaxCharLength): Multilines = '' StringLength = len(String) CurrentStringStart = 0 StringOffset = 0 BreakLineDict = [] if len(String) <= MaxCharLength: while (StringOffset < StringLength): if StringOffset >= 1: if String[StringOffset - 1] == '\\' and \ String[StringOffset] == 'n': BreakLineDict.append(StringOffset + 1) StringOffset += 1 if BreakLineDict != []: for Each in BreakLineDict: Multilines += " %s\n" % String[CurrentStringStart:Each].\ lstrip() CurrentStringStart = Each if StringLength - CurrentStringStart > 0: Multilines += " %s\n" % String[CurrentStringStart:].\ lstrip() else: Multilines = " %s\n" % String else: NewLineStart = 0 NewLineCount = 0 FoundSpaceChar = False while(StringOffset < StringLength): if StringOffset >= 1: if NewLineCount >= MaxCharLength - 1: if String[StringOffset] == ' ' and \ StringLength - StringOffset > 10: BreakLineDict.append(NewLineStart + NewLineCount) NewLineStart = NewLineStart + NewLineCount NewLineCount = 0 FoundSpaceChar = True elif StringOffset == StringLength - 1 \ and FoundSpaceChar is False: BreakLineDict.append(0) if String[StringOffset - 1] == '\\' and \ String[StringOffset] == 'n': BreakLineDict.append(StringOffset + 1) NewLineStart = StringOffset + 1 NewLineCount = 0 StringOffset += 1 NewLineCount += 1 if BreakLineDict != []: BreakLineDict.sort() for Each in BreakLineDict: if Each > 0: Multilines += " %s\n" % String[ CurrentStringStart:Each].lstrip() CurrentStringStart = Each if StringLength - CurrentStringStart > 0: Multilines += " %s\n" % String[CurrentStringStart:].\ lstrip() return Multilines def CreateField(self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength=None): PosName = 28 NameLine = '' HelpLine = '' OptionLine = '' if Length == 0 and Name == 'Dummy': return '\n' IsArray = False if Length in [1, 2, 4, 8]: Type = "UINT%d" % (Length * 8) else: IsArray = True Type = "UINT8" if Item and Item['value'].startswith('{'): Type = "UINT8" IsArray = True if Struct != '': Type = Struct if Struct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']: IsArray = True Unit = int(Type[4:]) // 8 Length = Length / Unit else: IsArray = False if IsArray: Name = Name + '[%d]' % Length if len(Type) < PosName: Space1 = PosName - len(Type) else: Space1 = 1 if BsfName != '': NameLine = " %s\n" % BsfName else: NameLine = "\n" if Help != '': HelpLine = self.ProcessMultilines(Help, 80) if Option != '': OptionLine = self.ProcessMultilines(Option, 80) if BitsLength is None: BitsLength = '' else: BitsLength = ' : %d' % BitsLength return "\n/** %s%s%s**/\n %s%s%s%s;\n" % \ (NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength) def SplitTextBody(self, TextBody): Marker1 = '{ /* _COMMON_STRUCT_START_ */' Marker2 = '; /* _COMMON_STRUCT_END_ */' ComBody = [] TxtBody = [] IsCommon = False for Line in TextBody: if Line.strip().endswith(Marker1): Line = Line.replace(Marker1[1:], '') IsCommon = True if Line.strip().endswith(Marker2): Line = Line.replace(Marker2[1:], '') if IsCommon: ComBody.append(Line) IsCommon = False continue if IsCommon: ComBody.append(Line) else: TxtBody.append(Line) return ComBody, TxtBody def GetStructArrayInfo(self, Input): ArrayStr = Input.split('[') Name = ArrayStr[0] if len(ArrayStr) > 1: NumStr = ''.join(c for c in ArrayStr[-1] if c.isdigit()) NumStr = '1000' if len(NumStr) == 0 else NumStr ArrayNum = int(NumStr) else: ArrayNum = 0 return Name, ArrayNum def PostProcessBody(self, TextBody, IncludeEmbedOnly=True): NewTextBody = [] OldTextBody = [] IncTextBody = [] StructBody = [] IncludeLine = False EmbedFound = False StructName = '' ArrayVarName = '' VariableName = '' Count = 0 Level = 0 IsCommonStruct = False for Line in TextBody: if Line.startswith('#define '): IncTextBody.append(Line) continue if not Line.startswith('/* EMBED_STRUCT:'): Match = False else: Match = re.match("^/\\*\\sEMBED_STRUCT:([\\w\\[\\]\\*]+):\ ([\\w\\[\\]\\*]+):(\\w+):(START|END)([\\s\\d]+)\\*/([\\s\\S]*)", Line) if Match: ArrayMarker = Match.group(5) if Match.group(4) == 'END': Level -= 1 if Level == 0: Line = Match.group(6) else: # 'START' Level += 1 if Level == 1: Line = Match.group(6) else: EmbedFound = True TagStr = Match.group(3) if TagStr.startswith('TAG_'): try: TagVal = int(TagStr[4:], 16) except Exception: TagVal = -1 if (TagVal >= 0) and (TagVal < self._MinCfgTagId): IsCommonStruct = True if Level == 1: if IsCommonStruct: Suffix = ' /* _COMMON_STRUCT_START_ */' else: Suffix = '' StructBody = ['typedef struct {%s' % Suffix] StructName = Match.group(1) StructType = Match.group(2) VariableName = Match.group(3) MatchOffset = re.search('/\\*\\*\\sOffset\\s0x\ ([a-fA-F0-9]+)', Line) if MatchOffset: Offset = int(MatchOffset.group(1), 16) else: Offset = None IncludeLine = True ModifiedStructType = StructType.rstrip() if ModifiedStructType.endswith(']'): Idx = ModifiedStructType.index('[') if ArrayMarker != ' ': # Auto array size OldTextBody.append('') ArrayVarName = VariableName if int(ArrayMarker) == 1000: Count = 1 else: Count = int(ArrayMarker) + 1000 else: if Count < 1000: Count += 1 VariableTemp = ArrayVarName + '[%d]' % ( Count if Count < 1000 else Count - 1000) OldTextBody[-1] = self.CreateField( None, VariableTemp, 0, Offset, ModifiedStructType[:Idx], '', 'Structure Array', '') else: ArrayVarName = '' OldTextBody.append(self.CreateField( None, VariableName, 0, Offset, ModifiedStructType, '', '', '')) if IncludeLine: StructBody.append(Line) else: OldTextBody.append(Line) if Match and Match.group(4) == 'END': if Level == 0: if (StructType != Match.group(2)) or \ (VariableName != Match.group(3)): print("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(2))) else: if IsCommonStruct: Suffix = ' /* _COMMON_STRUCT_END_ */' else: Suffix = '' Line = '} %s;%s\n\n\n' % (StructName, Suffix) StructBody.append(Line) if (Line not in NewTextBody) and \ (Line not in OldTextBody): NewTextBody.extend(StructBody) IncludeLine = False IsCommonStruct = False if not IncludeEmbedOnly: NewTextBody.extend(OldTextBody) if EmbedFound: NewTextBody = self.PostProcessBody(NewTextBody, False) NewTextBody = IncTextBody + NewTextBody return NewTextBody def WriteHeaderFile(self, TxtBody, FileName, Type='h'): FileNameDef = os.path.basename(FileName).replace('.', '_') FileNameDef = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', FileNameDef) FileNameDef = re.sub('([a-z0-9])([A-Z])', r'\1_\2', FileNameDef).upper() Lines = [] Lines.append("%s\n" % GetCopyrightHeader(Type)) Lines.append("#ifndef __%s__\n" % FileNameDef) Lines.append("#define __%s__\n\n" % FileNameDef) if Type == 'h': Lines.append("#pragma pack(1)\n\n") Lines.extend(TxtBody) if Type == 'h': Lines.append("#pragma pack()\n\n") Lines.append("#endif\n") # Don't rewrite if the contents are the same Create = True if os.path.exists(FileName): HdrFile = open(FileName, "r") OrgTxt = HdrFile.read() HdrFile.close() NewTxt = ''.join(Lines) if OrgTxt == NewTxt: Create = False if Create: HdrFile = open(FileName, "w") HdrFile.write(''.join(Lines)) HdrFile.close() def CreateHeaderFile(self, HdrFileName, ComHdrFileName=''): LastStruct = '' SpaceIdx = 0 Offset = 0 FieldIdx = 0 LastFieldIdx = 0 ResvOffset = 0 ResvIdx = 0 TxtBody = [] LineBuffer = [] CfgTags = [] LastVisible = True TxtBody.append("typedef struct {\n") for Item in self._CfgItemList: # Search for CFGDATA tags Embed = Item["embed"].upper() if Embed.endswith(':START'): Match = re.match(r'(\w+)_CFG_DATA:TAG_([0-9A-F]+):START', Embed) if Match: TagName = Match.group(1) TagId = int(Match.group(2), 16) CfgTags.append((TagId, TagName)) # Only process visible items NextVisible = LastVisible if LastVisible and (Item['header'] == 'OFF'): NextVisible = False ResvOffset = Item['offset'] elif (not LastVisible) and Item['header'] == 'ON': NextVisible = True Name = "ReservedUpdSpace%d" % ResvIdx ResvIdx = ResvIdx + 1 TxtBody.append(self.CreateField( Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', '')) FieldIdx += 1 if Offset < Item["offset"]: if LastVisible: Name = "UnusedUpdSpace%d" % SpaceIdx LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', '')) FieldIdx += 1 SpaceIdx = SpaceIdx + 1 Offset = Item["offset"] LastVisible = NextVisible Offset = Offset + Item["length"] if LastVisible: for Each in LineBuffer: TxtBody.append(Each) LineBuffer = [] Embed = Item["embed"].upper() if Embed.endswith(':START') or Embed.endswith(':END'): # EMBED_STRUCT: StructName : \ # ItemName : VariableName : START|END Name, ArrayNum = self.GetStructArrayInfo(Item["struct"]) Remaining = Item["embed"] if (LastFieldIdx + 1 == FieldIdx) and (LastStruct == Name): ArrayMarker = ' ' else: ArrayMarker = '%d' % ArrayNum LastFieldIdx = FieldIdx LastStruct = Name Marker = '/* EMBED_STRUCT:%s:%s%s*/ ' % (Name, Remaining, ArrayMarker) # if Embed.endswith(':START') and Comment != '': # Marker = '/* COMMENT:%s */ \n' % Item["comment"] + Marker else: if Embed == '': Marker = '' else: self.Error = "Invalid embedded structure \ format '%s'!\n" % Item["embed"] return 4 # Generate bit fields for structure if len(Item['subreg']) > 0 and Item["struct"]: StructType = Item["struct"] StructName, ArrayNum = self.GetStructArrayInfo(StructType) if (LastFieldIdx + 1 == FieldIdx) and \ (LastStruct == Item["struct"]): ArrayMarker = ' ' else: ArrayMarker = '%d' % ArrayNum TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:START%s*/\n' % (StructName, StructType, Item["cname"], ArrayMarker)) for SubItem in Item['subreg']: Name = SubItem["cname"] if Name.startswith(Item["cname"]): Name = Name[len(Item["cname"]) + 1:] Line = self.CreateField( SubItem, Name, SubItem["bitunit"], SubItem["offset"], SubItem['struct'], SubItem['name'], SubItem['help'], SubItem['option'], SubItem['bitlength']) TxtBody.append(Line) TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:END%s*/\n' % (StructName, StructType, Item["cname"], ArrayMarker)) LastFieldIdx = FieldIdx LastStruct = Item["struct"] FieldIdx += 1 else: FieldIdx += 1 Line = Marker + self.CreateField( Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option']) TxtBody.append(Line) TxtBody.append("}\n\n") # Handle the embedded data structure TxtBody = self.PostProcessBody(TxtBody) ComBody, TxtBody = self.SplitTextBody(TxtBody) # Prepare TAG defines PltTagDefTxt = ['\n'] ComTagDefTxt = ['\n'] for TagId, TagName in sorted(CfgTags): TagLine = '#define %-30s 0x%03X\n' % ('CDATA_%s_TAG' % TagName, TagId) if TagId < self._MinCfgTagId: # TAG ID < 0x100, it is a generic TAG ComTagDefTxt.append(TagLine) else: PltTagDefTxt.append(TagLine) PltTagDefTxt.append('\n\n') ComTagDefTxt.append('\n\n') # Write file back self.WriteHeaderFile(PltTagDefTxt + TxtBody, HdrFileName) if ComHdrFileName: self.WriteHeaderFile(ComTagDefTxt + ComBody, ComHdrFileName) return 0 def UpdateConfigItemValue(self, Item, ValueStr): IsArray = True if Item['value'].startswith('{') else False IsString = True if Item['value'].startswith("'") else False Bytes = self.ValueToByteArray(ValueStr, Item['length']) if IsString: NewValue = "'%s'" % Bytes.decode("utf-8") elif IsArray: NewValue = Bytes2Str(Bytes) else: Fmt = '0x%X' if Item['value'].startswith('0x') else '%d' NewValue = Fmt % Bytes2Val(Bytes) Item['value'] = NewValue def LoadDefaultFromBinaryArray(self, BinDat, IgnoreFind=False): FindOff = 0 StartOff = 0 for Item in self._CfgItemList: if Item['length'] == 0: continue if not IgnoreFind and Item['find']: FindBin = Item['find'].encode() Offset = BinDat.find(FindBin) if Offset >= 0: TestOff = BinDat[Offset+len(FindBin):].find(FindBin) if TestOff >= 0: raise Exception('Multiple match found for "%s" !' % Item['find']) FindOff = Offset + len(FindBin) StartOff = Item['offset'] else: raise Exception('Could not find "%s" !' % Item['find']) if Item['offset'] + Item['length'] > len(BinDat): raise Exception('Mismatching format between DSC \ and BIN files !') Offset = FindOff + (Item['offset'] - StartOff) ValStr = Bytes2Str(BinDat[Offset: Offset + Item['length']]) self.UpdateConfigItemValue(Item, ValStr) self.UpdateDefaultValue() def PatchBinaryArray(self, BinDat): FileOff = 0 Offset = 0 FindOff = 0 PatchList = [] CfgBin = bytearray() for Item in self._CfgItemList: if Item['length'] == 0: continue if Item['find']: if len(CfgBin) > 0: PatchList.append((FileOff, CfgBin)) FindBin = Item['find'].encode() FileOff = BinDat.find(FindBin) if FileOff < 0: raise Exception('Could not find "%s" !' % Item['find']) else: TestOff = BinDat[FileOff+len(FindBin):].find(FindBin) if TestOff >= 0: raise Exception('Multiple match found for "%s" !' % Item['find']) FileOff += len(FindBin) Offset = Item['offset'] FindOff = Offset CfgBin = bytearray() if Item['offset'] > Offset: Gap = Item['offset'] - Offset CfgBin.extend(b'\x00' * Gap) if Item['type'] == 'Reserved' and Item['option'] == '$SKIP': # keep old data NewOff = FileOff + (Offset - FindOff) FileData = bytearray(BinDat[NewOff: NewOff + Item['length']]) CfgBin.extend(FileData) else: CfgBin.extend(self.ValueToByteArray(Item['value'], Item['length'])) Offset = Item['offset'] + Item['length'] if len(CfgBin) > 0: PatchList.append((FileOff, CfgBin)) for FileOff, CfgBin in PatchList: Length = len(CfgBin) if FileOff + Length < len(BinDat): BinDat[FileOff:FileOff+Length] = CfgBin[:] return BinDat def GenerateBinaryArray(self): Offset = 0 BinDat = bytearray() for Item in self._CfgItemList: if Item['offset'] > Offset: Gap = Item['offset'] - Offset BinDat.extend(b'\x00' * Gap) BinDat.extend(self.ValueToByteArray(Item['value'], Item['length'])) Offset = Item['offset'] + Item['length'] return BinDat def GenerateBinary(self, BinFileName): BinFile = open(BinFileName, "wb") BinFile.write(self.GenerateBinaryArray()) BinFile.close() return 0 def GenerateDataIncFile(self, DatIncFileName, BinFile=None): # Put a prefix GUID before CFGDATA so that it can be located later on Prefix = b'\xa7\xbd\x7f\x73\x20\x1e\x46\xd6\xbe\x8f\ x64\x12\x05\x8d\x0a\xa8' if BinFile: Fin = open(BinFile, 'rb') BinDat = Prefix + bytearray(Fin.read()) Fin.close() else: BinDat = Prefix + self.GenerateBinaryArray() FileName = os.path.basename(DatIncFileName).upper() FileName = FileName.replace('.', '_') TxtLines = [] TxtLines.append("UINT8 mConfigDataBlob[%d] = {\n" % len(BinDat)) Count = 0 Line = [' '] for Each in BinDat: Line.append('0x%02X, ' % Each) Count = Count + 1 if (Count & 0x0F) == 0: Line.append('\n') TxtLines.append(''.join(Line)) Line = [' '] if len(Line) > 1: TxtLines.append(''.join(Line) + '\n') TxtLines.append("};\n\n") self.WriteHeaderFile(TxtLines, DatIncFileName, 'inc') return 0 def CheckCfgData(self): # Check if CfgData contains any duplicated name def AddItem(Item, ChkList): Name = Item['cname'] if Name in ChkList: return Item if Name not in ['Dummy', 'Reserved', 'CfgHeader', 'CondValue']: ChkList.append(Name) return None Duplicate = None ChkList = [] for Item in self._CfgItemList: Duplicate = AddItem(Item, ChkList) if not Duplicate: for SubItem in Item['subreg']: Duplicate = AddItem(SubItem, ChkList) if Duplicate: break if Duplicate: break if Duplicate: self.Error = "Duplicated CFGDATA '%s' found !\n" % \ Duplicate['cname'] return -1 return 0 def PrintData(self): for Item in self._CfgItemList: if not Item['length']: continue print("%-10s @Offset:0x%04X Len:%3d Val:%s" % (Item['cname'], Item['offset'], Item['length'], Item['value'])) for SubItem in Item['subreg']: print(" %-20s BitOff:0x%04X BitLen:%-3d Val:%s" % (SubItem['cname'], SubItem['bitoffset'], SubItem['bitlength'], SubItem['value'])) def FormatArrayValue(self, Input, Length): Dat = self.ValueToByteArray(Input, Length) return ','.join('0x%02X' % Each for Each in Dat) def GetItemOptionList(self, Item): TmpList = [] if Item['type'] == "Combo": if not Item['option'] in self._BuidinOption: OptList = Item['option'].split(',') for Option in OptList: Option = Option.strip() try: (OpVal, OpStr) = Option.split(':') except Exception: raise Exception("Invalide option format '%s' !" % Option) TmpList.append((OpVal, OpStr)) return TmpList def WriteBsfStruct(self, BsfFd, Item): if Item['type'] == "None": Space = "gPlatformFspPkgTokenSpaceGuid" else: Space = Item['space'] Line = " $%s_%s" % (Space, Item['cname']) Match = re.match("\\s*(\\{.+\\})\\s*", Item['value']) if Match: DefaultValue = self.FormatArrayValue(Match.group(1).strip(), Item['length']) else: DefaultValue = Item['value'].strip() if 'bitlength' in Item: if Item['bitlength']: BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue)) else: if Item['length']: BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue)) return self.GetItemOptionList(Item) def GetBsfOption(self, OptionName): if OptionName in self._CfgOptsDict: return self._CfgOptsDict[OptionName] else: return OptionName def WriteBsfOption(self, BsfFd, Item): PcdName = Item['space'] + '_' + Item['cname'] WriteHelp = 0 BsfLines = [] if Item['type'] == "Combo": if Item['option'] in self._BuidinOption: Options = self._BuidinOption[Item['option']] else: Options = self.GetBsfOption(PcdName) BsfLines.append(' %s $%s, "%s", &%s,\n' % ( Item['type'], PcdName, Item['name'], Options)) WriteHelp = 1 elif Item['type'].startswith("EditNum"): Match = re.match("EditNum\\s*,\\s*(HEX|DEC)\\s*,\\s*\\(\ (\\d+|0x[0-9A-Fa-f]+)\\s*,\\s*(\\d+|0x[0-9A-Fa-f]+)\\)", Item['type']) if Match: BsfLines.append(' EditNum $%s, "%s", %s,\n' % ( PcdName, Item['name'], Match.group(1))) WriteHelp = 2 elif Item['type'].startswith("EditText"): BsfLines.append(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name'])) WriteHelp = 1 elif Item['type'] == "Table": Columns = Item['option'].split(',') if len(Columns) != 0: BsfLines.append(' %s $%s "%s",' % (Item['type'], PcdName, Item['name'])) for Col in Columns: Fmt = Col.split(':') if len(Fmt) != 3: raise Exception("Column format '%s' is invalid !" % Fmt) try: Dtype = int(Fmt[1].strip()) except Exception: raise Exception("Column size '%s' is invalid !" % Fmt[1]) BsfLines.append('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip())) BsfLines.append(',\n') WriteHelp = 1 if WriteHelp > 0: HelpLines = Item['help'].split('\\n\\r') FirstLine = True for HelpLine in HelpLines: if FirstLine: FirstLine = False BsfLines.append(' Help "%s"\n' % (HelpLine)) else: BsfLines.append(' "%s"\n' % (HelpLine)) if WriteHelp == 2: BsfLines.append(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3))) if len(Item['condition']) > 4: CondList = Item['condition'].split(',') Idx = 0 for Cond in CondList: Cond = Cond.strip() if Cond.startswith('#'): BsfLines.insert(Idx, Cond + '\n') Idx += 1 elif Cond.startswith('@#'): BsfLines.append(Cond[1:] + '\n') for Line in BsfLines: BsfFd.write(Line) def WriteBsfPages(self, PageTree, BsfFd): BsfFd.write('\n') Key = next(iter(PageTree)) for Page in PageTree[Key]: PageName = next(iter(Page)) BsfFd.write('Page "%s"\n' % self._CfgPageDict[PageName]) if len(PageTree[Key]): self.WriteBsfPages(Page, BsfFd) BsfItems = [] for Item in self._CfgItemList: if Item['name'] != '': if Item['page'] != PageName: continue if len(Item['subreg']) > 0: for SubItem in Item['subreg']: if SubItem['name'] != '': BsfItems.append(SubItem) else: BsfItems.append(Item) BsfItems.sort(key=lambda x: x['order']) for Item in BsfItems: self.WriteBsfOption(BsfFd, Item) BsfFd.write("EndPage\n\n") def GenerateBsfFile(self, BsfFile): if BsfFile == '': self.Error = "BSF output file '%s' is invalid" % BsfFile return 1 Error = 0 OptionDict = {} BsfFd = open(BsfFile, "w") BsfFd.write("%s\n" % GetCopyrightHeader('bsf')) BsfFd.write("%s\n" % self._GlobalDataDef) BsfFd.write("StructDef\n") NextOffset = -1 for Item in self._CfgItemList: if Item['find'] != '': BsfFd.write('\n Find "%s"\n' % Item['find']) NextOffset = Item['offset'] + Item['length'] if Item['name'] != '': if NextOffset != Item['offset']: BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset)) if len(Item['subreg']) > 0: NextOffset = Item['offset'] BitsOffset = NextOffset * 8 for SubItem in Item['subreg']: BitsOffset += SubItem['bitlength'] if SubItem['name'] == '': if 'bitlength' in SubItem: BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength'])) else: BsfFd.write(" Skip %d bytes\n" % (SubItem['length'])) else: Options = self.WriteBsfStruct(BsfFd, SubItem) if len(Options) > 0: OptionDict[SubItem ['space']+'_'+SubItem ['cname']] = Options NextBitsOffset = (Item['offset'] + Item['length']) * 8 if NextBitsOffset > BitsOffset: BitsGap = NextBitsOffset - BitsOffset BitsRemain = BitsGap % 8 if BitsRemain: BsfFd.write(" Skip %d bits\n" % BitsRemain) BitsGap -= BitsRemain BytesRemain = BitsGap // 8 if BytesRemain: BsfFd.write(" Skip %d bytes\n" % BytesRemain) NextOffset = Item['offset'] + Item['length'] else: NextOffset = Item['offset'] + Item['length'] Options = self.WriteBsfStruct(BsfFd, Item) if len(Options) > 0: OptionDict[Item['space']+'_'+Item['cname']] = Options BsfFd.write("\nEndStruct\n\n") BsfFd.write("%s" % self._BuidinOptionTxt) NameList = [] OptionList = [] for Each in sorted(OptionDict): if OptionDict[Each] not in OptionList: NameList.append(Each) OptionList.append(OptionDict[Each]) BsfFd.write("List &%s\n" % Each) for Item in OptionDict[Each]: BsfFd.write(' Selection %s , "%s"\n' % (self.EvaluateExpress(Item[0]), Item[1])) BsfFd.write("EndList\n\n") else: # Item has idential options as other item # Try to reuse the previous options instead Idx = OptionList.index(OptionDict[Each]) self._CfgOptsDict[Each] = NameList[Idx] BsfFd.write("BeginInfoBlock\n") BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver'])) BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name'])) BsfFd.write("EndInfoBlock\n\n") self.WriteBsfPages(self._CfgPageTree, BsfFd) BsfFd.close() return Error def WriteDeltaLine(self, OutLines, Name, ValStr, IsArray): if IsArray: Output = '%s | { %s }' % (Name, ValStr) else: Output = '%s | 0x%X' % (Name, Array2Val(ValStr)) OutLines.append(Output) def WriteDeltaFile(self, OutFile, PlatformId, OutLines): DltFd = open(OutFile, "w") DltFd.write("%s\n" % GetCopyrightHeader('dlt', True)) if PlatformId is not None: DltFd.write('#\n') DltFd.write('# Delta configuration values \ for platform ID 0x%04X\n' % PlatformId) DltFd.write('#\n\n') for Line in OutLines: DltFd.write('%s\n' % Line) DltFd.close() def GenerateDeltaFile(self, OutFile, AbsfFile): # Parse ABSF Build in dict if not os.path.exists(AbsfFile): Lines = [] else: with open(AbsfFile) as Fin: Lines = Fin.readlines() AbsfBuiltValDict = {} Process = False for Line in Lines: Line = Line.strip() if Line.startswith('StructDef'): Process = True if Line.startswith('EndStruct'): break if not Process: continue Match = re.match('\\s*\\$gCfgData_(\\w+)\\s+\ (\\d+)\\s+(bits|bytes)\\s+\\$_AS_BUILT_\\s+=\\s+(.+)\\$', Line) if Match: if Match.group(1) not in AbsfBuiltValDict: AbsfBuiltValDict[Match.group(1)] = Match.group(4).strip() else: raise Exception("Duplicated configuration \ name '%s' found !", Match.group(1)) # Match config item in DSC PlatformId = None OutLines = [] TagName = '' Level = 0 for Item in self._CfgItemList: Name = None if Level == 0 and Item['embed'].endswith(':START'): TagName = Item['embed'].split(':')[0] Level += 1 if Item['cname'] in AbsfBuiltValDict: ValStr = AbsfBuiltValDict[Item['cname']] Name = '%s.%s' % (TagName, Item['cname']) if not Item['subreg'] and Item['value'].startswith('{'): Value = Array2Val(Item['value']) IsArray = True else: Value = int(Item['value'], 16) IsArray = False AbsfVal = Array2Val(ValStr) if AbsfVal != Value: if 'PLATFORMID_CFG_DATA.PlatformId' == Name: PlatformId = AbsfVal self.WriteDeltaLine(OutLines, Name, ValStr, IsArray) else: if 'PLATFORMID_CFG_DATA.PlatformId' == Name: raise Exception("'PlatformId' has the \ same value as DSC default !") if Item['subreg']: for SubItem in Item['subreg']: if SubItem['cname'] in AbsfBuiltValDict: ValStr = AbsfBuiltValDict[SubItem['cname']] if Array2Val(ValStr) == int(SubItem['value'], 16): continue Name = '%s.%s.%s' % (TagName, Item['cname'], SubItem['cname']) self.WriteDeltaLine(OutLines, Name, ValStr, False) if Item['embed'].endswith(':END'): Level -= 1 if PlatformId is None and Lines: raise Exception("'PlatformId' configuration \ is missing in ABSF file!") else: PlatformId = 0 self.WriteDeltaFile(OutFile, PlatformId, Lines) return 0 def GenerateDscFile(self, OutFile): DscFd = open(OutFile, "w") for Line in self._DscLines: DscFd.write(Line + '\n') DscFd.close() return 0 def Usage(): print('\n'.join([ "GenCfgData Version 0.01", "Usage:", " GenCfgData GENINC BinFile \ IncOutFile [-D Macros]", " GenCfgData GENPKL DscFile \ PklOutFile [-D Macros]", " GenCfgData GENINC DscFile[;DltFile] \ IncOutFile [-D Macros]", " GenCfgData GENBIN DscFile[;DltFile] \ BinOutFile [-D Macros]", " GenCfgData GENBSF DscFile[;DltFile] \ BsfOutFile [-D Macros]", " GenCfgData GENDLT DscFile[;AbsfFile] \ DltOutFile [-D Macros]", " GenCfgData GENDSC DscFile \ DscOutFile [-D Macros]", " GenCfgData GENHDR DscFile[;DltFile] \ HdrOutFile[;ComHdrOutFile] [-D Macros]" ])) def Main(): # # Parse the options and args # argc = len(sys.argv) if argc < 4: Usage() return 1 GenCfgData = CGenCfgData() Command = sys.argv[1].upper() OutFile = sys.argv[3] if argc > 5 and GenCfgData.ParseMacros(sys.argv[4:]) != 0: raise Exception("ERROR: Macro parsing failed !") FileList = sys.argv[2].split(';') if len(FileList) == 2: DscFile = FileList[0] DltFile = FileList[1] elif len(FileList) == 1: DscFile = FileList[0] DltFile = '' else: raise Exception("ERROR: Invalid parameter '%s' !" % sys.argv[2]) if Command == "GENDLT" and DscFile.endswith('.dlt'): # It needs to expand an existing DLT file DltFile = DscFile Lines = CGenCfgData.ExpandIncludeFiles(DltFile) OutTxt = ''.join([x[0] for x in Lines]) OutFile = open(OutFile, "w") OutFile.write(OutTxt) OutFile.close() return 0 if not os.path.exists(DscFile): raise Exception("ERROR: Cannot open file '%s' !" % DscFile) CfgBinFile = '' if DltFile: if not os.path.exists(DltFile): raise Exception("ERROR: Cannot open file '%s' !" % DltFile) if Command == "GENDLT": CfgBinFile = DltFile DltFile = '' BinFile = '' if (DscFile.lower().endswith('.bin')) and (Command == "GENINC"): # It is binary file BinFile = DscFile DscFile = '' if BinFile: if GenCfgData.GenerateDataIncFile(OutFile, BinFile) != 0: raise Exception(GenCfgData.Error) return 0 if DscFile.lower().endswith('.pkl'): with open(DscFile, "rb") as PklFile: GenCfgData.__dict__ = marshal.load(PklFile) else: if GenCfgData.ParseDscFile(DscFile) != 0: raise Exception(GenCfgData.Error) # if GenCfgData.CheckCfgData() != 0: # raise Exception(GenCfgData.Error) if GenCfgData.CreateVarDict() != 0: raise Exception(GenCfgData.Error) if Command == 'GENPKL': with open(OutFile, "wb") as PklFile: marshal.dump(GenCfgData.__dict__, PklFile) return 0 if DltFile and Command in ['GENHDR', 'GENBIN', 'GENINC', 'GENBSF']: if GenCfgData.OverrideDefaultValue(DltFile) != 0: raise Exception(GenCfgData.Error) if GenCfgData.UpdateDefaultValue() != 0: raise Exception(GenCfgData.Error) # GenCfgData.PrintData () if sys.argv[1] == "GENBIN": if GenCfgData.GenerateBinary(OutFile) != 0: raise Exception(GenCfgData.Error) elif sys.argv[1] == "GENHDR": OutFiles = OutFile.split(';') BrdOutFile = OutFiles[0].strip() if len(OutFiles) > 1: ComOutFile = OutFiles[1].strip() else: ComOutFile = '' if GenCfgData.CreateHeaderFile(BrdOutFile, ComOutFile) != 0: raise Exception(GenCfgData.Error) elif sys.argv[1] == "GENBSF": if GenCfgData.GenerateBsfFile(OutFile) != 0: raise Exception(GenCfgData.Error) elif sys.argv[1] == "GENINC": if GenCfgData.GenerateDataIncFile(OutFile) != 0: raise Exception(GenCfgData.Error) elif sys.argv[1] == "GENDLT": if GenCfgData.GenerateDeltaFile(OutFile, CfgBinFile) != 0: raise Exception(GenCfgData.Error) elif sys.argv[1] == "GENDSC": if GenCfgData.GenerateDscFile(OutFile) != 0: raise Exception(GenCfgData.Error) else: raise Exception("Unsuported command '%s' !" % Command) return 0 if __name__ == '__main__': sys.exit(Main())