ConvertFceToStructurePcd.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. #!/usr/bin/python
  2. ## @file
  3. # Firmware Configuration Editor (FCE) from https://firmware.intel.com/develop
  4. # can parse BIOS image and generate Firmware Configuration file.
  5. # This script bases on Firmware Configuration file, and generate the structure
  6. # PCD setting in DEC/DSC/INF files.
  7. #
  8. # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
  9. # SPDX-License-Identifier: BSD-2-Clause-Patent
  10. #
  11. '''
  12. ConvertFceToStructurePcd
  13. '''
  14. import re
  15. import os
  16. import datetime
  17. import argparse
  18. #
  19. # Globals for help information
  20. #
  21. __prog__ = 'ConvertFceToStructurePcd'
  22. __version__ = '%s Version %s' % (__prog__, '0.1 ')
  23. __copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'
  24. __description__ = 'Generate Structure PCD in DEC/DSC/INF based on Firmware Configuration.\n'
  25. dscstatement='''[Defines]
  26. VPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E08
  27. [SkuIds]
  28. 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
  29. [DefaultStores]
  30. 0|STANDARD # UEFI Standard default 0|STANDARD is reserved.
  31. 1|MANUFACTURING # UEFI Manufacturing default 1|MANUFACTURING is reserved.
  32. [PcdsDynamicExVpd.common.DEFAULT]
  33. gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer|*
  34. '''
  35. decstatement = '''[Guids]
  36. gStructPcdTokenSpaceGuid = {0x3f1406f4, 0x2b, 0x487a, {0x8b, 0x69, 0x74, 0x29, 0x1b, 0x36, 0x16, 0xf4}}
  37. [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx]
  38. '''
  39. infstatement = '''[Pcd]
  40. '''
  41. SECTION='PcdsDynamicHii'
  42. PCD_NAME='gStructPcdTokenSpaceGuid.Pcd'
  43. Max_Pcd_Len = 100
  44. WARNING=[]
  45. ERRORMSG=[]
  46. class parser_lst(object):
  47. def __init__(self,filelist):
  48. self._ignore=['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64']
  49. self.file=filelist
  50. self.text=self.megre_lst()[0]
  51. self.content=self.megre_lst()[1]
  52. def megre_lst(self):
  53. alltext=''
  54. content={}
  55. for file in self.file:
  56. with open(file,'r') as f:
  57. read =f.read()
  58. alltext += read
  59. content[file]=read
  60. return alltext,content
  61. def struct_lst(self):#{struct:lst file}
  62. structs_file={}
  63. name_format = re.compile(r'(?<!typedef)\s+struct (\w+) {.*?;', re.S)
  64. for i in list(self.content.keys()):
  65. structs= name_format.findall(self.content[i])
  66. if structs:
  67. for j in structs:
  68. if j not in self._ignore:
  69. structs_file[j]=i
  70. else:
  71. print("%s"%structs)
  72. return structs_file
  73. def struct(self):#struct:{offset:name}
  74. unit_num = re.compile('(\d+)')
  75. offset1_re = re.compile('(\d+)\[')
  76. pcdname_num_re = re.compile('\w+\[(\S+)\]')
  77. pcdname_re = re.compile('\](.*)\<')
  78. pcdname2_re = re.compile('(\w+)\[')
  79. uint_re = re.compile('\<(\S+)\>')
  80. name_format = re.compile(r'(?<!typedef)\s+struct (\w+) {.*?;', re.S)
  81. name=name_format.findall(self.text)
  82. info={}
  83. unparse=[]
  84. if name:
  85. tmp_n = [n for n in name if n not in self._ignore]
  86. name = list(set(tmp_n))
  87. name.sort(key = tmp_n.index)
  88. name.reverse()
  89. #name=list(set(name).difference(set(self._ignore)))
  90. for struct in name:
  91. s_re = re.compile(r'struct %s :(.*?)};'% struct, re.S)
  92. content = s_re.search(self.text)
  93. if content:
  94. tmp_dict = {}
  95. text = content.group().split('+')
  96. for line in text[1:]:
  97. offset = offset1_re.findall(line)
  98. t_name = pcdname_re.findall(line)
  99. uint = uint_re.findall(line)
  100. if offset and uint:
  101. offset = offset[0]
  102. uint = uint[0]
  103. if t_name:
  104. t_name = t_name[0].strip()
  105. if (' ' in t_name) or ("=" in t_name) or (";" in t_name) or("\\" in name) or (t_name ==''):
  106. WARNING.append("Warning:Invalid Pcd name '%s' for Offset %s in struct %s" % (t_name,offset, struct))
  107. else:
  108. if '[' in t_name:
  109. if uint in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
  110. offset = int(offset, 10)
  111. tmp_name = pcdname2_re.findall(t_name)[0] + '[0]'
  112. tmp_dict[offset] = tmp_name
  113. pcdname_num = int(pcdname_num_re.findall(t_name)[0],10)
  114. uint = int(unit_num.findall(uint)[0],10)
  115. bit = uint // 8
  116. for i in range(1, pcdname_num):
  117. offset += bit
  118. tmp_name = pcdname2_re.findall(t_name)[0] + '[%s]' % i
  119. tmp_dict[offset] = tmp_name
  120. else:
  121. tmp_name = pcdname2_re.findall(t_name)[0]
  122. pcdname_num = pcdname_num_re.findall(t_name)[0]
  123. line = [offset,tmp_name,pcdname_num,uint]
  124. line.append(struct)
  125. unparse.append(line)
  126. else:
  127. if uint not in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
  128. line = [offset, t_name, 0, uint]
  129. line.append(struct)
  130. unparse.append(line)
  131. else:
  132. offset = int(offset,10)
  133. tmp_dict[offset] = t_name
  134. info[struct] = tmp_dict
  135. if len(unparse) != 0:
  136. for u in unparse:
  137. if u[3] in list(info.keys()):
  138. unpar = self.nameISstruct(u,info[u[3]])
  139. info[u[4]]= dict(list(info[u[4]].items())+list(unpar[u[4]].items()))
  140. else:
  141. print("ERROR: No struct name found in %s" % self.file)
  142. ERRORMSG.append("ERROR: No struct name found in %s" % self.file)
  143. return info
  144. def nameISstruct(self,line,key_dict):
  145. dict={}
  146. dict2={}
  147. s_re = re.compile(r'struct %s :(.*?)};' % line[3], re.S)
  148. size_re = re.compile(r'mTotalSize \[(\S+)\]')
  149. content = s_re.search(self.text)
  150. if content:
  151. s_size = size_re.findall(content.group())[0]
  152. else:
  153. s_size = '0'
  154. print("ERROR: Struct %s not define mTotalSize in lst file" %line[3])
  155. ERRORMSG.append("ERROR: Struct %s not define mTotalSize in lst file" %line[3])
  156. size = int(line[0], 10)
  157. if line[2] != 0:
  158. for j in range(0, int(line[2], 10)):
  159. for k in list(key_dict.keys()):
  160. offset = size + k
  161. name ='%s.%s' %((line[1]+'[%s]'%j),key_dict[k])
  162. dict[offset] = name
  163. size = int(s_size,16)+size
  164. elif line[2] == 0:
  165. for k in list(key_dict.keys()):
  166. offset = size + k
  167. name = '%s.%s' % (line[1], key_dict[k])
  168. dict[offset] = name
  169. dict2[line[4]] = dict
  170. return dict2
  171. def efivarstore_parser(self):
  172. efivarstore_format = re.compile(r'efivarstore.*?;', re.S)
  173. struct_re = re.compile(r'efivarstore(.*?),',re.S)
  174. name_re = re.compile(r'name=(\w+)')
  175. efivarstore_dict={}
  176. efitxt = efivarstore_format.findall(self.text)
  177. for i in efitxt:
  178. struct = struct_re.findall(i.replace(' ',''))
  179. if struct[0] in self._ignore:
  180. continue
  181. name = name_re.findall(i.replace(' ',''))
  182. if struct and name:
  183. efivarstore_dict[name[0]]=struct[0]
  184. else:
  185. print("ERROR: Can't find Struct or name in lst file, please check have this format:efivarstore XXXX, name=xxxx")
  186. ERRORMSG.append("ERROR: Can't find Struct or name in lst file, please check have this format:efivarstore XXXX, name=xxxx")
  187. return efivarstore_dict
  188. class Config(object):
  189. def __init__(self,Config):
  190. self.config=Config
  191. #Parser .config file,return list[offset,name,guid,value,help]
  192. def config_parser(self):
  193. ids_re =re.compile('_ID:(\d+)',re.S)
  194. id_re= re.compile('\s+')
  195. info = []
  196. info_dict={}
  197. with open(self.config, 'r') as text:
  198. read = text.read()
  199. if 'DEFAULT_ID:' in read:
  200. all_txt = read.split('FCEKEY DEFAULT')
  201. for i in all_txt[1:]:
  202. part = [] #save all infomation for DEFAULT_ID
  203. str_id=''
  204. ids = ids_re.findall(i.replace(' ',''))
  205. for m in ids:
  206. str_id +=m+'_'
  207. str_id=str_id[:-1]
  208. part.append(ids)
  209. section = i.split('\nQ') #split with '\nQ ' to get every block
  210. part +=self.section_parser(section)
  211. info_dict[str_id] = self.section_parser(section)
  212. info.append(part)
  213. else:
  214. part = []
  215. id=('0','0')
  216. str_id='0_0'
  217. part.append(id)
  218. section = read.split('\nQ')
  219. part +=self.section_parser(section)
  220. info_dict[str_id] = self.section_parser(section)
  221. info.append(part)
  222. return info_dict
  223. def eval_id(self,id):
  224. id = id.split("_")
  225. default_id=id[0:len(id)//2]
  226. platform_id=id[len(id)//2:]
  227. text=''
  228. for i in range(len(default_id)):
  229. text +="%s.common.%s.%s,"%(SECTION,self.id_name(platform_id[i],'PLATFORM'),self.id_name(default_id[i],'DEFAULT'))
  230. return '\n[%s]\n'%text[:-1]
  231. def id_name(self,ID, flag):
  232. platform_dict = {'0': 'DEFAULT'}
  233. default_dict = {'0': 'STANDARD', '1': 'MANUFACTURING'}
  234. if flag == "PLATFORM":
  235. try:
  236. value = platform_dict[ID]
  237. except KeyError:
  238. value = 'SKUID%s' % ID
  239. elif flag == 'DEFAULT':
  240. try:
  241. value = default_dict[ID]
  242. except KeyError:
  243. value = 'DEFAULTID%s' % ID
  244. else:
  245. value = None
  246. return value
  247. def section_parser(self,section):
  248. offset_re = re.compile(r'offset=(\w+)')
  249. name_re = re.compile(r'name=(\S+)')
  250. guid_re = re.compile(r'guid=(\S+)')
  251. # help_re = re.compile(r'help = (.*)')
  252. attribute_re=re.compile(r'attribute=(\w+)')
  253. value_re = re.compile(r'(//.*)')
  254. part = []
  255. part_without_comment = []
  256. for x in section[1:]:
  257. line=x.split('\n')[0]
  258. comment_list = value_re.findall(line) # the string \\... in "Q...." line
  259. comment_list[0] = comment_list[0].replace('//', '')
  260. comment_ori = comment_list[0].strip()
  261. comment = ""
  262. for each in comment_ori:
  263. if each != " " and "\x21" > each or each > "\x7E":
  264. if bytes(each, 'utf-16') == b'\xff\xfe\xae\x00':
  265. each = '(R)'
  266. else:
  267. each = ""
  268. comment += each
  269. line=value_re.sub('',line) #delete \\... in "Q...." line
  270. list1=line.split(' ')
  271. value=self.value_parser(list1)
  272. offset = offset_re.findall(x.replace(' ',''))
  273. name = name_re.findall(x.replace(' ',''))
  274. guid = guid_re.findall(x.replace(' ',''))
  275. attribute =attribute_re.findall(x.replace(' ',''))
  276. if offset and name and guid and value and attribute:
  277. if attribute[0] in ['0x3','0x7']:
  278. offset = int(offset[0], 16)
  279. #help = help_re.findall(x)
  280. text_without_comment = offset, name[0], guid[0], value, attribute[0]
  281. if text_without_comment in part_without_comment:
  282. # check if exists same Pcd with different comments, add different comments in one line with "|".
  283. dupl_index = part_without_comment.index(text_without_comment)
  284. part[dupl_index] = list(part[dupl_index])
  285. if comment not in part[dupl_index][-1]:
  286. part[dupl_index][-1] += " | " + comment
  287. part[dupl_index] = tuple(part[dupl_index])
  288. else:
  289. text = offset, name[0], guid[0], value, attribute[0], comment
  290. part_without_comment.append(text_without_comment)
  291. part.append(text)
  292. return(part)
  293. def value_parser(self, list1):
  294. list1 = [t for t in list1 if t != ''] # remove '' form list
  295. first_num = int(list1[0], 16)
  296. if list1[first_num + 1] == 'STRING': # parser STRING
  297. if list1[-1] == '""':
  298. value = "{0x0, 0x0}"
  299. else:
  300. value = 'L%s' % list1[-1]
  301. elif list1[first_num + 1] == 'ORDERED_LIST': # parser ORDERED_LIST
  302. value_total = int(list1[first_num + 2])
  303. list2 = list1[-value_total:]
  304. tmp = []
  305. line = ''
  306. for i in list2:
  307. if len(i) % 2 == 0 and len(i) != 2:
  308. for m in range(0, len(i) // 2):
  309. tmp.append('0x%02x' % (int('0x%s' % i, 16) >> m * 8 & 0xff))
  310. else:
  311. tmp.append('0x%s' % i)
  312. for i in tmp:
  313. line += '%s,' % i
  314. value = '{%s}' % line[:-1]
  315. else:
  316. value = "0x%01x" % int(list1[-1], 16)
  317. return value
  318. #parser Guid file, get guid name form guid value
  319. class GUID(object):
  320. def __init__(self,path):
  321. self.path = path
  322. self.guidfile = self.gfile()
  323. self.guiddict = self.guid_dict()
  324. def gfile(self):
  325. for root, dir, file in os.walk(self.path, topdown=True, followlinks=False):
  326. if 'FV' in dir:
  327. gfile = os.path.join(root,'Fv','Guid.xref')
  328. if os.path.isfile(gfile):
  329. return gfile
  330. else:
  331. print("ERROR: Guid.xref file not found")
  332. ERRORMSG.append("ERROR: Guid.xref file not found")
  333. exit()
  334. def guid_dict(self):
  335. guiddict={}
  336. with open(self.guidfile,'r') as file:
  337. lines = file.readlines()
  338. guidinfo=lines
  339. for line in guidinfo:
  340. list=line.strip().split(' ')
  341. if list:
  342. if len(list)>1:
  343. guiddict[list[0].upper()]=list[1]
  344. elif list[0] != ''and len(list)==1:
  345. print("Error: line %s can't be parser in %s"%(line.strip(),self.guidfile))
  346. ERRORMSG.append("Error: line %s can't be parser in %s"%(line.strip(),self.guidfile))
  347. else:
  348. print("ERROR: No data in %s" %self.guidfile)
  349. ERRORMSG.append("ERROR: No data in %s" %self.guidfile)
  350. return guiddict
  351. def guid_parser(self,guid):
  352. if guid.upper() in self.guiddict:
  353. return self.guiddict[guid.upper()]
  354. else:
  355. print("ERROR: GUID %s not found in file %s"%(guid, self.guidfile))
  356. ERRORMSG.append("ERROR: GUID %s not found in file %s"%(guid, self.guidfile))
  357. return guid
  358. class PATH(object):
  359. def __init__(self,path):
  360. self.path=path
  361. self.rootdir=self.get_root_dir()
  362. self.usefuldir=set()
  363. self.lstinf = {}
  364. for path in self.rootdir:
  365. for o_root, o_dir, o_file in os.walk(os.path.join(path, "OUTPUT"), topdown=True, followlinks=False):
  366. for INF in o_file:
  367. if os.path.splitext(INF)[1] == '.inf':
  368. for l_root, l_dir, l_file in os.walk(os.path.join(path, "DEBUG"), topdown=True,
  369. followlinks=False):
  370. for LST in l_file:
  371. if os.path.splitext(LST)[1] == '.lst':
  372. self.lstinf[os.path.join(l_root, LST)] = os.path.join(o_root, INF)
  373. self.usefuldir.add(path)
  374. def get_root_dir(self):
  375. rootdir=[]
  376. for root,dir,file in os.walk(self.path,topdown=True,followlinks=False):
  377. if "OUTPUT" in root:
  378. updir=root.split("OUTPUT",1)[0]
  379. rootdir.append(updir)
  380. rootdir=list(set(rootdir))
  381. return rootdir
  382. def lst_inf(self):
  383. return self.lstinf
  384. def package(self):
  385. package={}
  386. package_re=re.compile(r'Packages\.\w+]\n(.*)',re.S)
  387. for i in list(self.lstinf.values()):
  388. with open(i,'r') as inf:
  389. read=inf.read()
  390. section=read.split('[')
  391. for j in section:
  392. p=package_re.findall(j)
  393. if p:
  394. package[i]=p[0].rstrip()
  395. return package
  396. def header(self,struct):
  397. header={}
  398. head_re = re.compile('typedef.*} %s;[\n]+(.*)(?:typedef|formset)'%struct,re.M|re.S)
  399. head_re2 = re.compile(r'#line[\s\d]+"(\S+h)"')
  400. for i in list(self.lstinf.keys()):
  401. with open(i,'r') as lst:
  402. read = lst.read()
  403. h = head_re.findall(read)
  404. if h:
  405. head=head_re2.findall(h[0])
  406. if head:
  407. format = head[0].replace('\\\\','/').replace('\\','/')
  408. name =format.split('/')[-1]
  409. head = self.headerfileset.get(name)
  410. if head:
  411. head = head.replace('\\','/')
  412. header[struct] = head
  413. return header
  414. @property
  415. def headerfileset(self):
  416. headerset = dict()
  417. for root,dirs,files in os.walk(self.path):
  418. for file in files:
  419. if os.path.basename(file) == 'deps.txt':
  420. with open(os.path.join(root,file),"r") as fr:
  421. for line in fr.readlines():
  422. headerset[os.path.basename(line).strip()] = line.strip()
  423. return headerset
  424. def makefile(self,filename):
  425. re_format = re.compile(r'DEBUG_DIR.*(?:\S+Pkg)\\(.*\\%s)'%filename)
  426. for i in self.usefuldir:
  427. with open(os.path.join(i,'Makefile'),'r') as make:
  428. read = make.read()
  429. dir = re_format.findall(read)
  430. if dir:
  431. return dir[0]
  432. return None
  433. class mainprocess(object):
  434. def __init__(self,InputPath,Config,OutputPath):
  435. self.init = 0xFCD00000
  436. self.inputpath = os.path.abspath(InputPath)
  437. self.outputpath = os.path.abspath(OutputPath)
  438. self.LST = PATH(self.inputpath)
  439. self.lst_dict = self.LST.lst_inf()
  440. self.Config = Config
  441. self.attribute_dict = {'0x3': 'NV, BS', '0x7': 'NV, BS, RT'}
  442. self.guid = GUID(self.inputpath)
  443. self.header={}
  444. def main(self):
  445. conf=Config(self.Config)
  446. config_dict=conf.config_parser() #get {'0_0':[offset,name,guid,value,attribute]...,'1_0':....}
  447. lst=parser_lst(list(self.lst_dict.keys()))
  448. efi_dict=lst.efivarstore_parser() #get {name:struct} form lst file
  449. keys=sorted(config_dict.keys())
  450. all_struct=lst.struct()
  451. stru_lst=lst.struct_lst()
  452. title_list=[]
  453. info_list=[]
  454. header_list=[]
  455. inf_list =[]
  456. for i in stru_lst:
  457. tmp = self.LST.header(i)
  458. self.header.update(tmp)
  459. for id_key in keys:
  460. tmp_id=[id_key] #['0_0',[(struct,[name...]),(struct,[name...])]]
  461. tmp_info={} #{name:struct}
  462. for section in config_dict[id_key]:
  463. c_offset,c_name,c_guid,c_value,c_attribute,c_comment = section
  464. if c_name in efi_dict:
  465. struct = efi_dict[c_name]
  466. title='%s%s|L"%s"|%s|0x00||%s\n'%(PCD_NAME,c_name,c_name,self.guid.guid_parser(c_guid),self.attribute_dict[c_attribute])
  467. if struct in all_struct:
  468. lstfile = stru_lst[struct]
  469. struct_dict=all_struct[struct]
  470. try:
  471. title2 = '%s%s|{0}|%s|0xFCD00000{\n <HeaderFiles>\n %s\n <Packages>\n%s\n}\n' % (PCD_NAME, c_name, struct, self.header[struct], self.LST.package()[self.lst_dict[lstfile]])
  472. except KeyError:
  473. WARNING.append("Warning: No <HeaderFiles> for struct %s"%struct)
  474. title2 = '%s%s|{0}|%s|0xFCD00000{\n <HeaderFiles>\n %s\n <Packages>\n%s\n}\n' % (PCD_NAME, c_name, struct, '', self.LST.package()[self.lst_dict[lstfile]])
  475. header_list.append(title2)
  476. elif struct not in lst._ignore:
  477. struct_dict ={}
  478. print("ERROR: Struct %s can't found in lst file" %struct)
  479. ERRORMSG.append("ERROR: Struct %s can't found in lst file" %struct)
  480. if c_offset in struct_dict:
  481. offset_name=struct_dict[c_offset]
  482. info = "%s%s.%s|%s\n"%(PCD_NAME,c_name,offset_name,c_value)
  483. blank_length = Max_Pcd_Len - len(info)
  484. if blank_length <= 0:
  485. info_comment = "%s%s.%s|%s%s# %s\n"%(PCD_NAME,c_name,offset_name,c_value," ",c_comment)
  486. else:
  487. info_comment = "%s%s.%s|%s%s# %s\n"%(PCD_NAME,c_name,offset_name,c_value,blank_length*" ",c_comment)
  488. inf = "%s%s\n"%(PCD_NAME,c_name)
  489. inf_list.append(inf)
  490. tmp_info[info_comment]=title
  491. else:
  492. print("ERROR: Can't find offset %s with struct name %s"%(c_offset,struct))
  493. ERRORMSG.append("ERROR: Can't find offset %s with name %s"%(c_offset,struct))
  494. else:
  495. print("ERROR: Can't find name %s in lst file"%(c_name))
  496. ERRORMSG.append("ERROR: Can't find name %s in lst file"%(c_name))
  497. tmp_id.append(list(self.reverse_dict(tmp_info).items()))
  498. id,tmp_title_list,tmp_info_list = self.read_list(tmp_id)
  499. title_list +=tmp_title_list
  500. info_list.append(tmp_info_list)
  501. inf_list = self.del_repeat(inf_list)
  502. header_list = self.plus(self.del_repeat(header_list))
  503. title_all=list(set(title_list))
  504. info_list = self.remove_bracket(self.del_repeat(info_list))
  505. for i in range(len(info_list)-1,-1,-1):
  506. if len(info_list[i]) == 0:
  507. info_list.remove(info_list[i])
  508. for i in (inf_list, title_all, header_list):
  509. i.sort()
  510. return keys,title_all,info_list,header_list,inf_list
  511. def correct_sort(self, PcdString):
  512. # sort the Pcd list with two rules:
  513. # First sort through Pcd name;
  514. # Second if the Pcd exists several elements, sort them through index value.
  515. if ("]|") in PcdString:
  516. Pcdname = PcdString.split("[")[0]
  517. Pcdindex = int(PcdString.split("[")[1].split("]")[0])
  518. else:
  519. Pcdname = PcdString.split("|")[0]
  520. Pcdindex = 0
  521. return Pcdname, Pcdindex
  522. def remove_bracket(self,List):
  523. for i in List:
  524. for j in i:
  525. tmp = j.split("|")
  526. if (('L"' in j) and ("[" in j)) or (tmp[1].split("#")[0].strip() == '{0x0, 0x0}'):
  527. tmp[0] = tmp[0][:tmp[0].index('[')]
  528. List[List.index(i)][i.index(j)] = "|".join(tmp)
  529. else:
  530. List[List.index(i)][i.index(j)] = j
  531. for i in List:
  532. if type(i) == type([0,0]):
  533. i.sort(key = lambda x:(self.correct_sort(x)[0], self.correct_sort(x)[1]))
  534. return List
  535. def write_all(self):
  536. title_flag=1
  537. info_flag=1
  538. if not os.path.isdir(self.outputpath):
  539. os.makedirs(self.outputpath)
  540. decwrite = write2file(os.path.join(self.outputpath,'StructurePcd.dec'))
  541. dscwrite = write2file(os.path.join(self.outputpath,'StructurePcd.dsc'))
  542. infwrite = write2file(os.path.join(self.outputpath, 'StructurePcd.inf'))
  543. conf = Config(self.Config)
  544. ids,title,info,header,inf=self.main()
  545. decwrite.add2file(decstatement)
  546. decwrite.add2file(header)
  547. infwrite.add2file(infstatement)
  548. infwrite.add2file(inf)
  549. dscwrite.add2file(dscstatement)
  550. for id in ids:
  551. dscwrite.add2file(conf.eval_id(id))
  552. if title_flag:
  553. dscwrite.add2file(title)
  554. title_flag=0
  555. if len(info) == 1:
  556. dscwrite.add2file(info)
  557. elif len(info) == 2:
  558. if info_flag:
  559. dscwrite.add2file(info[0])
  560. info_flag =0
  561. else:
  562. dscwrite.add2file(info[1])
  563. def del_repeat(self,List):
  564. if len(List) == 1 or len(List) == 0:
  565. return List
  566. else:
  567. if type(List[0]) != type('xxx'):
  568. alist=[]
  569. for i in range(len(List)):
  570. if i == 0:
  571. alist.append(List[0])
  572. else:
  573. plist = []
  574. for j in range(i):
  575. plist += List[j]
  576. alist.append(self.__del(list(set(plist)), List[i]))
  577. return alist
  578. else:
  579. return list(set(List))
  580. def __del(self,list1,list2):
  581. return list(set(list2).difference(set(list1)))
  582. def reverse_dict(self,dict):
  583. data={}
  584. for i in list(dict.items()):
  585. if i[1] not in list(data.keys()):
  586. data[i[1]]=[i[0]]
  587. else:
  588. data[i[1]].append(i[0])
  589. return data
  590. def read_list(self,list):
  591. title_list=[]
  592. info_list=[]
  593. for i in list[1]:
  594. title_list.append(i[0])
  595. for j in i[1]:
  596. info_list.append(j)
  597. return list[0],title_list,info_list
  598. def plus(self,list):
  599. nums=[]
  600. for i in list:
  601. if type(i) != type([0]):
  602. self.init += 1
  603. num = "0x%01x" % self.init
  604. j=i.replace('0xFCD00000',num.upper())
  605. nums.append(j)
  606. return nums
  607. class write2file(object):
  608. def __init__(self,Output):
  609. self.output=Output
  610. self.text=''
  611. if os.path.exists(self.output):
  612. os.remove(self.output)
  613. def add2file(self,content):
  614. self.text = ''
  615. with open(self.output,'a+') as file:
  616. file.write(self.__gen(content))
  617. def __gen(self,content):
  618. if type(content) == type(''):
  619. return content
  620. elif type(content) == type([0,0])or type(content) == type((0,0)):
  621. return self.__readlist(content)
  622. elif type(content) == type({0:0}):
  623. return self.__readdict(content)
  624. def __readlist(self,list):
  625. for i in list:
  626. if type(i) == type([0,0])or type(i) == type((0,0)):
  627. self.__readlist(i)
  628. elif type(i) == type('') :
  629. self.text +=i
  630. return self.text
  631. def __readdict(self,dict):
  632. content=list(dict.items())
  633. return self.__readlist(content)
  634. def stamp():
  635. return datetime.datetime.now()
  636. def dtime(start,end,id=None):
  637. if id:
  638. pass
  639. print("%s time:%s" % (id,str(end - start)))
  640. else:
  641. print("Total time:%s" %str(end-start)[:-7])
  642. def main():
  643. start = stamp()
  644. parser = argparse.ArgumentParser(prog = __prog__,
  645. description = __description__ + __copyright__,
  646. conflict_handler = 'resolve')
  647. parser.add_argument('-v', '--version', action = 'version',version = __version__, help="show program's version number and exit")
  648. parser.add_argument('-p', '--path', metavar='PATH', dest='path', help="platform build output directory")
  649. parser.add_argument('-c', '--config',metavar='FILENAME', dest='config', help="firmware configuration file")
  650. parser.add_argument('-o', '--outputdir', metavar='PATH', dest='output', help="output directoy")
  651. options = parser.parse_args()
  652. if options.config:
  653. if options.path:
  654. if options.output:
  655. run = mainprocess(options.path, options.config, options.output)
  656. print("Running...")
  657. run.write_all()
  658. if WARNING:
  659. warning = list(set(WARNING))
  660. for j in warning:
  661. print(j)
  662. if ERRORMSG:
  663. ERROR = list(set(ERRORMSG))
  664. with open("ERROR.log", 'w+') as error:
  665. for i in ERROR:
  666. error.write(i + '\n')
  667. print("Some error find, error log in ERROR.log")
  668. print('Finished, Output files in directory %s'%os.path.abspath(options.output))
  669. else:
  670. print('Error command, no output path, use -h for help')
  671. else:
  672. print('Error command, no build path input, use -h for help')
  673. else:
  674. print('Error command, no output file, use -h for help')
  675. end = stamp()
  676. dtime(start, end)
  677. if __name__ == '__main__':
  678. main()