X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=IntelFspPkg%2FTools%2FGenCfgOpt.py;fp=IntelFspPkg%2FTools%2FGenCfgOpt.py;h=4417bc33fe3a3c4221716c2bfbe0f7540087b5b6;hp=0000000000000000000000000000000000000000;hb=c8ec22a266cdd134ac99c3021003710130613a40;hpb=0d807dae4adf222ee0c1b3abe504c9a271a46062 diff --git a/IntelFspPkg/Tools/GenCfgOpt.py b/IntelFspPkg/Tools/GenCfgOpt.py new file mode 100644 index 0000000000..4417bc33fe --- /dev/null +++ b/IntelFspPkg/Tools/GenCfgOpt.py @@ -0,0 +1,894 @@ +## @ GenCfgOpt.py +# +# Copyright (c) 2014, 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. +# +## + +import os +import re +import sys +import struct +from datetime import date + +# Generated file copyright header + +__copyright_txt__ = """## @file +# +# THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION. +# +# This file lists all VPD informations for a platform collected by build.exe. +# +# Copyright (c) %4d, 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 +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +""" + +__copyright_bsf__ = """/** @file + + Boot Setting File for Platform Configuration. + + Copyright (c) %4d, 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 + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + This file is automatically generated. Please do NOT modify !!! + +**/ + +""" + +__copyright_h__ = """/** @file + +Copyright (c) %4d, Intel Corporation. All rights reserved.
+ +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + This file is automatically generated. Please do NOT modify !!! + +**/ +""" + +class CGenCfgOpt: + def __init__(self): + self.Error = '' + + self._GlobalDataDef = """ +GlobalDataDef + SKUID = 0, "DEFAULT" +EndGlobalData + +""" + self._BuidinOptionTxt = """ +List &EN_DIS + Selection 0x1 , "Enabled" + Selection 0x0 , "Disabled" +EndList + +""" + + self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER'] + self._HdrKeyList = ['HEADER','STRUCT'] + self._BuidinOption = {'$EN_DIS' : 'EN_DIS'} + + self._MacroDict = {} + self._CfgBlkDict = {} + self._CfgPageDict = {} + self._CfgItemList = [] + self._DscFile = '' + self._FvDir = '' + self._MapVer = 0 + + 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: + self.Error = "Invalid MACRO arguments" + Error = 1 + else: + Error = 0 + return Error + + + def ParseDscFile (self, DscFile, FvDir): + self._CfgItemList = [] + self._CfgPageDict = {} + self._CfgBlkDict = {} + self._DscFile = DscFile + self._FvDir = FvDir + + IsDefSect = False + IsUpdSect = False + IsVpdSect = False + Found = False + + IfStack = [True] + ElifStack = [] + Error = 0 + + DscFd = open(DscFile, "r") + DscLines = DscFd.readlines() + DscFd.close() + + ConfigDict = {} + + for DscLine in DscLines: + Handle = False + DscLine = DscLine.strip() + Match = re.match("^\[(.+)\]", DscLine) + if Match is not None: + if Match.group(1).lower() == "Defines".lower(): + IsDefSect = True + IsVpdSect = False + IsUpdSect = False + elif Match.group(1).lower() == "PcdsDynamicVpd".lower(): + ConfigDict = {} + ConfigDict['header'] = 'ON' + ConfigDict['region'] = 'VPD' + ConfigDict['order'] = -1 + ConfigDict['page'] = '' + ConfigDict['name'] = '' + ConfigDict['find'] = '' + ConfigDict['struct'] = '' + ConfigDict['subreg'] = [] + IsDefSect = False + IsVpdSect = True + IsUpdSect = False + elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower(): + ConfigDict = {} + ConfigDict['header'] = 'ON' + ConfigDict['region'] = 'UPD' + ConfigDict['order'] = -1 + ConfigDict['page'] = '' + ConfigDict['name'] = '' + ConfigDict['find'] = '' + ConfigDict['struct'] = '' + ConfigDict['subreg'] = [] + IsDefSect = False + IsUpdSect = True + IsVpdSect = False + Found = True + else: + IsDefSect = False + IsUpdSect = False + IsVpdSect = False + else: + if IsDefSect or IsUpdSect or IsVpdSect: + if DscLine == "!else": + IfStack[-1] = not IfStack[-1] + elif DscLine == "!endif": + IfStack.pop() + Level = ElifStack.pop() + while Level > 0: + IfStack.pop() + Level = Level - 1 + else: + Result = False + Match = re.match("!(ifdef|ifndef)\s+\$\((\w+)\)", DscLine) + if Match is not None: + if Match.group(2) in self._MacroDict: + if Match.group(1) == 'ifdef': + Result = True + else: + if Match.group(1) == 'ifndef': + Result = True + ElifStack.append(0) + IfStack.append(Result) + else: + Match = re.match("!(if|elseif)\s+\$\\((\w+)\)\s*==\s*(\w+|\$\(\w+\))", DscLine) + if Match is not None: + if Match.group(2) in self._MacroDict: + MacroName = self._MacroDict[Match.group(2)] + else: + MacroName = '' + Value = Match.group(3) + if Value.startswith('$'): + if Value[2:-1] in self._MacroDict: + Value = self._MacroDict[Value[2:-1]] + else: + Value = '' + if MacroName == Value: + Result = True + if Match.group(1) == "if": + ElifStack.append(0) + IfStack.append(Result) + else: #elseif + IfStack[-1] = not IfStack[-1] + IfStack.append(Result) + ElifStack[-1] = ElifStack[-1] + 1 + else: + if len(DscLine) > 0 and DscLine[0] == '!': + self.Error = "Invalid DscLine '%s'" % DscLine + Error = 3 + break; + else: + if reduce(lambda x,y: x and y, IfStack): + Handle = True + + if not Handle: + continue + + if IsDefSect: + #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09 + Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-\w]+)", DscLine) + if Match: + self._MacroDict[Match.group(1)] = Match.group(2) + else: + Match = re.match("^\s*#\s+!(BSF|HDR)\s+(.+)", DscLine) + if Match: + Remaining = Match.group(2) + if Match.group(1) == 'BSF': + Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining) + if Match: + # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"} + PageList = Match.group(1).split(',') + for Page in PageList: + Page = Page.strip() + Match = re.match("(\w+):\"(.+)\"", Page) + self._CfgPageDict[Match.group(1)] = Match.group(2) + + Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining) + if Match: + self._CfgBlkDict['name'] = Match.group(1) + self._CfgBlkDict['ver'] = Match.group(2) + + for Key in self._BsfKeyList: + Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining) + if Match: + if Key in ['HELP', 'OPTION'] and Match.group(1).startswith('+'): + ConfigDict[Key.lower()] += Match.group(1)[1:] + else: + ConfigDict[Key.lower()] = Match.group(1) + else: + for Key in self._HdrKeyList: + Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining) + if Match: + ConfigDict[Key.lower()] = Match.group(1) + + # Check VPD/UPD + if IsUpdSect: + Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]{4})\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine) + else: + Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine) + if Match: + ConfigDict['space'] = Match.group(1) + ConfigDict['cname'] = Match.group(2) + ConfigDict['offset'] = int (Match.group(3), 16) + if ConfigDict['order'] == -1: + ConfigDict['order'] = ConfigDict['offset'] << 8 + else: + (Major, Minor) = ConfigDict['order'].split('.') + ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16) + if IsUpdSect: + Value = Match.group(5).strip() + if Match.group(4).startswith("0x"): + Length = int (Match.group(4), 16) + else : + Length = int (Match.group(4)) + else: + Value = Match.group(4) + if Value is None: + Value = '' + Value = Value.strip() + if '|' in Value: + Match = re.match("^.+\s*\|\s*(.+)", Value) + if Match: + Value = Match.group(1) + Length = -1 + + 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 ConfigDict['name'] == '': + # Clear BSF specific items + ConfigDict['help'] = '' + ConfigDict['type'] = '' + ConfigDict['option'] = '' + + self._CfgItemList.append(ConfigDict.copy()) + ConfigDict['name'] = '' + ConfigDict['find'] = '' + ConfigDict['struct'] = '' + ConfigDict['order'] = -1 + ConfigDict['subreg'] = [] + else: + # It could be a virtual item as below + # !BSF FIELD:{1:SerialDebugPortAddress0} + Match = re.match("^\s*#\s+!BSF\s+FIELD:{(.+):(\d+)}", DscLine) + if Match: + SubCfgDict = ConfigDict + SubCfgDict['cname'] = Match.group(1) + SubCfgDict['length'] = int (Match.group(2)) + if SubCfgDict['length'] > 0: + LastItem = self._CfgItemList[-1] + if len(LastItem['subreg']) == 0: + SubOffset = 0 + else: + SubOffset += LastItem['subreg'][-1]['length'] + SubCfgDict['offset'] = SubOffset + LastItem['subreg'].append (SubCfgDict.copy()) + ConfigDict['name'] = '' + return Error + + def UpdateSubRegionDefaultValue (self): + Error = 0 + for Item in self._CfgItemList: + if len(Item['subreg']) == 0: + continue + bytearray = [] + if Item['value'][0] == '{': + binlist = Item['value'][1:-1].split(',') + for each in binlist: + each = each.strip() + if each.startswith('0x'): + value = int(each, 16) + else: + value = int(each) + bytearray.append(value) + else: + if Item['value'].startswith('0x'): + value = int(Item['value'], 16) + else: + value = int(Item['value']) + idx = 0; + while idx < Item['length']: + bytearray.append(value & 0xFF) + value = value >> 8 + idx = idx + 1 + for SubItem in Item['subreg']: + if SubItem['length'] in (1,2,4,8): + valuelist = [b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]] + valuelist.reverse() + valuestr = "".join('%02X' % b for b in valuelist) + SubItem['value'] = '0x%s' % valuestr + else: + valuestr = ",".join('0x%02X' % b for b in bytearray[SubItem['offset']:SubItem['offset']+SubItem['length']]) + SubItem['value'] = '{%s}' % valuestr + return Error + + def UpdateVpdSizeField (self): + FvDir = self._FvDir; + + if 'VPD_TOOL_GUID' not in self._MacroDict: + self.Error = "VPD_TOOL_GUID definition is missing in DSC file" + return 1 + + VpdMapFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + '.map') + if not os.path.exists(VpdMapFile): + self.Error = "VPD MAP file '%s' does not exist" % VpdMapFile + return 2 + + MapFd = open(VpdMapFile, "r") + MapLines = MapFd.readlines() + MapFd.close() + + VpdDict = {} + PcdDict = {} + for MapLine in MapLines: + #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | DEFAULT | 0x0000 | 8 | 0x534450565F425346 + #gPlatformFspPkgTokenSpaceGuid.PcdVpdRegionSign | 0x0000 | 8 | 0x534450565F425346 + #gPlatformFspPkgTokenSpaceGuid.PcdTest | 0x0008 | 5 | {0x01,0x02,0x03,0x04,0x05} + Match = re.match("([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)(\s\|\sDEFAULT)?\s\|\s(0x[0-9A-F]{4})\s\|\s(\d+|0x[0-9a-fA-F]+)\s\|\s(\{?[x0-9a-fA-F,\s]+\}?)", MapLine) + if Match: + Space = Match.group(1) + Name = Match.group(2) + if (self._MapVer == 0) and (Match.group(3) != None): + self._MapVer = 1 + Offset = int (Match.group(4), 16) + if Match.group(5).startswith("0x"): + Length = int (Match.group(5), 16) + else : + Length = int (Match.group(5)) + PcdDict["len"] = Length + PcdDict["value"] = Match.group(6) + VpdDict[Space+'.'+Name] = dict(PcdDict) + + for Item in self._CfgItemList: + if Item['value'] == '': + Item['value'] = VpdDict[Item['space']+'.'+Item['cname']]['value'] + if Item['length'] == -1: + Item['length'] = VpdDict[Item['space']+'.'+Item['cname']]['len'] + if Item['struct'] != '': + Type = Item['struct'].strip() + if Type.endswith('*') and (Item['length'] != 4): + self.Error = "Struct pointer '%s' has invalid size" % Type + return 3 + + return 0 + + def CreateUpdTxtFile (self, UpdTxtFile): + FvDir = self._FvDir + if 'UPD_TOOL_GUID' not in self._MacroDict: + self.Error = "UPD_TOOL_GUID definition is missing in DSC file" + return 1 + + if UpdTxtFile == '': + UpdTxtFile = os.path.join(FvDir, self._MacroDict['UPD_TOOL_GUID'] + '.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: + # 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' + return 256 + + TxtFd = open(UpdTxtFile, "w") + TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year)) + + NextOffset = 0 + SpaceIdx = 0 + if self._MapVer == 1: + Default = 'DEFAULT|' + else: + Default = '' + for Item in self._CfgItemList: + if Item['region'] != 'UPD': + continue + Offset = Item['offset'] + if NextOffset < Offset: + # insert one line + TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset, Offset - NextOffset)) + SpaceIdx = SpaceIdx + 1 + NextOffset = Offset + Item['length'] + TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'],Item['length'],Item['value'])) + TxtFd.close() + return 0 + + def CreateField (self, Name, Length, Offset, Struct): + PosName = 28 + PosComment = 30 + + IsArray = False + if Length == 1: + Type = "UINT8" + elif Length == 2: + Type = "UINT16" + elif Length == 4: + Type = "UINT32" + elif Length == 8: + Type = "UINT64" + else: + Type = "UINT8" + IsArray = True + + if Struct != '': + IsArray = False + Type = Struct + + if IsArray: + Name = Name + '[%d]' % Length + + if len(Type) < PosName: + Space1 = PosName - len(Type) + else: + Space1 = 1 + + if len(Name) < PosComment: + Space2 = PosComment - len(Name) + else: + Space2 = 1 + + return " %s%s%s;%s/* Offset 0x%04X */\n" % (Type, ' ' * Space1, Name, ' ' * Space2, Offset) + + + def CreateHeaderFile (self, InputHeaderFile, IsInternal): + Error = 0 + FvDir = self._FvDir + + if IsInternal: + HeaderFile = os.path.join(FvDir, 'VpdHeader.h') + else: + HeaderFile = os.path.join(FvDir, 'fsp_vpd.h') + + # Check if header needs to be recreated + ReCreate = False + if IsInternal: + if not os.path.exists(HeaderFile): + ReCreate = True + else: + DscTime = os.path.getmtime(self._DscFile) + HeadTime = os.path.getmtime(HeaderFile) + if not os.path.exists(InputHeaderFile): + InpTime = HeadTime + else: + InpTime = os.path.getmtime(InputHeaderFile) + if DscTime > HeadTime or InpTime > HeadTime: + ReCreate = True + + if not ReCreate: + self.Error = "No DSC or input header file is changed, skip the header file generating" + return 256 + + HeaderFd = open(HeaderFile, "w") + FileBase = os.path.basename(HeaderFile) + FileName = FileBase.replace(".", "_").upper() + HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year)) + HeaderFd.write("#ifndef __%s__\n" % FileName) + HeaderFd.write("#define __%s__\n\n" % FileName) + HeaderFd.write("#pragma pack(1)\n\n") + + if InputHeaderFile != '': + if not os.path.exists(InputHeaderFile): + self.Error = "Input header file '%s' does not exist" % InputHeaderFile + return 2 + + InFd = open(InputHeaderFile, "r") + IncLines = InFd.readlines() + InFd.close() + + Export = False + for Line in IncLines: + Match = re.search ("!EXPORT\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line) + if Match: + if Match.group(1) == "BEGIN": + Export = True + continue + else: + Export = False + continue + if Export: + HeaderFd.write(Line) + HeaderFd.write("\n\n") + + for Region in ['UPD', 'VPD']: + + # Write PcdVpdRegionSign and PcdImageRevision + if Region[0] == 'V': + if 'VPD_TOOL_GUID' not in self._MacroDict: + self.Error = "VPD_TOOL_GUID definition is missing in DSC file" + Error = 1 + break + + BinFile = os.path.join(FvDir, self._MacroDict['VPD_TOOL_GUID'] + ".bin") + if not os.path.exists(BinFile): + self.Error = "VPD binary file '%s' does not exist" % BinFile + Error = 2 + break + + BinFd = open(BinFile, "rb") + IdStr = BinFd.read(0x08) + ImageId = struct.unpack('Q', IdStr) + ImageRev = struct.unpack('L', BinFd.read(0x04)) + BinFd.close() + + HeaderFd.write("#define VPD_IMAGE_ID 0x%016X /* '%s' */\n" % (ImageId[0], IdStr)) + HeaderFd.write("#define VPD_IMAGE_REV 0x%08X \n\n" % ImageRev[0]) + + HeaderFd.write("typedef struct _" + Region[0] + "PD_DATA_REGION {\n") + NextOffset = 0 + SpaceIdx = 0 + Offset = 0 + + LastVisible = True + ResvOffset = 0 + ResvIdx = 0 + LineBuffer = [] + for Item in self._CfgItemList: + if Item['region'] != Region: + continue + + NextVisible = LastVisible + if not IsInternal: + if LastVisible and (Item['header'] == 'OFF'): + NextVisible = False + ResvOffset = Item['offset'] + elif (not LastVisible) and Item['header'] == 'ON': + NextVisible = True + Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx + ResvIdx = ResvIdx + 1 + HeaderFd.write(self.CreateField (Name, Item["offset"] - ResvOffset, ResvOffset, '')) + + if Offset < Item["offset"]: + if IsInternal or LastVisible: + Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx + LineBuffer.append(self.CreateField (Name, Item["offset"] - Offset, Offset, '')) + SpaceIdx = SpaceIdx + 1 + Offset = Item["offset"] + + if Offset != Item["offset"]: + print "Unsorted offset 0x%04X\n" % Item["offset"] + error = 2 + break; + + LastVisible = NextVisible + + Offset = Offset + Item["length"] + if IsInternal or LastVisible: + for Each in LineBuffer: + HeaderFd.write (Each) + LineBuffer = [] + HeaderFd.write(self.CreateField (Item["cname"], Item["length"], Item["offset"], Item['struct'])) + + HeaderFd.write("} " + Region[0] + "PD_DATA_REGION;\n\n") + HeaderFd.write("#pragma pack()\n\n") + HeaderFd.write("#endif\n") + HeaderFd.close() + + return Error + + 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*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value']) + if Match: + DefaultValue = Match.group(1).strip() + else: + DefaultValue = Item['value'].strip() + BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue)) + TmpList = [] + if Item['type'] == "Combo": + if not Item['option'] in self._BuidinOption: + OptList = Item['option'].split(',') + for Option in OptList: + Option = Option.strip() + (OpVal, OpStr) = Option.split(':') + TmpList.append((OpVal, OpStr)) + return TmpList + + def WriteBsfOption (self, BsfFd, Item): + PcdName = Item['space'] + '_' + Item['cname'] + WriteHelp = 0 + if Item['type'] == "Combo": + if Item['option'] in self._BuidinOption: + Options = self._BuidinOption[Item['option']] + else: + Options = PcdName + BsfFd.write(' %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: + BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1))); + WriteHelp = 2 + elif Item['type'].startswith("EditText"): + BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name'])); + WriteHelp = 1 + + if WriteHelp > 0: + HelpLines = Item['help'].split('\\n\\r') + FirstLine = True + for HelpLine in HelpLines: + if FirstLine: + FirstLine = False + BsfFd.write(' Help "%s"\n' % (HelpLine)); + else: + BsfFd.write(' "%s"\n' % (HelpLine)); + if WriteHelp == 2: + BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3))); + + 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" % (__copyright_bsf__ % date.today().year)) + 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'] + for SubItem in Item['subreg']: + NextOffset += SubItem['length'] + if SubItem['name'] == '': + BsfFd.write(" Skip %d bytes\n" % (SubItem['length'])) + else: + Options = self.WriteBsfStruct(BsfFd, SubItem) + if len(Options) > 0: + OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options + if (Item['offset'] + Item['length']) < NextOffset: + self.Error = "BSF sub region '%s' length does not match" % (Item['space']+'.'+Item['cname']) + return 2 + 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); + + for Each in OptionDict: + BsfFd.write("List &%s\n" % Each); + for Item in OptionDict[Each]: + BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1])); + BsfFd.write("EndList\n\n"); + + 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"); + + for Each in self._CfgPageDict: + BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]); + BsfItems = [] + for Item in self._CfgItemList: + if Item['name'] != '': + if Item['page'] != Each: + 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"); + + BsfFd.close() + return Error + + +def Usage(): + print "GenCfgOpt Version 0.50" + print "Usage:" + print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-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 + # + GenCfgOpt = CGenCfgOpt() + argc = len(sys.argv) + if argc < 4: + Usage() + return 1 + else: + DscFile = sys.argv[2] + if not os.path.exists(DscFile): + print "ERROR: Cannot open DSC file '%s' !" % DscFile + return 2 + + OutFile = '' + if argc > 4: + if sys.argv[4][0] == '-': + Start = 4 + else: + OutFile = sys.argv[4] + Start = 5 + if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 3 + + FvDir = sys.argv[3] + if not os.path.isdir(FvDir): + print "ERROR: FV folder '%s' is invalid !" % FvDir + return 4 + + if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 5 + + + if GenCfgOpt.UpdateVpdSizeField() != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 6 + + if GenCfgOpt.UpdateSubRegionDefaultValue() != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 7 + + if sys.argv[1] == "UPDTXT": + Ret = GenCfgOpt.CreateUpdTxtFile(OutFile) + if Ret != 0: + # No change is detected + if Ret == 256: + print "INFO: %s !" % (GenCfgOpt.Error) + else : + print "ERROR: %s !" % (GenCfgOpt.Error) + return Ret + elif sys.argv[1] == "HEADER": + Ret = GenCfgOpt.CreateHeaderFile(OutFile, True) + if Ret != 0: + # No change is detected + if Ret == 256: + print "INFO: %s !" % (GenCfgOpt.Error) + else : + print "ERROR: %s !" % (GenCfgOpt.Error) + return Ret + if GenCfgOpt.CreateHeaderFile(OutFile, False) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 8 + elif sys.argv[1] == "GENBSF": + if GenCfgOpt.GenerateBsfFile(OutFile) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 9 + else: + if argc < 5: + Usage() + return 1 + print "ERROR: Unknown command '%s' !" % sys.argv[1] + Usage() + return 1 + return 0 + return 0 + + +if __name__ == '__main__': + sys.exit(Main())