FspGenCfgData.py 103 KB

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