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