BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3396 This is a GUI interface that can be used by users who would like to change configuration settings directly from the interface without having to modify the source. This tool depends on Python GUI tool kit Tkinter. It runs on both Windows and Linux. The user needs to load the YAML file along with DLT file for a specific board into the ConfigEditor, change the desired configuration values. Finally, generate a new configuration delta file or a config binary blob for the newly changed values to take effect. These will be the inputs to the merge tool or the stitch tool so that new config changes can be merged and stitched into the final configuration blob. This tool also supports binary update directly and display FSP information. It is also backward compatible for BSF file format. Running Configuration Editor: python ConfigEditor.py Co-authored-by: Maurice Ma <maurice.ma@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Signed-off-by: Loo Tung Lun <tung.lun.loo@intel.com> Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
		
			
				
	
	
		
			2638 lines
		
	
	
		
			103 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2638 lines
		
	
	
		
			103 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# @ GenCfgData.py
 | 
						|
#
 | 
						|
# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
# SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
#
 | 
						|
##
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sys
 | 
						|
import marshal
 | 
						|
from functools import reduce
 | 
						|
from datetime import date
 | 
						|
 | 
						|
# Generated file copyright header
 | 
						|
 | 
						|
__copyright_tmp__ = """/** @file
 | 
						|
 | 
						|
  Configuration %s File.
 | 
						|
 | 
						|
  Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
  This file is automatically generated. Please do NOT modify !!!
 | 
						|
 | 
						|
**/
 | 
						|
"""
 | 
						|
 | 
						|
__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])
 | 
						|
 | 
						|
 | 
						|
def Bytes2Str(Bytes):
 | 
						|
    return '{ %s }' % (', '.join('0x%02X' % i for i in Bytes))
 | 
						|
 | 
						|
 | 
						|
def Str2Bytes(Value, Blen):
 | 
						|
    Result = bytearray(Value[1:-1], 'utf-8')  # Excluding quotes
 | 
						|
    if len(Result) < Blen:
 | 
						|
        Result.extend(b'\x00' * (Blen - len(Result)))
 | 
						|
    return Result
 | 
						|
 | 
						|
 | 
						|
def Val2Bytes(Value, Blen):
 | 
						|
    return [(Value >> (i * 8) & 0xff) for i in range(Blen)]
 | 
						|
 | 
						|
 | 
						|
def Array2Val(ValStr):
 | 
						|
    ValStr = ValStr.strip()
 | 
						|
    if ValStr.startswith('{'):
 | 
						|
        ValStr = ValStr[1:]
 | 
						|
    if ValStr.endswith('}'):
 | 
						|
        ValStr = ValStr[:-1]
 | 
						|
    if ValStr.startswith("'"):
 | 
						|
        ValStr = ValStr[1:]
 | 
						|
    if ValStr.endswith("'"):
 | 
						|
        ValStr = ValStr[:-1]
 | 
						|
    Value = 0
 | 
						|
    for Each in ValStr.split(',')[::-1]:
 | 
						|
        Each = Each.strip()
 | 
						|
        if Each.startswith('0x'):
 | 
						|
            Base = 16
 | 
						|
        else:
 | 
						|
            Base = 10
 | 
						|
        Value = (Value << 8) | int(Each, Base)
 | 
						|
    return Value
 | 
						|
 | 
						|
 | 
						|
def GetCopyrightHeader(FileType, AllowModify=False):
 | 
						|
    FileDescription = {
 | 
						|
        'bsf': 'Boot Setting',
 | 
						|
        'dsc': 'Definition',
 | 
						|
        'dlt': 'Delta',
 | 
						|
        'inc': 'C Binary Blob',
 | 
						|
        'h': 'C Struct Header'
 | 
						|
    }
 | 
						|
    if FileType in ['bsf', 'dsc', 'dlt']:
 | 
						|
        CommentChar = '#'
 | 
						|
    else:
 | 
						|
        CommentChar = ''
 | 
						|
    Lines = __copyright_tmp__.split('\n')
 | 
						|
 | 
						|
    if AllowModify:
 | 
						|
        Lines = [Line for Line in Lines if 'Please do NOT modify' not in Line]
 | 
						|
 | 
						|
    CopyrightHdr = '\n'.join('%s%s' % (
 | 
						|
        CommentChar, Line) for Line in Lines)[:-1] + '\n'
 | 
						|
 | 
						|
    return CopyrightHdr % (FileDescription[FileType], date.today().year)
 | 
						|
 | 
						|
 | 
						|
class CLogicalExpression:
 | 
						|
    def __init__(self):
 | 
						|
        self.index = 0
 | 
						|
        self.string = ''
 | 
						|
 | 
						|
    def errExit(self, err=''):
 | 
						|
        print("ERROR: Express parsing for:")
 | 
						|
        print("       %s" % self.string)
 | 
						|
        print("       %s^" % (' ' * self.index))
 | 
						|
        if err:
 | 
						|
            print("INFO : %s" % err)
 | 
						|
        raise SystemExit
 | 
						|
 | 
						|
    def getNonNumber(self, n1, n2):
 | 
						|
        if not n1.isdigit():
 | 
						|
            return n1
 | 
						|
        if not n2.isdigit():
 | 
						|
            return n2
 | 
						|
        return None
 | 
						|
 | 
						|
    def getCurr(self, lens=1):
 | 
						|
        try:
 | 
						|
            if lens == -1:
 | 
						|
                return self.string[self.index:]
 | 
						|
            else:
 | 
						|
                if self.index + lens > len(self.string):
 | 
						|
                    lens = len(self.string) - self.index
 | 
						|
                return self.string[self.index: self.index + lens]
 | 
						|
        except Exception:
 | 
						|
            return ''
 | 
						|
 | 
						|
    def isLast(self):
 | 
						|
        return self.index == len(self.string)
 | 
						|
 | 
						|
    def moveNext(self, len=1):
 | 
						|
        self.index += len
 | 
						|
 | 
						|
    def skipSpace(self):
 | 
						|
        while not self.isLast():
 | 
						|
            if self.getCurr() in ' \t':
 | 
						|
                self.moveNext()
 | 
						|
            else:
 | 
						|
                return
 | 
						|
 | 
						|
    def normNumber(self, val):
 | 
						|
        return True if val else False
 | 
						|
 | 
						|
    def getNumber(self, var):
 | 
						|
        var = var.strip()
 | 
						|
        if re.match('^0x[a-fA-F0-9]+$', var):
 | 
						|
            value = int(var, 16)
 | 
						|
        elif re.match('^[+-]?\\d+$', var):
 | 
						|
            value = int(var, 10)
 | 
						|
        else:
 | 
						|
            value = None
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseValue(self):
 | 
						|
        self.skipSpace()
 | 
						|
        var = ''
 | 
						|
        while not self.isLast():
 | 
						|
            char = self.getCurr()
 | 
						|
            if re.match('^[\\w.]', char):
 | 
						|
                var += char
 | 
						|
                self.moveNext()
 | 
						|
            else:
 | 
						|
                break
 | 
						|
        val = self.getNumber(var)
 | 
						|
        if val is None:
 | 
						|
            value = var
 | 
						|
        else:
 | 
						|
            value = "%d" % val
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseSingleOp(self):
 | 
						|
        self.skipSpace()
 | 
						|
        if re.match('^NOT\\W', self.getCurr(-1)):
 | 
						|
            self.moveNext(3)
 | 
						|
            op = self.parseBrace()
 | 
						|
            val = self.getNumber(op)
 | 
						|
            if val is None:
 | 
						|
                self.errExit("'%s' is not a number" % op)
 | 
						|
            return "%d" % (not self.normNumber(int(op)))
 | 
						|
        else:
 | 
						|
            return self.parseValue()
 | 
						|
 | 
						|
    def parseBrace(self):
 | 
						|
        self.skipSpace()
 | 
						|
        char = self.getCurr()
 | 
						|
        if char == '(':
 | 
						|
            self.moveNext()
 | 
						|
            value = self.parseExpr()
 | 
						|
            self.skipSpace()
 | 
						|
            if self.getCurr() != ')':
 | 
						|
                self.errExit("Expecting closing brace or operator")
 | 
						|
            self.moveNext()
 | 
						|
            return value
 | 
						|
        else:
 | 
						|
            value = self.parseSingleOp()
 | 
						|
            return value
 | 
						|
 | 
						|
    def parseCompare(self):
 | 
						|
        value = self.parseBrace()
 | 
						|
        while True:
 | 
						|
            self.skipSpace()
 | 
						|
            char = self.getCurr()
 | 
						|
            if char in ['<', '>']:
 | 
						|
                self.moveNext()
 | 
						|
                next = self.getCurr()
 | 
						|
                if next == '=':
 | 
						|
                    op = char + next
 | 
						|
                    self.moveNext()
 | 
						|
                else:
 | 
						|
                    op = char
 | 
						|
                result = self.parseBrace()
 | 
						|
                test = self.getNonNumber(result, value)
 | 
						|
                if test is None:
 | 
						|
                    value = "%d" % self.normNumber(eval(value + op + result))
 | 
						|
                else:
 | 
						|
                    self.errExit("'%s' is not a valid number for comparision"
 | 
						|
                                 % test)
 | 
						|
            elif char in ['=', '!']:
 | 
						|
                op = self.getCurr(2)
 | 
						|
                if op in ['==', '!=']:
 | 
						|
                    self.moveNext(2)
 | 
						|
                    result = self.parseBrace()
 | 
						|
                    test = self.getNonNumber(result, value)
 | 
						|
                    if test is None:
 | 
						|
                        value = "%d" % self.normNumber((eval(value + op
 | 
						|
                                                             + result)))
 | 
						|
                    else:
 | 
						|
                        value = "%d" % self.normNumber(eval("'" + value +
 | 
						|
                                                            "'" + op + "'" +
 | 
						|
                                                            result + "'"))
 | 
						|
                else:
 | 
						|
                    break
 | 
						|
            else:
 | 
						|
                break
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseAnd(self):
 | 
						|
        value = self.parseCompare()
 | 
						|
        while True:
 | 
						|
            self.skipSpace()
 | 
						|
            if re.match('^AND\\W', self.getCurr(-1)):
 | 
						|
                self.moveNext(3)
 | 
						|
                result = self.parseCompare()
 | 
						|
                test = self.getNonNumber(result, value)
 | 
						|
                if test is None:
 | 
						|
                    value = "%d" % self.normNumber(int(value) & int(result))
 | 
						|
                else:
 | 
						|
                    self.errExit("'%s' is not a valid op number for AND" %
 | 
						|
                                 test)
 | 
						|
            else:
 | 
						|
                break
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseOrXor(self):
 | 
						|
        value = self.parseAnd()
 | 
						|
        op = None
 | 
						|
        while True:
 | 
						|
            self.skipSpace()
 | 
						|
            op = None
 | 
						|
            if re.match('^XOR\\W', self.getCurr(-1)):
 | 
						|
                self.moveNext(3)
 | 
						|
                op = '^'
 | 
						|
            elif re.match('^OR\\W', self.getCurr(-1)):
 | 
						|
                self.moveNext(2)
 | 
						|
                op = '|'
 | 
						|
            else:
 | 
						|
                break
 | 
						|
            if op:
 | 
						|
                result = self.parseAnd()
 | 
						|
                test = self.getNonNumber(result, value)
 | 
						|
                if test is None:
 | 
						|
                    value = "%d" % self.normNumber(eval(value + op + result))
 | 
						|
                else:
 | 
						|
                    self.errExit("'%s' is not a valid op number for XOR/OR" %
 | 
						|
                                 test)
 | 
						|
        return value
 | 
						|
 | 
						|
    def parseExpr(self):
 | 
						|
        return self.parseOrXor()
 | 
						|
 | 
						|
    def getResult(self):
 | 
						|
        value = self.parseExpr()
 | 
						|
        self.skipSpace()
 | 
						|
        if not self.isLast():
 | 
						|
            self.errExit("Unexpected character found '%s'" % self.getCurr())
 | 
						|
        test = self.getNumber(value)
 | 
						|
        if test is None:
 | 
						|
            self.errExit("Result '%s' is not a number" % value)
 | 
						|
        return int(value)
 | 
						|
 | 
						|
    def evaluateExpress(self, Expr):
 | 
						|
        self.index = 0
 | 
						|
        self.string = Expr
 | 
						|
        if self.getResult():
 | 
						|
            Result = True
 | 
						|
        else:
 | 
						|
            Result = False
 | 
						|
        return Result
 | 
						|
 | 
						|
 | 
						|
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+(\$(.*?)|Skip)\s+',
 | 
						|
                           re.S | re.MULTILINE)
 | 
						|
        for match in regex.finditer(bsf_txt):
 | 
						|
            find = match.group(1)
 | 
						|
            name = match.group(3)
 | 
						|
            line = bsf_txt[:match.end()].count("\n")
 | 
						|
            find_list.append((name, find, line))
 | 
						|
 | 
						|
        idx = 0
 | 
						|
        count = 0
 | 
						|
        prefix = ''
 | 
						|
        chk_dict = {}
 | 
						|
        cfg_list = []
 | 
						|
        cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0',
 | 
						|
                    'type': 'Reserved', 'isbit': False,
 | 
						|
                    'embed': '', 'page': '', 'option': '', 'instance': 0}
 | 
						|
        regex = re.compile(
 | 
						|
            r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+(bits|bytes)(\s+\$_DEFAULT_\s'
 | 
						|
            r'+=\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(6)
 | 
						|
                option = ''
 | 
						|
            is_bit = True if match.group(4) == 'bits' else False
 | 
						|
 | 
						|
            cfg_item = dict(cfg_temp)
 | 
						|
            line = bsf_txt[:match.end()].count("\n")
 | 
						|
            finds = [i for i in find_list if line >= i[2]]
 | 
						|
            if len(finds) > 0:
 | 
						|
                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])
 | 
						|
                str2byte = Str2Bytes("'" + finds[0][1] + "'",
 | 
						|
                                     len(finds[0][1]))
 | 
						|
                cfg_item['value'] = '0x%X' % Bytes2Val(str2byte)
 | 
						|
 | 
						|
                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
 | 
						|
            cfg_item['isbit'] = is_bit
 | 
						|
 | 
						|
            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 = ''
 | 
						|
 | 
						|
        is_bit = False
 | 
						|
        dlen = 0
 | 
						|
        dval = 0
 | 
						|
        bit_fields = []
 | 
						|
        for idx, option in enumerate(option_list):
 | 
						|
            if not is_bit and option['isbit']:
 | 
						|
                is_bit = True
 | 
						|
                dlen = 0
 | 
						|
                dval = 0
 | 
						|
                idxs = idx
 | 
						|
            if is_bit and not option['isbit']:
 | 
						|
                is_bit = False
 | 
						|
                if dlen % 8 != 0:
 | 
						|
                    raise Exception("Bit fields are not aligned at "
 | 
						|
                                    "byte boundary !")
 | 
						|
                bit_fields.append((idxs, idx, dlen, dval))
 | 
						|
            if is_bit:
 | 
						|
                blen = option['length']
 | 
						|
                bval = int(option['value'], 0)
 | 
						|
                dval = dval + ((bval & ((1 << blen) - 1)) << dlen)
 | 
						|
                print(dlen, blen, bval, hex(dval))
 | 
						|
                dlen += blen
 | 
						|
 | 
						|
        struct_idx = 0
 | 
						|
        for idx, option in enumerate(option_list):
 | 
						|
            dsc_lines.append('')
 | 
						|
            default = option['value']
 | 
						|
            pos = option['cname'].find('_')
 | 
						|
            name = option['cname'][pos + 1:]
 | 
						|
 | 
						|
            for start_idx, end_idx, bits_len, bits_val in bit_fields:
 | 
						|
                if idx == start_idx:
 | 
						|
                    val_str = Bytes2Str(Val2Bytes(bits_val, bits_len // 8))
 | 
						|
                    dsc_lines.append('  # !HDR STRUCT:{BIT_FIELD_DATA_%d}'
 | 
						|
                                     % struct_idx)
 | 
						|
                    dsc_lines.append('  # !BSF NAME:{BIT_FIELD_STRUCT}')
 | 
						|
                    dsc_lines.append('  gCfgData.BitFiledStruct%d            '
 | 
						|
                                     ' | * | 0x%04X | %s' %
 | 
						|
                                     (struct_idx, bits_len // 8, val_str))
 | 
						|
                    dsc_lines.append('')
 | 
						|
                    struct_idx += 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
 | 
						|
 | 
						|
            if option['isbit']:
 | 
						|
                dsc_lines.append('  # !BSF FIELD:{%s:%db}'
 | 
						|
                                 % (name, option['length']))
 | 
						|
            else:
 | 
						|
                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 CGenCfgData:
 | 
						|
    def __init__(self, Mode=''):
 | 
						|
        self.Debug = False
 | 
						|
        self.Error = ''
 | 
						|
        self.ReleaseMode = True
 | 
						|
        self.Mode = Mode
 | 
						|
        self._GlobalDataDef = """
 | 
						|
GlobalDataDef
 | 
						|
    SKUID = 0, "DEFAULT"
 | 
						|
EndGlobalData
 | 
						|
 | 
						|
"""
 | 
						|
        self._BuidinOptionTxt = """
 | 
						|
List &EN_DIS
 | 
						|
    Selection 0x1 , "Enabled"
 | 
						|
    Selection 0x0 , "Disabled"
 | 
						|
EndList
 | 
						|
 | 
						|
"""
 | 
						|
        self._StructType = ['UINT8', 'UINT16', 'UINT32', 'UINT64']
 | 
						|
        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._CfgOptsDict = {}
 | 
						|
        self._BsfTempDict = {}
 | 
						|
        self._CfgItemList = []
 | 
						|
        self._DscLines = []
 | 
						|
        self._DscFile = ''
 | 
						|
        self._CfgPageTree = {}
 | 
						|
 | 
						|
        self._MapVer = 0
 | 
						|
        self._MinCfgTagId = 0x100
 | 
						|
 | 
						|
    def ParseMacros(self, MacroDefStr):
 | 
						|
        # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
 | 
						|
        self._MacroDict = {}
 | 
						|
        IsExpression = False
 | 
						|
        for Macro in MacroDefStr:
 | 
						|
            if Macro.startswith('-D'):
 | 
						|
                IsExpression = True
 | 
						|
                if len(Macro) > 2:
 | 
						|
                    Macro = Macro[2:]
 | 
						|
                else:
 | 
						|
                    continue
 | 
						|
            if IsExpression:
 | 
						|
                IsExpression = False
 | 
						|
                Match = re.match("(\\w+)=(.+)", Macro)
 | 
						|
                if Match:
 | 
						|
                    self._MacroDict[Match.group(1)] = Match.group(2)
 | 
						|
                else:
 | 
						|
                    Match = re.match("(\\w+)", Macro)
 | 
						|
                    if Match:
 | 
						|
                        self._MacroDict[Match.group(1)] = ''
 | 
						|
        if len(self._MacroDict) == 0:
 | 
						|
            Error = 1
 | 
						|
        else:
 | 
						|
            Error = 0
 | 
						|
            if self.Debug:
 | 
						|
                print("INFO : Macro dictionary:")
 | 
						|
                for Each in self._MacroDict:
 | 
						|
                    print("       $(%s) = [ %s ]" % (Each,
 | 
						|
                                                     self._MacroDict[Each]))
 | 
						|
        return Error
 | 
						|
 | 
						|
    def EvaulateIfdef(self, Macro):
 | 
						|
        Result = Macro in self._MacroDict
 | 
						|
        if self.Debug:
 | 
						|
            print("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))
 | 
						|
        return Result
 | 
						|
 | 
						|
    def ExpandMacros(self, Input, Preserve=False):
 | 
						|
        Line = Input
 | 
						|
        Match = re.findall("\\$\\(\\w+\\)", Input)
 | 
						|
        if Match:
 | 
						|
            for Each in Match:
 | 
						|
                Variable = Each[2:-1]
 | 
						|
                if Variable in self._MacroDict:
 | 
						|
                    Line = Line.replace(Each, self._MacroDict[Variable])
 | 
						|
                else:
 | 
						|
                    if self.Debug:
 | 
						|
                        print("WARN : %s is not defined" % Each)
 | 
						|
                    if not Preserve:
 | 
						|
                        Line = Line.replace(Each, Each[2:-1])
 | 
						|
        return Line
 | 
						|
 | 
						|
    def ExpandPcds(self, Input):
 | 
						|
        Line = Input
 | 
						|
        Match = re.findall("(\\w+\\.\\w+)", Input)
 | 
						|
        if Match:
 | 
						|
            for PcdName in Match:
 | 
						|
                if PcdName in self._PcdsDict:
 | 
						|
                    Line = Line.replace(PcdName, self._PcdsDict[PcdName])
 | 
						|
                else:
 | 
						|
                    if self.Debug:
 | 
						|
                        print("WARN : %s is not defined" % PcdName)
 | 
						|
        return Line
 | 
						|
 | 
						|
    def EvaluateExpress(self, Expr):
 | 
						|
        ExpExpr = self.ExpandPcds(Expr)
 | 
						|
        ExpExpr = self.ExpandMacros(ExpExpr)
 | 
						|
        LogExpr = CLogicalExpression()
 | 
						|
        Result = LogExpr.evaluateExpress(ExpExpr)
 | 
						|
        if self.Debug:
 | 
						|
            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:
 | 
						|
                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 FormatDeltaValue(self, ConfigDict):
 | 
						|
        ValStr = ConfigDict['value']
 | 
						|
        if ValStr[0] == "'":
 | 
						|
            # Remove padding \x00 in the value string
 | 
						|
            ValStr = "'%s'" % ValStr[1:-1].rstrip('\x00')
 | 
						|
 | 
						|
        Struct = ConfigDict['struct']
 | 
						|
        if Struct in self._StructType:
 | 
						|
            # Format the array using its struct type
 | 
						|
            Unit = int(Struct[4:]) // 8
 | 
						|
            Value = Array2Val(ConfigDict['value'])
 | 
						|
            Loop = ConfigDict['length'] // Unit
 | 
						|
            Values = []
 | 
						|
            for Each in range(Loop):
 | 
						|
                Values.append(Value & ((1 << (Unit * 8)) - 1))
 | 
						|
                Value = Value >> (Unit * 8)
 | 
						|
            ValStr = '{ ' + ', '.join([('0x%%0%dX' % (Unit * 2)) %
 | 
						|
                                       x for x in Values]) + ' }'
 | 
						|
 | 
						|
        return ValStr
 | 
						|
 | 
						|
    def FormatListValue(self, ConfigDict):
 | 
						|
        Struct = ConfigDict['struct']
 | 
						|
        if Struct not in self._StructType:
 | 
						|
            return
 | 
						|
 | 
						|
        DataList = self.ValueToList(ConfigDict['value'], ConfigDict['length'])
 | 
						|
        Unit = int(Struct[4:]) // 8
 | 
						|
        if int(ConfigDict['length']) != Unit * len(DataList):
 | 
						|
            # Fallback to byte array
 | 
						|
            Unit = 1
 | 
						|
            if int(ConfigDict['length']) != len(DataList):
 | 
						|
                raise Exception("Array size is not proper for '%s' !" %
 | 
						|
                                ConfigDict['cname'])
 | 
						|
 | 
						|
        ByteArray = []
 | 
						|
        for Value in DataList:
 | 
						|
            for Loop in range(Unit):
 | 
						|
                ByteArray.append("0x%02X" % (Value & 0xFF))
 | 
						|
                Value = Value >> 8
 | 
						|
        NewValue = '{' + ','.join(ByteArray) + '}'
 | 
						|
        ConfigDict['value'] = NewValue
 | 
						|
 | 
						|
        return ""
 | 
						|
 | 
						|
    def GetOrderNumber(self, Offset, Order, BitOff=0):
 | 
						|
        if isinstance(Order, int):
 | 
						|
            if Order == -1:
 | 
						|
                Order = Offset << 16
 | 
						|
        else:
 | 
						|
            (Major, Minor) = Order.split('.')
 | 
						|
            Order = (int(Major, 16) << 16) + ((int(Minor, 16) & 0xFF) << 8)
 | 
						|
        return Order + (BitOff & 0xFF)
 | 
						|
 | 
						|
    def SubtituteLine(self, Line, Args):
 | 
						|
        Args = Args.strip()
 | 
						|
        Vars = Args.split(':')
 | 
						|
        Line = self.ExpandMacros(Line, True)
 | 
						|
        for Idx in range(len(Vars)-1, 0, -1):
 | 
						|
            Line = Line.replace('$(%d)' % Idx, Vars[Idx].strip())
 | 
						|
        return Line
 | 
						|
 | 
						|
    def CfgDuplicationCheck(self, CfgDict, Name):
 | 
						|
        if not self.Debug:
 | 
						|
            return
 | 
						|
 | 
						|
        if Name == 'Dummy':
 | 
						|
            return
 | 
						|
 | 
						|
        if Name not in CfgDict:
 | 
						|
            CfgDict[Name] = 1
 | 
						|
        else:
 | 
						|
            print("WARNING: Duplicated item found '%s' !" %
 | 
						|
                  CfgDict['cname'])
 | 
						|
 | 
						|
    def AddBsfChildPage(self, Child, Parent='root'):
 | 
						|
        def AddBsfChildPageRecursive(PageTree, Parent, Child):
 | 
						|
            Key = next(iter(PageTree))
 | 
						|
            if Parent == Key:
 | 
						|
                PageTree[Key].append({Child: []})
 | 
						|
                return True
 | 
						|
            else:
 | 
						|
                Result = False
 | 
						|
                for Each in PageTree[Key]:
 | 
						|
                    if AddBsfChildPageRecursive(Each, Parent, Child):
 | 
						|
                        Result = True
 | 
						|
                        break
 | 
						|
                return Result
 | 
						|
 | 
						|
        return AddBsfChildPageRecursive(self._CfgPageTree, Parent, Child)
 | 
						|
 | 
						|
    def ParseDscFile(self, DscFile):
 | 
						|
        self._DscLines = []
 | 
						|
        self._CfgItemList = []
 | 
						|
        self._CfgPageDict = {}
 | 
						|
        self._CfgBlkDict = {}
 | 
						|
        self._BsfTempDict = {}
 | 
						|
        self._CfgPageTree = {'root': []}
 | 
						|
 | 
						|
        CfgDict = {}
 | 
						|
 | 
						|
        SectionNameList = ["Defines".lower(), "PcdsFeatureFlag".lower(),
 | 
						|
                           "PcdsDynamicVpd.Tmp".lower(),
 | 
						|
                           "PcdsDynamicVpd.Upd".lower()]
 | 
						|
 | 
						|
        IsDefSect = False
 | 
						|
        IsPcdSect = False
 | 
						|
        IsUpdSect = False
 | 
						|
        IsTmpSect = False
 | 
						|
 | 
						|
        TemplateName = ''
 | 
						|
 | 
						|
        IfStack = []
 | 
						|
        ElifStack = []
 | 
						|
        Error = 0
 | 
						|
        ConfigDict = {}
 | 
						|
 | 
						|
        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
 | 
						|
 | 
						|
        BsfRegExp = re.compile("(%s):{(.+?)}(?:$|\\s+)" % '|'.
 | 
						|
                               join(self._BsfKeyList))
 | 
						|
        HdrRegExp = re.compile("(%s):{(.+?)}" % '|'.join(self._HdrKeyList))
 | 
						|
        CfgRegExp = re.compile("^([_a-zA-Z0-9]+)\\s*\\|\\s*\
 | 
						|
(0x[0-9A-F]+|\\*)\\s*\\|\\s*(\\d+|0x[0-9a-fA-F]+)\\s*\\|\\s*(.+)")
 | 
						|
        TksRegExp = re.compile("^(g[_a-zA-Z0-9]+\\.)(.+)")
 | 
						|
        SkipLines = 0
 | 
						|
        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:
 | 
						|
                IsDefSect = False
 | 
						|
                IsPcdSect = False
 | 
						|
                IsUpdSect = False
 | 
						|
                IsTmpSect = False
 | 
						|
                SectionName = Match.group(1).lower()
 | 
						|
                if SectionName == SectionNameList[0]:
 | 
						|
                    IsDefSect = True
 | 
						|
                if SectionName == SectionNameList[1]:
 | 
						|
                    IsPcdSect = True
 | 
						|
                elif SectionName == SectionNameList[2]:
 | 
						|
                    IsTmpSect = True
 | 
						|
                elif SectionName == SectionNameList[3]:
 | 
						|
                    ConfigDict = {
 | 
						|
                        'header': 'ON',
 | 
						|
                        'page': '',
 | 
						|
                        'name': '',
 | 
						|
                        'find': '',
 | 
						|
                        'struct': '',
 | 
						|
                        'embed': '',
 | 
						|
                        'marker': '',
 | 
						|
                        'option': '',
 | 
						|
                        'comment': '',
 | 
						|
                        'condition': '',
 | 
						|
                        'order': -1,
 | 
						|
                        'subreg': []
 | 
						|
                    }
 | 
						|
                    IsUpdSect = True
 | 
						|
                    Offset = 0
 | 
						|
            else:
 | 
						|
                if IsDefSect or IsPcdSect or IsUpdSect 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:
 | 
						|
                            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:
 | 
						|
                            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:
 | 
						|
                            Handle = True
 | 
						|
                        if Handle:
 | 
						|
                            if Keyword == 'include':
 | 
						|
                                Remaining = self.ExpandMacros(Remaining)
 | 
						|
                                # Relative to DSC filepath
 | 
						|
                                IncludeFilePath = os.path.join(
 | 
						|
                                    os.path.dirname(self._DscFile), Remaining)
 | 
						|
                                if not os.path.exists(IncludeFilePath):
 | 
						|
                                    # Relative to repository to find \
 | 
						|
                                    # dsc in common platform
 | 
						|
                                    IncludeFilePath = os.path.join(
 | 
						|
                                        os.path.dirname(self._DscFile), "..",
 | 
						|
                                        Remaining)
 | 
						|
 | 
						|
                                try:
 | 
						|
                                    IncludeDsc = open(IncludeFilePath, "r")
 | 
						|
                                except Exception:
 | 
						|
                                    raise Exception("ERROR: Cannot open \
 | 
						|
file '%s'." % IncludeFilePath)
 | 
						|
                                NewDscLines = IncludeDsc.readlines()
 | 
						|
                                IncludeDsc.close()
 | 
						|
                                DscLines = NewDscLines + DscLines
 | 
						|
                                del self._DscLines[-1]
 | 
						|
                            else:
 | 
						|
                                if DscLine.startswith('!'):
 | 
						|
                                    raise Exception("ERROR: Unrecoginized \
 | 
						|
directive for line '%s'" % DscLine)
 | 
						|
 | 
						|
            if not Handle:
 | 
						|
                del self._DscLines[-1]
 | 
						|
                continue
 | 
						|
 | 
						|
            if IsDefSect:
 | 
						|
                Match = re.match("^\\s*(?:DEFINE\\s+)*(\\w+)\\s*=\\s*(.+)",
 | 
						|
                                 DscLine)
 | 
						|
                if Match:
 | 
						|
                    self._MacroDict[Match.group(1)] = Match.group(2)
 | 
						|
                    if self.Debug:
 | 
						|
                        print("INFO : DEFINE %s = [ %s ]" % (Match.group(1),
 | 
						|
                                                             Match.group(2)))
 | 
						|
 | 
						|
            elif IsPcdSect:
 | 
						|
                Match = re.match("^\\s*([\\w\\.]+)\\s*\\|\\s*(\\w+)", DscLine)
 | 
						|
                if Match:
 | 
						|
                    self._PcdsDict[Match.group(1)] = Match.group(2)
 | 
						|
                    if self.Debug:
 | 
						|
                        print("INFO : PCD %s = [ %s ]" % (Match.group(1),
 | 
						|
                                                          Match.group(2)))
 | 
						|
 | 
						|
            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|!HDR)\\s+(.+)", DscLine)
 | 
						|
                if Match:
 | 
						|
                    Remaining = Match.group(2)
 | 
						|
                    if Match.group(1) == '!BSF':
 | 
						|
                        Result = BsfRegExp.findall(Remaining)
 | 
						|
                        if Result:
 | 
						|
                            for Each in Result:
 | 
						|
                                Key = Each[0]
 | 
						|
                                Remaining = Each[1]
 | 
						|
 | 
						|
                                if Key == 'BLOCK':
 | 
						|
                                    Match = re.match(
 | 
						|
                                        "NAME:\"(.+)\"\\s*,\\s*\
 | 
						|
VER:\"(.+)\"\\s*", Remaining)
 | 
						|
                                    if Match:
 | 
						|
                                        self._CfgBlkDict['name'] = \
 | 
						|
                                                                 Match.group(1)
 | 
						|
                                        self._CfgBlkDict['ver'] = Match.group(2
 | 
						|
                                                                              )
 | 
						|
 | 
						|
                                elif Key == 'SUBT':
 | 
						|
                                    # GPIO_TMPL:1:2:3
 | 
						|
                                    Remaining = Remaining.strip()
 | 
						|
                                    Match = re.match("(\\w+)\\s*:", Remaining)
 | 
						|
                                    if Match:
 | 
						|
                                        TemplateName = Match.group(1)
 | 
						|
                                        for Line in self._BsfTempDict[
 | 
						|
                                                TemplateName][::-1]:
 | 
						|
                                            NewLine = self.SubtituteLine(
 | 
						|
                                                Line, Remaining)
 | 
						|
                                            DscLines.insert(0, NewLine)
 | 
						|
                                            SkipLines += 1
 | 
						|
 | 
						|
                                elif Key == 'PAGES':
 | 
						|
                                    # !BSF PAGES:{HSW:"Haswell System Agent", \
 | 
						|
                                    # LPT:"Lynx Point PCH"}
 | 
						|
                                    PageList = Remaining.split(',')
 | 
						|
                                    for Page in PageList:
 | 
						|
                                        Page = Page.strip()
 | 
						|
                                        Match = re.match('(\\w+):\
 | 
						|
(\\w*:)?\\"(.+)\\"', Page)
 | 
						|
                                        if Match:
 | 
						|
                                            PageName = Match.group(1)
 | 
						|
                                            ParentName = Match.group(2)
 | 
						|
                                            if not ParentName or \
 | 
						|
                                               ParentName == ':':
 | 
						|
                                                ParentName = 'root'
 | 
						|
                                            else:
 | 
						|
                                                ParentName = ParentName[:-1]
 | 
						|
                                            if not self.AddBsfChildPage(
 | 
						|
                                                   PageName, ParentName):
 | 
						|
                                                raise Exception("Cannot find \
 | 
						|
parent page '%s'!" % ParentName)
 | 
						|
                                            self._CfgPageDict[
 | 
						|
                                                PageName] = Match.group(3)
 | 
						|
                                        else:
 | 
						|
                                            raise Exception("Invalid page \
 | 
						|
definitions '%s'!" % Page)
 | 
						|
 | 
						|
                                elif Key in ['NAME', 'HELP', 'OPTION'
 | 
						|
                                             ] and Remaining.startswith('+'):
 | 
						|
                                    # Allow certain options to be extended \
 | 
						|
                                    # to multiple lines
 | 
						|
                                    ConfigDict[Key.lower()] += Remaining[1:]
 | 
						|
 | 
						|
                                else:
 | 
						|
                                    if Key == 'NAME':
 | 
						|
                                        Remaining = Remaining.strip()
 | 
						|
                                    elif Key == 'CONDITION':
 | 
						|
                                        Remaining = self.ExpandMacros(
 | 
						|
                                            Remaining.strip())
 | 
						|
                                    ConfigDict[Key.lower()] = Remaining
 | 
						|
                    else:
 | 
						|
                        Match = HdrRegExp.match(Remaining)
 | 
						|
                        if Match:
 | 
						|
                            Key = Match.group(1)
 | 
						|
                            Remaining = Match.group(2)
 | 
						|
                            if Key == 'EMBED':
 | 
						|
                                Parts = Remaining.split(':')
 | 
						|
                                Names = Parts[0].split(',')
 | 
						|
                                DummyDict = ConfigDict.copy()
 | 
						|
                                if len(Names) > 1:
 | 
						|
                                    Remaining = Names[0] + ':' + ':'.join(
 | 
						|
                                        Parts[1:])
 | 
						|
                                    DummyDict['struct'] = Names[1]
 | 
						|
                                else:
 | 
						|
                                    DummyDict['struct'] = Names[0]
 | 
						|
                                DummyDict['cname'] = 'Dummy'
 | 
						|
                                DummyDict['name'] = ''
 | 
						|
                                DummyDict['embed'] = Remaining
 | 
						|
                                DummyDict['offset'] = Offset
 | 
						|
                                DummyDict['length'] = 0
 | 
						|
                                DummyDict['value'] = '0'
 | 
						|
                                DummyDict['type'] = 'Reserved'
 | 
						|
                                DummyDict['help'] = ''
 | 
						|
                                DummyDict['subreg'] = []
 | 
						|
                                self._CfgItemList.append(DummyDict)
 | 
						|
                            else:
 | 
						|
                                ConfigDict[Key.lower()] = Remaining
 | 
						|
                # Check CFG line
 | 
						|
                #   gCfgData.VariableName   |    * | 0x01 | 0x1
 | 
						|
                Clear = False
 | 
						|
 | 
						|
                Match = TksRegExp.match(DscLine)
 | 
						|
                if Match:
 | 
						|
                    DscLine = 'gCfgData.%s' % Match.group(2)
 | 
						|
 | 
						|
                if DscLine.startswith('gCfgData.'):
 | 
						|
                    Match = CfgRegExp.match(DscLine[9:])
 | 
						|
                else:
 | 
						|
                    Match = None
 | 
						|
                if Match:
 | 
						|
                    ConfigDict['space'] = 'gCfgData'
 | 
						|
                    ConfigDict['cname'] = Match.group(1)
 | 
						|
                    if Match.group(2) != '*':
 | 
						|
                        Offset = int(Match.group(2), 16)
 | 
						|
                    ConfigDict['offset'] = Offset
 | 
						|
                    ConfigDict['order'] = self.GetOrderNumber(
 | 
						|
                        ConfigDict['offset'], ConfigDict['order'])
 | 
						|
 | 
						|
                    Value = Match.group(4).strip()
 | 
						|
                    if Match.group(3).startswith("0x"):
 | 
						|
                        Length = int(Match.group(3), 16)
 | 
						|
                    else:
 | 
						|
                        Length = int(Match.group(3))
 | 
						|
 | 
						|
                    Offset += Length
 | 
						|
 | 
						|
                    ConfigDict['length'] = Length
 | 
						|
                    Match = re.match("\\$\\((\\w+)\\)", Value)
 | 
						|
                    if Match:
 | 
						|
                        if Match.group(1) in self._MacroDict:
 | 
						|
                            Value = self._MacroDict[Match.group(1)]
 | 
						|
 | 
						|
                    ConfigDict['value'] = Value
 | 
						|
                    if re.match("\\{\\s*FILE:(.+)\\}", Value):
 | 
						|
                        # Expand embedded binary file
 | 
						|
                        ValArray = self.ValueToByteArray(ConfigDict['value'],
 | 
						|
                                                         ConfigDict['length'])
 | 
						|
                        NewValue = Bytes2Str(ValArray)
 | 
						|
                        self._DscLines[-1] = re.sub(r'(.*)(\{\s*FILE:.+\})',
 | 
						|
                                                    r'\1 %s' % NewValue,
 | 
						|
                                                    self._DscLines[-1])
 | 
						|
                        ConfigDict['value'] = NewValue
 | 
						|
 | 
						|
                    if ConfigDict['name'] == '':
 | 
						|
                        # Clear BSF specific items
 | 
						|
                        ConfigDict['bsfname'] = ''
 | 
						|
                        ConfigDict['help'] = ''
 | 
						|
                        ConfigDict['type'] = ''
 | 
						|
                        ConfigDict['option'] = ''
 | 
						|
 | 
						|
                    self.CfgDuplicationCheck(CfgDict, ConfigDict['cname'])
 | 
						|
                    self._CfgItemList.append(ConfigDict.copy())
 | 
						|
                    Clear = True
 | 
						|
 | 
						|
                else:
 | 
						|
                    # It could be a virtual item as below
 | 
						|
                    # !BSF FIELD:{SerialDebugPortAddress0:1}
 | 
						|
                    # or
 | 
						|
                    # @Bsf FIELD:{SerialDebugPortAddress0:1b}
 | 
						|
                    Match = re.match(r"^\s*#\s+(!BSF)\s+FIELD:{(.+)}", DscLine)
 | 
						|
                    if Match:
 | 
						|
                        BitFieldTxt = Match.group(2)
 | 
						|
                        Match = re.match("(.+):(\\d+)b([BWDQ])?", BitFieldTxt)
 | 
						|
                        if not Match:
 | 
						|
                            raise Exception("Incorrect bit field \
 | 
						|
format '%s' !" % BitFieldTxt)
 | 
						|
                        UnitBitLen = 1
 | 
						|
                        SubCfgDict = ConfigDict.copy()
 | 
						|
                        SubCfgDict['cname'] = Match.group(1)
 | 
						|
                        SubCfgDict['bitlength'] = int(
 | 
						|
                            Match.group(2)) * UnitBitLen
 | 
						|
                        if SubCfgDict['bitlength'] > 0:
 | 
						|
                            LastItem = self._CfgItemList[-1]
 | 
						|
                            if len(LastItem['subreg']) == 0:
 | 
						|
                                SubOffset = 0
 | 
						|
                            else:
 | 
						|
                                SubOffset = \
 | 
						|
                                          LastItem['subreg'][-1]['bitoffset'] \
 | 
						|
                                          + LastItem['subreg'][-1]['bitlength']
 | 
						|
                            if Match.group(3) == 'B':
 | 
						|
                                SubCfgDict['bitunit'] = 1
 | 
						|
                            elif Match.group(3) == 'W':
 | 
						|
                                SubCfgDict['bitunit'] = 2
 | 
						|
                            elif Match.group(3) == 'Q':
 | 
						|
                                SubCfgDict['bitunit'] = 8
 | 
						|
                            else:
 | 
						|
                                SubCfgDict['bitunit'] = 4
 | 
						|
                            SubCfgDict['bitoffset'] = SubOffset
 | 
						|
                            SubCfgDict['order'] = self.GetOrderNumber(
 | 
						|
                                SubCfgDict['offset'], SubCfgDict['order'],
 | 
						|
                                SubOffset)
 | 
						|
                            SubCfgDict['value'] = ''
 | 
						|
                            SubCfgDict['cname'] = '%s_%s' % (LastItem['cname'],
 | 
						|
                                                             Match.group(1))
 | 
						|
                            self.CfgDuplicationCheck(CfgDict,
 | 
						|
                                                     SubCfgDict['cname'])
 | 
						|
                            LastItem['subreg'].append(SubCfgDict.copy())
 | 
						|
                        Clear = True
 | 
						|
 | 
						|
                if Clear:
 | 
						|
                    ConfigDict['name'] = ''
 | 
						|
                    ConfigDict['find'] = ''
 | 
						|
                    ConfigDict['struct'] = ''
 | 
						|
                    ConfigDict['embed'] = ''
 | 
						|
                    ConfigDict['marker'] = ''
 | 
						|
                    ConfigDict['comment'] = ''
 | 
						|
                    ConfigDict['order'] = -1
 | 
						|
                    ConfigDict['subreg'] = []
 | 
						|
                    ConfigDict['option'] = ''
 | 
						|
                    ConfigDict['condition'] = ''
 | 
						|
 | 
						|
        return Error
 | 
						|
 | 
						|
    def GetBsfBitFields(self, subitem, bytes):
 | 
						|
        start = subitem['bitoffset']
 | 
						|
        end = start + subitem['bitlength']
 | 
						|
        bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])
 | 
						|
        bitsvalue = bitsvalue[::-1]
 | 
						|
        bitslen = len(bitsvalue)
 | 
						|
        if start > bitslen or end > bitslen:
 | 
						|
            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 UpdateBsfBitFields(self, SubItem, NewValue, ValueArray):
 | 
						|
        Start = SubItem['bitoffset']
 | 
						|
        End = Start + SubItem['bitlength']
 | 
						|
        Blen = len(ValueArray)
 | 
						|
        BitsValue = ''.join('{0:08b}'.format(i) for i in ValueArray[::-1])
 | 
						|
        BitsValue = BitsValue[::-1]
 | 
						|
        BitsLen = len(BitsValue)
 | 
						|
        if Start > BitsLen or End > BitsLen:
 | 
						|
            raise Exception("Invalid bits offset [%d,%d] %d for %s" %
 | 
						|
                            (Start, End, BitsLen, SubItem['name']))
 | 
						|
        BitsValue = BitsValue[:Start] + '{0:0{1}b}'.format(
 | 
						|
            NewValue, SubItem['bitlength'])[::-1] + BitsValue[End:]
 | 
						|
        ValueArray[:] = bytearray.fromhex(
 | 
						|
            '{0:0{1}x}'.format(int(BitsValue[::-1], 2), Blen * 2))[::-1]
 | 
						|
 | 
						|
    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:
 | 
						|
                    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:
 | 
						|
                ValArray = self.ValueToByteArray(Item['value'], Item['length'])
 | 
						|
                for SubItem in Item['subreg']:
 | 
						|
                    SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)
 | 
						|
                self.UpdateBsfBitUnit(Item)
 | 
						|
        return Error
 | 
						|
 | 
						|
    @staticmethod
 | 
						|
    def ExpandIncludeFiles(FilePath, CurDir=''):
 | 
						|
        if CurDir == '':
 | 
						|
            CurDir = os.path.dirname(FilePath)
 | 
						|
            FilePath = os.path.basename(FilePath)
 | 
						|
 | 
						|
        InputFilePath = os.path.join(CurDir, FilePath)
 | 
						|
        File = open(InputFilePath, "r")
 | 
						|
        Lines = File.readlines()
 | 
						|
        File.close()
 | 
						|
 | 
						|
        NewLines = []
 | 
						|
        for LineNum, Line in enumerate(Lines):
 | 
						|
            Match = re.match("^!include\\s*(.+)?$", Line)
 | 
						|
            if Match:
 | 
						|
                IncPath = Match.group(1)
 | 
						|
                TmpPath = os.path.join(CurDir, IncPath)
 | 
						|
                OrgPath = TmpPath
 | 
						|
                if not os.path.exists(TmpPath):
 | 
						|
                    CurDir = os.path.join(os.path.dirname(
 | 
						|
                        os.path.realpath(__file__)), "..", "..")
 | 
						|
                TmpPath = os.path.join(CurDir, IncPath)
 | 
						|
                if not os.path.exists(TmpPath):
 | 
						|
                    raise Exception("ERROR: Cannot open include file '%s'." %
 | 
						|
                                    OrgPath)
 | 
						|
                else:
 | 
						|
                    NewLines.append(('# Included from file: %s\n' %
 | 
						|
                                     IncPath, TmpPath, 0))
 | 
						|
                    NewLines.append(('# %s\n' % ('=' * 80), TmpPath, 0))
 | 
						|
                    NewLines.extend(CGenCfgData.ExpandIncludeFiles
 | 
						|
                                    (IncPath, CurDir))
 | 
						|
            else:
 | 
						|
                NewLines.append((Line, InputFilePath, LineNum))
 | 
						|
 | 
						|
        return NewLines
 | 
						|
 | 
						|
    def OverrideDefaultValue(self, DltFile):
 | 
						|
        Error = 0
 | 
						|
        DltLines = CGenCfgData.ExpandIncludeFiles(DltFile)
 | 
						|
 | 
						|
        PlatformId = None
 | 
						|
        for Line, FilePath, LineNum in DltLines:
 | 
						|
            Line = Line.strip()
 | 
						|
            if not Line or Line.startswith('#'):
 | 
						|
                continue
 | 
						|
            Match = re.match("\\s*(\\w+)\\.(\\w+)(\\.\\w+)?\\s*\\|\\s*(.+)",
 | 
						|
                             Line)
 | 
						|
            if not Match:
 | 
						|
                raise Exception("Unrecognized line '%s' (File:'%s' Line:%d) !"
 | 
						|
                                % (Line, FilePath, LineNum + 1))
 | 
						|
 | 
						|
            Found = False
 | 
						|
            InScope = False
 | 
						|
            for Idx, Item in enumerate(self._CfgItemList):
 | 
						|
                if not InScope:
 | 
						|
                    if not (Item['embed'].endswith(':START') and
 | 
						|
                            Item['embed'].startswith(Match.group(1))):
 | 
						|
                        continue
 | 
						|
                InScope = True
 | 
						|
                if Item['cname'] == Match.group(2):
 | 
						|
                    Found = True
 | 
						|
                    break
 | 
						|
                if Item['embed'].endswith(':END') and \
 | 
						|
                   Item['embed'].startswith(Match.group(1)):
 | 
						|
                    break
 | 
						|
            Name = '%s.%s' % (Match.group(1), Match.group(2))
 | 
						|
            if not Found:
 | 
						|
                ErrItem = Match.group(2) if InScope else Match.group(1)
 | 
						|
                raise Exception("Invalid configuration '%s' in '%s' \
 | 
						|
(File:'%s' Line:%d) !" % (ErrItem, Name, FilePath, LineNum + 1))
 | 
						|
 | 
						|
            ValueStr = Match.group(4).strip()
 | 
						|
            if Match.group(3) is not None:
 | 
						|
                # This is a subregion item
 | 
						|
                BitField = Match.group(3)[1:]
 | 
						|
                Found = False
 | 
						|
                if len(Item['subreg']) > 0:
 | 
						|
                    for SubItem in Item['subreg']:
 | 
						|
                        if SubItem['cname'] == '%s_%s' % \
 | 
						|
                           (Item['cname'], BitField):
 | 
						|
                            Found = True
 | 
						|
                            break
 | 
						|
                if not Found:
 | 
						|
                    raise Exception("Invalid configuration bit field \
 | 
						|
'%s' in '%s.%s' (File:'%s' Line:%d) !" % (BitField, Name, BitField,
 | 
						|
                                          FilePath, LineNum + 1))
 | 
						|
 | 
						|
                try:
 | 
						|
                    Value = int(ValueStr, 16) if ValueStr.startswith('0x') \
 | 
						|
                            else int(ValueStr, 10)
 | 
						|
                except Exception:
 | 
						|
                    raise Exception("Invalid value '%s' for bit field '%s.%s' \
 | 
						|
(File:'%s' Line:%d) !" % (ValueStr, Name, BitField, FilePath, LineNum + 1))
 | 
						|
 | 
						|
                if Value >= 2 ** SubItem['bitlength']:
 | 
						|
                    raise Exception("Invalid configuration bit field value \
 | 
						|
'%s' for '%s.%s' (File:'%s' Line:%d) !" % (Value, Name, BitField,
 | 
						|
                                           FilePath, LineNum + 1))
 | 
						|
 | 
						|
                ValArray = self.ValueToByteArray(Item['value'], Item['length'])
 | 
						|
                self.UpdateBsfBitFields(SubItem, Value, ValArray)
 | 
						|
 | 
						|
                if Item['value'].startswith('{'):
 | 
						|
                    Item['value'] = '{' + ', '.join('0x%02X' % i
 | 
						|
                                                    for i in ValArray) + '}'
 | 
						|
                else:
 | 
						|
                    BitsValue = ''.join('{0:08b}'.format(i)
 | 
						|
                                        for i in ValArray[::-1])
 | 
						|
                    Item['value'] = '0x%X' % (int(BitsValue, 2))
 | 
						|
            else:
 | 
						|
                if Item['value'].startswith('{') and  \
 | 
						|
                   not ValueStr.startswith('{'):
 | 
						|
                    raise Exception("Data array required for '%s' \
 | 
						|
(File:'%s' Line:%d) !" % (Name, FilePath, LineNum + 1))
 | 
						|
                Item['value'] = ValueStr
 | 
						|
 | 
						|
            if Name == 'PLATFORMID_CFG_DATA.PlatformId':
 | 
						|
                PlatformId = ValueStr
 | 
						|
 | 
						|
            if (PlatformId is None) and (self.Mode != 'FSP'):
 | 
						|
                raise Exception("PLATFORMID_CFG_DATA.PlatformId is missing \
 | 
						|
in file '%s' !" % (DltFile))
 | 
						|
 | 
						|
        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
 | 
						|
                            FoundSpaceChar = True
 | 
						|
                        elif StringOffset == StringLength - 1 \
 | 
						|
                                and FoundSpaceChar is 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
 | 
						|
        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)
 | 
						|
        else:
 | 
						|
            IsArray = True
 | 
						|
            Type = "UINT8"
 | 
						|
 | 
						|
        if Item and Item['value'].startswith('{'):
 | 
						|
            Type = "UINT8"
 | 
						|
            IsArray = True
 | 
						|
 | 
						|
        if Struct != '':
 | 
						|
            Type = Struct
 | 
						|
            if Struct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
 | 
						|
                IsArray = True
 | 
						|
                Unit = int(Type[4:]) // 8
 | 
						|
                Length = Length / Unit
 | 
						|
            else:
 | 
						|
                IsArray = False
 | 
						|
 | 
						|
        if IsArray:
 | 
						|
            Name = Name + '[%d]' % Length
 | 
						|
 | 
						|
        if len(Type) < PosName:
 | 
						|
            Space1 = PosName - len(Type)
 | 
						|
        else:
 | 
						|
            Space1 = 1
 | 
						|
 | 
						|
        if BsfName != '':
 | 
						|
            NameLine = " %s\n" % BsfName
 | 
						|
        else:
 | 
						|
            NameLine = "\n"
 | 
						|
 | 
						|
        if Help != '':
 | 
						|
            HelpLine = self.ProcessMultilines(Help, 80)
 | 
						|
 | 
						|
        if Option != '':
 | 
						|
            OptionLine = self.ProcessMultilines(Option, 80)
 | 
						|
 | 
						|
        if BitsLength is None:
 | 
						|
            BitsLength = ''
 | 
						|
        else:
 | 
						|
            BitsLength = ' : %d' % BitsLength
 | 
						|
 | 
						|
        return "\n/** %s%s%s**/\n  %s%s%s%s;\n" % \
 | 
						|
               (NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,
 | 
						|
                BitsLength)
 | 
						|
 | 
						|
    def SplitTextBody(self, TextBody):
 | 
						|
        Marker1 = '{ /* _COMMON_STRUCT_START_ */'
 | 
						|
        Marker2 = '; /* _COMMON_STRUCT_END_ */'
 | 
						|
        ComBody = []
 | 
						|
        TxtBody = []
 | 
						|
        IsCommon = False
 | 
						|
        for Line in TextBody:
 | 
						|
            if Line.strip().endswith(Marker1):
 | 
						|
                Line = Line.replace(Marker1[1:], '')
 | 
						|
                IsCommon = True
 | 
						|
            if Line.strip().endswith(Marker2):
 | 
						|
                Line = Line.replace(Marker2[1:], '')
 | 
						|
                if IsCommon:
 | 
						|
                    ComBody.append(Line)
 | 
						|
                    IsCommon = False
 | 
						|
                    continue
 | 
						|
            if IsCommon:
 | 
						|
                ComBody.append(Line)
 | 
						|
            else:
 | 
						|
                TxtBody.append(Line)
 | 
						|
        return ComBody, TxtBody
 | 
						|
 | 
						|
    def GetStructArrayInfo(self, Input):
 | 
						|
        ArrayStr = Input.split('[')
 | 
						|
        Name = ArrayStr[0]
 | 
						|
        if len(ArrayStr) > 1:
 | 
						|
            NumStr = ''.join(c for c in ArrayStr[-1] if c.isdigit())
 | 
						|
            NumStr = '1000' if len(NumStr) == 0 else NumStr
 | 
						|
            ArrayNum = int(NumStr)
 | 
						|
        else:
 | 
						|
            ArrayNum = 0
 | 
						|
        return Name, ArrayNum
 | 
						|
 | 
						|
    def PostProcessBody(self, TextBody, IncludeEmbedOnly=True):
 | 
						|
        NewTextBody = []
 | 
						|
        OldTextBody = []
 | 
						|
        IncTextBody = []
 | 
						|
        StructBody = []
 | 
						|
        IncludeLine = False
 | 
						|
        EmbedFound = False
 | 
						|
        StructName = ''
 | 
						|
        ArrayVarName = ''
 | 
						|
        VariableName = ''
 | 
						|
        Count = 0
 | 
						|
        Level = 0
 | 
						|
        IsCommonStruct = False
 | 
						|
 | 
						|
        for Line in TextBody:
 | 
						|
            if Line.startswith('#define '):
 | 
						|
                IncTextBody.append(Line)
 | 
						|
                continue
 | 
						|
 | 
						|
            if not Line.startswith('/* EMBED_STRUCT:'):
 | 
						|
                Match = False
 | 
						|
            else:
 | 
						|
                Match = re.match("^/\\*\\sEMBED_STRUCT:([\\w\\[\\]\\*]+):\
 | 
						|
([\\w\\[\\]\\*]+):(\\w+):(START|END)([\\s\\d]+)\\*/([\\s\\S]*)", Line)
 | 
						|
 | 
						|
            if Match:
 | 
						|
                ArrayMarker = Match.group(5)
 | 
						|
                if Match.group(4) == 'END':
 | 
						|
                    Level -= 1
 | 
						|
                    if Level == 0:
 | 
						|
                        Line = Match.group(6)
 | 
						|
                else:   # 'START'
 | 
						|
                    Level += 1
 | 
						|
                    if Level == 1:
 | 
						|
                        Line = Match.group(6)
 | 
						|
                    else:
 | 
						|
                        EmbedFound = True
 | 
						|
                    TagStr = Match.group(3)
 | 
						|
                    if TagStr.startswith('TAG_'):
 | 
						|
                        try:
 | 
						|
                            TagVal = int(TagStr[4:], 16)
 | 
						|
                        except Exception:
 | 
						|
                            TagVal = -1
 | 
						|
                        if (TagVal >= 0) and (TagVal < self._MinCfgTagId):
 | 
						|
                            IsCommonStruct = True
 | 
						|
 | 
						|
                    if Level == 1:
 | 
						|
                        if IsCommonStruct:
 | 
						|
                            Suffix = ' /* _COMMON_STRUCT_START_ */'
 | 
						|
                        else:
 | 
						|
                            Suffix = ''
 | 
						|
                        StructBody = ['typedef struct {%s' % Suffix]
 | 
						|
                        StructName = Match.group(1)
 | 
						|
                        StructType = Match.group(2)
 | 
						|
                        VariableName = Match.group(3)
 | 
						|
                        MatchOffset = re.search('/\\*\\*\\sOffset\\s0x\
 | 
						|
([a-fA-F0-9]+)', Line)
 | 
						|
                        if MatchOffset:
 | 
						|
                            Offset = int(MatchOffset.group(1), 16)
 | 
						|
                        else:
 | 
						|
                            Offset = None
 | 
						|
                        IncludeLine = True
 | 
						|
 | 
						|
                        ModifiedStructType = StructType.rstrip()
 | 
						|
                        if ModifiedStructType.endswith(']'):
 | 
						|
                            Idx = ModifiedStructType.index('[')
 | 
						|
                            if ArrayMarker != ' ':
 | 
						|
                                # Auto array size
 | 
						|
                                OldTextBody.append('')
 | 
						|
                                ArrayVarName = VariableName
 | 
						|
                                if int(ArrayMarker) == 1000:
 | 
						|
                                    Count = 1
 | 
						|
                                else:
 | 
						|
                                    Count = int(ArrayMarker) + 1000
 | 
						|
                            else:
 | 
						|
                                if Count < 1000:
 | 
						|
                                    Count += 1
 | 
						|
 | 
						|
                            VariableTemp = ArrayVarName + '[%d]' % (
 | 
						|
                                Count if Count < 1000 else Count - 1000)
 | 
						|
                            OldTextBody[-1] = self.CreateField(
 | 
						|
                                None, VariableTemp, 0, Offset,
 | 
						|
                                ModifiedStructType[:Idx], '',
 | 
						|
                                'Structure Array', '')
 | 
						|
                        else:
 | 
						|
                            ArrayVarName = ''
 | 
						|
                            OldTextBody.append(self.CreateField(
 | 
						|
                                None, VariableName, 0, Offset,
 | 
						|
                                ModifiedStructType, '', '', ''))
 | 
						|
 | 
						|
            if IncludeLine:
 | 
						|
                StructBody.append(Line)
 | 
						|
            else:
 | 
						|
                OldTextBody.append(Line)
 | 
						|
 | 
						|
            if Match and Match.group(4) == 'END':
 | 
						|
                if Level == 0:
 | 
						|
                    if (StructType != Match.group(2)) or \
 | 
						|
                       (VariableName != Match.group(3)):
 | 
						|
                        print("Unmatched struct name '%s' and '%s' !" %
 | 
						|
                              (StructName, Match.group(2)))
 | 
						|
                    else:
 | 
						|
                        if IsCommonStruct:
 | 
						|
                            Suffix = ' /* _COMMON_STRUCT_END_ */'
 | 
						|
                        else:
 | 
						|
                            Suffix = ''
 | 
						|
                        Line = '} %s;%s\n\n\n' % (StructName, Suffix)
 | 
						|
                        StructBody.append(Line)
 | 
						|
                        if (Line not in NewTextBody) and \
 | 
						|
                           (Line not in OldTextBody):
 | 
						|
                            NewTextBody.extend(StructBody)
 | 
						|
                    IncludeLine = False
 | 
						|
                IsCommonStruct = False
 | 
						|
 | 
						|
        if not IncludeEmbedOnly:
 | 
						|
            NewTextBody.extend(OldTextBody)
 | 
						|
 | 
						|
        if EmbedFound:
 | 
						|
            NewTextBody = self.PostProcessBody(NewTextBody, False)
 | 
						|
 | 
						|
        NewTextBody = IncTextBody + NewTextBody
 | 
						|
        return NewTextBody
 | 
						|
 | 
						|
    def WriteHeaderFile(self, TxtBody, FileName, Type='h'):
 | 
						|
        FileNameDef = os.path.basename(FileName).replace('.', '_')
 | 
						|
        FileNameDef = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', FileNameDef)
 | 
						|
        FileNameDef = re.sub('([a-z0-9])([A-Z])', r'\1_\2',
 | 
						|
                             FileNameDef).upper()
 | 
						|
 | 
						|
        Lines = []
 | 
						|
        Lines.append("%s\n" % GetCopyrightHeader(Type))
 | 
						|
        Lines.append("#ifndef __%s__\n" % FileNameDef)
 | 
						|
        Lines.append("#define __%s__\n\n" % FileNameDef)
 | 
						|
        if Type == 'h':
 | 
						|
            Lines.append("#pragma pack(1)\n\n")
 | 
						|
        Lines.extend(TxtBody)
 | 
						|
        if Type == 'h':
 | 
						|
            Lines.append("#pragma pack()\n\n")
 | 
						|
        Lines.append("#endif\n")
 | 
						|
 | 
						|
        # Don't rewrite if the contents are the same
 | 
						|
        Create = True
 | 
						|
        if os.path.exists(FileName):
 | 
						|
            HdrFile = open(FileName, "r")
 | 
						|
            OrgTxt = HdrFile.read()
 | 
						|
            HdrFile.close()
 | 
						|
 | 
						|
            NewTxt = ''.join(Lines)
 | 
						|
            if OrgTxt == NewTxt:
 | 
						|
                Create = False
 | 
						|
 | 
						|
        if Create:
 | 
						|
            HdrFile = open(FileName, "w")
 | 
						|
            HdrFile.write(''.join(Lines))
 | 
						|
            HdrFile.close()
 | 
						|
 | 
						|
    def CreateHeaderFile(self, HdrFileName, ComHdrFileName=''):
 | 
						|
        LastStruct = ''
 | 
						|
        SpaceIdx = 0
 | 
						|
        Offset = 0
 | 
						|
        FieldIdx = 0
 | 
						|
        LastFieldIdx = 0
 | 
						|
        ResvOffset = 0
 | 
						|
        ResvIdx = 0
 | 
						|
        TxtBody = []
 | 
						|
        LineBuffer = []
 | 
						|
        CfgTags = []
 | 
						|
        LastVisible = True
 | 
						|
 | 
						|
        TxtBody.append("typedef struct {\n")
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            # Search for CFGDATA tags
 | 
						|
            Embed = Item["embed"].upper()
 | 
						|
            if Embed.endswith(':START'):
 | 
						|
                Match = re.match(r'(\w+)_CFG_DATA:TAG_([0-9A-F]+):START',
 | 
						|
                                 Embed)
 | 
						|
                if Match:
 | 
						|
                    TagName = Match.group(1)
 | 
						|
                    TagId = int(Match.group(2), 16)
 | 
						|
                    CfgTags.append((TagId, TagName))
 | 
						|
 | 
						|
            # Only process visible items
 | 
						|
            NextVisible = LastVisible
 | 
						|
 | 
						|
            if LastVisible and (Item['header'] == 'OFF'):
 | 
						|
                NextVisible = False
 | 
						|
                ResvOffset = Item['offset']
 | 
						|
            elif (not LastVisible) and Item['header'] == 'ON':
 | 
						|
                NextVisible = True
 | 
						|
                Name = "ReservedUpdSpace%d" % ResvIdx
 | 
						|
                ResvIdx = ResvIdx + 1
 | 
						|
                TxtBody.append(self.CreateField(
 | 
						|
                    Item, Name, Item["offset"] - ResvOffset,
 | 
						|
                    ResvOffset, '', '', '', ''))
 | 
						|
                FieldIdx += 1
 | 
						|
 | 
						|
            if Offset < Item["offset"]:
 | 
						|
                if LastVisible:
 | 
						|
                    Name = "UnusedUpdSpace%d" % SpaceIdx
 | 
						|
                    LineBuffer.append(self.CreateField
 | 
						|
                                      (Item, Name, Item["offset"] -
 | 
						|
                                       Offset, Offset, '', '', '', ''))
 | 
						|
                    FieldIdx += 1
 | 
						|
                SpaceIdx = SpaceIdx + 1
 | 
						|
                Offset = Item["offset"]
 | 
						|
 | 
						|
            LastVisible = NextVisible
 | 
						|
 | 
						|
            Offset = Offset + Item["length"]
 | 
						|
            if LastVisible:
 | 
						|
                for Each in LineBuffer:
 | 
						|
                    TxtBody.append(Each)
 | 
						|
                LineBuffer = []
 | 
						|
                Embed = Item["embed"].upper()
 | 
						|
                if Embed.endswith(':START') or Embed.endswith(':END'):
 | 
						|
                    # EMBED_STRUCT: StructName : \
 | 
						|
                    # ItemName : VariableName : START|END
 | 
						|
                    Name, ArrayNum = self.GetStructArrayInfo(Item["struct"])
 | 
						|
                    Remaining = Item["embed"]
 | 
						|
                    if (LastFieldIdx + 1 == FieldIdx) and (LastStruct == Name):
 | 
						|
                        ArrayMarker = ' '
 | 
						|
                    else:
 | 
						|
                        ArrayMarker = '%d' % ArrayNum
 | 
						|
                    LastFieldIdx = FieldIdx
 | 
						|
                    LastStruct = Name
 | 
						|
                    Marker = '/* EMBED_STRUCT:%s:%s%s*/ ' % (Name, Remaining,
 | 
						|
                                                             ArrayMarker)
 | 
						|
                    # if Embed.endswith(':START') and Comment != '':
 | 
						|
                    # Marker = '/* COMMENT:%s */ \n' % Item["comment"] + Marker
 | 
						|
                else:
 | 
						|
                    if Embed == '':
 | 
						|
                        Marker = ''
 | 
						|
                    else:
 | 
						|
                        self.Error = "Invalid embedded structure \
 | 
						|
format '%s'!\n" % Item["embed"]
 | 
						|
                        return 4
 | 
						|
 | 
						|
                # Generate bit fields for structure
 | 
						|
                if len(Item['subreg']) > 0 and Item["struct"]:
 | 
						|
                    StructType = Item["struct"]
 | 
						|
                    StructName, ArrayNum = self.GetStructArrayInfo(StructType)
 | 
						|
                    if (LastFieldIdx + 1 == FieldIdx) and \
 | 
						|
                       (LastStruct == Item["struct"]):
 | 
						|
                        ArrayMarker = ' '
 | 
						|
                    else:
 | 
						|
                        ArrayMarker = '%d' % ArrayNum
 | 
						|
                    TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:START%s*/\n' %
 | 
						|
                                   (StructName, StructType, Item["cname"],
 | 
						|
                                    ArrayMarker))
 | 
						|
                    for SubItem in Item['subreg']:
 | 
						|
                        Name = SubItem["cname"]
 | 
						|
                        if Name.startswith(Item["cname"]):
 | 
						|
                            Name = Name[len(Item["cname"]) + 1:]
 | 
						|
                        Line = self.CreateField(
 | 
						|
                            SubItem, Name, SubItem["bitunit"],
 | 
						|
                            SubItem["offset"], SubItem['struct'],
 | 
						|
                            SubItem['name'], SubItem['help'],
 | 
						|
                            SubItem['option'], SubItem['bitlength'])
 | 
						|
                        TxtBody.append(Line)
 | 
						|
                    TxtBody.append('/* EMBED_STRUCT:%s:%s:%s:END%s*/\n' %
 | 
						|
                                   (StructName, StructType, Item["cname"],
 | 
						|
                                    ArrayMarker))
 | 
						|
                    LastFieldIdx = FieldIdx
 | 
						|
                    LastStruct = Item["struct"]
 | 
						|
                    FieldIdx += 1
 | 
						|
                else:
 | 
						|
                    FieldIdx += 1
 | 
						|
                    Line = Marker + self.CreateField(
 | 
						|
                        Item, Item["cname"], Item["length"], Item["offset"],
 | 
						|
                        Item['struct'], Item['name'], Item['help'],
 | 
						|
                        Item['option'])
 | 
						|
                    TxtBody.append(Line)
 | 
						|
 | 
						|
        TxtBody.append("}\n\n")
 | 
						|
 | 
						|
        # Handle the embedded data structure
 | 
						|
        TxtBody = self.PostProcessBody(TxtBody)
 | 
						|
        ComBody, TxtBody = self.SplitTextBody(TxtBody)
 | 
						|
 | 
						|
        # Prepare TAG defines
 | 
						|
        PltTagDefTxt = ['\n']
 | 
						|
        ComTagDefTxt = ['\n']
 | 
						|
        for TagId, TagName in sorted(CfgTags):
 | 
						|
            TagLine = '#define  %-30s  0x%03X\n' % ('CDATA_%s_TAG' %
 | 
						|
                                                    TagName, TagId)
 | 
						|
            if TagId < self._MinCfgTagId:
 | 
						|
                # TAG ID < 0x100, it is a generic TAG
 | 
						|
                ComTagDefTxt.append(TagLine)
 | 
						|
            else:
 | 
						|
                PltTagDefTxt.append(TagLine)
 | 
						|
        PltTagDefTxt.append('\n\n')
 | 
						|
        ComTagDefTxt.append('\n\n')
 | 
						|
 | 
						|
        # Write file back
 | 
						|
        self.WriteHeaderFile(PltTagDefTxt + TxtBody, HdrFileName)
 | 
						|
        if ComHdrFileName:
 | 
						|
            self.WriteHeaderFile(ComTagDefTxt + ComBody, ComHdrFileName)
 | 
						|
 | 
						|
        return 0
 | 
						|
 | 
						|
    def UpdateConfigItemValue(self, Item, ValueStr):
 | 
						|
        IsArray = True if Item['value'].startswith('{') else False
 | 
						|
        IsString = True if Item['value'].startswith("'") else False
 | 
						|
        Bytes = self.ValueToByteArray(ValueStr, Item['length'])
 | 
						|
        if IsString:
 | 
						|
            NewValue = "'%s'" % Bytes.decode("utf-8")
 | 
						|
        elif IsArray:
 | 
						|
            NewValue = Bytes2Str(Bytes)
 | 
						|
        else:
 | 
						|
            Fmt = '0x%X' if Item['value'].startswith('0x') else '%d'
 | 
						|
            NewValue = Fmt % Bytes2Val(Bytes)
 | 
						|
        Item['value'] = NewValue
 | 
						|
 | 
						|
    def LoadDefaultFromBinaryArray(self, BinDat, IgnoreFind=False):
 | 
						|
        FindOff = 0
 | 
						|
        StartOff = 0
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            if Item['length'] == 0:
 | 
						|
                continue
 | 
						|
            if not IgnoreFind and Item['find']:
 | 
						|
                FindBin = Item['find'].encode()
 | 
						|
                Offset = BinDat.find(FindBin)
 | 
						|
                if Offset >= 0:
 | 
						|
                    TestOff = BinDat[Offset+len(FindBin):].find(FindBin)
 | 
						|
                    if TestOff >= 0:
 | 
						|
                        raise Exception('Multiple match found for "%s" !' %
 | 
						|
                                        Item['find'])
 | 
						|
                    FindOff = Offset + len(FindBin)
 | 
						|
                    StartOff = Item['offset']
 | 
						|
                else:
 | 
						|
                    raise Exception('Could not find "%s" !' % Item['find'])
 | 
						|
            if Item['offset'] + Item['length'] > len(BinDat):
 | 
						|
                raise Exception('Mismatching format between DSC \
 | 
						|
and BIN files !')
 | 
						|
            Offset = FindOff + (Item['offset'] - StartOff)
 | 
						|
            ValStr = Bytes2Str(BinDat[Offset: Offset + Item['length']])
 | 
						|
            self.UpdateConfigItemValue(Item, ValStr)
 | 
						|
 | 
						|
        self.UpdateDefaultValue()
 | 
						|
 | 
						|
    def PatchBinaryArray(self, BinDat):
 | 
						|
        FileOff = 0
 | 
						|
        Offset = 0
 | 
						|
        FindOff = 0
 | 
						|
 | 
						|
        PatchList = []
 | 
						|
        CfgBin = bytearray()
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            if Item['length'] == 0:
 | 
						|
                continue
 | 
						|
 | 
						|
            if Item['find']:
 | 
						|
                if len(CfgBin) > 0:
 | 
						|
                    PatchList.append((FileOff, CfgBin))
 | 
						|
                FindBin = Item['find'].encode()
 | 
						|
                FileOff = BinDat.find(FindBin)
 | 
						|
                if FileOff < 0:
 | 
						|
                    raise Exception('Could not find "%s" !' % Item['find'])
 | 
						|
                else:
 | 
						|
                    TestOff = BinDat[FileOff+len(FindBin):].find(FindBin)
 | 
						|
                    if TestOff >= 0:
 | 
						|
                        raise Exception('Multiple match found for "%s" !' %
 | 
						|
                                        Item['find'])
 | 
						|
                FileOff += len(FindBin)
 | 
						|
                Offset = Item['offset']
 | 
						|
                FindOff = Offset
 | 
						|
                CfgBin = bytearray()
 | 
						|
 | 
						|
            if Item['offset'] > Offset:
 | 
						|
                Gap = Item['offset'] - Offset
 | 
						|
                CfgBin.extend(b'\x00' * Gap)
 | 
						|
 | 
						|
            if Item['type'] == 'Reserved' and Item['option'] == '$SKIP':
 | 
						|
                # keep old data
 | 
						|
                NewOff = FileOff + (Offset - FindOff)
 | 
						|
                FileData = bytearray(BinDat[NewOff: NewOff + Item['length']])
 | 
						|
                CfgBin.extend(FileData)
 | 
						|
            else:
 | 
						|
                CfgBin.extend(self.ValueToByteArray(Item['value'],
 | 
						|
                                                    Item['length']))
 | 
						|
            Offset = Item['offset'] + Item['length']
 | 
						|
 | 
						|
        if len(CfgBin) > 0:
 | 
						|
            PatchList.append((FileOff, CfgBin))
 | 
						|
 | 
						|
        for FileOff, CfgBin in PatchList:
 | 
						|
            Length = len(CfgBin)
 | 
						|
            if FileOff + Length < len(BinDat):
 | 
						|
                BinDat[FileOff:FileOff+Length] = CfgBin[:]
 | 
						|
 | 
						|
        return BinDat
 | 
						|
 | 
						|
    def GenerateBinaryArray(self):
 | 
						|
        Offset = 0
 | 
						|
        BinDat = bytearray()
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            if Item['offset'] > Offset:
 | 
						|
                Gap = Item['offset'] - Offset
 | 
						|
                BinDat.extend(b'\x00' * Gap)
 | 
						|
            BinDat.extend(self.ValueToByteArray(Item['value'], Item['length']))
 | 
						|
            Offset = Item['offset'] + Item['length']
 | 
						|
        return BinDat
 | 
						|
 | 
						|
    def GenerateBinary(self, BinFileName):
 | 
						|
        BinFile = open(BinFileName, "wb")
 | 
						|
        BinFile.write(self.GenerateBinaryArray())
 | 
						|
        BinFile.close()
 | 
						|
        return 0
 | 
						|
 | 
						|
    def GenerateDataIncFile(self, DatIncFileName, BinFile=None):
 | 
						|
        # Put a prefix GUID before CFGDATA so that it can be located later on
 | 
						|
        Prefix = b'\xa7\xbd\x7f\x73\x20\x1e\x46\xd6\xbe\x8f\
 | 
						|
x64\x12\x05\x8d\x0a\xa8'
 | 
						|
        if BinFile:
 | 
						|
            Fin = open(BinFile, 'rb')
 | 
						|
            BinDat = Prefix + bytearray(Fin.read())
 | 
						|
            Fin.close()
 | 
						|
        else:
 | 
						|
            BinDat = Prefix + self.GenerateBinaryArray()
 | 
						|
 | 
						|
        FileName = os.path.basename(DatIncFileName).upper()
 | 
						|
        FileName = FileName.replace('.', '_')
 | 
						|
 | 
						|
        TxtLines = []
 | 
						|
 | 
						|
        TxtLines.append("UINT8  mConfigDataBlob[%d] = {\n" % len(BinDat))
 | 
						|
        Count = 0
 | 
						|
        Line = ['  ']
 | 
						|
        for Each in BinDat:
 | 
						|
            Line.append('0x%02X, ' % Each)
 | 
						|
            Count = Count + 1
 | 
						|
            if (Count & 0x0F) == 0:
 | 
						|
                Line.append('\n')
 | 
						|
                TxtLines.append(''.join(Line))
 | 
						|
                Line = ['  ']
 | 
						|
        if len(Line) > 1:
 | 
						|
            TxtLines.append(''.join(Line) + '\n')
 | 
						|
 | 
						|
        TxtLines.append("};\n\n")
 | 
						|
 | 
						|
        self.WriteHeaderFile(TxtLines, DatIncFileName, 'inc')
 | 
						|
 | 
						|
        return 0
 | 
						|
 | 
						|
    def CheckCfgData(self):
 | 
						|
        # Check if CfgData contains any duplicated name
 | 
						|
        def AddItem(Item, ChkList):
 | 
						|
            Name = Item['cname']
 | 
						|
            if Name in ChkList:
 | 
						|
                return Item
 | 
						|
            if Name not in ['Dummy', 'Reserved', 'CfgHeader', 'CondValue']:
 | 
						|
                ChkList.append(Name)
 | 
						|
            return None
 | 
						|
 | 
						|
        Duplicate = None
 | 
						|
        ChkList = []
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            Duplicate = AddItem(Item, ChkList)
 | 
						|
            if not Duplicate:
 | 
						|
                for SubItem in Item['subreg']:
 | 
						|
                    Duplicate = AddItem(SubItem, ChkList)
 | 
						|
                    if Duplicate:
 | 
						|
                        break
 | 
						|
            if Duplicate:
 | 
						|
                break
 | 
						|
        if Duplicate:
 | 
						|
            self.Error = "Duplicated CFGDATA '%s' found !\n" % \
 | 
						|
                         Duplicate['cname']
 | 
						|
            return -1
 | 
						|
        return 0
 | 
						|
 | 
						|
    def PrintData(self):
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            if not Item['length']:
 | 
						|
                continue
 | 
						|
            print("%-10s @Offset:0x%04X  Len:%3d  Val:%s" %
 | 
						|
                  (Item['cname'], Item['offset'], Item['length'],
 | 
						|
                   Item['value']))
 | 
						|
            for SubItem in Item['subreg']:
 | 
						|
                print("  %-20s  BitOff:0x%04X  BitLen:%-3d  Val:%s" %
 | 
						|
                      (SubItem['cname'], SubItem['bitoffset'],
 | 
						|
                       SubItem['bitlength'], SubItem['value']))
 | 
						|
 | 
						|
    def FormatArrayValue(self, Input, Length):
 | 
						|
        Dat = self.ValueToByteArray(Input, Length)
 | 
						|
        return ','.join('0x%02X' % Each for Each in Dat)
 | 
						|
 | 
						|
    def GetItemOptionList(self, Item):
 | 
						|
        TmpList = []
 | 
						|
        if Item['type'] == "Combo":
 | 
						|
            if not Item['option'] in self._BuidinOption:
 | 
						|
                OptList = Item['option'].split(',')
 | 
						|
                for Option in OptList:
 | 
						|
                    Option = Option.strip()
 | 
						|
                    try:
 | 
						|
                        (OpVal, OpStr) = Option.split(':')
 | 
						|
                    except Exception:
 | 
						|
                        raise Exception("Invalide option format '%s' !" %
 | 
						|
                                        Option)
 | 
						|
                    TmpList.append((OpVal, OpStr))
 | 
						|
        return TmpList
 | 
						|
 | 
						|
    def WriteBsfStruct(self, BsfFd, Item):
 | 
						|
        if Item['type'] == "None":
 | 
						|
            Space = "gPlatformFspPkgTokenSpaceGuid"
 | 
						|
        else:
 | 
						|
            Space = Item['space']
 | 
						|
        Line = "    $%s_%s" % (Space, Item['cname'])
 | 
						|
        Match = re.match("\\s*(\\{.+\\})\\s*", Item['value'])
 | 
						|
        if Match:
 | 
						|
            DefaultValue = self.FormatArrayValue(Match.group(1).strip(),
 | 
						|
                                                 Item['length'])
 | 
						|
        else:
 | 
						|
            DefaultValue = Item['value'].strip()
 | 
						|
        if 'bitlength' in Item:
 | 
						|
            if Item['bitlength']:
 | 
						|
                BsfFd.write("    %s%s%4d bits     $_DEFAULT_ = %s\n" %
 | 
						|
                            (Line, ' ' * (64 - len(Line)), Item['bitlength'],
 | 
						|
                             DefaultValue))
 | 
						|
        else:
 | 
						|
            if Item['length']:
 | 
						|
                BsfFd.write("    %s%s%4d bytes    $_DEFAULT_ = %s\n" %
 | 
						|
                            (Line, ' ' * (64 - len(Line)), Item['length'],
 | 
						|
                             DefaultValue))
 | 
						|
 | 
						|
        return self.GetItemOptionList(Item)
 | 
						|
 | 
						|
    def GetBsfOption(self, OptionName):
 | 
						|
        if OptionName in self._CfgOptsDict:
 | 
						|
            return self._CfgOptsDict[OptionName]
 | 
						|
        else:
 | 
						|
            return OptionName
 | 
						|
 | 
						|
    def WriteBsfOption(self, BsfFd, Item):
 | 
						|
        PcdName = Item['space'] + '_' + Item['cname']
 | 
						|
        WriteHelp = 0
 | 
						|
        BsfLines = []
 | 
						|
        if Item['type'] == "Combo":
 | 
						|
            if Item['option'] in self._BuidinOption:
 | 
						|
                Options = self._BuidinOption[Item['option']]
 | 
						|
            else:
 | 
						|
                Options = self.GetBsfOption(PcdName)
 | 
						|
            BsfLines.append('    %s $%s, "%s", &%s,\n' % (
 | 
						|
                Item['type'], PcdName, Item['name'], Options))
 | 
						|
            WriteHelp = 1
 | 
						|
        elif Item['type'].startswith("EditNum"):
 | 
						|
            Match = re.match("EditNum\\s*,\\s*(HEX|DEC)\\s*,\\s*\\(\
 | 
						|
(\\d+|0x[0-9A-Fa-f]+)\\s*,\\s*(\\d+|0x[0-9A-Fa-f]+)\\)", Item['type'])
 | 
						|
            if Match:
 | 
						|
                BsfLines.append('    EditNum $%s, "%s", %s,\n' % (
 | 
						|
                    PcdName, Item['name'], Match.group(1)))
 | 
						|
                WriteHelp = 2
 | 
						|
        elif Item['type'].startswith("EditText"):
 | 
						|
            BsfLines.append('    %s $%s, "%s",\n' % (Item['type'], PcdName,
 | 
						|
                                                     Item['name']))
 | 
						|
            WriteHelp = 1
 | 
						|
        elif Item['type'] == "Table":
 | 
						|
            Columns = Item['option'].split(',')
 | 
						|
            if len(Columns) != 0:
 | 
						|
                BsfLines.append('    %s $%s "%s",' % (Item['type'], PcdName,
 | 
						|
                                                      Item['name']))
 | 
						|
                for Col in Columns:
 | 
						|
                    Fmt = Col.split(':')
 | 
						|
                    if len(Fmt) != 3:
 | 
						|
                        raise Exception("Column format '%s' is invalid !" %
 | 
						|
                                        Fmt)
 | 
						|
                    try:
 | 
						|
                        Dtype = int(Fmt[1].strip())
 | 
						|
                    except Exception:
 | 
						|
                        raise Exception("Column size '%s' is invalid !" %
 | 
						|
                                        Fmt[1])
 | 
						|
                    BsfLines.append('\n        Column "%s", %d bytes, %s' %
 | 
						|
                                    (Fmt[0].strip(), Dtype, Fmt[2].strip()))
 | 
						|
                BsfLines.append(',\n')
 | 
						|
                WriteHelp = 1
 | 
						|
 | 
						|
        if WriteHelp > 0:
 | 
						|
            HelpLines = Item['help'].split('\\n\\r')
 | 
						|
            FirstLine = True
 | 
						|
            for HelpLine in HelpLines:
 | 
						|
                if FirstLine:
 | 
						|
                    FirstLine = False
 | 
						|
                    BsfLines.append('        Help "%s"\n' % (HelpLine))
 | 
						|
                else:
 | 
						|
                    BsfLines.append('             "%s"\n' % (HelpLine))
 | 
						|
            if WriteHelp == 2:
 | 
						|
                BsfLines.append('             "Valid range: %s ~ %s"\n' %
 | 
						|
                                (Match.group(2), Match.group(3)))
 | 
						|
 | 
						|
            if len(Item['condition']) > 4:
 | 
						|
                CondList = Item['condition'].split(',')
 | 
						|
                Idx = 0
 | 
						|
                for Cond in CondList:
 | 
						|
                    Cond = Cond.strip()
 | 
						|
                    if Cond.startswith('#'):
 | 
						|
                        BsfLines.insert(Idx, Cond + '\n')
 | 
						|
                        Idx += 1
 | 
						|
                    elif Cond.startswith('@#'):
 | 
						|
                        BsfLines.append(Cond[1:] + '\n')
 | 
						|
 | 
						|
        for Line in BsfLines:
 | 
						|
            BsfFd.write(Line)
 | 
						|
 | 
						|
    def WriteBsfPages(self, PageTree, BsfFd):
 | 
						|
        BsfFd.write('\n')
 | 
						|
        Key = next(iter(PageTree))
 | 
						|
        for Page in PageTree[Key]:
 | 
						|
            PageName = next(iter(Page))
 | 
						|
            BsfFd.write('Page "%s"\n' % self._CfgPageDict[PageName])
 | 
						|
            if len(PageTree[Key]):
 | 
						|
                self.WriteBsfPages(Page, BsfFd)
 | 
						|
 | 
						|
            BsfItems = []
 | 
						|
            for Item in self._CfgItemList:
 | 
						|
                if Item['name'] != '':
 | 
						|
                    if Item['page'] != PageName:
 | 
						|
                        continue
 | 
						|
                    if len(Item['subreg']) > 0:
 | 
						|
                        for SubItem in Item['subreg']:
 | 
						|
                            if SubItem['name'] != '':
 | 
						|
                                BsfItems.append(SubItem)
 | 
						|
                    else:
 | 
						|
                        BsfItems.append(Item)
 | 
						|
 | 
						|
            BsfItems.sort(key=lambda x: x['order'])
 | 
						|
 | 
						|
            for Item in BsfItems:
 | 
						|
                self.WriteBsfOption(BsfFd, Item)
 | 
						|
            BsfFd.write("EndPage\n\n")
 | 
						|
 | 
						|
    def GenerateBsfFile(self, BsfFile):
 | 
						|
 | 
						|
        if BsfFile == '':
 | 
						|
            self.Error = "BSF output file '%s' is invalid" % BsfFile
 | 
						|
            return 1
 | 
						|
 | 
						|
        Error = 0
 | 
						|
        OptionDict = {}
 | 
						|
        BsfFd = open(BsfFile, "w")
 | 
						|
        BsfFd.write("%s\n" % GetCopyrightHeader('bsf'))
 | 
						|
        BsfFd.write("%s\n" % self._GlobalDataDef)
 | 
						|
        BsfFd.write("StructDef\n")
 | 
						|
        NextOffset = -1
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            if Item['find'] != '':
 | 
						|
                BsfFd.write('\n    Find "%s"\n' % Item['find'])
 | 
						|
                NextOffset = Item['offset'] + Item['length']
 | 
						|
            if Item['name'] != '':
 | 
						|
                if NextOffset != Item['offset']:
 | 
						|
                    BsfFd.write("        Skip %d bytes\n" %
 | 
						|
                                (Item['offset'] - NextOffset))
 | 
						|
                if len(Item['subreg']) > 0:
 | 
						|
                    NextOffset = Item['offset']
 | 
						|
                    BitsOffset = NextOffset * 8
 | 
						|
                    for SubItem in Item['subreg']:
 | 
						|
                        BitsOffset += SubItem['bitlength']
 | 
						|
                        if SubItem['name'] == '':
 | 
						|
                            if 'bitlength' in SubItem:
 | 
						|
                                BsfFd.write("        Skip %d bits\n" %
 | 
						|
                                            (SubItem['bitlength']))
 | 
						|
                            else:
 | 
						|
                                BsfFd.write("        Skip %d bytes\n" %
 | 
						|
                                            (SubItem['length']))
 | 
						|
                        else:
 | 
						|
                            Options = self.WriteBsfStruct(BsfFd, SubItem)
 | 
						|
                            if len(Options) > 0:
 | 
						|
                                OptionDict[SubItem
 | 
						|
                                           ['space']+'_'+SubItem
 | 
						|
                                           ['cname']] = Options
 | 
						|
 | 
						|
                    NextBitsOffset = (Item['offset'] + Item['length']) * 8
 | 
						|
                    if NextBitsOffset > BitsOffset:
 | 
						|
                        BitsGap = NextBitsOffset - BitsOffset
 | 
						|
                        BitsRemain = BitsGap % 8
 | 
						|
                        if BitsRemain:
 | 
						|
                            BsfFd.write("        Skip %d bits\n" % BitsRemain)
 | 
						|
                            BitsGap -= BitsRemain
 | 
						|
                        BytesRemain = BitsGap // 8
 | 
						|
                        if BytesRemain:
 | 
						|
                            BsfFd.write("        Skip %d bytes\n" %
 | 
						|
                                        BytesRemain)
 | 
						|
                    NextOffset = Item['offset'] + Item['length']
 | 
						|
                else:
 | 
						|
                    NextOffset = Item['offset'] + Item['length']
 | 
						|
                    Options = self.WriteBsfStruct(BsfFd, Item)
 | 
						|
                    if len(Options) > 0:
 | 
						|
                        OptionDict[Item['space']+'_'+Item['cname']] = Options
 | 
						|
        BsfFd.write("\nEndStruct\n\n")
 | 
						|
 | 
						|
        BsfFd.write("%s" % self._BuidinOptionTxt)
 | 
						|
 | 
						|
        NameList = []
 | 
						|
        OptionList = []
 | 
						|
        for Each in sorted(OptionDict):
 | 
						|
            if OptionDict[Each] not in OptionList:
 | 
						|
                NameList.append(Each)
 | 
						|
                OptionList.append(OptionDict[Each])
 | 
						|
                BsfFd.write("List &%s\n" % Each)
 | 
						|
                for Item in OptionDict[Each]:
 | 
						|
                    BsfFd.write('    Selection %s , "%s"\n' %
 | 
						|
                                (self.EvaluateExpress(Item[0]), Item[1]))
 | 
						|
                BsfFd.write("EndList\n\n")
 | 
						|
            else:
 | 
						|
                # Item has idential options as other item
 | 
						|
                # Try to reuse the previous options instead
 | 
						|
                Idx = OptionList.index(OptionDict[Each])
 | 
						|
                self._CfgOptsDict[Each] = NameList[Idx]
 | 
						|
 | 
						|
        BsfFd.write("BeginInfoBlock\n")
 | 
						|
        BsfFd.write('    PPVer       "%s"\n' % (self._CfgBlkDict['ver']))
 | 
						|
        BsfFd.write('    Description "%s"\n' % (self._CfgBlkDict['name']))
 | 
						|
        BsfFd.write("EndInfoBlock\n\n")
 | 
						|
 | 
						|
        self.WriteBsfPages(self._CfgPageTree, BsfFd)
 | 
						|
 | 
						|
        BsfFd.close()
 | 
						|
        return Error
 | 
						|
 | 
						|
    def WriteDeltaLine(self, OutLines, Name, ValStr, IsArray):
 | 
						|
        if IsArray:
 | 
						|
            Output = '%s | { %s }' % (Name, ValStr)
 | 
						|
        else:
 | 
						|
            Output = '%s | 0x%X' % (Name, Array2Val(ValStr))
 | 
						|
        OutLines.append(Output)
 | 
						|
 | 
						|
    def WriteDeltaFile(self, OutFile, PlatformId, OutLines):
 | 
						|
        DltFd = open(OutFile, "w")
 | 
						|
        DltFd.write("%s\n" % GetCopyrightHeader('dlt', True))
 | 
						|
        if PlatformId is not None:
 | 
						|
            DltFd.write('#\n')
 | 
						|
            DltFd.write('# Delta configuration values \
 | 
						|
for platform ID 0x%04X\n' % PlatformId)
 | 
						|
            DltFd.write('#\n\n')
 | 
						|
        for Line in OutLines:
 | 
						|
            DltFd.write('%s\n' % Line)
 | 
						|
        DltFd.close()
 | 
						|
 | 
						|
    def GenerateDeltaFile(self, OutFile, AbsfFile):
 | 
						|
        # Parse ABSF Build in dict
 | 
						|
        if not os.path.exists(AbsfFile):
 | 
						|
            Lines = []
 | 
						|
        else:
 | 
						|
            with open(AbsfFile) as Fin:
 | 
						|
                Lines = Fin.readlines()
 | 
						|
 | 
						|
        AbsfBuiltValDict = {}
 | 
						|
        Process = False
 | 
						|
        for Line in Lines:
 | 
						|
            Line = Line.strip()
 | 
						|
            if Line.startswith('StructDef'):
 | 
						|
                Process = True
 | 
						|
            if Line.startswith('EndStruct'):
 | 
						|
                break
 | 
						|
            if not Process:
 | 
						|
                continue
 | 
						|
            Match = re.match('\\s*\\$gCfgData_(\\w+)\\s+\
 | 
						|
(\\d+)\\s+(bits|bytes)\\s+\\$_AS_BUILT_\\s+=\\s+(.+)\\$', Line)
 | 
						|
            if Match:
 | 
						|
                if Match.group(1) not in AbsfBuiltValDict:
 | 
						|
                    AbsfBuiltValDict[Match.group(1)] = Match.group(4).strip()
 | 
						|
                else:
 | 
						|
                    raise Exception("Duplicated configuration \
 | 
						|
name '%s' found !", Match.group(1))
 | 
						|
 | 
						|
        # Match config item in DSC
 | 
						|
        PlatformId = None
 | 
						|
        OutLines = []
 | 
						|
        TagName = ''
 | 
						|
        Level = 0
 | 
						|
        for Item in self._CfgItemList:
 | 
						|
            Name = None
 | 
						|
            if Level == 0 and Item['embed'].endswith(':START'):
 | 
						|
                TagName = Item['embed'].split(':')[0]
 | 
						|
                Level += 1
 | 
						|
            if Item['cname'] in AbsfBuiltValDict:
 | 
						|
                ValStr = AbsfBuiltValDict[Item['cname']]
 | 
						|
                Name = '%s.%s' % (TagName, Item['cname'])
 | 
						|
                if not Item['subreg'] and Item['value'].startswith('{'):
 | 
						|
                    Value = Array2Val(Item['value'])
 | 
						|
                    IsArray = True
 | 
						|
                else:
 | 
						|
                    Value = int(Item['value'], 16)
 | 
						|
                    IsArray = False
 | 
						|
                AbsfVal = Array2Val(ValStr)
 | 
						|
                if AbsfVal != Value:
 | 
						|
                    if 'PLATFORMID_CFG_DATA.PlatformId' == Name:
 | 
						|
                        PlatformId = AbsfVal
 | 
						|
                    self.WriteDeltaLine(OutLines, Name, ValStr, IsArray)
 | 
						|
                else:
 | 
						|
                    if 'PLATFORMID_CFG_DATA.PlatformId' == Name:
 | 
						|
                        raise Exception("'PlatformId' has the \
 | 
						|
same value as DSC default !")
 | 
						|
 | 
						|
            if Item['subreg']:
 | 
						|
                for SubItem in Item['subreg']:
 | 
						|
                    if SubItem['cname'] in AbsfBuiltValDict:
 | 
						|
                        ValStr = AbsfBuiltValDict[SubItem['cname']]
 | 
						|
                        if Array2Val(ValStr) == int(SubItem['value'], 16):
 | 
						|
                            continue
 | 
						|
                        Name = '%s.%s.%s' % (TagName, Item['cname'],
 | 
						|
                                             SubItem['cname'])
 | 
						|
                        self.WriteDeltaLine(OutLines, Name, ValStr, False)
 | 
						|
 | 
						|
            if Item['embed'].endswith(':END'):
 | 
						|
                Level -= 1
 | 
						|
 | 
						|
        if PlatformId is None and Lines:
 | 
						|
            raise Exception("'PlatformId' configuration \
 | 
						|
is missing in ABSF file!")
 | 
						|
        else:
 | 
						|
            PlatformId = 0
 | 
						|
 | 
						|
        self.WriteDeltaFile(OutFile, PlatformId, Lines)
 | 
						|
 | 
						|
        return 0
 | 
						|
 | 
						|
    def GenerateDscFile(self, OutFile):
 | 
						|
        DscFd = open(OutFile, "w")
 | 
						|
        for Line in self._DscLines:
 | 
						|
            DscFd.write(Line + '\n')
 | 
						|
        DscFd.close()
 | 
						|
        return 0
 | 
						|
 | 
						|
 | 
						|
def Usage():
 | 
						|
    print('\n'.join([
 | 
						|
          "GenCfgData Version 0.01",
 | 
						|
          "Usage:",
 | 
						|
          "    GenCfgData  GENINC  BinFile             \
 | 
						|
IncOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENPKL  DscFile             \
 | 
						|
PklOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENINC  DscFile[;DltFile]   \
 | 
						|
IncOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENBIN  DscFile[;DltFile]   \
 | 
						|
BinOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENBSF  DscFile[;DltFile]   \
 | 
						|
BsfOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENDLT  DscFile[;AbsfFile]  \
 | 
						|
DltOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENDSC  DscFile             \
 | 
						|
DscOutFile   [-D Macros]",
 | 
						|
          "    GenCfgData  GENHDR  DscFile[;DltFile]   \
 | 
						|
HdrOutFile[;ComHdrOutFile]   [-D Macros]"
 | 
						|
          ]))
 | 
						|
 | 
						|
 | 
						|
def Main():
 | 
						|
    #
 | 
						|
    # Parse the options and args
 | 
						|
    #
 | 
						|
    argc = len(sys.argv)
 | 
						|
    if argc < 4:
 | 
						|
        Usage()
 | 
						|
        return 1
 | 
						|
 | 
						|
    GenCfgData = CGenCfgData()
 | 
						|
    Command = sys.argv[1].upper()
 | 
						|
    OutFile = sys.argv[3]
 | 
						|
 | 
						|
    if argc > 5 and GenCfgData.ParseMacros(sys.argv[4:]) != 0:
 | 
						|
        raise Exception("ERROR: Macro parsing failed !")
 | 
						|
 | 
						|
    FileList = sys.argv[2].split(';')
 | 
						|
    if len(FileList) == 2:
 | 
						|
        DscFile = FileList[0]
 | 
						|
        DltFile = FileList[1]
 | 
						|
    elif len(FileList) == 1:
 | 
						|
        DscFile = FileList[0]
 | 
						|
        DltFile = ''
 | 
						|
    else:
 | 
						|
        raise Exception("ERROR: Invalid parameter '%s' !" % sys.argv[2])
 | 
						|
 | 
						|
    if Command == "GENDLT" and DscFile.endswith('.dlt'):
 | 
						|
        # It needs to expand an existing DLT file
 | 
						|
        DltFile = DscFile
 | 
						|
        Lines = CGenCfgData.ExpandIncludeFiles(DltFile)
 | 
						|
        OutTxt = ''.join([x[0] for x in Lines])
 | 
						|
        OutFile = open(OutFile, "w")
 | 
						|
        OutFile.write(OutTxt)
 | 
						|
        OutFile.close()
 | 
						|
        return 0
 | 
						|
 | 
						|
    if not os.path.exists(DscFile):
 | 
						|
        raise Exception("ERROR: Cannot open file '%s' !" % DscFile)
 | 
						|
 | 
						|
    CfgBinFile = ''
 | 
						|
    if DltFile:
 | 
						|
        if not os.path.exists(DltFile):
 | 
						|
            raise Exception("ERROR: Cannot open file '%s' !" % DltFile)
 | 
						|
        if Command == "GENDLT":
 | 
						|
            CfgBinFile = DltFile
 | 
						|
            DltFile = ''
 | 
						|
 | 
						|
    BinFile = ''
 | 
						|
    if (DscFile.lower().endswith('.bin')) and (Command == "GENINC"):
 | 
						|
        # It is binary file
 | 
						|
        BinFile = DscFile
 | 
						|
        DscFile = ''
 | 
						|
 | 
						|
    if BinFile:
 | 
						|
        if GenCfgData.GenerateDataIncFile(OutFile, BinFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
        return 0
 | 
						|
 | 
						|
    if DscFile.lower().endswith('.pkl'):
 | 
						|
        with open(DscFile, "rb") as PklFile:
 | 
						|
            GenCfgData.__dict__ = marshal.load(PklFile)
 | 
						|
    else:
 | 
						|
        if GenCfgData.ParseDscFile(DscFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
        # if GenCfgData.CheckCfgData() != 0:
 | 
						|
        #    raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
        if GenCfgData.CreateVarDict() != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
        if Command == 'GENPKL':
 | 
						|
            with open(OutFile, "wb") as PklFile:
 | 
						|
                marshal.dump(GenCfgData.__dict__, PklFile)
 | 
						|
            return 0
 | 
						|
 | 
						|
    if DltFile and Command in ['GENHDR', 'GENBIN', 'GENINC', 'GENBSF']:
 | 
						|
        if GenCfgData.OverrideDefaultValue(DltFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    if GenCfgData.UpdateDefaultValue() != 0:
 | 
						|
        raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    # GenCfgData.PrintData ()
 | 
						|
 | 
						|
    if sys.argv[1] == "GENBIN":
 | 
						|
        if GenCfgData.GenerateBinary(OutFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    elif sys.argv[1] == "GENHDR":
 | 
						|
        OutFiles = OutFile.split(';')
 | 
						|
        BrdOutFile = OutFiles[0].strip()
 | 
						|
        if len(OutFiles) > 1:
 | 
						|
            ComOutFile = OutFiles[1].strip()
 | 
						|
        else:
 | 
						|
            ComOutFile = ''
 | 
						|
        if GenCfgData.CreateHeaderFile(BrdOutFile, ComOutFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    elif sys.argv[1] == "GENBSF":
 | 
						|
        if GenCfgData.GenerateBsfFile(OutFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    elif sys.argv[1] == "GENINC":
 | 
						|
        if GenCfgData.GenerateDataIncFile(OutFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    elif sys.argv[1] == "GENDLT":
 | 
						|
        if GenCfgData.GenerateDeltaFile(OutFile, CfgBinFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    elif sys.argv[1] == "GENDSC":
 | 
						|
        if GenCfgData.GenerateDscFile(OutFile) != 0:
 | 
						|
            raise Exception(GenCfgData.Error)
 | 
						|
 | 
						|
    else:
 | 
						|
        raise Exception("Unsuported command '%s' !" % Command)
 | 
						|
 | 
						|
    return 0
 | 
						|
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    sys.exit(Main())
 |