123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637 |
- # @ GenCfgData.py
- #
- # Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
- # 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.<BR>
- 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.<BR>
- # 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())
|