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 | '''
|
---|
13 | ConvertFceToStructurePcd
|
---|
14 | '''
|
---|
15 |
|
---|
16 | import re
|
---|
17 | import os
|
---|
18 | import datetime
|
---|
19 | import 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 |
|
---|
30 | dscstatement='''[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 |
|
---|
44 | decstatement = '''[Guids]
|
---|
45 | gStructPcdTokenSpaceGuid = {0x3f1406f4, 0x2b, 0x487a, {0x8b, 0x69, 0x74, 0x29, 0x1b, 0x36, 0x16, 0xf4}}
|
---|
46 |
|
---|
47 | [PcdsFixedAtBuild,PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx]
|
---|
48 | '''
|
---|
49 |
|
---|
50 | infstatement = '''[Pcd]
|
---|
51 | '''
|
---|
52 |
|
---|
53 | SECTION='PcdsDynamicHii'
|
---|
54 | PCD_NAME='gStructPcdTokenSpaceGuid.Pcd'
|
---|
55 | Max_Pcd_Len = 100
|
---|
56 |
|
---|
57 | WARNING=[]
|
---|
58 | ERRORMSG=[]
|
---|
59 |
|
---|
60 | class parser_lst(object):
|
---|
61 |
|
---|
62 | def __init__(self,filelist):
|
---|
63 | self._ignore=['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64']
|
---|
64 | self.file=filelist
|
---|
65 | self.text=self.megre_lst()[0]
|
---|
66 | self.content=self.megre_lst()[1]
|
---|
67 |
|
---|
68 | def megre_lst(self):
|
---|
69 | alltext=''
|
---|
70 | content={}
|
---|
71 | for file in self.file:
|
---|
72 | with open(file,'r') as f:
|
---|
73 | read =f.read()
|
---|
74 | alltext += read
|
---|
75 | content[file]=read
|
---|
76 | return alltext,content
|
---|
77 |
|
---|
78 | def struct_lst(self):#{struct:lst file}
|
---|
79 | structs_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])
|
---|
83 | if structs:
|
---|
84 | for j in structs:
|
---|
85 | if j not in self._ignore:
|
---|
86 | structs_file[j]=i
|
---|
87 | else:
|
---|
88 | print("%s"%structs)
|
---|
89 | return structs_file
|
---|
90 |
|
---|
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)
|
---|
100 | info={}
|
---|
101 | unparse=[]
|
---|
102 | if name:
|
---|
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)
|
---|
106 | name.reverse()
|
---|
107 | #name=list(set(name).difference(set(self._ignore)))
|
---|
108 | for struct in name:
|
---|
109 | s_re = re.compile(r'struct %s :(.*?)};'% struct, re.S)
|
---|
110 | content = s_re.search(self.text)
|
---|
111 | if content:
|
---|
112 | tmp_dict = {}
|
---|
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)
|
---|
118 | if offset and uint:
|
---|
119 | offset = offset[0]
|
---|
120 | uint = uint[0]
|
---|
121 | if t_name:
|
---|
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))
|
---|
125 | else:
|
---|
126 | if '[' in t_name:
|
---|
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)
|
---|
133 | bit = uint // 8
|
---|
134 | for i in range(1, pcdname_num):
|
---|
135 | offset += bit
|
---|
136 | tmp_name = pcdname2_re.findall(t_name)[0] + '[%s]' % i
|
---|
137 | tmp_dict[offset] = tmp_name
|
---|
138 | else:
|
---|
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]
|
---|
142 | line.append(struct)
|
---|
143 | unparse.append(line)
|
---|
144 | else:
|
---|
145 | if uint not in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:
|
---|
146 | line = [offset, t_name, 0, uint]
|
---|
147 | line.append(struct)
|
---|
148 | unparse.append(line)
|
---|
149 | else:
|
---|
150 | offset = int(offset,10)
|
---|
151 | tmp_dict[offset] = t_name
|
---|
152 | info[struct] = tmp_dict
|
---|
153 | if len(unparse) != 0:
|
---|
154 | for u in unparse:
|
---|
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()))
|
---|
158 | else:
|
---|
159 | print("ERROR: No struct name found in %s" % self.file)
|
---|
160 | ERRORMSG.append("ERROR: No struct name found in %s" % self.file)
|
---|
161 | return info
|
---|
162 |
|
---|
163 |
|
---|
164 | def nameISstruct(self,line,key_dict):
|
---|
165 | dict={}
|
---|
166 | dict2={}
|
---|
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)
|
---|
170 | if content:
|
---|
171 | s_size = size_re.findall(content.group())[0]
|
---|
172 | else:
|
---|
173 | s_size = '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)
|
---|
177 | if line[2] != 0:
|
---|
178 | for j in range(0, int(line[2], 10)):
|
---|
179 | for k in list(key_dict.keys()):
|
---|
180 | offset = size + k
|
---|
181 | name ='%s.%s' %((line[1]+'[%s]'%j),key_dict[k])
|
---|
182 | dict[offset] = name
|
---|
183 | size = int(s_size,16)+size
|
---|
184 | elif line[2] == 0:
|
---|
185 | for k in list(key_dict.keys()):
|
---|
186 | offset = size + k
|
---|
187 | name = '%s.%s' % (line[1], key_dict[k])
|
---|
188 | dict[offset] = name
|
---|
189 | dict2[line[4]] = dict
|
---|
190 | return dict2
|
---|
191 |
|
---|
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+)')
|
---|
196 | efivarstore_dict={}
|
---|
197 | efitxt = efivarstore_format.findall(self.text)
|
---|
198 | for i in efitxt:
|
---|
199 | struct = struct_re.findall(i.replace(' ',''))
|
---|
200 | if struct[0] in self._ignore:
|
---|
201 | continue
|
---|
202 | name = name_re.findall(i.replace(' ',''))
|
---|
203 | if struct and name:
|
---|
204 | efivarstore_dict[name[0]]=struct[0]
|
---|
205 | else:
|
---|
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
|
---|
209 |
|
---|
210 | class Config(object):
|
---|
211 |
|
---|
212 | def __init__(self,Config):
|
---|
213 | self.config=Config
|
---|
214 |
|
---|
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+')
|
---|
219 | info = []
|
---|
220 | info_dict={}
|
---|
221 | with open(self.config, 'r') as text:
|
---|
222 | read = text.read()
|
---|
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
|
---|
227 | str_id=''
|
---|
228 | ids = ids_re.findall(i.replace(' ',''))
|
---|
229 | for m in ids:
|
---|
230 | str_id +=m+'_'
|
---|
231 | str_id=str_id[:-1]
|
---|
232 | part.append(ids)
|
---|
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)
|
---|
236 | info.append(part)
|
---|
237 | else:
|
---|
238 | part = []
|
---|
239 | id=('0','0')
|
---|
240 | str_id='0_0'
|
---|
241 | part.append(id)
|
---|
242 | section = read.split('\nQ')
|
---|
243 | part +=self.section_parser(section)
|
---|
244 | info_dict[str_id] = self.section_parser(section)
|
---|
245 | info.append(part)
|
---|
246 | return info_dict
|
---|
247 |
|
---|
248 | def eval_id(self,id):
|
---|
249 | id = id.split("_")
|
---|
250 | default_id=id[0:len(id)//2]
|
---|
251 | platform_id=id[len(id)//2:]
|
---|
252 | text=''
|
---|
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]
|
---|
256 |
|
---|
257 | def id_name(self,ID, flag):
|
---|
258 | platform_dict = {'0': 'DEFAULT'}
|
---|
259 | default_dict = {'0': 'STANDARD', '1': 'MANUFACTURING'}
|
---|
260 | if flag == "PLATFORM":
|
---|
261 | try:
|
---|
262 | value = platform_dict[ID]
|
---|
263 | except KeyError:
|
---|
264 | value = 'SKUID%s' % ID
|
---|
265 | elif flag == 'DEFAULT':
|
---|
266 | try:
|
---|
267 | value = default_dict[ID]
|
---|
268 | except KeyError:
|
---|
269 | value = 'DEFAULTID%s' % ID
|
---|
270 | else:
|
---|
271 | value = None
|
---|
272 | return value
|
---|
273 |
|
---|
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'(//.*)')
|
---|
281 | part = []
|
---|
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()
|
---|
288 | comment = ""
|
---|
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':
|
---|
292 | each = '(R)'
|
---|
293 | else:
|
---|
294 | each = ""
|
---|
295 | comment += each
|
---|
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])
|
---|
315 | else:
|
---|
316 | text = offset, name[0], guid[0], value, attribute[0], comment
|
---|
317 | part_without_comment.append(text_without_comment)
|
---|
318 | part.append(text)
|
---|
319 | return(part)
|
---|
320 |
|
---|
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] == '""':
|
---|
326 | value = "{0x0, 0x0}"
|
---|
327 | else:
|
---|
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:]
|
---|
332 | tmp = []
|
---|
333 | line = ''
|
---|
334 | for i in list2:
|
---|
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))
|
---|
338 | else:
|
---|
339 | tmp.append('0x%s' % i)
|
---|
340 | for i in tmp:
|
---|
341 | line += '%s,' % i
|
---|
342 | value = '{%s}' % line[:-1]
|
---|
343 | else:
|
---|
344 | value = "0x%01x" % int(list1[-1], 16)
|
---|
345 | return value
|
---|
346 |
|
---|
347 |
|
---|
348 | #parser Guid file, get guid name form guid value
|
---|
349 | class GUID(object):
|
---|
350 |
|
---|
351 | def __init__(self,path):
|
---|
352 | self.path = path
|
---|
353 | self.guidfile = self.gfile()
|
---|
354 | self.guiddict = self.guid_dict()
|
---|
355 |
|
---|
356 | def gfile(self):
|
---|
357 | for root, dir, file in os.walk(self.path, topdown=True, followlinks=False):
|
---|
358 | if 'FV' in dir:
|
---|
359 | gfile = os.path.join(root,'Fv','Guid.xref')
|
---|
360 | if os.path.isfile(gfile):
|
---|
361 | return gfile
|
---|
362 | else:
|
---|
363 | print("ERROR: Guid.xref file not found")
|
---|
364 | ERRORMSG.append("ERROR: Guid.xref file not found")
|
---|
365 | exit()
|
---|
366 |
|
---|
367 | def guid_dict(self):
|
---|
368 | guiddict={}
|
---|
369 | with open(self.guidfile,'r') as file:
|
---|
370 | lines = file.readlines()
|
---|
371 | guidinfo=lines
|
---|
372 | for line in guidinfo:
|
---|
373 | list=line.strip().split(' ')
|
---|
374 | if list:
|
---|
375 | if len(list)>1:
|
---|
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))
|
---|
380 | else:
|
---|
381 | print("ERROR: No data in %s" %self.guidfile)
|
---|
382 | ERRORMSG.append("ERROR: No data in %s" %self.guidfile)
|
---|
383 | return guiddict
|
---|
384 |
|
---|
385 | def guid_parser(self,guid):
|
---|
386 | if guid.upper() in self.guiddict:
|
---|
387 | return self.guiddict[guid.upper()]
|
---|
388 | else:
|
---|
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))
|
---|
391 | return guid
|
---|
392 |
|
---|
393 | class PATH(object):
|
---|
394 |
|
---|
395 | def __init__(self,path):
|
---|
396 | self.path=path
|
---|
397 | self.rootdir=self.get_root_dir()
|
---|
398 | self.usefuldir=set()
|
---|
399 | self.lstinf = {}
|
---|
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):
|
---|
402 | for INF in o_file:
|
---|
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,
|
---|
405 | followlinks=False):
|
---|
406 | for LST in l_file:
|
---|
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)
|
---|
410 |
|
---|
411 | def get_root_dir(self):
|
---|
412 | rootdir=[]
|
---|
413 | for root,dir,file in os.walk(self.path,topdown=True,followlinks=False):
|
---|
414 | if "OUTPUT" in root:
|
---|
415 | updir=root.split("OUTPUT",1)[0]
|
---|
416 | rootdir.append(updir)
|
---|
417 | rootdir=list(set(rootdir))
|
---|
418 | return rootdir
|
---|
419 |
|
---|
420 | def lst_inf(self):
|
---|
421 | return self.lstinf
|
---|
422 |
|
---|
423 | def package(self):
|
---|
424 | package={}
|
---|
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:
|
---|
428 | read=inf.read()
|
---|
429 | section=read.split('[')
|
---|
430 | for j in section:
|
---|
431 | p=package_re.findall(j)
|
---|
432 | if p:
|
---|
433 | package[i]=p[0].rstrip()
|
---|
434 | return package
|
---|
435 |
|
---|
436 | def header(self,struct):
|
---|
437 | header={}
|
---|
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:
|
---|
442 | read = lst.read()
|
---|
443 | h = head_re.findall(read)
|
---|
444 | if h:
|
---|
445 | head=head_re2.findall(h[0])
|
---|
446 | if head:
|
---|
447 | format = head[0].replace('\\\\','/').replace('\\','/')
|
---|
448 | name =format.split('/')[-1]
|
---|
449 | head = self.headerfileset.get(name)
|
---|
450 | if head:
|
---|
451 | head = head.replace('\\','/')
|
---|
452 | header[struct] = head
|
---|
453 | return header
|
---|
454 | @property
|
---|
455 | def headerfileset(self):
|
---|
456 | headerset = dict()
|
---|
457 | for root,dirs,files in os.walk(self.path):
|
---|
458 | for file in files:
|
---|
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()
|
---|
463 | return headerset
|
---|
464 |
|
---|
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:
|
---|
469 | read = make.read()
|
---|
470 | dir = re_format.findall(read)
|
---|
471 | if dir:
|
---|
472 | return dir[0]
|
---|
473 | return None
|
---|
474 |
|
---|
475 | class mainprocess(object):
|
---|
476 |
|
---|
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()
|
---|
483 | self.Config = Config
|
---|
484 | self.attribute_dict = {'0x3': 'NV, BS', '0x7': 'NV, BS, RT'}
|
---|
485 | self.guid = GUID(self.inputpath)
|
---|
486 | self.header={}
|
---|
487 |
|
---|
488 | def main(self):
|
---|
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()
|
---|
496 | title_list=[]
|
---|
497 | info_list=[]
|
---|
498 | header_list=[]
|
---|
499 | inf_list =[]
|
---|
500 | for i in stru_lst:
|
---|
501 | tmp = self.LST.header(i)
|
---|
502 | self.header.update(tmp)
|
---|
503 | for id_key in keys:
|
---|
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]
|
---|
514 | try:
|
---|
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]])
|
---|
516 | except KeyError:
|
---|
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:
|
---|
521 | struct_dict ={}
|
---|
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)
|
---|
530 | else:
|
---|
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)
|
---|
533 | inf_list.append(inf)
|
---|
534 | tmp_info[info_comment]=title
|
---|
535 | else:
|
---|
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))
|
---|
538 | else:
|
---|
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):
|
---|
553 | i.sort()
|
---|
554 | return keys,title_all,info_list,header_list,inf_list
|
---|
555 |
|
---|
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])
|
---|
563 | else:
|
---|
564 | Pcdname = PcdString.split("|")[0]
|
---|
565 | Pcdindex = 0
|
---|
566 | return Pcdname, Pcdindex
|
---|
567 |
|
---|
568 | def remove_bracket(self,List):
|
---|
569 | for i in List:
|
---|
570 | for j in i:
|
---|
571 | tmp = j.split("|")
|
---|
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)
|
---|
575 | else:
|
---|
576 | List[List.index(i)][i.index(j)] = j
|
---|
577 | for i in List:
|
---|
578 | if type(i) == type([0,0]):
|
---|
579 | i.sort(key = lambda x:(self.correct_sort(x)[0], self.correct_sort(x)[1]))
|
---|
580 | return List
|
---|
581 |
|
---|
582 | def write_all(self):
|
---|
583 | title_flag=1
|
---|
584 | info_flag=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)
|
---|
597 | for id in ids:
|
---|
598 | dscwrite.add2file(conf.eval_id(id))
|
---|
599 | if title_flag:
|
---|
600 | dscwrite.add2file(title)
|
---|
601 | title_flag=0
|
---|
602 | if len(info) == 1:
|
---|
603 | dscwrite.add2file(info)
|
---|
604 | elif len(info) == 2:
|
---|
605 | if info_flag:
|
---|
606 | dscwrite.add2file(info[0])
|
---|
607 | info_flag =0
|
---|
608 | else:
|
---|
609 | dscwrite.add2file(info[1])
|
---|
610 |
|
---|
611 | def del_repeat(self,List):
|
---|
612 | if len(List) == 1 or len(List) == 0:
|
---|
613 | return List
|
---|
614 | else:
|
---|
615 | if type(List[0]) != type('xxx'):
|
---|
616 | alist=[]
|
---|
617 | for i in range(len(List)):
|
---|
618 | if i == 0:
|
---|
619 | alist.append(List[0])
|
---|
620 | else:
|
---|
621 | plist = []
|
---|
622 | for j in range(i):
|
---|
623 | plist += List[j]
|
---|
624 | alist.append(self.__del(list(set(plist)), List[i]))
|
---|
625 | return alist
|
---|
626 | else:
|
---|
627 | return list(set(List))
|
---|
628 |
|
---|
629 |
|
---|
630 | def __del(self,list1,list2):
|
---|
631 | return list(set(list2).difference(set(list1)))
|
---|
632 |
|
---|
633 | def reverse_dict(self,dict):
|
---|
634 | data={}
|
---|
635 | for i in list(dict.items()):
|
---|
636 | if i[1] not in list(data.keys()):
|
---|
637 | data[i[1]]=[i[0]]
|
---|
638 | else:
|
---|
639 | data[i[1]].append(i[0])
|
---|
640 | return data
|
---|
641 |
|
---|
642 | def read_list(self,list):
|
---|
643 | title_list=[]
|
---|
644 | info_list=[]
|
---|
645 | for i in list[1]:
|
---|
646 | title_list.append(i[0])
|
---|
647 | for j in i[1]:
|
---|
648 | info_list.append(j)
|
---|
649 | return list[0],title_list,info_list
|
---|
650 |
|
---|
651 | def plus(self,list):
|
---|
652 | nums=[]
|
---|
653 | for i in list:
|
---|
654 | if type(i) != type([0]):
|
---|
655 | self.init += 1
|
---|
656 | num = "0x%01x" % self.init
|
---|
657 | j=i.replace('0xFCD00000',num.upper())
|
---|
658 | nums.append(j)
|
---|
659 | return nums
|
---|
660 |
|
---|
661 | class write2file(object):
|
---|
662 |
|
---|
663 | def __init__(self,Output):
|
---|
664 | self.output=Output
|
---|
665 | self.text=''
|
---|
666 | if os.path.exists(self.output):
|
---|
667 | os.remove(self.output)
|
---|
668 |
|
---|
669 | def add2file(self,content):
|
---|
670 | self.text = ''
|
---|
671 | with open(self.output,'a+') as file:
|
---|
672 | file.write(self.__gen(content))
|
---|
673 |
|
---|
674 | def __gen(self,content):
|
---|
675 | if type(content) == type(''):
|
---|
676 | return content
|
---|
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)
|
---|
681 |
|
---|
682 | def __readlist(self,list):
|
---|
683 | for i in list:
|
---|
684 | if type(i) == type([0,0])or type(i) == type((0,0)):
|
---|
685 | self.__readlist(i)
|
---|
686 | elif type(i) == type('') :
|
---|
687 | self.text +=i
|
---|
688 | return self.text
|
---|
689 |
|
---|
690 | def __readdict(self,dict):
|
---|
691 | content=list(dict.items())
|
---|
692 | return self.__readlist(content)
|
---|
693 |
|
---|
694 | def stamp():
|
---|
695 | return datetime.datetime.now()
|
---|
696 |
|
---|
697 | def dtime(start,end,id=None):
|
---|
698 | if id:
|
---|
699 | pass
|
---|
700 | print("%s time:%s" % (id,str(end - start)))
|
---|
701 | else:
|
---|
702 | print("Total time:%s" %str(end-start)[:-7])
|
---|
703 |
|
---|
704 |
|
---|
705 | def main():
|
---|
706 | start = stamp()
|
---|
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()
|
---|
715 | if options.config:
|
---|
716 | if options.path:
|
---|
717 | if options.output:
|
---|
718 | run = mainprocess(options.path, options.config, options.output)
|
---|
719 | print("Running...")
|
---|
720 | run.write_all()
|
---|
721 | if WARNING:
|
---|
722 | warning = list(set(WARNING))
|
---|
723 | for j in warning:
|
---|
724 | print(j)
|
---|
725 | if ERRORMSG:
|
---|
726 | ERROR = list(set(ERRORMSG))
|
---|
727 | with open("ERROR.log", 'w+') as error:
|
---|
728 | for i in 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))
|
---|
732 | else:
|
---|
733 | print('Error command, no output path, use -h for help')
|
---|
734 | else:
|
---|
735 | print('Error command, no build path input, use -h for help')
|
---|
736 | else:
|
---|
737 | print('Error command, no output file, use -h for help')
|
---|
738 | end = stamp()
|
---|
739 | dtime(start, end)
|
---|
740 |
|
---|
741 | if __name__ == '__main__':
|
---|
742 | main()
|
---|