1 | #!/usr/bin/env python
|
---|
2 | ## @ FspDscBsf2Yaml.py
|
---|
3 | # This script convert DSC or BSF format file into YAML format
|
---|
4 | #
|
---|
5 | # Copyright(c) 2021, Intel Corporation. All rights reserved.<BR>
|
---|
6 | # SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 | #
|
---|
8 | ##
|
---|
9 |
|
---|
10 | import os
|
---|
11 | import re
|
---|
12 | import sys
|
---|
13 |
|
---|
14 | from collections import OrderedDict
|
---|
15 | from datetime import date
|
---|
16 |
|
---|
17 | from FspGenCfgData import CFspBsf2Dsc, CGenCfgData
|
---|
18 |
|
---|
19 | __copyright_tmp__ = """## @file
|
---|
20 | #
|
---|
21 | # Slim Bootloader CFGDATA %s File.
|
---|
22 | #
|
---|
23 | # Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
|
---|
24 | # SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
25 | #
|
---|
26 | ##
|
---|
27 | """
|
---|
28 |
|
---|
29 |
|
---|
30 | class CFspDsc2Yaml():
|
---|
31 |
|
---|
32 | def __init__(self):
|
---|
33 | self._Hdr_key_list = ['EMBED', 'STRUCT']
|
---|
34 | self._Bsf_key_list = ['NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES',
|
---|
35 | 'OPTION', 'CONDITION', 'ORDER', 'MARKER',
|
---|
36 | 'SUBT', 'FIELD', 'FIND']
|
---|
37 | self.gen_cfg_data = None
|
---|
38 | self.cfg_reg_exp = re.compile(
|
---|
39 | "^([_a-zA-Z0-9$\\(\\)]+)\\s*\\|\\s*(0x[0-9A-F]+|\\*)"
|
---|
40 | "\\s*\\|\\s*(\\d+|0x[0-9a-fA-F]+)\\s*\\|\\s*(.+)")
|
---|
41 | self.bsf_reg_exp = re.compile("(%s):{(.+?)}(?:$|\\s+)"
|
---|
42 | % '|'.join(self._Bsf_key_list))
|
---|
43 | self.hdr_reg_exp = re.compile("(%s):{(.+?)}"
|
---|
44 | % '|'.join(self._Hdr_key_list))
|
---|
45 | self.prefix = ''
|
---|
46 | self.unused_idx = 0
|
---|
47 | self.offset = 0
|
---|
48 | self.base_offset = 0
|
---|
49 |
|
---|
50 | def load_config_data_from_dsc(self, file_name):
|
---|
51 | """
|
---|
52 | Load and parse a DSC CFGDATA file.
|
---|
53 | """
|
---|
54 | gen_cfg_data = CGenCfgData('FSP')
|
---|
55 | if file_name.endswith('.dsc'):
|
---|
56 | if gen_cfg_data.ParseDscFile(file_name) != 0:
|
---|
57 | raise Exception('DSC file parsing error !')
|
---|
58 | if gen_cfg_data.CreateVarDict() != 0:
|
---|
59 | raise Exception('DSC variable creation error !')
|
---|
60 | else:
|
---|
61 | raise Exception('Unsupported file "%s" !' % file_name)
|
---|
62 | gen_cfg_data.UpdateDefaultValue()
|
---|
63 | self.gen_cfg_data = gen_cfg_data
|
---|
64 |
|
---|
65 | def print_dsc_line(self):
|
---|
66 | """
|
---|
67 | Debug function to print all DSC lines.
|
---|
68 | """
|
---|
69 | for line in self.gen_cfg_data._DscLines:
|
---|
70 | print(line)
|
---|
71 |
|
---|
72 | def format_value(self, field, text, indent=''):
|
---|
73 | """
|
---|
74 | Format a CFGDATA item into YAML format.
|
---|
75 | """
|
---|
76 | if (not text.startswith('!expand')) and (': ' in text):
|
---|
77 | tgt = ':' if field == 'option' else '- '
|
---|
78 | text = text.replace(': ', tgt)
|
---|
79 | lines = text.splitlines()
|
---|
80 | if len(lines) == 1 and field != 'help':
|
---|
81 | return text
|
---|
82 | else:
|
---|
83 | return '>\n ' + '\n '.join(
|
---|
84 | [indent + i.lstrip() for i in lines])
|
---|
85 |
|
---|
86 | def reformat_pages(self, val):
|
---|
87 | # Convert XXX:YYY into XXX::YYY format for page definition
|
---|
88 | parts = val.split(',')
|
---|
89 | if len(parts) <= 1:
|
---|
90 | return val
|
---|
91 |
|
---|
92 | new_val = []
|
---|
93 | for each in parts:
|
---|
94 | nodes = each.split(':')
|
---|
95 | if len(nodes) == 2:
|
---|
96 | each = '%s::%s' % (nodes[0], nodes[1])
|
---|
97 | new_val.append(each)
|
---|
98 | ret = ','.join(new_val)
|
---|
99 | return ret
|
---|
100 |
|
---|
101 | def reformat_struct_value(self, utype, val):
|
---|
102 | # Convert DSC UINT16/32/64 array into new format by
|
---|
103 | # adding prefix 0:0[WDQ] to provide hint to the array format
|
---|
104 | if utype in ['UINT16', 'UINT32', 'UINT64']:
|
---|
105 | if val and val[0] == '{' and val[-1] == '}':
|
---|
106 | if utype == 'UINT16':
|
---|
107 | unit = 'W'
|
---|
108 | elif utype == 'UINT32':
|
---|
109 | unit = 'D'
|
---|
110 | else:
|
---|
111 | unit = 'Q'
|
---|
112 | val = '{ 0:0%s, %s }' % (unit, val[1:-1])
|
---|
113 | return val
|
---|
114 |
|
---|
115 | def process_config(self, cfg):
|
---|
116 | if 'page' in cfg:
|
---|
117 | cfg['page'] = self.reformat_pages(cfg['page'])
|
---|
118 |
|
---|
119 | if 'struct' in cfg:
|
---|
120 | cfg['value'] = self.reformat_struct_value(
|
---|
121 | cfg['struct'], cfg['value'])
|
---|
122 |
|
---|
123 | def parse_dsc_line(self, dsc_line, config_dict, init_dict, include):
|
---|
124 | """
|
---|
125 | Parse a line in DSC and update the config dictionary accordingly.
|
---|
126 | """
|
---|
127 | init_dict.clear()
|
---|
128 | match = re.match('g(CfgData|\\w+FspPkgTokenSpaceGuid)\\.(.+)',
|
---|
129 | dsc_line)
|
---|
130 | if match:
|
---|
131 | match = self.cfg_reg_exp.match(match.group(2))
|
---|
132 | if not match:
|
---|
133 | return False
|
---|
134 | config_dict['cname'] = self.prefix + match.group(1)
|
---|
135 | value = match.group(4).strip()
|
---|
136 | length = match.group(3).strip()
|
---|
137 | config_dict['length'] = length
|
---|
138 | config_dict['value'] = value
|
---|
139 | if match.group(2) == '*':
|
---|
140 | self.offset += int(length, 0)
|
---|
141 | else:
|
---|
142 | org_offset = int(match.group(2), 0)
|
---|
143 | if org_offset == 0:
|
---|
144 | self.base_offset = self.offset
|
---|
145 | offset = org_offset + self.base_offset
|
---|
146 | if self.offset != offset:
|
---|
147 | if offset > self.offset:
|
---|
148 | init_dict['padding'] = offset - self.offset
|
---|
149 | self.offset = offset + int(length, 0)
|
---|
150 | return True
|
---|
151 |
|
---|
152 | match = re.match("^\\s*#\\s+!([<>])\\s+include\\s+(.+)", dsc_line)
|
---|
153 | if match and len(config_dict) == 0:
|
---|
154 | # !include should not be inside a config field
|
---|
155 | # if so, do not convert include into YAML
|
---|
156 | init_dict = dict(config_dict)
|
---|
157 | config_dict.clear()
|
---|
158 | config_dict['cname'] = '$ACTION'
|
---|
159 | if match.group(1) == '<':
|
---|
160 | config_dict['include'] = match.group(2)
|
---|
161 | else:
|
---|
162 | config_dict['include'] = ''
|
---|
163 | return True
|
---|
164 |
|
---|
165 | match = re.match("^\\s*#\\s+(!BSF|!HDR)\\s+(.+)", dsc_line)
|
---|
166 | if not match:
|
---|
167 | return False
|
---|
168 |
|
---|
169 | remaining = match.group(2)
|
---|
170 | if match.group(1) == '!BSF':
|
---|
171 | result = self.bsf_reg_exp.findall(remaining)
|
---|
172 | if not result:
|
---|
173 | return False
|
---|
174 |
|
---|
175 | for each in result:
|
---|
176 | key = each[0].lower()
|
---|
177 | val = each[1]
|
---|
178 | if key == 'field':
|
---|
179 | name = each[1]
|
---|
180 | if ':' not in name:
|
---|
181 | raise Exception('Incorrect bit field format !')
|
---|
182 | parts = name.split(':')
|
---|
183 | config_dict['length'] = parts[1]
|
---|
184 | config_dict['cname'] = '@' + parts[0]
|
---|
185 | return True
|
---|
186 | elif key in ['pages', 'page', 'find']:
|
---|
187 | init_dict = dict(config_dict)
|
---|
188 | config_dict.clear()
|
---|
189 | config_dict['cname'] = '$ACTION'
|
---|
190 | if key == 'find':
|
---|
191 | config_dict['find'] = val
|
---|
192 | else:
|
---|
193 | config_dict['page'] = val
|
---|
194 | return True
|
---|
195 | elif key == 'subt':
|
---|
196 | config_dict.clear()
|
---|
197 | parts = each[1].split(':')
|
---|
198 | tmp_name = parts[0][:-5]
|
---|
199 | if tmp_name == 'CFGHDR':
|
---|
200 | cfg_tag = '_$FFF_'
|
---|
201 | sval = '!expand { %s_TMPL : [ ' % \
|
---|
202 | tmp_name + '%s, %s, ' % (parts[1], cfg_tag) + \
|
---|
203 | ', '.join(parts[2:]) + ' ] }'
|
---|
204 | else:
|
---|
205 | sval = '!expand { %s_TMPL : [ ' % \
|
---|
206 | tmp_name + ', '.join(parts[1:]) + ' ] }'
|
---|
207 | config_dict.clear()
|
---|
208 | config_dict['cname'] = tmp_name
|
---|
209 | config_dict['expand'] = sval
|
---|
210 | return True
|
---|
211 | else:
|
---|
212 | if key in ['name', 'help', 'option'] and \
|
---|
213 | val.startswith('+'):
|
---|
214 | val = config_dict[key] + '\n' + val[1:]
|
---|
215 | if val.strip() == '':
|
---|
216 | val = "''"
|
---|
217 | config_dict[key] = val
|
---|
218 |
|
---|
219 | else:
|
---|
220 | match = self.hdr_reg_exp.match(remaining)
|
---|
221 | if not match:
|
---|
222 | return False
|
---|
223 | key = match.group(1)
|
---|
224 | remaining = match.group(2)
|
---|
225 | if key == 'EMBED':
|
---|
226 | parts = remaining.split(':')
|
---|
227 | names = parts[0].split(',')
|
---|
228 | if parts[-1] == 'END':
|
---|
229 | prefix = '>'
|
---|
230 | else:
|
---|
231 | prefix = '<'
|
---|
232 | skip = False
|
---|
233 | if parts[1].startswith('TAG_'):
|
---|
234 | tag_txt = '%s:%s' % (names[0], parts[1])
|
---|
235 | else:
|
---|
236 | tag_txt = names[0]
|
---|
237 | if parts[2] in ['START', 'END']:
|
---|
238 | if names[0] == 'PCIE_RP_PIN_CTRL[]':
|
---|
239 | skip = True
|
---|
240 | else:
|
---|
241 | tag_txt = '%s:%s' % (names[0], parts[1])
|
---|
242 | if not skip:
|
---|
243 | config_dict.clear()
|
---|
244 | config_dict['cname'] = prefix + tag_txt
|
---|
245 | return True
|
---|
246 |
|
---|
247 | if key == 'STRUCT':
|
---|
248 | text = remaining.strip()
|
---|
249 | config_dict[key.lower()] = text
|
---|
250 |
|
---|
251 | return False
|
---|
252 |
|
---|
253 | def process_template_lines(self, lines):
|
---|
254 | """
|
---|
255 | Process a line in DSC template section.
|
---|
256 | """
|
---|
257 | template_name = ''
|
---|
258 | bsf_temp_dict = OrderedDict()
|
---|
259 | temp_file_dict = OrderedDict()
|
---|
260 | include_file = ['.']
|
---|
261 |
|
---|
262 | for line in lines:
|
---|
263 | match = re.match("^\\s*#\\s+!([<>])\\s+include\\s+(.+)", line)
|
---|
264 | if match:
|
---|
265 | if match.group(1) == '<':
|
---|
266 | include_file.append(match.group(2))
|
---|
267 | else:
|
---|
268 | include_file.pop()
|
---|
269 |
|
---|
270 | match = re.match(
|
---|
271 | "^\\s*#\\s+(!BSF)\\s+DEFT:{(.+?):(START|END)}", line)
|
---|
272 | if match:
|
---|
273 | if match.group(3) == 'START' and not template_name:
|
---|
274 | template_name = match.group(2).strip()
|
---|
275 | temp_file_dict[template_name] = list(include_file)
|
---|
276 | bsf_temp_dict[template_name] = []
|
---|
277 | if match.group(3) == 'END' and \
|
---|
278 | (template_name == match.group(2).strip()) and \
|
---|
279 | template_name:
|
---|
280 | template_name = ''
|
---|
281 | else:
|
---|
282 | if template_name:
|
---|
283 | bsf_temp_dict[template_name].append(line)
|
---|
284 | return bsf_temp_dict, temp_file_dict
|
---|
285 |
|
---|
286 | def process_option_lines(self, lines):
|
---|
287 | """
|
---|
288 | Process a line in DSC config section.
|
---|
289 | """
|
---|
290 | cfgs = []
|
---|
291 | struct_end = False
|
---|
292 | config_dict = dict()
|
---|
293 | init_dict = dict()
|
---|
294 | include = ['']
|
---|
295 | for line in lines:
|
---|
296 | ret = self.parse_dsc_line(line, config_dict, init_dict, include)
|
---|
297 | if ret:
|
---|
298 | if 'padding' in init_dict:
|
---|
299 | num = init_dict['padding']
|
---|
300 | init_dict.clear()
|
---|
301 | padding_dict = {}
|
---|
302 | cfgs.append(padding_dict)
|
---|
303 | padding_dict['cname'] = 'UnusedUpdSpace%d' % \
|
---|
304 | self.unused_idx
|
---|
305 | padding_dict['length'] = '0x%x' % num
|
---|
306 | padding_dict['value'] = '{ 0 }'
|
---|
307 | self.unused_idx += 1
|
---|
308 |
|
---|
309 | if cfgs and cfgs[-1]['cname'][0] != '@' and \
|
---|
310 | config_dict['cname'][0] == '@':
|
---|
311 | # it is a bit field, mark the previous one as virtual
|
---|
312 | cname = cfgs[-1]['cname']
|
---|
313 | new_cfg = dict(cfgs[-1])
|
---|
314 | new_cfg['cname'] = '@$STRUCT'
|
---|
315 | cfgs[-1].clear()
|
---|
316 | cfgs[-1]['cname'] = cname
|
---|
317 | cfgs.append(new_cfg)
|
---|
318 |
|
---|
319 | if cfgs and cfgs[-1]['cname'] == 'CFGHDR' and \
|
---|
320 | config_dict['cname'][0] == '<':
|
---|
321 | # swap CfgHeader and the CFG_DATA order
|
---|
322 | if ':' in config_dict['cname']:
|
---|
323 | # replace the real TAG for CFG_DATA
|
---|
324 | cfgs[-1]['expand'] = cfgs[-1]['expand'].replace(
|
---|
325 | '_$FFF_', '0x%s' %
|
---|
326 | config_dict['cname'].split(':')[1][4:])
|
---|
327 | cfgs.insert(-1, config_dict)
|
---|
328 | else:
|
---|
329 | self.process_config(config_dict)
|
---|
330 | if struct_end:
|
---|
331 | struct_end = False
|
---|
332 | cfgs.insert(-1, config_dict)
|
---|
333 | else:
|
---|
334 | cfgs.append(config_dict)
|
---|
335 | if config_dict['cname'][0] == '>':
|
---|
336 | struct_end = True
|
---|
337 |
|
---|
338 | config_dict = dict(init_dict)
|
---|
339 | return cfgs
|
---|
340 |
|
---|
341 | def variable_fixup(self, each):
|
---|
342 | """
|
---|
343 | Fix up some variable definitions for SBL.
|
---|
344 | """
|
---|
345 | key = each
|
---|
346 | val = self.gen_cfg_data._MacroDict[each]
|
---|
347 | return key, val
|
---|
348 |
|
---|
349 | def template_fixup(self, tmp_name, tmp_list):
|
---|
350 | """
|
---|
351 | Fix up some special config templates for SBL
|
---|
352 | """
|
---|
353 | return
|
---|
354 |
|
---|
355 | def config_fixup(self, cfg_list):
|
---|
356 | """
|
---|
357 | Fix up some special config items for SBL.
|
---|
358 | """
|
---|
359 |
|
---|
360 | # Insert FSPT_UPD/FSPM_UPD/FSPS_UPD tag so as to create C strcture
|
---|
361 | idxs = []
|
---|
362 | for idx, cfg in enumerate(cfg_list):
|
---|
363 | if cfg['cname'].startswith('<FSP_UPD_HEADER'):
|
---|
364 | idxs.append(idx)
|
---|
365 |
|
---|
366 | if len(idxs) != 3:
|
---|
367 | return
|
---|
368 |
|
---|
369 | # Handle insert backwards so that the index does not change in the loop
|
---|
370 | fsp_comp = 'SMT'
|
---|
371 | idx_comp = 0
|
---|
372 | for idx in idxs[::-1]:
|
---|
373 | # Add current FSP?_UPD start tag
|
---|
374 | cfgfig_dict = {}
|
---|
375 | cfgfig_dict['cname'] = '<FSP%s_UPD' % fsp_comp[idx_comp]
|
---|
376 | cfg_list.insert(idx, cfgfig_dict)
|
---|
377 | if idx_comp < 2:
|
---|
378 | # Add previous FSP?_UPD end tag
|
---|
379 | cfgfig_dict = {}
|
---|
380 | cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[idx_comp + 1]
|
---|
381 | cfg_list.insert(idx, cfgfig_dict)
|
---|
382 | idx_comp += 1
|
---|
383 |
|
---|
384 | # Add final FSPS_UPD end tag
|
---|
385 | cfgfig_dict = {}
|
---|
386 | cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[0]
|
---|
387 | cfg_list.append(cfgfig_dict)
|
---|
388 |
|
---|
389 | return
|
---|
390 |
|
---|
391 | def get_section_range(self, section_name):
|
---|
392 | """
|
---|
393 | Extract line number range from config file for a given section name.
|
---|
394 | """
|
---|
395 | start = -1
|
---|
396 | end = -1
|
---|
397 | for idx, line in enumerate(self.gen_cfg_data._DscLines):
|
---|
398 | if start < 0 and line.startswith('[%s]' % section_name):
|
---|
399 | start = idx
|
---|
400 | elif start >= 0 and line.startswith('['):
|
---|
401 | end = idx
|
---|
402 | break
|
---|
403 | if start == -1:
|
---|
404 | start = 0
|
---|
405 | if end == -1:
|
---|
406 | end = len(self.gen_cfg_data._DscLines)
|
---|
407 | return start, end
|
---|
408 |
|
---|
409 | def normalize_file_name(self, file, is_temp=False):
|
---|
410 | """
|
---|
411 | Normalize file name convention so that it is consistent.
|
---|
412 | """
|
---|
413 | if file.endswith('.dsc'):
|
---|
414 | file = file[:-4] + '.yaml'
|
---|
415 | dir_name = os.path.dirname(file)
|
---|
416 | base_name = os.path.basename(file)
|
---|
417 | if is_temp:
|
---|
418 | if 'Template_' not in file:
|
---|
419 | base_name = base_name.replace('Template', 'Template_')
|
---|
420 | else:
|
---|
421 | if 'CfgData_' not in file:
|
---|
422 | base_name = base_name.replace('CfgData', 'CfgData_')
|
---|
423 | if dir_name:
|
---|
424 | path = dir_name + '/' + base_name
|
---|
425 | else:
|
---|
426 | path = base_name
|
---|
427 | return path
|
---|
428 |
|
---|
429 | def output_variable(self):
|
---|
430 | """
|
---|
431 | Output variable block into a line list.
|
---|
432 | """
|
---|
433 | lines = []
|
---|
434 | for each in self.gen_cfg_data._MacroDict:
|
---|
435 | key, value = self.variable_fixup(each)
|
---|
436 | lines.append('%-30s : %s' % (key, value))
|
---|
437 | return lines
|
---|
438 |
|
---|
439 | def output_template(self):
|
---|
440 | """
|
---|
441 | Output template block into a line list.
|
---|
442 | """
|
---|
443 | self.offset = 0
|
---|
444 | self.base_offset = 0
|
---|
445 | start, end = self.get_section_range('PcdsDynamicVpd.Tmp')
|
---|
446 | bsf_temp_dict, temp_file_dict = self.process_template_lines(
|
---|
447 | self.gen_cfg_data._DscLines[start:end])
|
---|
448 | template_dict = dict()
|
---|
449 | lines = []
|
---|
450 | file_lines = {}
|
---|
451 | last_file = '.'
|
---|
452 | file_lines[last_file] = []
|
---|
453 |
|
---|
454 | for tmp_name in temp_file_dict:
|
---|
455 | temp_file_dict[tmp_name][-1] = self.normalize_file_name(
|
---|
456 | temp_file_dict[tmp_name][-1], True)
|
---|
457 | if len(temp_file_dict[tmp_name]) > 1:
|
---|
458 | temp_file_dict[tmp_name][-2] = self.normalize_file_name(
|
---|
459 | temp_file_dict[tmp_name][-2], True)
|
---|
460 |
|
---|
461 | for tmp_name in bsf_temp_dict:
|
---|
462 | file = temp_file_dict[tmp_name][-1]
|
---|
463 | if last_file != file and len(temp_file_dict[tmp_name]) > 1:
|
---|
464 | inc_file = temp_file_dict[tmp_name][-2]
|
---|
465 | file_lines[inc_file].extend(
|
---|
466 | ['', '- !include %s' % temp_file_dict[tmp_name][-1], ''])
|
---|
467 | last_file = file
|
---|
468 | if file not in file_lines:
|
---|
469 | file_lines[file] = []
|
---|
470 | lines = file_lines[file]
|
---|
471 | text = bsf_temp_dict[tmp_name]
|
---|
472 | tmp_list = self.process_option_lines(text)
|
---|
473 | self.template_fixup(tmp_name, tmp_list)
|
---|
474 | template_dict[tmp_name] = tmp_list
|
---|
475 | lines.append('%s: >' % tmp_name)
|
---|
476 | lines.extend(self.output_dict(tmp_list, False)['.'])
|
---|
477 | lines.append('\n')
|
---|
478 | return file_lines
|
---|
479 |
|
---|
480 | def output_config(self):
|
---|
481 | """
|
---|
482 | Output config block into a line list.
|
---|
483 | """
|
---|
484 | self.offset = 0
|
---|
485 | self.base_offset = 0
|
---|
486 | start, end = self.get_section_range('PcdsDynamicVpd.Upd')
|
---|
487 | cfgs = self.process_option_lines(
|
---|
488 | self.gen_cfg_data._DscLines[start:end])
|
---|
489 | self.config_fixup(cfgs)
|
---|
490 | file_lines = self.output_dict(cfgs, True)
|
---|
491 | return file_lines
|
---|
492 |
|
---|
493 | def output_dict(self, cfgs, is_configs):
|
---|
494 | """
|
---|
495 | Output one config item into a line list.
|
---|
496 | """
|
---|
497 | file_lines = {}
|
---|
498 | level = 0
|
---|
499 | file = '.'
|
---|
500 | for each in cfgs:
|
---|
501 | if 'length' in each:
|
---|
502 | if not each['length'].endswith('b') and int(each['length'],
|
---|
503 | 0) == 0:
|
---|
504 | continue
|
---|
505 |
|
---|
506 | if 'include' in each:
|
---|
507 | if each['include']:
|
---|
508 | each['include'] = self.normalize_file_name(
|
---|
509 | each['include'])
|
---|
510 | file_lines[file].extend(
|
---|
511 | ['', '- !include %s' % each['include'], ''])
|
---|
512 | file = each['include']
|
---|
513 | else:
|
---|
514 | file = '.'
|
---|
515 | continue
|
---|
516 |
|
---|
517 | if file not in file_lines:
|
---|
518 | file_lines[file] = []
|
---|
519 |
|
---|
520 | lines = file_lines[file]
|
---|
521 | name = each['cname']
|
---|
522 |
|
---|
523 | prefix = name[0]
|
---|
524 | if prefix == '<':
|
---|
525 | level += 1
|
---|
526 |
|
---|
527 | padding = ' ' * level
|
---|
528 | if prefix not in '<>@':
|
---|
529 | padding += ' '
|
---|
530 | else:
|
---|
531 | name = name[1:]
|
---|
532 | if prefix == '@':
|
---|
533 | padding += ' '
|
---|
534 |
|
---|
535 | if ':' in name:
|
---|
536 | parts = name.split(':')
|
---|
537 | name = parts[0]
|
---|
538 |
|
---|
539 | padding = padding[2:] if is_configs else padding
|
---|
540 |
|
---|
541 | if prefix != '>':
|
---|
542 | if 'expand' in each:
|
---|
543 | lines.append('%s- %s' % (padding, each['expand']))
|
---|
544 | else:
|
---|
545 | lines.append('%s- %-12s :' % (padding, name))
|
---|
546 |
|
---|
547 | for field in each:
|
---|
548 | if field in ['cname', 'expand', 'include']:
|
---|
549 | continue
|
---|
550 | value_str = self.format_value(
|
---|
551 | field, each[field], padding + ' ' * 16)
|
---|
552 | full_line = ' %s %-12s : %s' % (padding, field, value_str)
|
---|
553 | lines.extend(full_line.splitlines())
|
---|
554 |
|
---|
555 | if prefix == '>':
|
---|
556 | level -= 1
|
---|
557 | if level == 0:
|
---|
558 | lines.append('')
|
---|
559 |
|
---|
560 | return file_lines
|
---|
561 |
|
---|
562 |
|
---|
563 | def bsf_to_dsc(bsf_file, dsc_file):
|
---|
564 | fsp_dsc = CFspBsf2Dsc(bsf_file)
|
---|
565 | dsc_lines = fsp_dsc.get_dsc_lines()
|
---|
566 | fd = open(dsc_file, 'w')
|
---|
567 | fd.write('\n'.join(dsc_lines))
|
---|
568 | fd.close()
|
---|
569 | return
|
---|
570 |
|
---|
571 |
|
---|
572 | def dsc_to_yaml(dsc_file, yaml_file):
|
---|
573 | dsc2yaml = CFspDsc2Yaml()
|
---|
574 | dsc2yaml.load_config_data_from_dsc(dsc_file)
|
---|
575 |
|
---|
576 | cfgs = {}
|
---|
577 | for cfg in ['Template', 'Option']:
|
---|
578 | if cfg == 'Template':
|
---|
579 | file_lines = dsc2yaml.output_template()
|
---|
580 | else:
|
---|
581 | file_lines = dsc2yaml.output_config()
|
---|
582 | for file in file_lines:
|
---|
583 | lines = file_lines[file]
|
---|
584 | if file == '.':
|
---|
585 | cfgs[cfg] = lines
|
---|
586 | else:
|
---|
587 | if ('/' in file or '\\' in file):
|
---|
588 | continue
|
---|
589 | file = os.path.basename(file)
|
---|
590 | out_dir = os.path.dirname(file)
|
---|
591 | fo = open(os.path.join(out_dir, file), 'w')
|
---|
592 | fo.write(__copyright_tmp__ % (
|
---|
593 | cfg, date.today().year) + '\n\n')
|
---|
594 | for line in lines:
|
---|
595 | fo.write(line + '\n')
|
---|
596 | fo.close()
|
---|
597 |
|
---|
598 | variables = dsc2yaml.output_variable()
|
---|
599 | fo = open(yaml_file, 'w')
|
---|
600 | fo.write(__copyright_tmp__ % ('Default', date.today().year))
|
---|
601 | if len(variables) > 0:
|
---|
602 | fo.write('\n\nvariable:\n')
|
---|
603 | for line in variables:
|
---|
604 | fo.write(' ' + line + '\n')
|
---|
605 |
|
---|
606 | fo.write('\n\ntemplate:\n')
|
---|
607 | for line in cfgs['Template']:
|
---|
608 | fo.write(' ' + line + '\n')
|
---|
609 |
|
---|
610 | fo.write('\n\nconfigs:\n')
|
---|
611 | for line in cfgs['Option']:
|
---|
612 | fo.write(' ' + line + '\n')
|
---|
613 |
|
---|
614 | fo.close()
|
---|
615 |
|
---|
616 |
|
---|
617 | def get_fsp_name_from_path(bsf_file):
|
---|
618 | name = ''
|
---|
619 | parts = bsf_file.split(os.sep)
|
---|
620 | for part in parts:
|
---|
621 | if part.endswith('FspBinPkg'):
|
---|
622 | name = part[:-9]
|
---|
623 | break
|
---|
624 | if not name:
|
---|
625 | raise Exception('Could not get FSP name from file path!')
|
---|
626 | return name
|
---|
627 |
|
---|
628 |
|
---|
629 | def usage():
|
---|
630 | print('\n'.join([
|
---|
631 | "FspDscBsf2Yaml Version 0.10",
|
---|
632 | "Usage:",
|
---|
633 | " FspDscBsf2Yaml BsfFile|DscFile YamlFile"
|
---|
634 | ]))
|
---|
635 |
|
---|
636 |
|
---|
637 | def main():
|
---|
638 | #
|
---|
639 | # Parse the options and args
|
---|
640 | #
|
---|
641 | argc = len(sys.argv)
|
---|
642 | if argc < 3:
|
---|
643 | usage()
|
---|
644 | return 1
|
---|
645 |
|
---|
646 | bsf_file = sys.argv[1]
|
---|
647 | yaml_file = sys.argv[2]
|
---|
648 | if os.path.isdir(yaml_file):
|
---|
649 | yaml_file = os.path.join(
|
---|
650 | yaml_file, get_fsp_name_from_path(bsf_file) + '.yaml')
|
---|
651 |
|
---|
652 | if bsf_file.endswith('.dsc'):
|
---|
653 | dsc_file = bsf_file
|
---|
654 | bsf_file = ''
|
---|
655 | else:
|
---|
656 | dsc_file = os.path.splitext(yaml_file)[0] + '.dsc'
|
---|
657 | bsf_to_dsc(bsf_file, dsc_file)
|
---|
658 |
|
---|
659 | dsc_to_yaml(dsc_file, yaml_file)
|
---|
660 |
|
---|
661 | print("'%s' was created successfully!" % yaml_file)
|
---|
662 |
|
---|
663 | return 0
|
---|
664 |
|
---|
665 |
|
---|
666 | if __name__ == '__main__':
|
---|
667 | sys.exit(main())
|
---|