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