summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py877
-rw-r--r--IntelFsp2Pkg/Tools/GenCfgOpt.py470
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h16
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h75
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h69
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h87
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf88
-rw-r--r--IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml267
-rw-r--r--IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc469
-rw-r--r--IntelFsp2Pkg/Tools/Tests/test_yaml.py96
-rw-r--r--IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md39
11 files changed, 2421 insertions, 132 deletions
diff --git a/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py b/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
new file mode 100644
index 0000000000..cad9b60e73
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
@@ -0,0 +1,877 @@
+#!/usr/bin/env python
+## @ FspDscBsf2Yaml.py
+# This script convert DSC or BSF format file into YAML format
+#
+# Copyright(c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import re
+import sys
+from datetime import date
+from collections import OrderedDict
+from functools import reduce
+
+from GenCfgOpt import CGenCfgOpt
+
+__copyright_tmp__ = """## @file
+#
+# YAML CFGDATA %s File.
+#
+# Copyright(c) %4d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+"""
+
+__copyright_dsc__ = """## @file
+#
+# Copyright (c) %04d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[PcdsDynamicVpd.Upd]
+ #
+ # Global definitions in BSF
+ # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"}
+ #
+
+"""
+
+
+def Bytes2Val(Bytes):
+ return reduce(lambda x, y: (x << 8) | y, Bytes[::-1])
+
+
+class CFspBsf2Dsc:
+
+ def __init__(self, bsf_file):
+ self.cfg_list = CFspBsf2Dsc.parse_bsf(bsf_file)
+
+ def get_dsc_lines(self):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list)
+
+ def save_dsc(self, dsc_file):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list, dsc_file)
+
+ @staticmethod
+ def parse_bsf(bsf_file):
+
+ fd = open(bsf_file, 'r')
+ bsf_txt = fd.read()
+ fd.close()
+
+ find_list = []
+ regex = re.compile(r'\s+Find\s+"(.*?)"(.*?)^\s+\$(.*?)\s+', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ find = match.group(1)
+ name = match.group(3)
+ if not name.endswith('_Revision'):
+ raise Exception("Unexpected CFG item following 'Find' !")
+ find_list.append((name, find))
+
+ idx = 0
+ count = 0
+ prefix = ''
+ chk_dict = {}
+ cfg_list = []
+ cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0', 'type': 'Reserved',
+ 'embed': '', 'page': '', 'option': '', 'instance': 0}
+ regex = re.compile(r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+bytes(\s+\$_DEFAULT_\s+=\s+(.+?))?$',
+ re.S | re.MULTILINE)
+
+ for match in regex.finditer(bsf_txt):
+ dlen = int(match.group(3))
+ if match.group(1) == 'Skip':
+ key = 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx
+ val = ', '.join(['%02X' % ord(i) for i in '\x00' * dlen])
+ idx += 1
+ option = '$SKIP'
+ else:
+ key = match.group(2)
+ val = match.group(5)
+ option = ''
+
+ cfg_item = dict(cfg_temp)
+ finds = [i for i in find_list if i[0] == key]
+ if len(finds) > 0:
+ if count >= 1:
+ # Append a dummy one
+ cfg_item['cname'] = 'Dummy'
+ cfg_list.append(dict(cfg_item))
+ cfg_list[-1]['embed'] = '%s:TAG_%03X:END' % (prefix, ord(prefix[-1]))
+ prefix = finds[0][1]
+ cfg_item['embed'] = '%s:TAG_%03X:START' % (prefix, ord(prefix[-1]))
+ cfg_item['find'] = prefix
+ cfg_item['cname'] = 'Signature'
+ cfg_item['length'] = len(finds[0][1])
+ cfg_item['value'] = '0x%X' % Bytes2Val(finds[0][1].encode('UTF-8'))
+ cfg_list.append(dict(cfg_item))
+ cfg_item = dict(cfg_temp)
+ find_list.pop(0)
+ count = 0
+
+ cfg_item['cname'] = key
+ cfg_item['length'] = dlen
+ cfg_item['value'] = val
+ cfg_item['option'] = option
+
+ if key not in chk_dict.keys():
+ chk_dict[key] = 0
+ else:
+ chk_dict[key] += 1
+ cfg_item['instance'] = chk_dict[key]
+
+ cfg_list.append(cfg_item)
+ count += 1
+
+ if prefix:
+ cfg_item = dict(cfg_temp)
+ cfg_item['cname'] = 'Dummy'
+ cfg_item['embed'] = '%s:%03X:END' % (prefix, ord(prefix[-1]))
+ cfg_list.append(cfg_item)
+
+ option_dict = {}
+ selreg = re.compile(r'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re.S | re.MULTILINE)
+ regex = re.compile(r'^List\s&(.+?)$(.+?)^EndList$', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ key = match.group(1)
+ option_dict[key] = []
+ for select in selreg.finditer(match.group(2)):
+ option_dict[key].append((int(select.group(1), 0), select.group(2)))
+
+ chk_dict = {}
+ pagereg = re.compile(r'^Page\s"(.*?)"$(.+?)^EndPage$', re.S | re.MULTILINE)
+ for match in pagereg.finditer(bsf_txt):
+ page = match.group(1)
+ for line in match.group(2).splitlines():
+ match = re.match(r'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line)
+ if match:
+ cname = match.group(2)
+ if cname not in chk_dict.keys():
+ chk_dict[cname] = 0
+ else:
+ chk_dict[cname] += 1
+ instance = chk_dict[cname]
+ cfg_idxs = [i for i, j in enumerate(cfg_list) if j['cname'] == cname and j['instance'] == instance]
+ if len(cfg_idxs) != 1:
+ raise Exception("Multiple CFG item '%s' found !" % cname)
+ cfg_item = cfg_list[cfg_idxs[0]]
+ cfg_item['page'] = page
+ cfg_item['type'] = match.group(1)
+ cfg_item['prompt'] = match.group(3)
+ cfg_item['range'] = None
+ if cfg_item['type'] == 'Combo':
+ cfg_item['option'] = option_dict[match.group(4)[1:]]
+ elif cfg_item['type'] == 'EditNum':
+ cfg_item['option'] = match.group(4)
+ match = re.match(r'\s+ Help\s"(.*?)"$', line)
+ if match:
+ cfg_item['help'] = match.group(1)
+
+ match = re.match(r'\s+"Valid\srange:\s(.*)"$', line)
+ if match:
+ parts = match.group(1).split()
+ cfg_item['option'] = (
+ (int(parts[0], 0), int(parts[2], 0), cfg_item['option']))
+
+ return cfg_list
+
+ @staticmethod
+ def generate_dsc(option_list, dsc_file=None):
+ dsc_lines = []
+ header = '%s' % (__copyright_dsc__ % date.today().year)
+ dsc_lines.extend(header.splitlines())
+
+ pages = []
+ for cfg_item in option_list:
+ if cfg_item['page'] and (cfg_item['page'] not in pages):
+ pages.append(cfg_item['page'])
+
+ page_id = 0
+ for page in pages:
+ dsc_lines.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id, page))
+ page_id += 1
+ dsc_lines.append('')
+
+ last_page = ''
+ for option in option_list:
+ dsc_lines.append('')
+ default = option['value']
+ pos = option['cname'].find('_')
+ name = option['cname'][pos + 1:]
+
+ if option['find']:
+ dsc_lines.append(' # !BSF FIND:{%s}' % option['find'])
+ dsc_lines.append('')
+
+ if option['instance'] > 0:
+ name = name + '_%s' % option['instance']
+
+ if option['embed']:
+ dsc_lines.append(' # !HDR EMBED:{%s}' % option['embed'])
+
+ if option['type'] == 'Reserved':
+ dsc_lines.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}')
+ if option['option'] == '$SKIP':
+ dsc_lines.append(' # !BSF OPTION:{$SKIP}')
+ else:
+ prompt = option['prompt']
+
+ if last_page != option['page']:
+ last_page = option['page']
+ dsc_lines.append(' # !BSF PAGE:{PG%02X}' % (pages.index(option['page'])))
+
+ if option['type'] == 'Combo':
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{%s}' %
+ (prompt, option['type']))
+ ops = []
+ for val, text in option['option']:
+ ops.append('0x%x:%s' % (val, text))
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ elif option['type'] == 'EditNum':
+ cfg_len = option['length']
+ if ',' in default and cfg_len > 8:
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{Table}' % (prompt))
+ if cfg_len > 16:
+ cfg_len = 16
+ ops = []
+ for i in range(cfg_len):
+ ops.append('%X:1:HEX' % i)
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ else:
+ dsc_lines.append(
+ ' # !BSF NAME:{%s} TYPE:{%s, %s,(0x%X, 0x%X)}' %
+ (prompt, option['type'], option['option'][2],
+ option['option'][0], option['option'][1]))
+ dsc_lines.append(' # !BSF HELP:{%s}' % option['help'])
+
+ if ',' in default:
+ default = '{%s}' % default
+ dsc_lines.append(' gCfgData.%-30s | * | 0x%04X | %s' %
+ (name, option['length'], default))
+
+ if dsc_file:
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+
+ return dsc_lines
+
+
+class CFspDsc2Yaml():
+
+ def __init__(self):
+ self._Hdr_key_list = ['EMBED', 'STRUCT']
+ self._Bsf_key_list = ['NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES', 'OPTION',
+ 'CONDITION', 'ORDER', 'MARKER', 'SUBT', 'FIELD', 'FIND']
+ self.gen_cfg_data = None
+ self.cfg_reg_exp = re.compile(r"^([_a-zA-Z0-9$\(\)]+)\s*\|\s*(0x[0-9A-F]+|\*)\s*\|"
+ + r"\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)")
+ self.bsf_reg_exp = re.compile(r"(%s):{(.+?)}(?:$|\s+)" % '|'.join(self._Bsf_key_list))
+ self.hdr_reg_exp = re.compile(r"(%s):{(.+?)}" % '|'.join(self._Hdr_key_list))
+ self.prefix = ''
+ self.unused_idx = 0
+ self.offset = 0
+ self.base_offset = 0
+
+ def load_config_data_from_dsc(self, file_name):
+ """
+ Load and parse a DSC CFGDATA file.
+ """
+ gen_cfg_data = CGenCfgOpt('FSP')
+ if file_name.endswith('.dsc'):
+ # if gen_cfg_data.ParseDscFileYaml(file_name, '') != 0:
+ if gen_cfg_data.ParseDscFile(file_name, '') != 0:
+ raise Exception('DSC file parsing error !')
+ if gen_cfg_data.CreateVarDict() != 0:
+ raise Exception('DSC variable creation error !')
+ else:
+ raise Exception('Unsupported file "%s" !' % file_name)
+ gen_cfg_data.UpdateDefaultValue()
+ self.gen_cfg_data = gen_cfg_data
+
+ def print_dsc_line(self):
+ """
+ Debug function to print all DSC lines.
+ """
+ for line in self.gen_cfg_data._DscLines:
+ print(line)
+
+ def format_value(self, field, text, indent=''):
+ """
+ Format a CFGDATA item into YAML format.
+ """
+ if(not text.startswith('!expand')) and (': ' in text):
+ tgt = ':' if field == 'option' else '- '
+ text = text.replace(': ', tgt)
+ lines = text.splitlines()
+ if len(lines) == 1 and field != 'help':
+ return text
+ else:
+ return '>\n ' + '\n '.join([indent + i.lstrip() for i in lines])
+
+ def reformat_pages(self, val):
+ # Convert XXX:YYY into XXX::YYY format for page definition
+ parts = val.split(',')
+ if len(parts) <= 1:
+ return val
+
+ new_val = []
+ for each in parts:
+ nodes = each.split(':')
+ if len(nodes) == 2:
+ each = '%s::%s' % (nodes[0], nodes[1])
+ new_val.append(each)
+ ret = ','.join(new_val)
+ return ret
+
+ def reformat_struct_value(self, utype, val):
+ # Convert DSC UINT16/32/64 array into new format by
+ # adding prefix 0:0[WDQ] to provide hint to the array format
+ if utype in ['UINT16', 'UINT32', 'UINT64']:
+ if val and val[0] == '{' and val[-1] == '}':
+ if utype == 'UINT16':
+ unit = 'W'
+ elif utype == 'UINT32':
+ unit = 'D'
+ else:
+ unit = 'Q'
+ val = '{ 0:0%s, %s }' % (unit, val[1:-1])
+ return val
+
+ def process_config(self, cfg):
+ if 'page' in cfg:
+ cfg['page'] = self.reformat_pages(cfg['page'])
+
+ if 'struct' in cfg:
+ cfg['value'] = self.reformat_struct_value(cfg['struct'], cfg['value'])
+
+ def parse_dsc_line(self, dsc_line, config_dict, init_dict, include):
+ """
+ Parse a line in DSC and update the config dictionary accordingly.
+ """
+ init_dict.clear()
+ match = re.match(r'g(CfgData|\w+FspPkgTokenSpaceGuid)\.(.+)', dsc_line)
+ if match:
+ match = self.cfg_reg_exp.match(match.group(2))
+ if not match:
+ return False
+ config_dict['cname'] = self.prefix + match.group(1)
+ value = match.group(4).strip()
+ length = match.group(3).strip()
+ config_dict['length'] = length
+ config_dict['value'] = value
+ if match.group(2) == '*':
+ self.offset += int(length, 0)
+ else:
+ org_offset = int(match.group(2), 0)
+ if org_offset == 0:
+ self.base_offset = self.offset
+ offset = org_offset + self.base_offset
+ if self.offset != offset:
+ if offset > self.offset:
+ init_dict['padding'] = offset - self.offset
+ self.offset = offset + int(length, 0)
+ return True
+
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", dsc_line)
+ if match and len(config_dict) == 0:
+ # !include should not be inside a config field
+ # if so, do not convert include into YAML
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if match.group(1) == '<':
+ config_dict['include'] = match.group(2)
+ else:
+ config_dict['include'] = ''
+ return True
+
+ match = re.match(r"^\s*#\s+(!BSF|!HDR)\s+(.+)", dsc_line)
+ if not match:
+ return False
+
+ remaining = match.group(2)
+ if match.group(1) == '!BSF':
+ result = self.bsf_reg_exp.findall(remaining)
+ if not result:
+ return False
+
+ for each in result:
+ key = each[0].lower()
+ val = each[1]
+ if key == 'field':
+ name = each[1]
+ if ':' not in name:
+ raise Exception('Incorrect bit field format !')
+ parts = name.split(':')
+ config_dict['length'] = parts[1]
+ config_dict['cname'] = '@' + parts[0]
+ return True
+ elif key in ['pages', 'page', 'find']:
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if key == 'find':
+ config_dict['find'] = val
+ else:
+ config_dict['page'] = val
+ return True
+ elif key == 'subt':
+ config_dict.clear()
+ parts = each[1].split(':')
+ tmp_name = parts[0][:-5]
+ if tmp_name == 'CFGHDR':
+ cfg_tag = '_$FFF_'
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + '%s, %s, ' % (parts[1], cfg_tag) \
+ + ', '.join(parts[2:]) + ' ] }'
+ else:
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + ', '.join(parts[1:]) + ' ] }'
+ config_dict.clear()
+ config_dict['cname'] = tmp_name
+ config_dict['expand'] = sval
+ return True
+ else:
+ if key in ['name', 'help', 'option'] and val.startswith('+'):
+ val = config_dict[key] + '\n' + val[1:]
+ if val.strip() == '':
+ val = "''"
+ config_dict[key] = val
+
+ else:
+ match = self.hdr_reg_exp.match(remaining)
+ if not match:
+ return False
+ key = match.group(1)
+ remaining = match.group(2)
+ if key == 'EMBED':
+ parts = remaining.split(':')
+ names = parts[0].split(',')
+ if parts[-1] == 'END':
+ prefix = '>'
+ else:
+ prefix = '<'
+ skip = False
+ if parts[1].startswith('TAG_'):
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ else:
+ tag_txt = names[0]
+ if parts[2] in ['START', 'END']:
+ if names[0] == 'PCIE_RP_PIN_CTRL[]':
+ skip = True
+ else:
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ if not skip:
+ config_dict.clear()
+ config_dict['cname'] = prefix + tag_txt
+ return True
+
+ if key == 'STRUCT':
+ text = remaining.strip()
+ config_dict[key.lower()] = text
+
+ return False
+
+ def process_template_lines(self, lines):
+ """
+ Process a line in DSC template section.
+ """
+ template_name = ''
+ bsf_temp_dict = OrderedDict()
+ temp_file_dict = OrderedDict()
+ include_file = ['.']
+
+ for line in lines:
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", line)
+ if match:
+ if match.group(1) == '<':
+ include_file.append(match.group(2))
+ else:
+ include_file.pop()
+
+ match = re.match(r"^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", line)
+ if match:
+ if match.group(3) == 'START' and not template_name:
+ template_name = match.group(2).strip()
+ temp_file_dict[template_name] = list(include_file)
+ bsf_temp_dict[template_name] = []
+ if match.group(3) == 'END' and (template_name == match.group(2).strip()) \
+ and template_name:
+ template_name = ''
+ else:
+ if template_name:
+ bsf_temp_dict[template_name].append(line)
+ return bsf_temp_dict, temp_file_dict
+
+ def process_option_lines(self, lines):
+ """
+ Process a line in DSC config section.
+ """
+ cfgs = []
+ struct_end = False
+ config_dict = dict()
+ init_dict = dict()
+ include = ['']
+ for line in lines:
+ ret = self.parse_dsc_line(line, config_dict, init_dict, include)
+ if ret:
+ if 'padding' in init_dict:
+ num = init_dict['padding']
+ init_dict.clear()
+ padding_dict = {}
+ cfgs.append(padding_dict)
+ padding_dict['cname'] = 'UnusedUpdSpace%d' % self.unused_idx
+ padding_dict['length'] = '0x%x' % num
+ padding_dict['value'] = '{ 0 }'
+ self.unused_idx += 1
+
+ if cfgs and cfgs[-1]['cname'][0] != '@' and config_dict['cname'][0] == '@':
+ # it is a bit field, mark the previous one as virtual
+ cname = cfgs[-1]['cname']
+ new_cfg = dict(cfgs[-1])
+ new_cfg['cname'] = '@$STRUCT'
+ cfgs[-1].clear()
+ cfgs[-1]['cname'] = cname
+ cfgs.append(new_cfg)
+
+ if cfgs and cfgs[-1]['cname'] == 'CFGHDR' and config_dict['cname'][0] == '<':
+ # swap CfgHeader and the CFG_DATA order
+ if ':' in config_dict['cname']:
+ # replace the real TAG for CFG_DATA
+ cfgs[-1]['expand'] = cfgs[-1]['expand'].replace(
+ '_$FFF_', '0x%s' %
+ config_dict['cname'].split(':')[1][4:])
+ cfgs.insert(-1, config_dict)
+ else:
+ self.process_config(config_dict)
+ if struct_end:
+ struct_end = False
+ cfgs.insert(-1, config_dict)
+ else:
+ cfgs.append(config_dict)
+ if config_dict['cname'][0] == '>':
+ struct_end = True
+
+ config_dict = dict(init_dict)
+ return cfgs
+
+ def variable_fixup(self, each):
+ """
+ Fix up some variable definitions for SBL.
+ """
+ key = each
+ val = self.gen_cfg_data._MacroDict[each]
+ return key, val
+
+ def template_fixup(self, tmp_name, tmp_list):
+ """
+ Fix up some special config templates for SBL
+ """
+ return
+
+ def config_fixup(self, cfg_list):
+ """
+ Fix up some special config items for SBL.
+ """
+
+ # Insert FSPT_UPD/FSPM_UPD/FSPS_UPD tag so as to create C strcture
+ idxs = []
+ for idx, cfg in enumerate(cfg_list):
+ if cfg['cname'].startswith('<FSP_UPD_HEADER'):
+ idxs.append(idx)
+
+ if len(idxs) != 3:
+ return
+
+ # Handle insert backwards so that the index does not change in the loop
+ fsp_comp = 'SMT'
+ idx_comp = 0
+ for idx in idxs[::-1]:
+ # Add current FSP?_UPD start tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '<FSP%s_UPD' % fsp_comp[idx_comp]
+ cfg_list.insert(idx, cfgfig_dict)
+ if idx_comp < 2:
+ # Add previous FSP?_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[idx_comp + 1]
+ cfg_list.insert(idx, cfgfig_dict)
+ idx_comp += 1
+
+ # Add final FSPS_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[0]
+ cfg_list.append(cfgfig_dict)
+
+ return
+
+ def get_section_range(self, section_name):
+ """
+ Extract line number range from config file for a given section name.
+ """
+ start = -1
+ end = -1
+ for idx, line in enumerate(self.gen_cfg_data._DscLines):
+ if start < 0 and line.startswith('[%s]' % section_name):
+ start = idx
+ elif start >= 0 and line.startswith('['):
+ end = idx
+ break
+ if start == -1:
+ start = 0
+ if end == -1:
+ end = len(self.gen_cfg_data._DscLines)
+ return start, end
+
+ def normalize_file_name(self, file, is_temp=False):
+ """
+ Normalize file name convention so that it is consistent.
+ """
+ if file.endswith('.dsc'):
+ file = file[:-4] + '.yaml'
+ dir_name = os.path.dirname(file)
+ base_name = os.path.basename(file)
+ if is_temp:
+ if 'Template_' not in file:
+ base_name = base_name.replace('Template', 'Template_')
+ else:
+ if 'CfgData_' not in file:
+ base_name = base_name.replace('CfgData', 'CfgData_')
+ if dir_name:
+ path = dir_name + '/' + base_name
+ else:
+ path = base_name
+ return path
+
+ def output_variable(self):
+ """
+ Output variable block into a line list.
+ """
+ lines = []
+ for each in self.gen_cfg_data._MacroDict:
+ key, value = self.variable_fixup(each)
+ lines.append('%-30s : %s' % (key, value))
+ return lines
+
+ def output_template(self):
+ """
+ Output template block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Tmp')
+ bsf_temp_dict, temp_file_dict = self.process_template_lines(self.gen_cfg_data._DscLines[start:end])
+ template_dict = dict()
+ lines = []
+ file_lines = {}
+ last_file = '.'
+ file_lines[last_file] = []
+
+ for tmp_name in temp_file_dict:
+ temp_file_dict[tmp_name][-1] = self.normalize_file_name(temp_file_dict[tmp_name][-1], True)
+ if len(temp_file_dict[tmp_name]) > 1:
+ temp_file_dict[tmp_name][-2] = self.normalize_file_name(temp_file_dict[tmp_name][-2], True)
+
+ for tmp_name in bsf_temp_dict:
+ file = temp_file_dict[tmp_name][-1]
+ if last_file != file and len(temp_file_dict[tmp_name]) > 1:
+ inc_file = temp_file_dict[tmp_name][-2]
+ file_lines[inc_file].extend(['', '- !include %s' % temp_file_dict[tmp_name][-1], ''])
+ last_file = file
+ if file not in file_lines:
+ file_lines[file] = []
+ lines = file_lines[file]
+ text = bsf_temp_dict[tmp_name]
+ tmp_list = self.process_option_lines(text)
+ self.template_fixup(tmp_name, tmp_list)
+ template_dict[tmp_name] = tmp_list
+ lines.append('%s: >' % tmp_name)
+ lines.extend(self.output_dict(tmp_list, False)['.'])
+ lines.append('\n')
+ return file_lines
+
+ def output_config(self):
+ """
+ Output config block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Upd')
+ cfgs = self.process_option_lines(self.gen_cfg_data._DscLines[start:end])
+ self.config_fixup(cfgs)
+ file_lines = self.output_dict(cfgs, True)
+ return file_lines
+
+ def output_dict(self, cfgs, is_configs):
+ """
+ Output one config item into a line list.
+ """
+ file_lines = {}
+ level = 0
+ file = '.'
+ for each in cfgs:
+ if 'length' in each and int(each['length'], 0) == 0:
+ continue
+
+ if 'include' in each:
+ if each['include']:
+ each['include'] = self.normalize_file_name(each['include'])
+ file_lines[file].extend(['', '- !include %s' % each['include'], ''])
+ file = each['include']
+ else:
+ file = '.'
+ continue
+
+ if file not in file_lines:
+ file_lines[file] = []
+
+ lines = file_lines[file]
+ name = each['cname']
+
+ prefix = name[0]
+ if prefix == '<':
+ level += 1
+
+ padding = ' ' * level
+ if prefix not in '<>@':
+ padding += ' '
+ else:
+ name = name[1:]
+ if prefix == '@':
+ padding += ' '
+
+ if ':' in name:
+ parts = name.split(':')
+ name = parts[0]
+
+ padding = padding[2:] if is_configs else padding
+
+ if prefix != '>':
+ if 'expand' in each:
+ lines.append('%s- %s' % (padding, each['expand']))
+ else:
+ lines.append('%s- %-12s :' % (padding, name))
+
+ for field in each:
+ if field in ['cname', 'expand', 'include']:
+ continue
+ value_str = self.format_value(field, each[field], padding + ' ' * 16)
+ full_line = ' %s %-12s : %s' % (padding, field, value_str)
+ lines.extend(full_line.splitlines())
+
+ if prefix == '>':
+ level -= 1
+ if level == 0:
+ lines.append('')
+
+ return file_lines
+
+
+def bsf_to_dsc(bsf_file, dsc_file):
+ fsp_dsc = CFspBsf2Dsc(bsf_file)
+ dsc_lines = fsp_dsc.get_dsc_lines()
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+ return
+
+
+def dsc_to_yaml(dsc_file, yaml_file):
+ dsc2yaml = CFspDsc2Yaml()
+ dsc2yaml.load_config_data_from_dsc(dsc_file)
+
+ cfgs = {}
+ for cfg in ['Template', 'Option']:
+ if cfg == 'Template':
+ file_lines = dsc2yaml.output_template()
+ else:
+ file_lines = dsc2yaml.output_config()
+ for file in file_lines:
+ lines = file_lines[file]
+ if file == '.':
+ cfgs[cfg] = lines
+ else:
+ if('/' in file or '\\' in file):
+ continue
+ file = os.path.basename(file)
+ fo = open(os.path.join(file), 'w')
+ fo.write(__copyright_tmp__ % (cfg, date.today().year) + '\n\n')
+ for line in lines:
+ fo.write(line + '\n')
+ fo.close()
+
+ variables = dsc2yaml.output_variable()
+ fo = open(yaml_file, 'w')
+ fo.write(__copyright_tmp__ % ('Default', date.today().year))
+ if len(variables) > 0:
+ fo.write('\n\nvariable:\n')
+ for line in variables:
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\ntemplate:\n')
+ for line in cfgs['Template']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\nconfigs:\n')
+ for line in cfgs['Option']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.close()
+
+
+def get_fsp_name_from_path(bsf_file):
+ name = ''
+ parts = bsf_file.split(os.sep)
+ for part in parts:
+ if part.endswith('FspBinPkg'):
+ name = part[:-9]
+ break
+ if not name:
+ raise Exception('Could not get FSP name from file path!')
+ return name
+
+
+def usage():
+ print('\n'.join([
+ "FspDscBsf2Yaml Version 0.10",
+ "Usage:",
+ " FspDscBsf2Yaml BsfFile|DscFile YamlFile"
+ ]))
+
+
+def main():
+ #
+ # Parse the options and args
+ #
+ argc = len(sys.argv)
+ if argc < 3:
+ usage()
+ return 1
+
+ bsf_file = sys.argv[1]
+ yaml_file = sys.argv[2]
+ if os.path.isdir(yaml_file):
+ yaml_file = os.path.join(yaml_file, get_fsp_name_from_path(bsf_file) + '.yaml')
+
+ if bsf_file.endswith('.dsc'):
+ dsc_file = bsf_file
+ bsf_file = ''
+ else:
+ dsc_file = os.path.splitext(yaml_file)[0] + '.dsc'
+ bsf_to_dsc(bsf_file, dsc_file)
+
+ dsc_to_yaml(dsc_file, yaml_file)
+
+ print("'%s' was created successfully!" % yaml_file)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/IntelFsp2Pkg/Tools/GenCfgOpt.py b/IntelFsp2Pkg/Tools/GenCfgOpt.py
index a0b8bba81e..660824b740 100644
--- a/IntelFsp2Pkg/Tools/GenCfgOpt.py
+++ b/IntelFsp2Pkg/Tools/GenCfgOpt.py
@@ -1,6 +1,6 @@
## @ GenCfgOpt.py
#
-# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -283,10 +283,10 @@ class CLogicalExpression:
return Result
class CGenCfgOpt:
- def __init__(self):
+ def __init__(self, Mode = ''):
self.Debug = False
self.Error = ''
-
+ self.Mode = Mode
self._GlobalDataDef = """
GlobalDataDef
SKUID = 0, "DEFAULT"
@@ -300,18 +300,20 @@ List &EN_DIS
EndList
"""
-
- self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
+ self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT']
self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']
self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}
self._MacroDict = {}
+ self._VarDict = {}
self._PcdsDict = {}
self._CfgBlkDict = {}
self._CfgPageDict = {}
+ self._BsfTempDict = {}
self._CfgItemList = []
+ self._DscLines = []
self._DscFile = ''
- self._FvDir = ''
+
self._MapVer = 0
self._DscTime = 0
@@ -351,7 +353,7 @@ EndList
print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))
return Result
- def ExpandMacros (self, Input):
+ def ExpandMacros (self, Input, Preserve = False):
Line = Input
Match = re.findall("\$\(\w+\)", Input)
if Match:
@@ -362,7 +364,8 @@ EndList
else:
if self.Debug:
print ("WARN : %s is not defined" % Each)
- Line = Line.replace(Each, Each[2:-1])
+ if not Preserve:
+ Line = Line.replace(Each, Each[2:-1])
return Line
def ExpandPcds (self, Input):
@@ -386,6 +389,70 @@ EndList
print ("INFO : Eval Express [%s] : %s" % (Expr, Result))
return Result
+ def ValueToByteArray (self, ValueStr, Length):
+ Match = re.match("\{\s*FILE:(.+)\}", ValueStr)
+ if Match:
+ FileList = Match.group(1).split(',')
+ Result = bytearray()
+ for File in FileList:
+ File = File.strip()
+ BinPath = os.path.join(os.path.dirname(self._DscFile), File)
+ Result.extend(bytearray(open(BinPath, 'rb').read()))
+ else:
+ try:
+ Result = bytearray(self.ValueToList(ValueStr, Length))
+ except ValueError as e:
+ raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr)
+ if len(Result) < Length:
+ Result.extend(b'\x00' * (Length - len(Result)))
+ elif len(Result) > Length:
+ raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length))
+
+ return Result[:Length]
+
+ def ValueToList (self, ValueStr, Length):
+ if ValueStr[0] == '{':
+ Result = []
+ BinList = ValueStr[1:-1].split(',')
+ InBitField = False
+ LastInBitField = False
+ Value = 0
+ BitLen = 0
+ for Element in BinList:
+ InBitField = False
+ Each = Element.strip()
+ if len(Each) == 0:
+ pass
+ else:
+ if Each[0] in ['"', "'"]:
+ Result.extend(list(bytearray(Each[1:-1], 'utf-8')))
+ elif ':' in Each:
+ Match = re.match("(.+):(\d+)b", Each)
+ if Match is None:
+ raise Exception("Invald value list format '%s' !" % Each)
+ InBitField = True
+ CurrentBitLen = int(Match.group(2))
+ CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<<CurrentBitLen) - 1)) << BitLen
+ else:
+ Result.append(self.EvaluateExpress(Each.strip()))
+ if InBitField:
+ Value += CurrentValue
+ BitLen += CurrentBitLen
+ if LastInBitField and ((not InBitField) or (Element == BinList[-1])):
+ if BitLen % 8 != 0:
+ raise Exception("Invald bit field length!")
+ Result.extend(Val2Bytes(Value, BitLen // 8))
+ Value = 0
+ BitLen = 0
+ LastInBitField = InBitField
+ elif ValueStr.startswith("'") and ValueStr.endswith("'"):
+ Result = Str2Bytes (ValueStr, Length)
+ elif ValueStr.startswith('"') and ValueStr.endswith('"'):
+ Result = Str2Bytes (ValueStr, Length)
+ else:
+ Result = Val2Bytes (self.EvaluateExpress(ValueStr), Length)
+ return Result
+
def FormatListValue(self, ConfigDict):
Struct = ConfigDict['struct']
if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
@@ -424,28 +491,53 @@ EndList
self._DscFile = DscFile
self._FvDir = FvDir
+ self._DscLines = []
+ self._BsfTempDict = {}
+
# Initial DSC time is parent DSC time.
self._DscTime = os.path.getmtime(DscFile)
+ CfgDict = {}
+
IsDefSect = False
IsPcdSect = False
IsUpdSect = False
IsVpdSect = False
+ IsTmpSect = False
+
+ TemplateName = ''
IfStack = []
ElifStack = []
Error = 0
ConfigDict = {}
- DscFd = open(DscFile, "r")
- DscLines = DscFd.readlines()
- DscFd.close()
+
+ if type(DscFile) is list:
+ # it is DSC lines already
+ DscLines = DscFile
+ self._DscFile = '.'
+ else:
+ DscFd = open(DscFile, "r")
+ DscLines = DscFd.readlines()
+ DscFd.close()
+ self._DscFile = DscFile
+
+ SkipLines = 0
MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64
SizeAlign = 0 #record the struct max align
Base = 0 #Starting offset of sub-structure.
+
while len(DscLines):
DscLine = DscLines.pop(0).strip()
+ if SkipLines == 0:
+ self._DscLines.append (DscLine)
+ else:
+ SkipLines = SkipLines - 1
+ if len(DscLine) == 0:
+ continue
+
Handle = False
Match = re.match("^\[(.+)\]", DscLine)
if Match is not None:
@@ -453,11 +545,15 @@ EndList
IsPcdSect = False
IsVpdSect = False
IsUpdSect = False
- if Match.group(1).lower() == "Defines".lower():
+ IsTmpSect = False
+ SectionName = Match.group(1).lower()
+ if SectionName == "Defines".lower():
IsDefSect = True
- if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()):
+ if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()):
IsPcdSect = True
- elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
+ elif SectionName == "PcdsDynamicVpd.Tmp".lower():
+ IsTmpSect = True
+ elif SectionName == "PcdsDynamicVpd.Upd".lower():
ConfigDict = {}
ConfigDict['header'] = 'ON'
ConfigDict['region'] = 'UPD'
@@ -465,90 +561,98 @@ EndList
ConfigDict['page'] = ''
ConfigDict['name'] = ''
ConfigDict['find'] = ''
+ ConfigDict['marker'] = ''
ConfigDict['struct'] = ''
ConfigDict['embed'] = ''
ConfigDict['comment'] = ''
ConfigDict['subreg'] = []
+ ConfigDict['condition'] = ''
+ ConfigDict['option'] = ''
IsUpdSect = True
Offset = 0
else:
- if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:
- if re.match("^!else($|\s+#.+)", DscLine):
+ if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect:
+
+ Match = False if DscLine[0] != '!' else True
+ if Match:
+ Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine.split("#")[0])
+ Keyword = Match.group(1) if Match else ''
+ Remaining = Match.group(2) if Match else ''
+ Remaining = '' if Remaining is None else Remaining.strip()
+
+ if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining:
+ raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine)
+
+ if Keyword == 'else':
if IfStack:
IfStack[-1] = not IfStack[-1]
else:
- print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
- raise SystemExit
- elif re.match("^!endif($|\s+#.+)", DscLine):
+ raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
+ elif Keyword == 'endif':
if IfStack:
IfStack.pop()
Level = ElifStack.pop()
if Level > 0:
del IfStack[-Level:]
else:
- print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
- raise SystemExit
- else:
- Result = False
- Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
- if Match:
- Result = self.EvaulateIfdef (Match.group(2))
- if Match.group(1) == 'ifndef':
- Result = not Result
- IfStack.append(Result)
+ raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
+ elif Keyword == 'ifdef' or Keyword == 'ifndef':
+ Result = self.EvaulateIfdef (Remaining)
+ if Keyword == 'ifndef':
+ Result = not Result
+ IfStack.append(Result)
+ ElifStack.append(0)
+ elif Keyword == 'if' or Keyword == 'elseif':
+ Result = self.EvaluateExpress(Remaining)
+ if Keyword == "if":
ElifStack.append(0)
+ IfStack.append(Result)
+ else: #elseif
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ IfStack.append(Result)
+ ElifStack[-1] = ElifStack[-1] + 1
+ else:
+ raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
+ else:
+ if IfStack:
+ Handle = reduce(lambda x,y: x and y, IfStack)
else:
- Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0])
+ Handle = True
+ if Handle:
+ Match = re.match("!include\s+(.+)", DscLine)
if Match:
- Result = self.EvaluateExpress(Match.group(2))
- if Match.group(1) == "if":
- ElifStack.append(0)
- IfStack.append(Result)
- else: #elseif
- if IfStack:
- IfStack[-1] = not IfStack[-1]
- IfStack.append(Result)
- ElifStack[-1] = ElifStack[-1] + 1
- else:
- print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
- raise SystemExit
- else:
- if IfStack:
- Handle = reduce(lambda x,y: x and y, IfStack)
+ IncludeFilePath = Match.group(1)
+ IncludeFilePath = self.ExpandMacros(IncludeFilePath)
+ PackagesPath = os.getenv("PACKAGES_PATH")
+ if PackagesPath:
+ for PackagePath in PackagesPath.split(os.pathsep):
+ IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
+ if os.path.exists(IncludeFilePathAbs):
+ IncludeDsc = open(IncludeFilePathAbs, "r")
+ break
else:
- Handle = True
- if Handle:
- Match = re.match("!include\s+(.+)", DscLine)
- if Match:
- IncludeFilePath = Match.group(1)
- IncludeFilePath = self.ExpandMacros(IncludeFilePath)
- PackagesPath = os.getenv("PACKAGES_PATH")
- if PackagesPath:
- for PackagePath in PackagesPath.split(os.pathsep):
- IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
- if os.path.exists(IncludeFilePathAbs):
- IncludeDsc = open(IncludeFilePathAbs, "r")
- break
- else:
- IncludeDsc = open(IncludeFilePath, "r")
- if IncludeDsc == None:
- print("ERROR: Cannot open file '%s'" % IncludeFilePath)
- raise SystemExit
-
- # Update DscTime when newer DSC time found.
- CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name))
- if CurrentDscTime > self._DscTime:
- self._DscTime = CurrentDscTime
-
- NewDscLines = IncludeDsc.readlines()
- IncludeDsc.close()
- DscLines = NewDscLines + DscLines
- Offset = 0
- else:
- if DscLine.startswith('!'):
- print("ERROR: Unrecognized directive for line '%s'" % DscLine)
- raise SystemExit
+ IncludeDsc = open(IncludeFilePath, "r")
+ if IncludeDsc == None:
+ print("ERROR: Cannot open file '%s'" % IncludeFilePath)
+ raise SystemExit
+
+ # Update DscTime when newer DSC time found.
+ CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name))
+ if CurrentDscTime > self._DscTime:
+ self._DscTime = CurrentDscTime
+
+ NewDscLines = IncludeDsc.readlines()
+ IncludeDsc.close()
+ DscLines = NewDscLines + DscLines
+ del self._DscLines[-1]
+ Offset = 0
+ else:
+ if DscLine.startswith('!'):
+ print("ERROR: Unrecognized directive for line '%s'" % DscLine)
+ raise SystemExit
if not Handle:
+ del self._DscLines[-1]
continue
if IsDefSect:
@@ -556,7 +660,7 @@ EndList
#DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
#DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
#DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
- Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([/$()-.\w]+)", DscLine)
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine)
if Match:
self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2))
if self.Debug:
@@ -575,6 +679,23 @@ EndList
if Match:
self._PcdsDict[Match.group(1)] = Match.group(2)
i += 1
+
+ elif IsTmpSect:
+ # !BSF DEFT:{GPIO_TMPL:START}
+ Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine)
+ if Match:
+ if Match.group(3) == 'START' and not TemplateName:
+ TemplateName = Match.group(2).strip()
+ self._BsfTempDict[TemplateName] = []
+ if Match.group(3) == 'END' and (TemplateName == Match.group(2).strip()) and TemplateName:
+ TemplateName = ''
+ else:
+ if TemplateName:
+ Match = re.match("^!include\s*(.+)?$", DscLine)
+ if Match:
+ continue
+ self._BsfTempDict[TemplateName].append(DscLine)
+
else:
Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)
if Match:
@@ -630,9 +751,9 @@ EndList
Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)
if Match:
if "0x" in Match.group(2) or "0x" in Match.group(3):
- ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
+ ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
else:
- ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
+ ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
Match = re.match("^\s*##\s+(.+)", DscLine)
if Match:
@@ -748,6 +869,7 @@ EndList
ConfigDict['struct'] = ''
ConfigDict['embed'] = ''
ConfigDict['comment'] = ''
+ ConfigDict['marker'] = ''
ConfigDict['order'] = -1
ConfigDict['subreg'] = []
ConfigDict['option'] = ''
@@ -786,9 +908,8 @@ EndList
bitsvalue = bitsvalue[::-1]
bitslen = len(bitsvalue)
if start > bitslen or end > bitslen:
- print ("Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name']))
- raise SystemExit
- return hex(int(bitsvalue[start:end][::-1], 2))
+ raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))
+ return '0x%X' % (int(bitsvalue[start:end][::-1], 2))
def UpdateSubRegionDefaultValue (self):
Error = 0
@@ -888,63 +1009,142 @@ EndList
TxtFd.close()
return 0
- def ProcessMultilines (self, String, MaxCharLength):
- Multilines = ''
- StringLength = len(String)
- CurrentStringStart = 0
- StringOffset = 0
- BreakLineDict = []
- if len(String) <= MaxCharLength:
- while (StringOffset < StringLength):
- if StringOffset >= 1:
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
- BreakLineDict.append (StringOffset + 1)
- StringOffset += 1
- if BreakLineDict != []:
- for Each in BreakLineDict:
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
- CurrentStringStart = Each
- if StringLength - CurrentStringStart > 0:
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ def CreateVarDict (self):
+ Error = 0
+ self._VarDict = {}
+ if len(self._CfgItemList) > 0:
+ Item = self._CfgItemList[-1]
+ self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])
+ for Item in self._CfgItemList:
+ Embed = Item['embed']
+ Match = re.match("^(\w+):(\w+):(START|END)", Embed)
+ if Match:
+ StructName = Match.group(1)
+ VarName = '_%s_%s_' % (Match.group(3), StructName)
+ if Match.group(3) == 'END':
+ self._VarDict[VarName] = Item['offset'] + Item['length']
+ self._VarDict['_LENGTH_%s_' % StructName] = \
+ self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]
+ if Match.group(2).startswith('TAG_'):
+ if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):
+ raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))
+ self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF
else:
- Multilines = " %s\n" % String
+ self._VarDict[VarName] = Item['offset']
+ if Item['marker']:
+ self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']
+ return Error
+
+ def UpdateBsfBitUnit (self, Item):
+ BitTotal = 0
+ BitOffset = 0
+ StartIdx = 0
+ Unit = None
+ UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}
+ for Idx, SubItem in enumerate(Item['subreg']):
+ if Unit is None:
+ Unit = SubItem['bitunit']
+ BitLength = SubItem['bitlength']
+ BitTotal += BitLength
+ BitOffset += BitLength
+
+ if BitOffset > 64 or BitOffset > Unit * 8:
+ break
+
+ if BitOffset == Unit * 8:
+ for SubIdx in range (StartIdx, Idx + 1):
+ Item['subreg'][SubIdx]['bitunit'] = Unit
+ BitOffset = 0
+ StartIdx = Idx + 1
+ Unit = None
+
+ if BitOffset > 0:
+ raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))
+
+ ExpectedTotal = Item['length'] * 8
+ if Item['length'] * 8 != BitTotal:
+ raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))
+
+ def UpdateDefaultValue (self):
+ Error = 0
+ for Idx, Item in enumerate(self._CfgItemList):
+ if len(Item['subreg']) == 0:
+ Value = Item['value']
+ if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):
+ # {XXX} or 'XXX' strings
+ self.FormatListValue(self._CfgItemList[Idx])
+ else:
+ Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)
+ if not Match:
+ NumValue = self.EvaluateExpress (Value)
+ Item['value'] = '0x%X' % NumValue
else:
- NewLineStart = 0
- NewLineCount = 0
- FoundSpaceChar = False
- while (StringOffset < StringLength):
- if StringOffset >= 1:
- if NewLineCount >= MaxCharLength - 1:
- if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
- BreakLineDict.append (NewLineStart + NewLineCount)
- NewLineStart = NewLineStart + NewLineCount
- NewLineCount = 0
- FoundSpaceChar = True
- elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
- BreakLineDict.append (0)
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
- BreakLineDict.append (StringOffset + 1)
- NewLineStart = StringOffset + 1
+ ValArray = self.ValueToByteArray (Item['value'], Item['length'])
+ for SubItem in Item['subreg']:
+ SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)
+ self.UpdateBsfBitUnit (Item)
+ return Error
+
+ def ProcessMultilines (self, String, MaxCharLength):
+ Multilines = ''
+ StringLength = len(String)
+ CurrentStringStart = 0
+ StringOffset = 0
+ BreakLineDict = []
+ if len(String) <= MaxCharLength:
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ StringOffset += 1
+ if BreakLineDict != []:
+ for Each in BreakLineDict:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ else:
+ Multilines = " %s\n" % String
+ else:
+ NewLineStart = 0
+ NewLineCount = 0
+ FoundSpaceChar = False
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if NewLineCount >= MaxCharLength - 1:
+ if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
+ BreakLineDict.append (NewLineStart + NewLineCount)
+ NewLineStart = NewLineStart + NewLineCount
NewLineCount = 0
- StringOffset += 1
- NewLineCount += 1
- if BreakLineDict != []:
- BreakLineDict.sort ()
- for Each in BreakLineDict:
- if Each > 0:
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
- CurrentStringStart = Each
- if StringLength - CurrentStringStart > 0:
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
- return Multilines
-
- def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):
+ FoundSpaceChar = True
+ elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
+ BreakLineDict.append (0)
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ NewLineStart = StringOffset + 1
+ NewLineCount = 0
+ StringOffset += 1
+ NewLineCount += 1
+ if BreakLineDict != []:
+ BreakLineDict.sort ()
+ for Each in BreakLineDict:
+ if Each > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ return Multilines
+
+ def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):
PosName = 28
PosComment = 30
NameLine=''
HelpLine=''
OptionLine=''
+ if Length == 0 and Name == 'Dummy':
+ return '\n'
+
IsArray = False
if Length in [1,2,4,8]:
Type = "UINT%d" % (Length * 8)
@@ -992,7 +1192,12 @@ EndList
else:
OffsetStr = '0x%04X' % Offset
- return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)
+ if BitsLength is None:
+ BitsLength = ''
+ else:
+ BitsLength = ' : %d' % BitsLength
+
+ return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)
def PostProcessBody (self, TextBody):
NewTextBody = []
@@ -1097,6 +1302,7 @@ EndList
UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
for Item in self._CfgItemList:
if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:
+ Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting
UpdOffsetTable.append (Item["offset"])
for UpdIdx in range(len(UpdOffsetTable)):
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h b/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
new file mode 100644
index 0000000000..be2ed8aa99
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
@@ -0,0 +1,16 @@
+#ifndef __FSPUPD_H__
+#define __FSPUPD_H__
+
+#include <FspEas.h>
+
+#pragma pack(1)
+
+#define FSPT_UPD_SIGNATURE 0x545F4450554D4551 /* 'QEMUPD_T' */
+
+#define FSPM_UPD_SIGNATURE 0x4D5F4450554D4551 /* 'QEMUPD_M' */
+
+#define FSPS_UPD_SIGNATURE 0x535F4450554D4551 /* 'QEMUPD_S' */
+
+#pragma pack()
+
+#endif
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h b/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
new file mode 100644
index 0000000000..49dadbac62
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
@@ -0,0 +1,75 @@
+#ifndef __FSPMUPD_H__
+#define __FSPMUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp M Configuration
+**/
+typedef struct {
+
+/** Offset 0x00C8 - Debug Serial Port Base address
+ Debug serial port base address. This option will be used only when the 'Serial Port
+ Debug Device' option is set to 'External Device'. 0x00000000(Default).
+**/
+ UINT32 SerialDebugPortAddress;
+
+/** Offset 0x00CC - Debug Serial Port Type
+ 16550 compatible debug serial port resource type. NONE means no serial port support.
+ 0x02:MMIO(Default).
+ 0:NONE, 1:I/O, 2:MMIO
+**/
+ UINT8 SerialDebugPortType;
+
+/** Offset 0x00CD - Serial Port Debug Device
+ Select active serial port device for debug.For SOC UART devices,'Debug Serial Port
+ Base' options will be ignored. 0x02:SOC UART2(Default).
+ 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+**/
+ UINT8 SerialDebugPortDevice;
+
+/** Offset 0x00CE - Debug Serial Port Stride Size
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ 0:1, 2:4
+**/
+ UINT8 SerialDebugPortStrideSize;
+
+/** Offset 0x00CF
+**/
+ UINT8 UnusedUpdSpace2[1];
+
+/** Offset 0x00D0
+**/
+ UINT8 ReservedFspmUpd[4];
+} FSP_M_CONFIG;
+
+/** Fsp M UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00A8
+**/
+ FSPM_ARCH_UPD FspmArchUpd;
+
+/** Offset 0x00C8
+**/
+ FSP_M_CONFIG FspmConfig;
+
+/** Offset 0x00D4
+**/
+ UINT8 UnusedUpdSpace3[2];
+
+/** Offset 0x00D6
+**/
+ UINT16 UpdTerminator;
+} FSPM_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h b/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
new file mode 100644
index 0000000000..e2bc54a61d
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
@@ -0,0 +1,69 @@
+#ifndef __FSPSUPD_H__
+#define __FSPSUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp S Configuration
+**/
+typedef struct {
+
+/** Offset 0x0118 - BMP Logo Data Size
+ BMP logo data buffer size. 0x00000000(Default).
+**/
+ UINT32 LogoSize;
+
+/** Offset 0x011C - BMP Logo Data Pointer
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+**/
+ UINT32 LogoPtr;
+
+/** Offset 0x0120 - Graphics Configuration Data Pointer
+ Graphics configuration data used for initialization. 0x00000000(Default).
+**/
+ UINT32 GraphicsConfigPtr;
+
+/** Offset 0x0124 - PCI GFX Temporary MMIO Base
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+**/
+ UINT32 PciTempResourceBase;
+
+/** Offset 0x0128
+**/
+ UINT8 UnusedUpdSpace1[3];
+
+/** Offset 0x012B
+**/
+ UINT8 ReservedFspsUpd;
+} FSP_S_CONFIG;
+
+/** Fsp S UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00F8
+**/
+ FSPS_ARCH_UPD FspsArchUpd;
+
+/** Offset 0x0118
+**/
+ FSP_S_CONFIG FspsConfig;
+
+/** Offset 0x012C
+**/
+ UINT8 UnusedUpdSpace2[2];
+
+/** Offset 0x012E
+**/
+ UINT16 UpdTerminator;
+} FSPS_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h b/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
new file mode 100644
index 0000000000..25b8a7d63a
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
@@ -0,0 +1,87 @@
+#ifndef __FSPTUPD_H__
+#define __FSPTUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp T Common UPD
+**/
+typedef struct {
+
+/** Offset 0x0040
+**/
+ UINT8 Revision;
+
+/** Offset 0x0041
+**/
+ UINT8 Reserved[3];
+
+/** Offset 0x0044
+**/
+ UINT32 MicrocodeRegionBase;
+
+/** Offset 0x0048
+**/
+ UINT32 MicrocodeRegionLength;
+
+/** Offset 0x004C
+**/
+ UINT32 CodeRegionBase;
+
+/** Offset 0x0050
+**/
+ UINT32 CodeRegionLength;
+
+/** Offset 0x0054
+**/
+ UINT8 Reserved1[12];
+} FSPT_COMMON_UPD;
+
+/** Fsp T Configuration
+**/
+typedef struct {
+
+/** Offset 0x0060 - Chicken bytes to test Hex config
+ This option shows how to present option for 4 bytes data
+**/
+ UINT32 ChickenBytes;
+
+/** Offset 0x0064
+**/
+ UINT8 ReservedFsptUpd1[28];
+} FSP_T_CONFIG;
+
+/** Fsp T UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x0020
+**/
+ FSPT_ARCH_UPD FsptArchUpd;
+
+/** Offset 0x0040
+**/
+ FSPT_COMMON_UPD FsptCommonUpd;
+
+/** Offset 0x0060
+**/
+ FSP_T_CONFIG FsptConfig;
+
+/** Offset 0x0080
+**/
+ UINT8 UnusedUpdSpace0[6];
+
+/** Offset 0x0086
+**/
+ UINT16 UpdTerminator;
+} FSPT_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf b/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
new file mode 100644
index 0000000000..c4a041dcd5
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
@@ -0,0 +1,88 @@
+GlobalDataDef
+ SKUID = 0, "DEFAULT"
+EndGlobalData
+
+
+StructDef
+
+ Find "QEMUPD_T"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 87 bytes
+ $gQemuFspPkgTokenSpaceGuid_ChickenBytes 4 bytes $_DEFAULT_ = 0x00000000
+
+ Find "QEMUPD_M"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 35 bytes
+ $gQemuFspPkgTokenSpaceGuid_StackBase 4 bytes $_DEFAULT_ = 0x00070000
+ $gQemuFspPkgTokenSpaceGuid_StackSize 4 bytes $_DEFAULT_ = 0x00010000
+ $gQemuFspPkgTokenSpaceGuid_BootLoaderTolumSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gPlatformFspPkgTokenSpaceGuid_Bootmode 4 bytes $_DEFAULT_ = 0x00000000
+ Skip 8 bytes
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize 1 bytes $_DEFAULT_ = 0x02
+
+ Find "QEMUPD_S"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 55 bytes
+ $gQemuFspPkgTokenSpaceGuid_LogoSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_LogoPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_GraphicsConfigPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase 4 bytes $_DEFAULT_ = 0x80000000
+
+EndStruct
+
+
+List &EN_DIS
+ Selection 0x1 , "Enabled"
+ Selection 0x0 , "Disabled"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType
+ Selection 0 , "NONE"
+ Selection 1 , "I/O"
+ Selection 2 , "MMIO"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice
+ Selection 0 , "SOC UART0"
+ Selection 1 , "SOC UART1"
+ Selection 2 , "SOC UART2"
+ Selection 3 , "External Device"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize
+ Selection 0 , "1"
+ Selection 2 , "4"
+EndList
+
+BeginInfoBlock
+ PPVer "0.1"
+ Description "QEMU Platform"
+EndInfoBlock
+
+Page "FSP T"
+ EditNum $gQemuFspPkgTokenSpaceGuid_ChickenBytes, "Chicken bytes to test Hex config", HEX,
+ Help "This option shows how to present option for 4 bytes data"
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+EndPage
+
+Page "FSP MemoryInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress, "Debug Serial Port Base address", HEX,
+ Help "Debug serial port base address. This option will be used only when the 'Serial Port Debug Device' option is set to 'External Device'. 0x00000000(Default)."
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType, "Debug Serial Port Type", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType,
+ Help "16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice, "Serial Port Debug Device", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice,
+ Help "Select active serial port device for debug.For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize, "Debug Serial Port Stride Size", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize,
+ Help "Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default)."
+EndPage
+
+Page "FSP SiliconInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase, "PCI GFX Temporary MMIO Base", HEX,
+ Help "PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default)."
+ "Valid range: 0x80000000 ~ 0xDFFFFFFF"
+EndPage
+
diff --git a/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml b/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
new file mode 100644
index 0000000000..8f90ff316e
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
@@ -0,0 +1,267 @@
+variable:
+ PLATFORM_NAME : QemuFspPkg
+ PLATFORM_GUID : 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION : 0.1
+ DSC_SPECIFICATION : 0x00010005
+ OUTPUT_DIRECTORY : Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES : IA32|X64
+ BUILD_TARGETS : DEBUG|RELEASE
+ SKUID_IDENTIFIER : DEFAULT
+ FLASH_DEFINITION : QemuFspPkg/QemuFspPkg.fdf
+ FSP_T_UPD_TOOL_GUID : 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID : 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID : 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID : CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID : 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID : 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID : D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID : E3CD9B18-998C-4F76-B65E-98B154E5446F
+ FSP_PACKAGE : QemuFspPkg
+ FSP_IMAGE_ID : 0x245053464D455124 # $QEMFSP$
+ FSP_IMAGE_REV : 0x00001010
+ CAR_BASE_ADDRESS : 0x00000000
+ CAR_REGION_SIZE : 0x00080000
+ CAR_BLD_REGION_SIZE : 0x00070000
+ CAR_FSP_REGION_SIZE : 0x00010000
+ FSP_ARCH : X64
+
+
+template:
+
+
+configs:
+ - $ACTION :
+ page : TMP::"FSP T", MEM::"FSP MemoryInit Settings", SIL::"FSP SiliconInit Settings"
+ - $ACTION :
+ find : QEMUPD_T
+ - FSPT_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x545F4450554D4551
+ - Revision :
+ name : FsptUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPT_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspDebugHandler :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x14
+ value : {0x00}
+ - FSPT_COMMON_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - MicrocodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - MicrocodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x0C
+ value : {0x00}
+ - FSP_T_CONFIG :
+ - $ACTION :
+ page : TMP
+ - ChickenBytes :
+ name : Chicken bytes to test Hex config
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ This option shows how to present option for 4 bytes data
+ length : 0x04
+ value : 0x00000000
+ - ReservedFsptUpd1 :
+ length : 0x1C
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_M
+ - FSPM_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x4D5F4450554D4551
+ - Revision :
+ name : FspmUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPM_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - NvsBufferPtr :
+ struct : VOID*
+ length : 0x04
+ value : 0x00000000
+ - StackBase :
+ struct : VOID*
+ name : StackBase
+ help : >
+ Stack base for FSP use. Default- 0xFEF16000
+ length : 0x04
+ value : $(CAR_BLD_REGION_SIZE)
+ - StackSize :
+ name : StackSize
+ help : >
+ To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default- 0x2A000
+ length : 0x04
+ value : $(CAR_FSP_REGION_SIZE)
+ - BootLoaderTolumSize :
+ name : BootLoaderTolumSize
+ help : >
+ To pass Bootloader Tolum size.
+ length : 0x04
+ value : 0x00000000
+ - Bootmode :
+ name : Bootmode
+ help : >
+ To maintain Bootmode details.
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x08
+ value : {0x00}
+ - FSP_M_CONFIG :
+ - $ACTION :
+ page : MEM
+ - SerialDebugPortAddress :
+ name : Debug Serial Port Base address
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'
+ option is set to 'External Device'. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - SerialDebugPortType :
+ name : Debug Serial Port Type
+ type : Combo
+ option : 0:NONE, 1:I/O, 2:MMIO
+ help : >
+ 16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortDevice :
+ name : Serial Port Debug Device
+ type : Combo
+ option : 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+ help : >
+ Select active serial port device for debug.
+ For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortStrideSize :
+ name : Debug Serial Port Stride Size
+ type : Combo
+ option : 0:1, 2:4
+ help : >
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ length : 0x01
+ value : 0x02
+ - ReservedFspmUpd :
+ length : 0x04
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_S
+ - FSPS_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x535F4450554D4551
+ - Revision :
+ name : FspsUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPS_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspEventHandler :
+ length : 0x04
+ value : 0x00000000
+ - EnableMultiPhaseSiliconInit :
+ length : 0x01
+ value : 0x00
+ - Reserved1 :
+ length : 0x13
+ value : {0x00}
+ - FSP_S_CONFIG :
+ - $ACTION :
+ page : SIL
+ - LogoSize :
+ name : BMP Logo Data Size
+ type : Reserved
+ help : >
+ BMP logo data buffer size. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - LogoPtr :
+ name : BMP Logo Data Pointer
+ type : Reserved
+ help : >
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - GraphicsConfigPtr :
+ name : Graphics Configuration Data Pointer
+ type : Reserved
+ help : >
+ Graphics configuration data used for initialization. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - PciTempResourceBase :
+ name : PCI GFX Temporary MMIO Base
+ type : EditNum, HEX, (0x80000000,0xDFFFFFFF)
+ help : >
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+ length : 0x04
+ value : 0x80000000
+ - ReservedFspsUpd :
+ length : 0x01
+ value : 0x00
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
diff --git a/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc b/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
new file mode 100644
index 0000000000..bc4912313a
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
@@ -0,0 +1,469 @@
+## @file
+# FSP DSC build file for QEMU platform
+#
+# Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = QemuFspPkg
+ PLATFORM_GUID = 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = QemuFspPkg/QemuFspPkg.fdf
+
+ #
+ # UPD tool definition
+ #
+ FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID = 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID = 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID = 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID = D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID = E3CD9B18-998C-4F76-B65E-98B154E5446F
+
+ #
+ # Set platform specific package/folder name, same as passed from PREBUILD script.
+ # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder
+ # DEFINE only takes effect at R9 DSC and FDF.
+ #
+ DEFINE FSP_PACKAGE = QemuFspPkg
+ DEFINE FSP_IMAGE_ID = 0x245053464D455124 # $QEMFSP$
+ DEFINE FSP_IMAGE_REV = 0x00001010
+
+ DEFINE CAR_BASE_ADDRESS = 0x00000000
+ DEFINE CAR_REGION_SIZE = 0x00080000
+ DEFINE CAR_BLD_REGION_SIZE = 0x00070000
+ DEFINE CAR_FSP_REGION_SIZE = 0x00010000
+
+ DEFINE FSP_ARCH = X64
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+[LibraryClasses]
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ CacheLib|IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
+ CacheAsRamLib|IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+ FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+!if $(TARGET) == DEBUG
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+!endif
+
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot | TRUE
+ gQemuFspPkgTokenSpaceGuid.PcdFspHeaderRevision | 0x03
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageIdString | $(FSP_IMAGE_ID)
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageRevision | $(FSP_IMAGE_REV)
+ #
+ # FSP CAR Usages (BL RAM | FSP RAM | FSP CODE)
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase | $(CAR_BASE_ADDRESS)
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize | $(CAR_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize | $(CAR_FSP_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize | 0x0100
+
+ # This defines how much space will be used for heap in FSP temporary memory
+ # x % of FSP temporary memory will be used for heap
+ # (100 - x) % of FSP temporary memory will be used for stack
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage | 65
+
+ # This is a platform specific global pointer used by FSP
+ gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress | 0xFED00148
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength | 0x00100000
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x00000000
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x80000047
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0x27
+!endif
+
+[PcdsPatchableInModule]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress | 0xE0000000
+ #
+ # This entry will be patched during the build process
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress | 0x12345678
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0x80000047
+!endif
+
+[PcdsDynamicVpd.Upd]
+ #
+ # This section is not used by the normal build process
+ # However, FSP will use dedicated tool to handle it and generate a
+ # VPD similar binary block (User Configuration Data). This block will
+ # be accessed through a generated data structure directly rather than
+ # PCD services. This is for size consideration.
+ # Format:
+ # gQemuFspPkgTokenSpaceGuid.Updxxxxxxxxxxxxn | OFFSET | LENGTH | VALUE
+ # Only simple data type is supported
+ #
+
+ #
+ # Comments with !BSF will be used to generate BSF file
+ # Comments with !HDR will be used to generate H header file
+ #
+
+ # Global definitions in BSF
+ # !BSF PAGES:{TMP:"FSP T", MEM:"FSP MemoryInit Settings", SIL:"FSP SiliconInit Settings"}
+ # !BSF BLOCK:{NAME:"QEMU Platform", VER:"0.1"}
+
+ # !BSF FIND:{QEMUPD_T}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FsptUpdSignature: {QEMUPD_T}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x545F4450554D4551
+ # !BSF NAME:{FsptUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPT_ARCH_UPD:FSPT_ARCH_UPD}
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspDebugHandler | * | 0x04 | 0x00000000
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x14 | {0x00}
+
+ # !HDR COMMENT:{FSPT_COMMON_UPD:Fsp T Common UPD}
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # Base address of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionLength | * | 0x04 | 0x00000000
+
+ # Base address of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionLength | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x0C | {0x00}
+
+ # !HDR COMMENT:{FSP_T_CONFIG:Fsp T Configuration}
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:START}
+ # !BSF PAGE:{TMP}
+ # !BSF NAME:{Chicken bytes to test Hex config}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{This option shows how to present option for 4 bytes data}
+ gQemuFspPkgTokenSpaceGuid.ChickenBytes | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFsptUpd1 | * | 0x1C | {0x00}
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspMemoryInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_M}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspmUpdSignature: {QEMUPD_M}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x4D5F4450554D4551
+ # !BSF NAME:{FspmUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPM_ARCH_UPD:Fsp M Architectural UPD}
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:START}
+
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # !HDR STRUCT:{VOID*}
+ gQemuFspPkgTokenSpaceGuid.NvsBufferPtr | * | 0x04 | 0x00000000
+
+ # !HDR STRUCT:{VOID*}
+ # !BSF NAME:{StackBase}
+ # !BSF HELP:{Stack base for FSP use. Default: 0xFEF16000}
+ gQemuFspPkgTokenSpaceGuid.StackBase | * | 0x04 | $(CAR_BLD_REGION_SIZE)
+
+ # !BSF NAME:{StackSize}
+ # !BSF HELP:{To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default: 0x2A000}
+ gQemuFspPkgTokenSpaceGuid.StackSize | * | 0x04 | $(CAR_FSP_REGION_SIZE)
+
+ # !BSF NAME:{BootLoaderTolumSize}
+ # !BSF HELP:{To pass Bootloader Tolum size.}
+ gQemuFspPkgTokenSpaceGuid.BootLoaderTolumSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Bootmode}
+ # !BSF HELP:{To maintain Bootmode details.}
+ gPlatformFspPkgTokenSpaceGuid.Bootmode | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x08 | {0x00}
+
+ # !HDR COMMENT:{FSP_M_CONFIG:Fsp M Configuration}
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:START}
+ # !BSF PAGE:{MEM}
+ # !BSF NAME:{Debug Serial Port Base address}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'}
+ # !BSF HELP:{+ option is set to 'External Device'. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortAddress | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Debug Serial Port Type} TYPE:{Combo}
+ # !BSF OPTION:{0:NONE, 1:I/O, 2:MMIO}
+ # !BSF HELP:{16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortType | * | 0x01 | 0x02
+
+ # !BSF NAME:{Serial Port Debug Device} TYPE:{Combo}
+ # !BSF OPTION:{0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device}
+ # !BSF HELP:{Select active serial port device for debug.}
+ # !BSF HELP:{+For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortDevice | * | 0x01 | 0x02
+
+ # !BSF NAME:{Debug Serial Port Stride Size} TYPE:{Combo}
+ # !BSF OPTION:{0:1, 2:4}
+ # !BSF HELP:{Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortStrideSize | * | 0x01 | 0x02
+
+
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspmUpd | * | 0x04 | {0x00}
+
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspSiliconInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_S}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspsUpdSignature: {QEMUPD_S}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x535F4450554D4551
+ # !BSF NAME:{FspsUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPS_ARCH_UPD:FSPS_ARCH_UPD}
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspEventHandler | * | 0x04 | 0x00000000
+ gQemuFspPkgTokenSpaceGuid.EnableMultiPhaseSiliconInit | * | 0x01 | 0x00
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x13 | {0x00}
+
+ # !HDR COMMENT:{FSP_S_CONFIG:Fsp S Configuration}
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:START}
+ # !BSF PAGE:{SIL}
+
+ # !BSF NAME:{BMP Logo Data Size}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data buffer size. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{BMP Logo Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data pointer to a BMP format buffer. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Graphics Configuration Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{Graphics configuration data used for initialization. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.GraphicsConfigPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{PCI GFX Temporary MMIO Base}
+ # !BSF TYPE:{EditNum, HEX, (0x80000000,0xDFFFFFFF)}
+ # !BSF HELP:{PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.PciTempResourceBase | * | 0x04 | 0x80000000
+
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspsUpd | * | 0x01 | 0x00
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+[Components.IA32]
+ #
+ # FSP Binary Components
+ #
+ $(FSP_PACKAGE)/FspHeader/FspHeader.inf
+
+ #
+ # SEC
+ #
+ IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecTLib.inf
+ }
+
+[Components.$(FSP_ARCH)]
+ IntelFsp2Pkg/FspSecCore/FspSecCoreV.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecVLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecMLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecSLib.inf
+ }
+
+ #
+ # PEI Core
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+
+ #
+ # PCD
+ #
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ $(FSP_PACKAGE)/FspvInit/FspvInit.inf
+ $(FSP_PACKAGE)/FspmInit/FspmInit.inf
+ $(FSP_PACKAGE)/FspsInit/FspsInit.inf
+ $(FSP_PACKAGE)/QemuVideo/QemuVideo.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ }
+ IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
+
+###################################################################################################
+#
+# BuildOptions Section - Define the module specific tool chain flags that should be used as
+# the default flags for a module. These flags are appended to any
+# standard flags that are defined by the build process. They can be
+# applied for any modules or only those modules with the specific
+# module style (EDK or EDKII) specified in [Components] section.
+#
+###################################################################################################
+[BuildOptions]
+# Append build options for EDK and EDKII drivers (= is Append, == is Replace)
+ # Enable link-time optimization when building with GCC49
+ *_GCC49_IA32_CC_FLAGS = -flto
+ *_GCC49_IA32_DLINK_FLAGS = -flto
+ *_GCC5_IA32_CC_FLAGS = -fno-pic
+ *_GCC5_IA32_DLINK_FLAGS = -no-pie
+ *_GCC5_IA32_ASLCC_FLAGS = -fno-pic
+ *_GCC5_IA32_ASLDLINK_FLAGS = -no-pie
diff --git a/IntelFsp2Pkg/Tools/Tests/test_yaml.py b/IntelFsp2Pkg/Tools/Tests/test_yaml.py
new file mode 100644
index 0000000000..d81d7f7c4e
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/Tests/test_yaml.py
@@ -0,0 +1,96 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+import unittest
+import tempfile
+import os
+import shutil
+import struct as st
+import filecmp
+
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+import FspDscBsf2Yaml
+
+YamlHeaderLineLength = 10
+HdrFileHeaderLineLength = 32
+BsfFileHeaderLineLength = 19
+
+def GenFileWithoutHdr(inputfile, numLineToStrip):
+ yaml_file = open(inputfile, "r")
+ lines = yaml_file.readlines()
+ yaml_file.close()
+ del lines[:numLineToStrip]
+
+ noHdrOutputFileName = "no-header-" + inputfile
+ stripped_file = open(noHdrOutputFileName, "w")
+ for line in lines:
+ stripped_file.write(line)
+ stripped_file.close()
+ return noHdrOutputFileName
+
+class TestFspScripts(unittest.TestCase):
+ def test_generateFspHeader_fromDsc(self):
+ # Generate HEADER
+ cmd = '{} {} HEADER {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("FspUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspUpd.h'))
+
+ def test_generateFspsHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspsUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspsUpd.h'))
+
+ def test_generateFsptHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FsptUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFsptUpd.h'))
+
+ def test_generateFspmHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspmUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspmUpd.h'))
+
+ def test_generateBsf_fromDsc(self):
+ # Generate BSF
+ cmd = '{} {} GENBSF {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "Output.bsf")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.bsf", BsfFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.bsf'))
+
+ def test_generateYaml_fromDsc(self):
+ # Generate YAML
+ cmd = '{} {} {} {}'.format(
+ 'python',
+ '..\FspDscBsf2Yaml.py',
+ 'QemuFspPkg.dsc',
+ "Output.yaml")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.yaml", YamlHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.yaml'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md b/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
new file mode 100644
index 0000000000..ba2311445c
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
@@ -0,0 +1,39 @@
+#Name
+**FspDscBsf2Yaml.py** The python script that generates YAML file for
+the Boot Settings from an EDK II Platform Description (**DSC**) file
+or from a Boot Settings File (**BSF**). It is created to help
+transitioning FSP Updateable Product Data (**UPD**) file format to
+new standardized YAML format so that it can be configured through
+open source tools.
+
+#Synopsis
+```
+FspDscBsf2Yaml DscFile|BsfFile YamlFile
+```
+
+#Description
+**FspDscBsf2Yaml.py** is a script that generates configuration options from an
+**EDK II Platform Description (DSC)** file or **a Boot Settings File (BSF)** file.
+
+It generates a **YAML file** that can be used by the **Config Editor** to provide
+a graphical user interface for manipulating settings in the UPD regions.
+
+The following sections explain the usage of this script.
+
+## 1. FspDscBsf2Yaml.py DscFile YamlFile
+
+The **DscFile** option is an input DSC file.
+
+The **YamlFile** option is an output YAML file.
+
+The script takes the FSP DSC file consisting BSF syntax and generates a YAML
+output file describing the boot settings.
+
+## 2. FspDscBsf2Yaml.py BsfFile YamlFile
+
+The **BsfFile** option is an input BSF file.
+
+The **YamlFile** option is an output YAML file.
+
+The script generates a YAML output file from a BSF file. The BSF file
+can be generated using GenCfgOpt tool.