]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/ConvertFceToStructurePcd.py
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.
8 # Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
9 # SPDX-License-Identifier: BSD-2-Clause-Patent
13 ConvertFceToStructurePcd
22 # Globals for help information
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'
30 dscstatement
='''[Defines]
31 VPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E08
34 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
37 0|STANDARD # UEFI Standard default 0|STANDARD is reserved.
38 1|MANUFACTURING # UEFI Manufacturing default 1|MANUFACTURING is reserved.
40 [PcdsDynamicExVpd.common.DEFAULT]
41 gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer|*
44 decstatement
= '''[Guids]
45 gStructPcdTokenSpaceGuid = {0x3f1406f4, 0x2b, 0x487a, {0x8b, 0x69, 0x74, 0x29, 0x1b, 0x36, 0x16, 0xf4}}
47 [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx]
50 infstatement
= '''[Pcd]
53 SECTION
='PcdsDynamicHii'
54 PCD_NAME
='gStructPcdTokenSpaceGuid.Pcd'
60 class parser_lst(object):
62 def __init__(self
,filelist
):
63 self
._ignore
=['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64']
65 self
.text
=self
.megre_lst()[0]
66 self
.content
=self
.megre_lst()[1]
71 for file in self
.file:
72 with
open(file,'r') as f
:
76 return alltext
,content
78 def struct_lst(self
):#{struct:lst file}
80 name_format
= re
.compile(r
'(?<!typedef)\s+struct (\w+) {.*?;', re
.S
)
81 for i
in list(self
.content
.keys()):
82 structs
= name_format
.findall(self
.content
[i
])
85 if j
not in self
._ignore
:
91 def struct(self
):#struct:{offset:name}
92 unit_num
= re
.compile('(\d+)')
93 offset1_re
= re
.compile('(\d+)\[')
94 pcdname_num_re
= re
.compile('\w+\[(\S+)\]')
95 pcdname_re
= re
.compile('\](.*)\<')
96 pcdname2_re
= re
.compile('(\w+)\[')
97 uint_re
= re
.compile('\<(\S+)\>')
98 name_format
= re
.compile(r
'(?<!typedef)\s+struct (\w+) {.*?;', re
.S
)
99 name
=name_format
.findall(self
.text
)
103 tmp_n
= [n
for n
in name
if n
not in self
._ignore
]
104 name
= list(set(tmp_n
))
105 name
.sort(key
= tmp_n
.index
)
107 #name=list(set(name).difference(set(self._ignore)))
109 s_re
= re
.compile(r
'struct %s :(.*?)};'% struct
, re
.S
)
110 content
= s_re
.search(self
.text
)
113 text
= content
.group().split('+')
114 for line
in text
[1:]:
115 offset
= offset1_re
.findall(line
)
116 t_name
= pcdname_re
.findall(line
)
117 uint
= uint_re
.findall(line
)
122 t_name
= t_name
[0].strip()
123 if (' ' in t_name
) or ("=" in t_name
) or (";" in t_name
) or("\\" in name
) or (t_name
==''):
124 WARNING
.append("Warning:Invalid Pcd name '%s' for Offset %s in struct %s" % (t_name
,offset
, struct
))
127 if uint
in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
128 offset
= int(offset
, 10)
129 tmp_name
= pcdname2_re
.findall(t_name
)[0] + '[0]'
130 tmp_dict
[offset
] = tmp_name
131 pcdname_num
= int(pcdname_num_re
.findall(t_name
)[0],10)
132 uint
= int(unit_num
.findall(uint
)[0],10)
134 for i
in range(1, pcdname_num
):
136 tmp_name
= pcdname2_re
.findall(t_name
)[0] + '[%s]' % i
137 tmp_dict
[offset
] = tmp_name
139 tmp_name
= pcdname2_re
.findall(t_name
)[0]
140 pcdname_num
= pcdname_num_re
.findall(t_name
)[0]
141 line
= [offset
,tmp_name
,pcdname_num
,uint
]
145 if uint
not in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
146 line
= [offset
, t_name
, 0, uint
]
150 offset
= int(offset
,10)
151 tmp_dict
[offset
] = t_name
152 info
[struct
] = tmp_dict
153 if len(unparse
) != 0:
155 if u
[3] in list(info
.keys()):
156 unpar
= self
.nameISstruct(u
,info
[u
[3]])
157 info
[u
[4]]= dict(list(info
[u
[4]].items())+list(unpar
[u
[4]].items()))
159 print("ERROR: No struct name found in %s" % self
.file)
160 ERRORMSG
.append("ERROR: No struct name found in %s" % self
.file)
164 def nameISstruct(self
,line
,key_dict
):
167 s_re
= re
.compile(r
'struct %s :(.*?)};' % line
[3], re
.S
)
168 size_re
= re
.compile(r
'mTotalSize \[(\S+)\]')
169 content
= s_re
.search(self
.text
)
171 s_size
= size_re
.findall(content
.group())[0]
174 print("ERROR: Struct %s not define mTotalSize in lst file" %line
[3])
175 ERRORMSG
.append("ERROR: Struct %s not define mTotalSize in lst file" %line
[3])
176 size
= int(line
[0], 10)
178 for j
in range(0, int(line
[2], 10)):
179 for k
in list(key_dict
.keys()):
181 name
='%s.%s' %((line
[1]+'[%s]'%j
),key_dict
[k
])
183 size
= int(s_size
,16)+size
185 for k
in list(key_dict
.keys()):
187 name
= '%s.%s' % (line
[1], key_dict
[k
])
189 dict2
[line
[4]] = dict
192 def efivarstore_parser(self
):
193 efivarstore_format
= re
.compile(r
'efivarstore.*?;', re
.S
)
194 struct_re
= re
.compile(r
'efivarstore(.*?),',re
.S
)
195 name_re
= re
.compile(r
'name=(\w+)')
197 efitxt
= efivarstore_format
.findall(self
.text
)
199 struct
= struct_re
.findall(i
.replace(' ',''))
200 if struct
[0] in self
._ignore
:
202 name
= name_re
.findall(i
.replace(' ',''))
204 efivarstore_dict
[name
[0]]=struct
[0]
206 print("ERROR: Can't find Struct or name in lst file, please check have this format:efivarstore XXXX, name=xxxx")
207 ERRORMSG
.append("ERROR: Can't find Struct or name in lst file, please check have this format:efivarstore XXXX, name=xxxx")
208 return efivarstore_dict
210 class Config(object):
212 def __init__(self
,Config
):
215 #Parser .config file,return list[offset,name,guid,value,help]
216 def config_parser(self
):
217 ids_re
=re
.compile('_ID:(\d+)',re
.S
)
218 id_re
= re
.compile('\s+')
221 with
open(self
.config
, 'r') as text
:
223 if 'DEFAULT_ID:' in read
:
224 all_txt
= read
.split('FCEKEY DEFAULT')
225 for i
in all_txt
[1:]:
226 part
= [] #save all infomation for DEFAULT_ID
228 ids
= ids_re
.findall(i
.replace(' ',''))
233 section
= i
.split('\nQ') #split with '\nQ ' to get every block
234 part
+=self
.section_parser(section
)
235 info_dict
[str_id
] = self
.section_parser(section
)
242 section
= read
.split('\nQ')
243 part
+=self
.section_parser(section
)
244 info_dict
[str_id
] = self
.section_parser(section
)
248 def eval_id(self
,id):
250 default_id
=id[0:len(id)//2]
251 platform_id
=id[len(id)//2:]
253 for i
in range(len(default_id
)):
254 text
+="%s.common.%s.%s,"%(SECTION
,self
.id_name(platform_id
[i
],'PLATFORM'),self
.id_name(default_id
[i
],'DEFAULT'))
255 return '\n[%s]\n'%text
[:-1]
257 def id_name(self
,ID
, flag
):
258 platform_dict
= {'0': 'DEFAULT'}
259 default_dict
= {'0': 'STANDARD', '1': 'MANUFACTURING'}
260 if flag
== "PLATFORM":
262 value
= platform_dict
[ID
]
264 value
= 'SKUID%s' % ID
265 elif flag
== 'DEFAULT':
267 value
= default_dict
[ID
]
269 value
= 'DEFAULTID%s' % ID
274 def section_parser(self
,section
):
275 offset_re
= re
.compile(r
'offset=(\w+)')
276 name_re
= re
.compile(r
'name=(\S+)')
277 guid_re
= re
.compile(r
'guid=(\S+)')
278 # help_re = re.compile(r'help = (.*)')
279 attribute_re
=re
.compile(r
'attribute=(\w+)')
280 value_re
= re
.compile(r
'(//.*)')
282 part_without_comment
= []
283 for x
in section
[1:]:
284 line
=x
.split('\n')[0]
285 comment_list
= value_re
.findall(line
) # the string \\... in "Q...." line
286 comment_list
[0] = comment_list
[0].replace('//', '')
287 comment_ori
= comment_list
[0].strip()
289 for each
in comment_ori
:
290 if each
!= " " and "\x21" > each
or each
> "\x7E":
291 if bytes(each
, 'utf-16') == b
'\xff\xfe\xae\x00':
296 line
=value_re
.sub('',line
) #delete \\... in "Q...." line
297 list1
=line
.split(' ')
298 value
=self
.value_parser(list1
)
299 offset
= offset_re
.findall(x
.replace(' ',''))
300 name
= name_re
.findall(x
.replace(' ',''))
301 guid
= guid_re
.findall(x
.replace(' ',''))
302 attribute
=attribute_re
.findall(x
.replace(' ',''))
303 if offset
and name
and guid
and value
and attribute
:
304 if attribute
[0] in ['0x3','0x7']:
305 offset
= int(offset
[0], 16)
306 #help = help_re.findall(x)
307 text_without_comment
= offset
, name
[0], guid
[0], value
, attribute
[0]
308 if text_without_comment
in part_without_comment
:
309 # check if exists same Pcd with different comments, add different comments in one line with "|".
310 dupl_index
= part_without_comment
.index(text_without_comment
)
311 part
[dupl_index
] = list(part
[dupl_index
])
312 if comment
not in part
[dupl_index
][-1]:
313 part
[dupl_index
][-1] += " | " + comment
314 part
[dupl_index
] = tuple(part
[dupl_index
])
316 text
= offset
, name
[0], guid
[0], value
, attribute
[0], comment
317 part_without_comment
.append(text_without_comment
)
321 def value_parser(self
, list1
):
322 list1
= [t
for t
in list1
if t
!= ''] # remove '' form list
323 first_num
= int(list1
[0], 16)
324 if list1
[first_num
+ 1] == 'STRING': # parser STRING
325 if list1
[-1] == '""':
328 value
= 'L%s' % list1
[-1]
329 elif list1
[first_num
+ 1] == 'ORDERED_LIST': # parser ORDERED_LIST
330 value_total
= int(list1
[first_num
+ 2])
331 list2
= list1
[-value_total
:]
335 if len(i
) % 2 == 0 and len(i
) != 2:
336 for m
in range(0, len(i
) // 2):
337 tmp
.append('0x%02x' % (int('0x%s' % i
, 16) >> m
* 8 & 0xff))
339 tmp
.append('0x%s' % i
)
342 value
= '{%s}' % line
[:-1]
344 value
= "0x%01x" % int(list1
[-1], 16)
348 #parser Guid file, get guid name form guid value
351 def __init__(self
,path
):
353 self
.guidfile
= self
.gfile()
354 self
.guiddict
= self
.guid_dict()
357 for root
, dir, file in os
.walk(self
.path
, topdown
=True, followlinks
=False):
359 gfile
= os
.path
.join(root
,'Fv','Guid.xref')
360 if os
.path
.isfile(gfile
):
363 print("ERROR: Guid.xref file not found")
364 ERRORMSG
.append("ERROR: Guid.xref file not found")
369 with
open(self
.guidfile
,'r') as file:
370 lines
= file.readlines()
372 for line
in guidinfo
:
373 list=line
.strip().split(' ')
376 guiddict
[list[0].upper()]=list[1]
377 elif list[0] != ''and len(list)==1:
378 print("Error: line %s can't be parser in %s"%(line
.strip(),self
.guidfile
))
379 ERRORMSG
.append("Error: line %s can't be parser in %s"%(line
.strip(),self
.guidfile
))
381 print("ERROR: No data in %s" %self
.guidfile
)
382 ERRORMSG
.append("ERROR: No data in %s" %self
.guidfile
)
385 def guid_parser(self
,guid
):
386 if guid
.upper() in self
.guiddict
:
387 return self
.guiddict
[guid
.upper()]
389 print("ERROR: GUID %s not found in file %s"%(guid
, self
.guidfile
))
390 ERRORMSG
.append("ERROR: GUID %s not found in file %s"%(guid
, self
.guidfile
))
395 def __init__(self
,path
):
397 self
.rootdir
=self
.get_root_dir()
400 for path
in self
.rootdir
:
401 for o_root
, o_dir
, o_file
in os
.walk(os
.path
.join(path
, "OUTPUT"), topdown
=True, followlinks
=False):
403 if os
.path
.splitext(INF
)[1] == '.inf':
404 for l_root
, l_dir
, l_file
in os
.walk(os
.path
.join(path
, "DEBUG"), topdown
=True,
407 if os
.path
.splitext(LST
)[1] == '.lst':
408 self
.lstinf
[os
.path
.join(l_root
, LST
)] = os
.path
.join(o_root
, INF
)
409 self
.usefuldir
.add(path
)
411 def get_root_dir(self
):
413 for root
,dir,file in os
.walk(self
.path
,topdown
=True,followlinks
=False):
415 updir
=root
.split("OUTPUT",1)[0]
416 rootdir
.append(updir
)
417 rootdir
=list(set(rootdir
))
425 package_re
=re
.compile(r
'Packages\.\w+]\n(.*)',re
.S
)
426 for i
in list(self
.lstinf
.values()):
427 with
open(i
,'r') as inf
:
429 section
=read
.split('[')
431 p
=package_re
.findall(j
)
433 package
[i
]=p
[0].rstrip()
436 def header(self
,struct
):
438 head_re
= re
.compile('typedef.*} %s;[\n]+(.*)(?:typedef|formset)'%struct
,re
.M|re
.S
)
439 head_re2
= re
.compile(r
'#line[\s\d]+"(\S+h)"')
440 for i
in list(self
.lstinf
.keys()):
441 with
open(i
,'r') as lst
:
443 h
= head_re
.findall(read
)
445 head
=head_re2
.findall(h
[0])
447 format
= head
[0].replace('\\\\','/').replace('\\','/')
448 name
=format
.split('/')[-1]
449 head
= self
.headerfileset
.get(name
)
451 head
= head
.replace('\\','/')
452 header
[struct
] = head
455 def headerfileset(self
):
457 for root
,dirs
,files
in os
.walk(self
.path
):
459 if os
.path
.basename(file) == 'deps.txt':
460 with
open(os
.path
.join(root
,file),"r") as fr
:
461 for line
in fr
.readlines():
462 headerset
[os
.path
.basename(line
).strip()] = line
.strip()
465 def makefile(self
,filename
):
466 re_format
= re
.compile(r
'DEBUG_DIR.*(?:\S+Pkg)\\(.*\\%s)'%filename
)
467 for i
in self
.usefuldir
:
468 with
open(os
.path
.join(i
,'Makefile'),'r') as make
:
470 dir = re_format
.findall(read
)
475 class mainprocess(object):
477 def __init__(self
,InputPath
,Config
,OutputPath
):
478 self
.init
= 0xFCD00000
479 self
.inputpath
= os
.path
.abspath(InputPath
)
480 self
.outputpath
= os
.path
.abspath(OutputPath
)
481 self
.LST
= PATH(self
.inputpath
)
482 self
.lst_dict
= self
.LST
.lst_inf()
484 self
.attribute_dict
= {'0x3': 'NV, BS', '0x7': 'NV, BS, RT'}
485 self
.guid
= GUID(self
.inputpath
)
489 conf
=Config(self
.Config
)
490 config_dict
=conf
.config_parser() #get {'0_0':[offset,name,guid,value,attribute]...,'1_0':....}
491 lst
=parser_lst(list(self
.lst_dict
.keys()))
492 efi_dict
=lst
.efivarstore_parser() #get {name:struct} form lst file
493 keys
=sorted(config_dict
.keys())
494 all_struct
=lst
.struct()
495 stru_lst
=lst
.struct_lst()
501 tmp
= self
.LST
.header(i
)
502 self
.header
.update(tmp
)
504 tmp_id
=[id_key
] #['0_0',[(struct,[name...]),(struct,[name...])]]
505 tmp_info
={} #{name:struct}
506 for section
in config_dict
[id_key
]:
507 c_offset
,c_name
,c_guid
,c_value
,c_attribute
,c_comment
= section
508 if c_name
in efi_dict
:
509 struct
= efi_dict
[c_name
]
510 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
])
511 if struct
in all_struct
:
512 lstfile
= stru_lst
[struct
]
513 struct_dict
=all_struct
[struct
]
515 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
]])
517 WARNING
.append("Warning: No <HeaderFiles> for struct %s"%struct
)
518 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
]])
519 header_list
.append(title2
)
520 elif struct
not in lst
._ignore
:
522 print("ERROR: Struct %s can't found in lst file" %struct
)
523 ERRORMSG
.append("ERROR: Struct %s can't found in lst file" %struct
)
524 if c_offset
in struct_dict
:
525 offset_name
=struct_dict
[c_offset
]
526 info
= "%s%s.%s|%s\n"%(PCD_NAME
,c_name
,offset_name
,c_value
)
527 blank_length
= Max_Pcd_Len
- len(info
)
528 if blank_length
<= 0:
529 info_comment
= "%s%s.%s|%s%s# %s\n"%(PCD_NAME
,c_name
,offset_name
,c_value
," ",c_comment
)
531 info_comment
= "%s%s.%s|%s%s# %s\n"%(PCD_NAME
,c_name
,offset_name
,c_value
,blank_length
*" ",c_comment
)
532 inf
= "%s%s\n"%(PCD_NAME
,c_name
)
534 tmp_info
[info_comment
]=title
536 print("ERROR: Can't find offset %s with struct name %s"%(c_offset
,struct
))
537 ERRORMSG
.append("ERROR: Can't find offset %s with name %s"%(c_offset
,struct
))
539 print("ERROR: Can't find name %s in lst file"%(c_name))
540 ERRORMSG
.append("ERROR: Can't find name %s in lst file"%(c_name))
541 tmp_id
.append(list(self
.reverse_dict(tmp_info
).items()))
542 id,tmp_title_list
,tmp_info_list
= self
.read_list(tmp_id
)
543 title_list
+=tmp_title_list
544 info_list
.append(tmp_info_list
)
545 inf_list
= self
.del_repeat(inf_list
)
546 header_list
= self
.plus(self
.del_repeat(header_list
))
547 title_all
=list(set(title_list
))
548 info_list
= self
.remove_bracket(self
.del_repeat(info_list
))
549 for i
in range(len(info_list
)-1,-1,-1):
550 if len(info_list
[i
]) == 0:
551 info_list
.remove(info_list
[i
])
552 for i
in (inf_list
, title_all
, header_list
):
554 return keys
,title_all
,info_list
,header_list
,inf_list
556 def correct_sort(self
, PcdString
):
557 # sort the Pcd list with two rules:
558 # First sort through Pcd name;
559 # Second if the Pcd exists several elements, sort them through index value.
560 if ("]|") in PcdString
:
561 Pcdname
= PcdString
.split("[")[0]
562 Pcdindex
= int(PcdString
.split("[")[1].split("]")[0])
564 Pcdname
= PcdString
.split("|")[0]
566 return Pcdname
, Pcdindex
568 def remove_bracket(self
,List
):
572 if (('L"' in j
) and ("[" in j
)) or (tmp
[1].split("#")[0].strip() == '{0x0, 0x0}'):
573 tmp
[0] = tmp
[0][:tmp
[0].index('[')]
574 List
[List
.index(i
)][i
.index(j
)] = "|".join(tmp
)
576 List
[List
.index(i
)][i
.index(j
)] = j
578 if type(i
) == type([0,0]):
579 i
.sort(key
= lambda x
:(self
.correct_sort(x
)[0], self
.correct_sort(x
)[1]))
585 if not os
.path
.isdir(self
.outputpath
):
586 os
.makedirs(self
.outputpath
)
587 decwrite
= write2file(os
.path
.join(self
.outputpath
,'StructurePcd.dec'))
588 dscwrite
= write2file(os
.path
.join(self
.outputpath
,'StructurePcd.dsc'))
589 infwrite
= write2file(os
.path
.join(self
.outputpath
, 'StructurePcd.inf'))
590 conf
= Config(self
.Config
)
591 ids
,title
,info
,header
,inf
=self
.main()
592 decwrite
.add2file(decstatement
)
593 decwrite
.add2file(header
)
594 infwrite
.add2file(infstatement
)
595 infwrite
.add2file(inf
)
596 dscwrite
.add2file(dscstatement
)
598 dscwrite
.add2file(conf
.eval_id(id))
600 dscwrite
.add2file(title
)
603 dscwrite
.add2file(info
)
606 dscwrite
.add2file(info
[0])
609 dscwrite
.add2file(info
[1])
611 def del_repeat(self
,List
):
612 if len(List
) == 1 or len(List
) == 0:
615 if type(List
[0]) != type('xxx'):
617 for i
in range(len(List
)):
619 alist
.append(List
[0])
624 alist
.append(self
.__del
(list(set(plist
)), List
[i
]))
627 return list(set(List
))
630 def __del(self
,list1
,list2
):
631 return list(set(list2
).difference(set(list1
)))
633 def reverse_dict(self
,dict):
635 for i
in list(dict.items()):
636 if i
[1] not in list(data
.keys()):
639 data
[i
[1]].append(i
[0])
642 def read_list(self
,list):
646 title_list
.append(i
[0])
649 return list[0],title_list
,info_list
654 if type(i
) != type([0]):
656 num
= "0x%01x" % self
.init
657 j
=i
.replace('0xFCD00000',num
.upper())
661 class write2file(object):
663 def __init__(self
,Output
):
666 if os
.path
.exists(self
.output
):
667 os
.remove(self
.output
)
669 def add2file(self
,content
):
671 with
open(self
.output
,'a+') as file:
672 file.write(self
.__gen
(content
))
674 def __gen(self
,content
):
675 if type(content
) == type(''):
677 elif type(content
) == type([0,0])or type(content
) == type((0,0)):
678 return self
.__readlist
(content
)
679 elif type(content
) == type({0:0}):
680 return self
.__readdict
(content
)
682 def __readlist(self
,list):
684 if type(i
) == type([0,0])or type(i
) == type((0,0)):
686 elif type(i
) == type('') :
690 def __readdict(self
,dict):
691 content
=list(dict.items())
692 return self
.__readlist
(content
)
695 return datetime
.datetime
.now()
697 def dtime(start
,end
,id=None):
700 print("%s time:%s" % (id,str(end
- start
)))
702 print("Total time:%s" %str
(end
-start
)[:-7])
707 parser
= argparse
.ArgumentParser(prog
= __prog__
,
708 description
= __description__
+ __copyright__
,
709 conflict_handler
= 'resolve')
710 parser
.add_argument('-v', '--version', action
= 'version',version
= __version__
, help="show program's version number and exit")
711 parser
.add_argument('-p', '--path', metavar
='PATH', dest
='path', help="platform build output directory")
712 parser
.add_argument('-c', '--config',metavar
='FILENAME', dest
='config', help="firmware configuration file")
713 parser
.add_argument('-o', '--outputdir', metavar
='PATH', dest
='output', help="output directoy")
714 options
= parser
.parse_args()
718 run
= mainprocess(options
.path
, options
.config
, options
.output
)
722 warning
= list(set(WARNING
))
726 ERROR
= list(set(ERRORMSG
))
727 with
open("ERROR.log", 'w+') as error
:
729 error
.write(i
+ '\n')
730 print("Some error find, error log in ERROR.log")
731 print('Finished, Output files in directory %s'%os.path
.abspath(options
.output
))
733 print('Error command, no output path, use -h for help')
735 print('Error command, no build path input, use -h for help')
737 print('Error command, no output file, use -h for help')
741 if __name__
== '__main__':