summaryrefslogtreecommitdiffstats
path: root/IntelFsp2Pkg/Tools/FspGenCfgData.py
diff options
context:
space:
mode:
authorLoo, Tung Lun <tung.lun.loo@intel.com>2021-06-29 12:32:35 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2021-06-30 03:56:59 +0000
commit580b11201ed001f9533c6782ec87d430b1736040 (patch)
treedd8ccb45baf49b457dd48ca98d4cb3b5b92d61ff /IntelFsp2Pkg/Tools/FspGenCfgData.py
parent55dee4947b20103fc48858b18307bd2b114dc145 (diff)
downloadedk2-580b11201ed001f9533c6782ec87d430b1736040.tar.gz
edk2-580b11201ed001f9533c6782ec87d430b1736040.tar.bz2
edk2-580b11201ed001f9533c6782ec87d430b1736040.zip
IntelFsp2Pkg: Add Config Editor tool support
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>
Diffstat (limited to 'IntelFsp2Pkg/Tools/FspGenCfgData.py')
-rw-r--r--IntelFsp2Pkg/Tools/FspGenCfgData.py2637
1 files changed, 2637 insertions, 0 deletions
diff --git a/IntelFsp2Pkg/Tools/FspGenCfgData.py b/IntelFsp2Pkg/Tools/FspGenCfgData.py
new file mode 100644
index 0000000000..8d4e49c8d2
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/FspGenCfgData.py
@@ -0,0 +1,2637 @@
+# @ 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())