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