X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=IntelFsp2Pkg%2FTools%2FGenCfgOpt.py;h=c4fb1f1bb24013c59a35dca9b98ea23da6e32e22;hb=6f219bef55f819cb88c86bd7e9b550de4d4345a1;hp=059cfcb7e4179ba7b91b939f4f11f5539962b07e;hpb=737f812b00b36d2a78971be03fe27efa0a992bfe;p=mirror_edk2.git diff --git a/IntelFsp2Pkg/Tools/GenCfgOpt.py b/IntelFsp2Pkg/Tools/GenCfgOpt.py index 059cfcb7e4..c4fb1f1bb2 100644 --- a/IntelFsp2Pkg/Tools/GenCfgOpt.py +++ b/IntelFsp2Pkg/Tools/GenCfgOpt.py @@ -1,13 +1,7 @@ ## @ GenCfgOpt.py # -# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
-# This program and the accompanying materials are licensed and made available under -# the terms and conditions of the BSD License that accompanies this distribution. -# The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php. -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -16,6 +10,7 @@ import re import sys import struct from datetime import date +from functools import reduce # Generated file copyright header @@ -88,17 +83,19 @@ are permitted provided that the following conditions are met: **/ """ +BuildOptionPcd = [] + 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) + print ("ERROR: Express parsing for:") + print (" %s" % self.string) + print (" %s^" % (' ' * self.index)) if err: - print "INFO : %s" % err + print ("INFO : %s" % err) raise SystemExit def getNonNumber (self, n1, n2): @@ -286,10 +283,10 @@ class CLogicalExpression: return Result class CGenCfgOpt: - def __init__(self): + def __init__(self, Mode = ''): self.Debug = False self.Error = '' - + self.Mode = Mode self._GlobalDataDef = """ GlobalDataDef SKUID = 0, "DEFAULT" @@ -303,19 +300,22 @@ List &EN_DIS EndList """ - - self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER'] + self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT'] self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT'] self._BuidinOption = {'$EN_DIS' : 'EN_DIS'} self._MacroDict = {} + self._VarDict = {} self._PcdsDict = {} self._CfgBlkDict = {} self._CfgPageDict = {} + self._BsfTempDict = {} self._CfgItemList = [] + self._DscLines = [] self._DscFile = '' - self._FvDir = '' + self._MapVer = 0 + self._DscTime = 0 def ParseMacros (self, MacroDefStr): # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build'] @@ -342,18 +342,18 @@ EndList else: Error = 0 if self.Debug: - print "INFO : Macro dictionary:" + print ("INFO : Macro dictionary:") for Each in self._MacroDict: - print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each]) + 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) + print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result)) return Result - def ExpandMacros (self, Input): + def ExpandMacros (self, Input, Preserve = False): Line = Input Match = re.findall("\$\(\w+\)", Input) if Match: @@ -363,8 +363,9 @@ EndList Line = Line.replace(Each, self._MacroDict[Variable]) else: if self.Debug: - print "WARN : %s is not defined" % Each - Line = Line.replace(Each, Each[2:-1]) + print ("WARN : %s is not defined" % Each) + if not Preserve: + Line = Line.replace(Each, Each[2:-1]) return Line def ExpandPcds (self, Input): @@ -376,7 +377,7 @@ EndList Line = Line.replace(PcdName, self._PcdsDict[PcdName]) else: if self.Debug: - print "WARN : %s is not defined" % PcdName + print ("WARN : %s is not defined" % PcdName) return Line def EvaluateExpress (self, Expr): @@ -385,7 +386,71 @@ EndList LogExpr = CLogicalExpression() Result = LogExpr.evaluateExpress (ExpExpr) if self.Debug: - print "INFO : Eval Express [%s] : %s" % (Expr, Result) + print ("INFO : Eval Express [%s] : %s" % (Expr, Result)) + return Result + + def ValueToByteArray (self, ValueStr, Length): + Match = re.match("\{\s*FILE:(.+)\}", ValueStr) + if Match: + FileList = Match.group(1).split(',') + Result = bytearray() + for File in FileList: + File = File.strip() + BinPath = os.path.join(os.path.dirname(self._DscFile), File) + Result.extend(bytearray(open(BinPath, 'rb').read())) + else: + try: + Result = bytearray(self.ValueToList(ValueStr, Length)) + except ValueError as e: + raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr) + if len(Result) < Length: + Result.extend(b'\x00' * (Length - len(Result))) + elif len(Result) > Length: + raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length)) + + return Result[:Length] + + def ValueToList (self, ValueStr, Length): + if ValueStr[0] == '{': + Result = [] + BinList = ValueStr[1:-1].split(',') + InBitField = False + LastInBitField = False + Value = 0 + BitLen = 0 + for Element in BinList: + InBitField = False + Each = Element.strip() + if len(Each) == 0: + pass + else: + if Each[0] in ['"', "'"]: + Result.extend(list(bytearray(Each[1:-1], 'utf-8'))) + elif ':' in Each: + Match = re.match("(.+):(\d+)b", Each) + if Match is None: + raise Exception("Invald value list format '%s' !" % Each) + InBitField = True + CurrentBitLen = int(Match.group(2)) + CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<> 8 newvalue = '{' + ','.join(bytearray) + '}' @@ -426,24 +491,53 @@ EndList self._DscFile = DscFile self._FvDir = FvDir + self._DscLines = [] + self._BsfTempDict = {} + + # Initial DSC time is parent DSC time. + self._DscTime = os.path.getmtime(DscFile) + + CfgDict = {} + IsDefSect = False IsPcdSect = False IsUpdSect = False IsVpdSect = False + IsTmpSect = False + + TemplateName = '' IfStack = [] ElifStack = [] Error = 0 ConfigDict = {} - DscFd = open(DscFile, "r") - DscLines = DscFd.readlines() - DscFd.close() + + if type(DscFile) is list: + # it is DSC lines already + DscLines = DscFile + self._DscFile = '.' + else: + DscFd = open(DscFile, "r") + DscLines = DscFd.readlines() + DscFd.close() + self._DscFile = DscFile + + SkipLines = 0 MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64 SizeAlign = 0 #record the struct max align + Base = 0 #Starting offset of sub-structure. + while len(DscLines): DscLine = DscLines.pop(0).strip() + if SkipLines == 0: + self._DscLines.append (DscLine) + else: + SkipLines = SkipLines - 1 + if len(DscLine) == 0: + continue + Handle = False Match = re.match("^\[(.+)\]", DscLine) if Match is not None: @@ -451,11 +545,15 @@ EndList IsPcdSect = False IsVpdSect = False IsUpdSect = False - if Match.group(1).lower() == "Defines".lower(): + IsTmpSect = False + SectionName = Match.group(1).lower() + if SectionName == "Defines".lower(): IsDefSect = True - if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()): + if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()): IsPcdSect = True - elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower(): + elif SectionName == "PcdsDynamicVpd.Tmp".lower(): + IsTmpSect = True + elif SectionName == "PcdsDynamicVpd.Upd".lower(): ConfigDict = {} ConfigDict['header'] = 'ON' ConfigDict['region'] = 'UPD' @@ -463,84 +561,98 @@ EndList ConfigDict['page'] = '' ConfigDict['name'] = '' ConfigDict['find'] = '' + ConfigDict['marker'] = '' ConfigDict['struct'] = '' ConfigDict['embed'] = '' ConfigDict['comment'] = '' ConfigDict['subreg'] = [] + ConfigDict['condition'] = '' + ConfigDict['option'] = '' IsUpdSect = True Offset = 0 else: - if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect: - if re.match("^!else($|\s+#.+)", DscLine): + if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect: + + Match = False if DscLine[0] != '!' else True + if Match: + Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine.split("#")[0]) + Keyword = Match.group(1) if Match else '' + Remaining = Match.group(2) if Match else '' + Remaining = '' if Remaining is None else Remaining.strip() + + if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining: + raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine) + + if Keyword == 'else': if IfStack: IfStack[-1] = not IfStack[-1] else: - print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine) - raise SystemExit - elif re.match("^!endif($|\s+#.+)", DscLine): + raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine) + elif Keyword == 'endif': if IfStack: IfStack.pop() Level = ElifStack.pop() if Level > 0: del IfStack[-Level:] else: - print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine) - raise SystemExit - else: - Result = False - Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine) - if Match: - Result = self.EvaulateIfdef (Match.group(2)) - if Match.group(1) == 'ifndef': - Result = not Result - IfStack.append(Result) + raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine) + elif Keyword == 'ifdef' or Keyword == 'ifndef': + Result = self.EvaulateIfdef (Remaining) + if Keyword == 'ifndef': + Result = not Result + IfStack.append(Result) + ElifStack.append(0) + elif Keyword == 'if' or Keyword == 'elseif': + Result = self.EvaluateExpress(Remaining) + if Keyword == "if": ElifStack.append(0) + IfStack.append(Result) + else: #elseif + if IfStack: + IfStack[-1] = not IfStack[-1] + IfStack.append(Result) + ElifStack[-1] = ElifStack[-1] + 1 + else: + raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine) + else: + if IfStack: + Handle = reduce(lambda x,y: x and y, IfStack) else: - Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0]) + Handle = True + if Handle: + Match = re.match("!include\s+(.+)", DscLine) if Match: - Result = self.EvaluateExpress(Match.group(2)) - if Match.group(1) == "if": - ElifStack.append(0) - IfStack.append(Result) - else: #elseif - if IfStack: - IfStack[-1] = not IfStack[-1] - IfStack.append(Result) - ElifStack[-1] = ElifStack[-1] + 1 - else: - print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine) - raise SystemExit - else: - if IfStack: - Handle = reduce(lambda x,y: x and y, IfStack) + IncludeFilePath = Match.group(1) + IncludeFilePath = self.ExpandMacros(IncludeFilePath) + PackagesPath = os.getenv("PACKAGES_PATH") + if PackagesPath: + for PackagePath in PackagesPath.split(os.pathsep): + IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath)) + if os.path.exists(IncludeFilePathAbs): + IncludeDsc = open(IncludeFilePathAbs, "r") + break else: - Handle = True - if Handle: - Match = re.match("!include\s+(.+)", DscLine) - if Match: - IncludeFilePath = Match.group(1) - IncludeFilePath = self.ExpandMacros(IncludeFilePath) - PackagesPath = os.getenv("PACKAGES_PATH") - if PackagesPath: - for PackagePath in PackagesPath.split(os.pathsep): - IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath)) - if os.path.exists(IncludeFilePathAbs): - IncludeDsc = open(IncludeFilePathAbs, "r") - break - else: - IncludeDsc = open(IncludeFilePath, "r") - if IncludeDsc == None: - print("ERROR: Cannot open file '%s'" % IncludeFilePath) - raise SystemExit - NewDscLines = IncludeDsc.readlines() - IncludeDsc.close() - DscLines = NewDscLines + DscLines - Offset = 0 - else: - if DscLine.startswith('!'): - print("ERROR: Unrecoginized directive for line '%s'" % DscLine) - raise SystemExit + IncludeDsc = open(IncludeFilePath, "r") + if IncludeDsc == None: + print("ERROR: Cannot open file '%s'" % IncludeFilePath) + raise SystemExit + + # Update DscTime when newer DSC time found. + CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name)) + if CurrentDscTime > self._DscTime: + self._DscTime = CurrentDscTime + + NewDscLines = IncludeDsc.readlines() + IncludeDsc.close() + DscLines = NewDscLines + DscLines + del self._DscLines[-1] + Offset = 0 + else: + if DscLine.startswith('!'): + print("ERROR: Unrecognized directive for line '%s'" % DscLine) + raise SystemExit if not Handle: + del self._DscLines[-1] continue if IsDefSect: @@ -548,11 +660,11 @@ EndList #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6 #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385 #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F - Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine) + Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine) if Match: - self._MacroDict[Match.group(1)] = Match.group(2) + self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2)) if self.Debug: - print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2)) + print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), self.ExpandMacros(Match.group(2)))) elif IsPcdSect: #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE @@ -560,7 +672,30 @@ EndList if Match: self._PcdsDict[Match.group(1)] = Match.group(2) if self.Debug: - print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2)) + print ("INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2))) + i = 0 + while i < len(BuildOptionPcd): + Match = re.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd[i]) + if Match: + self._PcdsDict[Match.group(1)] = Match.group(2) + i += 1 + + elif IsTmpSect: + # !BSF DEFT:{GPIO_TMPL:START} + Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine) + if Match: + if Match.group(3) == 'START' and not TemplateName: + TemplateName = Match.group(2).strip() + self._BsfTempDict[TemplateName] = [] + if Match.group(3) == 'END' and (TemplateName == Match.group(2).strip()) and TemplateName: + TemplateName = '' + else: + if TemplateName: + Match = re.match("^!include\s*(.+)?$", DscLine) + if Match: + continue + self._BsfTempDict[TemplateName].append(DscLine) + else: Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine) if Match: @@ -573,7 +708,8 @@ EndList for Page in PageList: Page = Page.strip() Match = re.match("(\w+):\"(.+)\"", Page) - self._CfgPageDict[Match.group(1)] = Match.group(2) + if Match != None: + self._CfgPageDict[Match.group(1)] = Match.group(2) Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining) if Match: @@ -616,9 +752,9 @@ EndList Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine) if Match: if "0x" in Match.group(2) or "0x" in Match.group(3): - ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3)) + ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3)) else: - ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3)) + ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3)) Match = re.match("^\s*##\s+(.+)", DscLine) if Match: @@ -712,7 +848,7 @@ EndList if (ConfigDict['embed'].find(':END') != -1): Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64 if Remainder: - Diff = (MaxAlign/8) - Remainder + Diff = int((MaxAlign/8) - Remainder) Offset = Offset + Diff ItemOffset = ItemOffset + Diff MaxAlign = 32 # Reset to default 32 align when struct end @@ -724,7 +860,7 @@ EndList Remainder = Offset % max(ItemLength/8, 4, SizeAlign) Offset = Offset + ItemLength if Remainder: - Diff = max(ItemLength/8, 4, SizeAlign) - Remainder + Diff = int(max(ItemLength/8, 4, SizeAlign) - Remainder) ItemOffset = ItemOffset + Diff ConfigDict['offset'] = ItemOffset @@ -734,6 +870,7 @@ EndList ConfigDict['struct'] = '' ConfigDict['embed'] = '' ConfigDict['comment'] = '' + ConfigDict['marker'] = '' ConfigDict['order'] = -1 ConfigDict['subreg'] = [] ConfigDict['option'] = '' @@ -772,9 +909,8 @@ EndList bitsvalue = bitsvalue[::-1] bitslen = len(bitsvalue) if start > bitslen or end > bitslen: - print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name']) - raise SystemExit - return hex(int(bitsvalue[start:end][::-1], 2)) + raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name'])) + return '0x%X' % (int(bitsvalue[start:end][::-1], 2)) def UpdateSubRegionDefaultValue (self): Error = 0 @@ -806,6 +942,16 @@ EndList SubItem['value'] = valuestr return Error + def NoDscFileChange (self, OutPutFile): + NoFileChange = True + if not os.path.exists(OutPutFile): + NoFileChange = False + else: + OutputTime = os.path.getmtime(OutPutFile) + if self._DscTime > OutputTime: + NoFileChange = False + return NoFileChange + def CreateSplitUpdTxt (self, UpdTxtFile): GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID'] SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS @@ -819,16 +965,7 @@ EndList if UpdTxtFile == '': UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt') - ReCreate = False - if not os.path.exists(UpdTxtFile): - ReCreate = True - else: - DscTime = os.path.getmtime(self._DscFile) - TxtTime = os.path.getmtime(UpdTxtFile) - if DscTime > TxtTime: - ReCreate = True - - if not ReCreate: + if (self.NoDscFileChange (UpdTxtFile)): # DSC has not been modified yet # So don't have to re-generate other files self.Error = 'No DSC file change, skip to create UPD TXT file' @@ -873,63 +1010,142 @@ EndList TxtFd.close() return 0 - def ProcessMultilines (self, String, MaxCharLength): - Multilines = '' - StringLength = len(String) - CurrentStringStart = 0 - StringOffset = 0 - BreakLineDict = [] - if len(String) <= MaxCharLength: - while (StringOffset < StringLength): - if StringOffset >= 1: - if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': - BreakLineDict.append (StringOffset + 1) - StringOffset += 1 - if BreakLineDict != []: - for Each in BreakLineDict: - Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() - CurrentStringStart = Each - if StringLength - CurrentStringStart > 0: - Multilines += " %s\n" % String[CurrentStringStart:].lstrip() + def CreateVarDict (self): + Error = 0 + self._VarDict = {} + if len(self._CfgItemList) > 0: + Item = self._CfgItemList[-1] + self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length']) + for Item in self._CfgItemList: + Embed = Item['embed'] + Match = re.match("^(\w+):(\w+):(START|END)", Embed) + if Match: + StructName = Match.group(1) + VarName = '_%s_%s_' % (Match.group(3), StructName) + if Match.group(3) == 'END': + self._VarDict[VarName] = Item['offset'] + Item['length'] + self._VarDict['_LENGTH_%s_' % StructName] = \ + self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName] + if Match.group(2).startswith('TAG_'): + if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4): + raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName])) + self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF else: - Multilines = " %s\n" % String + self._VarDict[VarName] = Item['offset'] + if Item['marker']: + self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset'] + return Error + + def UpdateBsfBitUnit (self, Item): + BitTotal = 0 + BitOffset = 0 + StartIdx = 0 + Unit = None + UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'} + for Idx, SubItem in enumerate(Item['subreg']): + if Unit is None: + Unit = SubItem['bitunit'] + BitLength = SubItem['bitlength'] + BitTotal += BitLength + BitOffset += BitLength + + if BitOffset > 64 or BitOffset > Unit * 8: + break + + if BitOffset == Unit * 8: + for SubIdx in range (StartIdx, Idx + 1): + Item['subreg'][SubIdx]['bitunit'] = Unit + BitOffset = 0 + StartIdx = Idx + 1 + Unit = None + + if BitOffset > 0: + raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname'])) + + ExpectedTotal = Item['length'] * 8 + if Item['length'] * 8 != BitTotal: + raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname'])) + + def UpdateDefaultValue (self): + Error = 0 + for Idx, Item in enumerate(self._CfgItemList): + if len(Item['subreg']) == 0: + Value = Item['value'] + if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'): + # {XXX} or 'XXX' strings + self.FormatListValue(self._CfgItemList[Idx]) + else: + Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value) + if not Match: + NumValue = self.EvaluateExpress (Value) + Item['value'] = '0x%X' % NumValue else: - NewLineStart = 0 - NewLineCount = 0 - FoundSpaceChar = False - while (StringOffset < StringLength): - if StringOffset >= 1: - if NewLineCount >= MaxCharLength - 1: - if String[StringOffset] == ' ' and StringLength - StringOffset > 10: - BreakLineDict.append (NewLineStart + NewLineCount) - NewLineStart = NewLineStart + NewLineCount - NewLineCount = 0 - FoundSpaceChar = True - elif StringOffset == StringLength - 1 and FoundSpaceChar == False: - BreakLineDict.append (0) - if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': - BreakLineDict.append (StringOffset + 1) - NewLineStart = StringOffset + 1 + ValArray = self.ValueToByteArray (Item['value'], Item['length']) + for SubItem in Item['subreg']: + SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray) + self.UpdateBsfBitUnit (Item) + return Error + + def ProcessMultilines (self, String, MaxCharLength): + Multilines = '' + StringLength = len(String) + CurrentStringStart = 0 + StringOffset = 0 + BreakLineDict = [] + if len(String) <= MaxCharLength: + while (StringOffset < StringLength): + if StringOffset >= 1: + if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': + BreakLineDict.append (StringOffset + 1) + StringOffset += 1 + if BreakLineDict != []: + for Each in BreakLineDict: + Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() + CurrentStringStart = Each + if StringLength - CurrentStringStart > 0: + Multilines += " %s\n" % String[CurrentStringStart:].lstrip() + else: + Multilines = " %s\n" % String + else: + NewLineStart = 0 + NewLineCount = 0 + FoundSpaceChar = False + while (StringOffset < StringLength): + if StringOffset >= 1: + if NewLineCount >= MaxCharLength - 1: + if String[StringOffset] == ' ' and StringLength - StringOffset > 10: + BreakLineDict.append (NewLineStart + NewLineCount) + NewLineStart = NewLineStart + NewLineCount NewLineCount = 0 - StringOffset += 1 - NewLineCount += 1 - if BreakLineDict != []: - BreakLineDict.sort () - for Each in BreakLineDict: - if Each > 0: - Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() - CurrentStringStart = Each - if StringLength - CurrentStringStart > 0: - Multilines += " %s\n" % String[CurrentStringStart:].lstrip() - return Multilines - - def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option): + FoundSpaceChar = True + elif StringOffset == StringLength - 1 and FoundSpaceChar == False: + BreakLineDict.append (0) + if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': + BreakLineDict.append (StringOffset + 1) + NewLineStart = StringOffset + 1 + NewLineCount = 0 + StringOffset += 1 + NewLineCount += 1 + if BreakLineDict != []: + BreakLineDict.sort () + for Each in BreakLineDict: + if Each > 0: + Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() + CurrentStringStart = Each + if StringLength - CurrentStringStart > 0: + Multilines += " %s\n" % String[CurrentStringStart:].lstrip() + return Multilines + + def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None): PosName = 28 PosComment = 30 NameLine='' HelpLine='' OptionLine='' + if Length == 0 and Name == 'Dummy': + return '\n' + IsArray = False if Length in [1,2,4,8]: Type = "UINT%d" % (Length * 8) @@ -977,7 +1193,12 @@ EndList else: OffsetStr = '0x%04X' % Offset - return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,) + if BitsLength is None: + BitsLength = '' + else: + BitsLength = ' : %d' % BitsLength + + return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength) def PostProcessBody (self, TextBody): NewTextBody = [] @@ -1029,7 +1250,7 @@ EndList if Match and Match.group(3) == 'END': if (StructName != Match.group(1)) or (VariableName != Match.group(2)): - print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)) + print ("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1))) else: if IsUpdHdrDefined != True or IsUpdHeader != True: NewTextBody.append ('} %s;\n\n' % StructName) @@ -1052,7 +1273,11 @@ EndList HeaderFile = os.path.join(FvDir, HeaderFileName) # Check if header needs to be recreated - ReCreate = False + if (self.NoDscFileChange (HeaderFile)): + # DSC has not been modified yet + # So don't have to re-generate other files + self.Error = 'No DSC file change, skip to create UPD header file' + return 256 TxtBody = [] for Item in self._CfgItemList: @@ -1078,6 +1303,7 @@ EndList UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD'] for Item in self._CfgItemList: if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature: + Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting UpdOffsetTable.append (Item["offset"]) for UpdIdx in range(len(UpdOffsetTable)): @@ -1171,8 +1397,10 @@ EndList UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE'] - ExcludedSpecificUpd = 'FSPM_ARCH_UPD' + ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD'] + ExcludedSpecificUpd1 = ['FSPT_ARCH2_UPD', 'FSPM_ARCH2_UPD', 'FSPS_ARCH2_UPD'] + IncLines = [] if InputHeaderFile != '': if not os.path.exists(InputHeaderFile): self.Error = "Input header file '%s' does not exist" % InputHeaderFile @@ -1225,7 +1453,7 @@ EndList if Match: StartIndex = Index - 1 Match = re.match("}\s([_A-Z0-9]+);", Line) - if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)): + if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd[item] not in Match.group(1)) and (ExcludedSpecificUpd1[item] not in Match.group(1)): EndIndex = Index StructStart.append(StartIndex) StructEnd.append(EndIndex) @@ -1377,6 +1605,12 @@ EndList self.Error = "BSF output file '%s' is invalid" % BsfFile return 1 + if (self.NoDscFileChange (BsfFile)): + # DSC has not been modified yet + # So don't have to re-generate other files + self.Error = 'No DSC file change, skip to create UPD BSF file' + return 256 + Error = 0 OptionDict = {} BsfFd = open(BsfFile, "w") @@ -1413,7 +1647,7 @@ EndList if BitsRemain: BsfFd.write(" Skip %d bits\n" % BitsRemain) BitsGap -= BitsRemain - BytesRemain = BitsGap / 8 + BytesRemain = int(BitsGap / 8) if BytesRemain: BsfFd.write(" Skip %d bytes\n" % BytesRemain) NextOffset = Item['offset'] + Item['length'] @@ -1462,17 +1696,24 @@ EndList def Usage(): - print "GenCfgOpt Version 0.52" - print "Usage:" - print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]" - print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]" - print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]" + print ("GenCfgOpt Version 0.57") + print ("Usage:") + print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]") + print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]") + print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]") def Main(): # # Parse the options and args # + i = 1 + GenCfgOpt = CGenCfgOpt() + while i < len(sys.argv): + if sys.argv[i].strip().lower() == "--pcd": + BuildOptionPcd.append(sys.argv[i+1]) + i += 1 + i += 1 argc = len(sys.argv) if argc < 4: Usage() @@ -1480,7 +1721,7 @@ def Main(): else: DscFile = sys.argv[2] if not os.path.exists(DscFile): - print "ERROR: Cannot open DSC file '%s' !" % DscFile + print ("ERROR: Cannot open DSC file '%s' !" % DscFile) return 2 OutFile = '' @@ -1492,7 +1733,7 @@ def Main(): Start = 5 if argc > Start: if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0: - print "ERROR: Macro parsing failed !" + print ("ERROR: Macro parsing failed !") return 3 FvDir = sys.argv[3] @@ -1500,11 +1741,11 @@ def Main(): os.makedirs(FvDir) if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0: - print "ERROR: %s !" % GenCfgOpt.Error + print ("ERROR: %s !" % GenCfgOpt.Error) return 5 if GenCfgOpt.UpdateSubRegionDefaultValue() != 0: - print "ERROR: %s !" % GenCfgOpt.Error + print ("ERROR: %s !" % GenCfgOpt.Error) return 7 if sys.argv[1] == "UPDTXT": @@ -1512,23 +1753,35 @@ def Main(): if Ret != 0: # No change is detected if Ret == 256: - print "INFO: %s !" % (GenCfgOpt.Error) + print ("INFO: %s !" % (GenCfgOpt.Error)) else : - print "ERROR: %s !" % (GenCfgOpt.Error) + print ("ERROR: %s !" % (GenCfgOpt.Error)) return Ret elif sys.argv[1] == "HEADER": - if GenCfgOpt.CreateHeaderFile(OutFile) != 0: - print "ERROR: %s !" % GenCfgOpt.Error - return 8 + Ret = GenCfgOpt.CreateHeaderFile(OutFile) + if Ret != 0: + # No change is detected + if Ret == 256: + print ("INFO: %s !" % (GenCfgOpt.Error)) + else : + print ("ERROR: %s !" % (GenCfgOpt.Error)) + return 8 + return Ret elif sys.argv[1] == "GENBSF": - if GenCfgOpt.GenerateBsfFile(OutFile) != 0: - print "ERROR: %s !" % GenCfgOpt.Error - return 9 + Ret = GenCfgOpt.GenerateBsfFile(OutFile) + if Ret != 0: + # No change is detected + if Ret == 256: + print ("INFO: %s !" % (GenCfgOpt.Error)) + else : + print ("ERROR: %s !" % (GenCfgOpt.Error)) + return 9 + return Ret else: if argc < 5: Usage() return 1 - print "ERROR: Unknown command '%s' !" % sys.argv[1] + print ("ERROR: Unknown command '%s' !" % sys.argv[1]) Usage() return 1 return 0