## @ GenCfgOpt.py\r
#\r
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
##\r
return Result\r
\r
class CGenCfgOpt:\r
- def __init__(self):\r
+ def __init__(self, Mode = ''):\r
self.Debug = False\r
self.Error = ''\r
-\r
+ self.Mode = Mode\r
self._GlobalDataDef = """\r
GlobalDataDef\r
SKUID = 0, "DEFAULT"\r
EndList\r
\r
"""\r
-\r
- self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']\r
+ self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT']\r
self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']\r
self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}\r
\r
self._MacroDict = {}\r
+ self._VarDict = {}\r
self._PcdsDict = {}\r
self._CfgBlkDict = {}\r
self._CfgPageDict = {}\r
+ self._BsfTempDict = {}\r
self._CfgItemList = []\r
+ self._DscLines = []\r
self._DscFile = ''\r
- self._FvDir = ''\r
+\r
self._MapVer = 0\r
+ self._DscTime = 0\r
\r
def ParseMacros (self, MacroDefStr):\r
# ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']\r
print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))\r
return Result\r
\r
- def ExpandMacros (self, Input):\r
+ def ExpandMacros (self, Input, Preserve = False):\r
Line = Input\r
Match = re.findall("\$\(\w+\)", Input)\r
if Match:\r
else:\r
if self.Debug:\r
print ("WARN : %s is not defined" % Each)\r
- Line = Line.replace(Each, Each[2:-1])\r
+ if not Preserve:\r
+ Line = Line.replace(Each, Each[2:-1])\r
return Line\r
\r
def ExpandPcds (self, Input):\r
print ("INFO : Eval Express [%s] : %s" % (Expr, Result))\r
return Result\r
\r
+ def ValueToByteArray (self, ValueStr, Length):\r
+ Match = re.match("\{\s*FILE:(.+)\}", ValueStr)\r
+ if Match:\r
+ FileList = Match.group(1).split(',')\r
+ Result = bytearray()\r
+ for File in FileList:\r
+ File = File.strip()\r
+ BinPath = os.path.join(os.path.dirname(self._DscFile), File)\r
+ Result.extend(bytearray(open(BinPath, 'rb').read()))\r
+ else:\r
+ try:\r
+ Result = bytearray(self.ValueToList(ValueStr, Length))\r
+ except ValueError as e:\r
+ raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr)\r
+ if len(Result) < Length:\r
+ Result.extend(b'\x00' * (Length - len(Result)))\r
+ elif len(Result) > Length:\r
+ raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length))\r
+\r
+ return Result[:Length]\r
+\r
+ def ValueToList (self, ValueStr, Length):\r
+ if ValueStr[0] == '{':\r
+ Result = []\r
+ BinList = ValueStr[1:-1].split(',')\r
+ InBitField = False\r
+ LastInBitField = False\r
+ Value = 0\r
+ BitLen = 0\r
+ for Element in BinList:\r
+ InBitField = False\r
+ Each = Element.strip()\r
+ if len(Each) == 0:\r
+ pass\r
+ else:\r
+ if Each[0] in ['"', "'"]:\r
+ Result.extend(list(bytearray(Each[1:-1], 'utf-8')))\r
+ elif ':' in Each:\r
+ Match = re.match("(.+):(\d+)b", Each)\r
+ if Match is None:\r
+ raise Exception("Invald value list format '%s' !" % Each)\r
+ InBitField = True\r
+ CurrentBitLen = int(Match.group(2))\r
+ CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<<CurrentBitLen) - 1)) << BitLen\r
+ else:\r
+ Result.append(self.EvaluateExpress(Each.strip()))\r
+ if InBitField:\r
+ Value += CurrentValue\r
+ BitLen += CurrentBitLen\r
+ if LastInBitField and ((not InBitField) or (Element == BinList[-1])):\r
+ if BitLen % 8 != 0:\r
+ raise Exception("Invald bit field length!")\r
+ Result.extend(Val2Bytes(Value, BitLen // 8))\r
+ Value = 0\r
+ BitLen = 0\r
+ LastInBitField = InBitField\r
+ elif ValueStr.startswith("'") and ValueStr.endswith("'"):\r
+ Result = Str2Bytes (ValueStr, Length)\r
+ elif ValueStr.startswith('"') and ValueStr.endswith('"'):\r
+ Result = Str2Bytes (ValueStr, Length)\r
+ else:\r
+ Result = Val2Bytes (self.EvaluateExpress(ValueStr), Length)\r
+ return Result\r
+\r
def FormatListValue(self, ConfigDict):\r
Struct = ConfigDict['struct']\r
if Struct not in ['UINT8','UINT16','UINT32','UINT64']:\r
self._DscFile = DscFile\r
self._FvDir = FvDir\r
\r
+ self._DscLines = []\r
+ self._BsfTempDict = {}\r
+\r
+ # Initial DSC time is parent DSC time.\r
+ self._DscTime = os.path.getmtime(DscFile)\r
+\r
+ CfgDict = {}\r
+\r
IsDefSect = False\r
IsPcdSect = False\r
IsUpdSect = False\r
IsVpdSect = False\r
+ IsTmpSect = False\r
+\r
+ TemplateName = ''\r
\r
IfStack = []\r
ElifStack = []\r
Error = 0\r
ConfigDict = {}\r
\r
- DscFd = open(DscFile, "r")\r
- DscLines = DscFd.readlines()\r
- DscFd.close()\r
+\r
+ if type(DscFile) is list:\r
+ # it is DSC lines already\r
+ DscLines = DscFile\r
+ self._DscFile = '.'\r
+ else:\r
+ DscFd = open(DscFile, "r")\r
+ DscLines = DscFd.readlines()\r
+ DscFd.close()\r
+ self._DscFile = DscFile\r
+\r
+ SkipLines = 0\r
\r
MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64\r
SizeAlign = 0 #record the struct max align\r
+ Base = 0 #Starting offset of sub-structure.\r
+\r
while len(DscLines):\r
DscLine = DscLines.pop(0).strip()\r
+ if SkipLines == 0:\r
+ self._DscLines.append (DscLine)\r
+ else:\r
+ SkipLines = SkipLines - 1\r
+ if len(DscLine) == 0:\r
+ continue\r
+\r
Handle = False\r
Match = re.match("^\[(.+)\]", DscLine)\r
if Match is not None:\r
IsPcdSect = False\r
IsVpdSect = False\r
IsUpdSect = False\r
- if Match.group(1).lower() == "Defines".lower():\r
+ IsTmpSect = False\r
+ SectionName = Match.group(1).lower()\r
+ if SectionName == "Defines".lower():\r
IsDefSect = True\r
- if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()):\r
+ if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()):\r
IsPcdSect = True\r
- elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():\r
+ elif SectionName == "PcdsDynamicVpd.Tmp".lower():\r
+ IsTmpSect = True\r
+ elif SectionName == "PcdsDynamicVpd.Upd".lower():\r
ConfigDict = {}\r
ConfigDict['header'] = 'ON'\r
ConfigDict['region'] = 'UPD'\r
ConfigDict['page'] = ''\r
ConfigDict['name'] = ''\r
ConfigDict['find'] = ''\r
+ ConfigDict['marker'] = ''\r
ConfigDict['struct'] = ''\r
ConfigDict['embed'] = ''\r
ConfigDict['comment'] = ''\r
ConfigDict['subreg'] = []\r
+ ConfigDict['condition'] = ''\r
+ ConfigDict['option'] = ''\r
IsUpdSect = True\r
Offset = 0\r
else:\r
- if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:\r
- if re.match("^!else($|\s+#.+)", DscLine):\r
+ if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect:\r
+\r
+ Match = False if DscLine[0] != '!' else True\r
+ if Match:\r
+ Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine.split("#")[0])\r
+ Keyword = Match.group(1) if Match else ''\r
+ Remaining = Match.group(2) if Match else ''\r
+ Remaining = '' if Remaining is None else Remaining.strip()\r
+\r
+ if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining:\r
+ raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine)\r
+\r
+ if Keyword == 'else':\r
if IfStack:\r
IfStack[-1] = not IfStack[-1]\r
else:\r
- print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
- raise SystemExit\r
- elif re.match("^!endif($|\s+#.+)", DscLine):\r
+ raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)\r
+ elif Keyword == 'endif':\r
if IfStack:\r
IfStack.pop()\r
Level = ElifStack.pop()\r
if Level > 0:\r
del IfStack[-Level:]\r
else:\r
- print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
- raise SystemExit\r
- else:\r
- Result = False\r
- Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)\r
- if Match:\r
- Result = self.EvaulateIfdef (Match.group(2))\r
- if Match.group(1) == 'ifndef':\r
- Result = not Result\r
- IfStack.append(Result)\r
+ raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)\r
+ elif Keyword == 'ifdef' or Keyword == 'ifndef':\r
+ Result = self.EvaulateIfdef (Remaining)\r
+ if Keyword == 'ifndef':\r
+ Result = not Result\r
+ IfStack.append(Result)\r
+ ElifStack.append(0)\r
+ elif Keyword == 'if' or Keyword == 'elseif':\r
+ Result = self.EvaluateExpress(Remaining)\r
+ if Keyword == "if":\r
ElifStack.append(0)\r
+ IfStack.append(Result)\r
+ else: #elseif\r
+ if IfStack:\r
+ IfStack[-1] = not IfStack[-1]\r
+ IfStack.append(Result)\r
+ ElifStack[-1] = ElifStack[-1] + 1\r
+ else:\r
+ raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
+ else:\r
+ if IfStack:\r
+ Handle = reduce(lambda x,y: x and y, IfStack)\r
else:\r
- Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0])\r
+ Handle = True\r
+ if Handle:\r
+ Match = re.match("!include\s+(.+)", DscLine)\r
if Match:\r
- Result = self.EvaluateExpress(Match.group(2))\r
- if Match.group(1) == "if":\r
- ElifStack.append(0)\r
- IfStack.append(Result)\r
- else: #elseif\r
- if IfStack:\r
- IfStack[-1] = not IfStack[-1]\r
- IfStack.append(Result)\r
- ElifStack[-1] = ElifStack[-1] + 1\r
- else:\r
- print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)\r
- raise SystemExit\r
- else:\r
- if IfStack:\r
- Handle = reduce(lambda x,y: x and y, IfStack)\r
+ IncludeFilePath = Match.group(1)\r
+ IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
+ PackagesPath = os.getenv("PACKAGES_PATH")\r
+ if PackagesPath:\r
+ for PackagePath in PackagesPath.split(os.pathsep):\r
+ IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))\r
+ if os.path.exists(IncludeFilePathAbs):\r
+ IncludeDsc = open(IncludeFilePathAbs, "r")\r
+ break\r
else:\r
- Handle = True\r
- if Handle:\r
- Match = re.match("!include\s+(.+)", DscLine)\r
- if Match:\r
- IncludeFilePath = Match.group(1)\r
- IncludeFilePath = self.ExpandMacros(IncludeFilePath)\r
- PackagesPath = os.getenv("PACKAGES_PATH")\r
- if PackagesPath:\r
- for PackagePath in PackagesPath.split(os.pathsep):\r
- IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))\r
- if os.path.exists(IncludeFilePathAbs):\r
- IncludeDsc = open(IncludeFilePathAbs, "r")\r
- break\r
- else:\r
- IncludeDsc = open(IncludeFilePath, "r")\r
- if IncludeDsc == None:\r
- print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
- raise SystemExit\r
- NewDscLines = IncludeDsc.readlines()\r
- IncludeDsc.close()\r
- DscLines = NewDscLines + DscLines\r
- Offset = 0\r
- else:\r
- if DscLine.startswith('!'):\r
- print("ERROR: Unrecognized directive for line '%s'" % DscLine)\r
- raise SystemExit\r
+ IncludeDsc = open(IncludeFilePath, "r")\r
+ if IncludeDsc == None:\r
+ print("ERROR: Cannot open file '%s'" % IncludeFilePath)\r
+ raise SystemExit\r
+\r
+ # Update DscTime when newer DSC time found.\r
+ CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name))\r
+ if CurrentDscTime > self._DscTime:\r
+ self._DscTime = CurrentDscTime\r
+\r
+ NewDscLines = IncludeDsc.readlines()\r
+ IncludeDsc.close()\r
+ DscLines = NewDscLines + DscLines\r
+ del self._DscLines[-1]\r
+ Offset = 0\r
+ else:\r
+ if DscLine.startswith('!'):\r
+ print("ERROR: Unrecognized directive for line '%s'" % DscLine)\r
+ raise SystemExit\r
if not Handle:\r
+ del self._DscLines[-1]\r
continue\r
\r
if IsDefSect:\r
#DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6\r
#DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385\r
#DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F\r
- Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)\r
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine)\r
if Match:\r
- self._MacroDict[Match.group(1)] = Match.group(2)\r
+ self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2))\r
if self.Debug:\r
- print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2)))\r
+ print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), self.ExpandMacros(Match.group(2))))\r
elif IsPcdSect:\r
#gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE\r
#gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE\r
if Match:\r
self._PcdsDict[Match.group(1)] = Match.group(2)\r
i += 1\r
+\r
+ elif IsTmpSect:\r
+ # !BSF DEFT:{GPIO_TMPL:START}\r
+ Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine)\r
+ if Match:\r
+ if Match.group(3) == 'START' and not TemplateName:\r
+ TemplateName = Match.group(2).strip()\r
+ self._BsfTempDict[TemplateName] = []\r
+ if Match.group(3) == 'END' and (TemplateName == Match.group(2).strip()) and TemplateName:\r
+ TemplateName = ''\r
+ else:\r
+ if TemplateName:\r
+ Match = re.match("^!include\s*(.+)?$", DscLine)\r
+ if Match:\r
+ continue\r
+ self._BsfTempDict[TemplateName].append(DscLine)\r
+\r
else:\r
Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)\r
if Match:\r
for Page in PageList:\r
Page = Page.strip()\r
Match = re.match("(\w+):\"(.+)\"", Page)\r
- self._CfgPageDict[Match.group(1)] = Match.group(2)\r
+ if Match != None:\r
+ self._CfgPageDict[Match.group(1)] = Match.group(2)\r
\r
Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)\r
if Match:\r
Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)\r
if Match:\r
if "0x" in Match.group(2) or "0x" in Match.group(3):\r
- ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
+ ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))\r
else:\r
- ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
+ ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))\r
\r
Match = re.match("^\s*##\s+(.+)", DscLine)\r
if Match:\r
if (ConfigDict['embed'].find(':END') != -1):\r
Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64\r
if Remainder:\r
- Diff = (MaxAlign/8) - Remainder\r
+ Diff = int((MaxAlign/8) - Remainder)\r
Offset = Offset + Diff\r
ItemOffset = ItemOffset + Diff\r
MaxAlign = 32 # Reset to default 32 align when struct end\r
Remainder = Offset % max(ItemLength/8, 4, SizeAlign)\r
Offset = Offset + ItemLength\r
if Remainder:\r
- Diff = max(ItemLength/8, 4, SizeAlign) - Remainder\r
+ Diff = int(max(ItemLength/8, 4, SizeAlign) - Remainder)\r
ItemOffset = ItemOffset + Diff\r
ConfigDict['offset'] = ItemOffset\r
\r
ConfigDict['struct'] = ''\r
ConfigDict['embed'] = ''\r
ConfigDict['comment'] = ''\r
+ ConfigDict['marker'] = ''\r
ConfigDict['order'] = -1\r
ConfigDict['subreg'] = []\r
ConfigDict['option'] = ''\r
bitsvalue = bitsvalue[::-1]\r
bitslen = len(bitsvalue)\r
if start > bitslen or end > bitslen:\r
- print ("Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name']))\r
- raise SystemExit\r
- return hex(int(bitsvalue[start:end][::-1], 2))\r
+ raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))\r
+ return '0x%X' % (int(bitsvalue[start:end][::-1], 2))\r
\r
def UpdateSubRegionDefaultValue (self):\r
Error = 0\r
SubItem['value'] = valuestr\r
return Error\r
\r
+ def NoDscFileChange (self, OutPutFile):\r
+ NoFileChange = True\r
+ if not os.path.exists(OutPutFile):\r
+ NoFileChange = False\r
+ else:\r
+ OutputTime = os.path.getmtime(OutPutFile)\r
+ if self._DscTime > OutputTime:\r
+ NoFileChange = False\r
+ return NoFileChange\r
+\r
def CreateSplitUpdTxt (self, UpdTxtFile):\r
GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']\r
SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS\r
if UpdTxtFile == '':\r
UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')\r
\r
- ReCreate = False\r
- if not os.path.exists(UpdTxtFile):\r
- ReCreate = True\r
- else:\r
- DscTime = os.path.getmtime(self._DscFile)\r
- TxtTime = os.path.getmtime(UpdTxtFile)\r
- if DscTime > TxtTime:\r
- ReCreate = True\r
-\r
- if not ReCreate:\r
+ if (self.NoDscFileChange (UpdTxtFile)):\r
# DSC has not been modified yet\r
# So don't have to re-generate other files\r
self.Error = 'No DSC file change, skip to create UPD TXT file'\r
TxtFd.close()\r
return 0\r
\r
- def ProcessMultilines (self, String, MaxCharLength):\r
- Multilines = ''\r
- StringLength = len(String)\r
- CurrentStringStart = 0\r
- StringOffset = 0\r
- BreakLineDict = []\r
- if len(String) <= MaxCharLength:\r
- while (StringOffset < StringLength):\r
- if StringOffset >= 1:\r
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
- BreakLineDict.append (StringOffset + 1)\r
- StringOffset += 1\r
- if BreakLineDict != []:\r
- for Each in BreakLineDict:\r
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
- CurrentStringStart = Each\r
- if StringLength - CurrentStringStart > 0:\r
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
+ def CreateVarDict (self):\r
+ Error = 0\r
+ self._VarDict = {}\r
+ if len(self._CfgItemList) > 0:\r
+ Item = self._CfgItemList[-1]\r
+ self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])\r
+ for Item in self._CfgItemList:\r
+ Embed = Item['embed']\r
+ Match = re.match("^(\w+):(\w+):(START|END)", Embed)\r
+ if Match:\r
+ StructName = Match.group(1)\r
+ VarName = '_%s_%s_' % (Match.group(3), StructName)\r
+ if Match.group(3) == 'END':\r
+ self._VarDict[VarName] = Item['offset'] + Item['length']\r
+ self._VarDict['_LENGTH_%s_' % StructName] = \\r
+ self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]\r
+ if Match.group(2).startswith('TAG_'):\r
+ if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):\r
+ raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))\r
+ self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF\r
else:\r
- Multilines = " %s\n" % String\r
+ self._VarDict[VarName] = Item['offset']\r
+ if Item['marker']:\r
+ self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']\r
+ return Error\r
+\r
+ def UpdateBsfBitUnit (self, Item):\r
+ BitTotal = 0\r
+ BitOffset = 0\r
+ StartIdx = 0\r
+ Unit = None\r
+ UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}\r
+ for Idx, SubItem in enumerate(Item['subreg']):\r
+ if Unit is None:\r
+ Unit = SubItem['bitunit']\r
+ BitLength = SubItem['bitlength']\r
+ BitTotal += BitLength\r
+ BitOffset += BitLength\r
+\r
+ if BitOffset > 64 or BitOffset > Unit * 8:\r
+ break\r
+\r
+ if BitOffset == Unit * 8:\r
+ for SubIdx in range (StartIdx, Idx + 1):\r
+ Item['subreg'][SubIdx]['bitunit'] = Unit\r
+ BitOffset = 0\r
+ StartIdx = Idx + 1\r
+ Unit = None\r
+\r
+ if BitOffset > 0:\r
+ raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))\r
+\r
+ ExpectedTotal = Item['length'] * 8\r
+ if Item['length'] * 8 != BitTotal:\r
+ raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))\r
+\r
+ def UpdateDefaultValue (self):\r
+ Error = 0\r
+ for Idx, Item in enumerate(self._CfgItemList):\r
+ if len(Item['subreg']) == 0:\r
+ Value = Item['value']\r
+ if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):\r
+ # {XXX} or 'XXX' strings\r
+ self.FormatListValue(self._CfgItemList[Idx])\r
+ else:\r
+ Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)\r
+ if not Match:\r
+ NumValue = self.EvaluateExpress (Value)\r
+ Item['value'] = '0x%X' % NumValue\r
+ else:\r
+ ValArray = self.ValueToByteArray (Item['value'], Item['length'])\r
+ for SubItem in Item['subreg']:\r
+ SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)\r
+ self.UpdateBsfBitUnit (Item)\r
+ return Error\r
+\r
+ def ProcessMultilines (self, String, MaxCharLength):\r
+ Multilines = ''\r
+ StringLength = len(String)\r
+ CurrentStringStart = 0\r
+ StringOffset = 0\r
+ BreakLineDict = []\r
+ if len(String) <= MaxCharLength:\r
+ while (StringOffset < StringLength):\r
+ if StringOffset >= 1:\r
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
+ BreakLineDict.append (StringOffset + 1)\r
+ StringOffset += 1\r
+ if BreakLineDict != []:\r
+ for Each in BreakLineDict:\r
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
+ CurrentStringStart = Each\r
+ if StringLength - CurrentStringStart > 0:\r
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
else:\r
- NewLineStart = 0\r
- NewLineCount = 0\r
- FoundSpaceChar = False\r
- while (StringOffset < StringLength):\r
- if StringOffset >= 1:\r
- if NewLineCount >= MaxCharLength - 1:\r
- if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
- BreakLineDict.append (NewLineStart + NewLineCount)\r
- NewLineStart = NewLineStart + NewLineCount\r
- NewLineCount = 0\r
- FoundSpaceChar = True\r
- elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
- BreakLineDict.append (0)\r
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
- BreakLineDict.append (StringOffset + 1)\r
- NewLineStart = StringOffset + 1\r
+ Multilines = " %s\n" % String\r
+ else:\r
+ NewLineStart = 0\r
+ NewLineCount = 0\r
+ FoundSpaceChar = False\r
+ while (StringOffset < StringLength):\r
+ if StringOffset >= 1:\r
+ if NewLineCount >= MaxCharLength - 1:\r
+ if String[StringOffset] == ' ' and StringLength - StringOffset > 10:\r
+ BreakLineDict.append (NewLineStart + NewLineCount)\r
+ NewLineStart = NewLineStart + NewLineCount\r
NewLineCount = 0\r
- StringOffset += 1\r
- NewLineCount += 1\r
- if BreakLineDict != []:\r
- BreakLineDict.sort ()\r
- for Each in BreakLineDict:\r
- if Each > 0:\r
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
- CurrentStringStart = Each\r
- if StringLength - CurrentStringStart > 0:\r
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
- return Multilines\r
-\r
- def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):\r
+ FoundSpaceChar = True\r
+ elif StringOffset == StringLength - 1 and FoundSpaceChar == False:\r
+ BreakLineDict.append (0)\r
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':\r
+ BreakLineDict.append (StringOffset + 1)\r
+ NewLineStart = StringOffset + 1\r
+ NewLineCount = 0\r
+ StringOffset += 1\r
+ NewLineCount += 1\r
+ if BreakLineDict != []:\r
+ BreakLineDict.sort ()\r
+ for Each in BreakLineDict:\r
+ if Each > 0:\r
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()\r
+ CurrentStringStart = Each\r
+ if StringLength - CurrentStringStart > 0:\r
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()\r
+ return Multilines\r
+\r
+ def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):\r
PosName = 28\r
PosComment = 30\r
NameLine=''\r
HelpLine=''\r
OptionLine=''\r
\r
+ if Length == 0 and Name == 'Dummy':\r
+ return '\n'\r
+\r
IsArray = False\r
if Length in [1,2,4,8]:\r
Type = "UINT%d" % (Length * 8)\r
else:\r
OffsetStr = '0x%04X' % Offset\r
\r
- return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)\r
+ if BitsLength is None:\r
+ BitsLength = ''\r
+ else:\r
+ BitsLength = ' : %d' % BitsLength\r
+\r
+ return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)\r
\r
def PostProcessBody (self, TextBody):\r
NewTextBody = []\r
HeaderFile = os.path.join(FvDir, HeaderFileName)\r
\r
# Check if header needs to be recreated\r
- ReCreate = False\r
+ if (self.NoDscFileChange (HeaderFile)):\r
+ # DSC has not been modified yet\r
+ # So don't have to re-generate other files\r
+ self.Error = 'No DSC file change, skip to create UPD header file'\r
+ return 256\r
\r
TxtBody = []\r
for Item in self._CfgItemList:\r
UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']\r
for Item in self._CfgItemList:\r
if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:\r
+ Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting\r
UpdOffsetTable.append (Item["offset"])\r
\r
for UpdIdx in range(len(UpdOffsetTable)):\r
UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION\r
UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG\r
UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']\r
- ExcludedSpecificUpd = 'FSPM_ARCH_UPD'\r
+ ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']\r
+ ExcludedSpecificUpd1 = ['FSPT_ARCH2_UPD', 'FSPM_ARCH2_UPD', 'FSPS_ARCH2_UPD']\r
\r
+ IncLines = []\r
if InputHeaderFile != '':\r
if not os.path.exists(InputHeaderFile):\r
self.Error = "Input header file '%s' does not exist" % InputHeaderFile\r
if Match:\r
StartIndex = Index - 1\r
Match = re.match("}\s([_A-Z0-9]+);", Line)\r
- if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):\r
+ 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)):\r
EndIndex = Index\r
StructStart.append(StartIndex)\r
StructEnd.append(EndIndex)\r
self.Error = "BSF output file '%s' is invalid" % BsfFile\r
return 1\r
\r
+ if (self.NoDscFileChange (BsfFile)):\r
+ # DSC has not been modified yet\r
+ # So don't have to re-generate other files\r
+ self.Error = 'No DSC file change, skip to create UPD BSF file'\r
+ return 256\r
+\r
Error = 0\r
OptionDict = {}\r
BsfFd = open(BsfFile, "w")\r
if BitsRemain:\r
BsfFd.write(" Skip %d bits\n" % BitsRemain)\r
BitsGap -= BitsRemain\r
- BytesRemain = BitsGap / 8\r
+ BytesRemain = int(BitsGap / 8)\r
if BytesRemain:\r
BsfFd.write(" Skip %d bytes\n" % BytesRemain)\r
NextOffset = Item['offset'] + Item['length']\r
\r
\r
def Usage():\r
- print ("GenCfgOpt Version 0.54")\r
+ print ("GenCfgOpt Version 0.57")\r
print ("Usage:")\r
print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")\r
print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")\r
print ("ERROR: %s !" % (GenCfgOpt.Error))\r
return Ret\r
elif sys.argv[1] == "HEADER":\r
- if GenCfgOpt.CreateHeaderFile(OutFile) != 0:\r
- print ("ERROR: %s !" % GenCfgOpt.Error)\r
- return 8\r
+ Ret = GenCfgOpt.CreateHeaderFile(OutFile)\r
+ if Ret != 0:\r
+ # No change is detected\r
+ if Ret == 256:\r
+ print ("INFO: %s !" % (GenCfgOpt.Error))\r
+ else :\r
+ print ("ERROR: %s !" % (GenCfgOpt.Error))\r
+ return 8\r
+ return Ret\r
elif sys.argv[1] == "GENBSF":\r
- if GenCfgOpt.GenerateBsfFile(OutFile) != 0:\r
- print ("ERROR: %s !" % GenCfgOpt.Error)\r
- return 9\r
+ Ret = GenCfgOpt.GenerateBsfFile(OutFile)\r
+ if Ret != 0:\r
+ # No change is detected\r
+ if Ret == 256:\r
+ print ("INFO: %s !" % (GenCfgOpt.Error))\r
+ else :\r
+ print ("ERROR: %s !" % (GenCfgOpt.Error))\r
+ return 9\r
+ return Ret\r
else:\r
if argc < 5:\r
Usage()\r