From c8ec22a266cdd134ac99c3021003710130613a40 Mon Sep 17 00:00:00 2001 From: jyao1 Date: Tue, 29 Jul 2014 02:21:52 +0000 Subject: Add IntelFspPkg to support create FSP bin based on EDKII. Contributed-under: TianoCore Contribution Agreement 1.0 Signed off by: Ravi Rangarajan Reviewed by: Maurice Ma Reviewed by: Jiewen Yao Reviewed by: Giri Mudusuru Reviewed by: Liming Gao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15705 6f19259b-4bc3-4df7-8a09-765794883524 --- IntelFspPkg/Tools/GenCfgOpt.py | 894 +++++++++++++++++++++ IntelFspPkg/Tools/PatchFv.py | 567 +++++++++++++ .../Tools/UserManuals/GenCfgOptUserManual.docx | Bin 0 -> 22177 bytes .../Tools/UserManuals/PatchFvUserManual.docx | Bin 0 -> 21481 bytes 4 files changed, 1461 insertions(+) create mode 100644 IntelFspPkg/Tools/GenCfgOpt.py create mode 100644 IntelFspPkg/Tools/PatchFv.py create mode 100644 IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx create mode 100644 IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx (limited to 'IntelFspPkg/Tools') diff --git a/IntelFspPkg/Tools/GenCfgOpt.py b/IntelFspPkg/Tools/GenCfgOpt.py new file mode 100644 index 0000000..4417bc3 --- /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()) diff --git a/IntelFspPkg/Tools/PatchFv.py b/IntelFspPkg/Tools/PatchFv.py new file mode 100644 index 0000000..cc22cc2 --- /dev/null +++ b/IntelFspPkg/Tools/PatchFv.py @@ -0,0 +1,567 @@ +## @ PatchFv.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 + +def readDataFromFile (binfile, offset, len=1): + fd = open(binfile, "r+b") + fsize = os.path.getsize(binfile) + offval = offset & 0xFFFFFFFF + if (offval & 0x80000000): + offval = fsize - (0xFFFFFFFF - offval + 1) + fd.seek(offval) + bytearray = [ord(b) for b in fd.read(len)] + value = 0; + idx = len - 1; + while idx >= 0: + value = value << 8 | bytearray[idx] + idx = idx - 1 + fd.close() + return value + +def patchDataInFile (binfile, offset, value, len=1): + fd = open(binfile, "r+b") + fsize = os.path.getsize(binfile) + offval = offset & 0xFFFFFFFF + if (offval & 0x80000000): + offval = fsize - (0xFFFFFFFF - offval + 1) + bytearray = [] + idx = 0; + while idx < len: + bytearray.append(value & 0xFF) + value = value >> 8 + idx = idx + 1 + fd.seek(offval) + fd.write("".join(chr(b) for b in bytearray)) + fd.close() + return len; + + +class Symbols: + def __init__(self): + self.dictSymbolAddress = {} + self.dictGuidNameXref = {} + self.dictFfsOffset = {} + self.dictVariable = {} + self.dictModBase = {} + self.fdFile = None + self.string = "" + self.fdBase = 0xFFFFFFFF + self.fdSize = 0 + self.index = 0 + self.parenthesisOpenSet = '([{<' + self.parenthesisCloseSet = ')]}>' + + def getFdFile (self): + return self.fdFile + + def getFdSize (self): + return self.fdSize + + def createDicts (self, fvDir, fvNames): + if not os.path.isdir(fvDir): + raise Exception ("'%s' is not a valid directory!" % FvDir) + + xrefFile = os.path.join(fvDir, "Guid.xref") + if not os.path.exists(xrefFile): + raise Exception("Cannot open GUID Xref file '%s'!" % xrefFile) + + self.dictGuidNameXref = {} + self.parseGuidXrefFile(xrefFile) + + fvList = fvNames.split(":") + fdBase = fvList.pop() + if len(fvList) == 0: + fvList.append(fdBase) + + fdFile = os.path.join(fvDir, fdBase.strip() + ".fd") + if not os.path.exists(fdFile): + raise Exception("Cannot open FD file '%s'!" % fdFile) + + self.fdFile = fdFile + self.fdSize = os.path.getsize(fdFile) + + infFile = os.path.join(fvDir, fvList[0].strip()) + ".inf" + if not os.path.exists(infFile): + raise Exception("Cannot open INF file '%s'!" % infFile) + + self.parseInfFile(infFile) + + self.dictVariable = {} + self.dictVariable["FDSIZE"] = self.fdSize + self.dictVariable["FDBASE"] = self.fdBase + + self.dictSymbolAddress = {} + self.dictFfsOffset = {} + for file in fvList: + + fvFile = os.path.join(fvDir, file.strip()) + ".Fv" + mapFile = fvFile + ".map" + if not os.path.exists(mapFile): + raise Exception("Cannot open MAP file '%s'!" % mapFile) + + self.parseFvMapFile(mapFile) + + fvTxtFile = fvFile + ".txt" + if not os.path.exists(fvTxtFile): + raise Exception("Cannot open FV TXT file '%s'!" % fvTxtFile) + + self.parseFvTxtFile(fvTxtFile) + + ffsDir = os.path.join(fvDir, "Ffs") + if (os.path.isdir(ffsDir)): + for item in os.listdir(ffsDir): + if len(item) <= 0x24: + continue + mapFile =os.path.join(ffsDir, item, "%s.map" % item[0:0x24]) + if not os.path.exists(mapFile): + continue + self.parseModMapFile(item[0x24:], mapFile) + + return 0 + + def getFvOffsetInFd(self, fvFile): + fvHandle = open(fvFile, "r+b") + fdHandle = open(self.fdFile, "r+b") + offset = fdHandle.read().find(fvHandle.read(0x70)) + fvHandle.close() + fdHandle.close() + if offset == -1: + raise Exception("Could not locate FV file %s in FD!" % fvFile) + return offset + + def parseInfFile(self, infFile): + fvOffset = self.getFvOffsetInFd(infFile[0:-4] + ".Fv") + fdIn = open(infFile, "r") + rptLine = fdIn.readline() + self.fdBase = 0xFFFFFFFF + while (rptLine != "" ): + #EFI_BASE_ADDRESS = 0xFFFDF400 + match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine) + if match is not None: + self.fdBase = int(match.group(1), 16) - fvOffset + rptLine = fdIn.readline() + fdIn.close() + if self.fdBase == 0xFFFFFFFF: + raise Exception("Could not find EFI_BASE_ADDRESS in INF file!" % fvFile) + return 0 + + def parseFvTxtFile(self, fvTxtFile): + fvOffset = self.getFvOffsetInFd(fvTxtFile[0:-4]) + fdIn = open(fvTxtFile, "r") + rptLine = fdIn.readline() + while (rptLine != "" ): + match = re.match("(0x[a-fA-F0-9]+)\s([0-9a-fA-F\-]+)", rptLine) + if match is not None: + self.dictFfsOffset[match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + def parseFvMapFile(self, mapFile): + fdIn = open(mapFile, "r") + rptLine = fdIn.readline() + modName = "" + while (rptLine != "" ): + if rptLine[0] != ' ': + #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958) + #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178) + match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine) + if match is not None: + modName = match.group(1) + if len(modName) == 36: + modName = self.dictGuidNameXref[modName.upper()] + self.dictModBase['%s:BASE' % modName] = int (match.group(2), 16) + self.dictModBase['%s:ENTRY' % modName] = int (match.group(3), 16) + match = re.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine) + if match is not None: + modName = match.group(1) + if len(modName) == 36: + modName = self.dictGuidNameXref[modName.upper()] + self.dictModBase['%s:TEXT' % modName] = int (match.group(2), 16) + self.dictModBase['%s:DATA' % modName] = int (match.group(3), 16) + else: + # 0x00fff8016c __ModuleEntryPoint + match = re.match("^\s+(0x[a-z0-9]+)\s+([_a-zA-Z0-9]+)", rptLine) + if match is not None: + self.dictSymbolAddress["%s:%s"%(modName, match.group(2))] = match.group(1) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + def parseModMapFile(self, moduleName, mapFile): + modSymbols = {} + fdIn = open(mapFile, "r") + reportLine = fdIn.readline() + if reportLine.strip().find("Archive member included because of file (symbol)") != -1: + #GCC + # 0x0000000000001d55 IoRead8 + patchMapFileMatchString = "\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s" + matchKeyGroupIndex = 2 + matchSymbolGroupIndex = 1 + moduleEntryPoint = "_ModuleEntryPoint" + else: + #MSFT + #0003:00000190 _gComBase 00007a50 SerialPo + patchMapFileMatchString = "^\s[0-9a-fA-F]{4}:[0-9a-fA-F]{8}\s+(\w+)\s+([0-9a-fA-F]{8}\s+)" + matchKeyGroupIndex = 1 + matchSymbolGroupIndex = 2 + moduleEntryPoint = "__ModuleEntryPoint" + while (reportLine != "" ): + match = re.match(patchMapFileMatchString, reportLine) + if match is not None: + modSymbols[match.group(matchKeyGroupIndex)] = match.group(matchSymbolGroupIndex) + reportLine = fdIn.readline() + fdIn.close() + + if not moduleEntryPoint in modSymbols: + return 1 + + modEntry = '%s:%s' % (moduleName,moduleEntryPoint) + if not modEntry in self.dictSymbolAddress: + modKey = '%s:ENTRY' % moduleName + if modKey in self.dictModBase: + baseOffset = self.dictModBase['%s:ENTRY' % moduleName] - int(modSymbols[moduleEntryPoint], 16) + else: + return 2 + else: + baseOffset = int(self.dictSymbolAddress[modEntry], 16) - int(modSymbols[moduleEntryPoint], 16) + for symbol in modSymbols: + fullSym = "%s:%s" % (moduleName, symbol) + if not fullSym in self.dictSymbolAddress: + self.dictSymbolAddress[fullSym] = "0x00%08x" % (baseOffset+ int(modSymbols[symbol], 16)) + return 0 + + def parseGuidXrefFile(self, xrefFile): + fdIn = open(xrefFile, "r") + rptLine = fdIn.readline() + while (rptLine != "" ): + match = re.match("([0-9a-fA-F\-]+)\s([_a-zA-Z0-9]+)", rptLine) + if match is not None: + self.dictGuidNameXref[match.group(1).upper()] = match.group(2) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + def getCurr(self): + try: + return self.string[self.index] + except Exception: + return '' + + def isLast(self): + return self.index == len(self.string) + + def moveNext(self): + self.index += 1 + + def skipSpace(self): + while not self.isLast(): + if self.getCurr() in ' \t': + self.moveNext() + else: + return + + def parseValue(self): + self.skipSpace() + var = '' + while not self.isLast(): + char = self.getCurr() + if char.lower() in '_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-': + var += char + self.moveNext() + else: + break + + if ':' in var: + partList = var.split(':') + if len(partList) != 2: + raise Exception("Unrecognized expression %s" % var) + modName = partList[0] + modOff = partList[1] + if ('-' not in modName) and (modOff[0] in '0123456789'): + # MOD: OFFSET + var = self.getModGuid(modName) + ":" + modOff + if '-' in var: # GUID:OFFSET + value = self.getGuidOff(var) + else: + value = self.getSymbols(var) + self.synUsed = True + else: + if var[0] in '0123456789': + value = self.getNumber(var) + else: + value = self.getVariable(var) + return int(value) + + def parseSingleOp(self): + self.skipSpace() + char = self.getCurr() + if char == '~': + self.moveNext() + return ~self.parseBrace() + else: + return self.parseValue() + + def parseBrace(self): + self.skipSpace() + char = self.getCurr() + parenthesisType = self.parenthesisOpenSet.find(char) + if parenthesisType >= 0: + self.moveNext() + value = self.parseExpr() + self.skipSpace() + if self.getCurr() != self.parenthesisCloseSet[parenthesisType]: + raise Exception("No closing brace") + self.moveNext() + if parenthesisType == 1: # [ : Get content + value = self.getContent(value) + elif parenthesisType == 2: # { : To address + value = self.toAddress(value) + elif parenthesisType == 3: # < : To offset + value = self.toOffset(value) + return value + else: + return self.parseSingleOp() + + def parseMul(self): + values = [self.parseBrace()] + while True: + self.skipSpace() + char = self.getCurr() + if char == '*': + self.moveNext() + values.append(self.parseBrace()) + else: + break + value = 1; + for each in values: + value *= each + return value + + def parseAndOr(self): + values = [self.parseMul()] + op = None + value = 0xFFFFFFFF; + while True: + self.skipSpace() + char = self.getCurr() + if char == '&': + self.moveNext() + values.append(self.parseMul()) + op = char + elif char == '|': + div_index = self.index + self.moveNext() + values.append(self.parseMul()) + value = 0 + op = char + else: + break + + for each in values: + if op == '|': + value |= each + else: + value &= each + + return value + + def parseAddMinus(self): + values = [self.parseAndOr()] + while True: + self.skipSpace() + char = self.getCurr() + if char == '+': + self.moveNext() + values.append(self.parseAndOr()) + elif char == '-': + self.moveNext() + values.append(-1 * self.parseAndOr()) + else: + break + return sum(values) + + def parseExpr(self): + return self.parseAddMinus() + + def getResult(self): + value = self.parseExpr() + self.skipSpace() + if not self.isLast(): + raise Exception("Unexpected character found '%s'" % self.getCurr()) + return value + + def getModGuid(self, var): + guid = (guid for guid,name in self.dictGuidNameXref.items() if name==var) + try: + value = guid.next() + except Exception: + raise Exception("Unknown module name %s !" % var) + return value + + def getVariable(self, var): + value = self.dictVariable.get(var, None) + if value == None: + raise Exception("Unrecognized variable '%s'" % var) + return value + + def getNumber(self, var): + var = var.strip() + if var.startswith('0x'): # HEX + value = int(var, 16) + else: + value = int(var, 10) + return value + + def getContent(self, value): + if (value >= self.fdBase) and (value < self.fdBase + self.fdSize): + value = value - self.fdBase + if value >= self.fdSize: + raise Exception("Invalid file offset 0x%08x !" % value) + return readDataFromFile (self.fdFile, value, 4) + + def toAddress(self, value): + if value < self.fdSize: + value = value + self.fdBase + return value + + def toOffset(self, value): + if value > self.fdBase: + value = value - self.fdBase + return value + + def getGuidOff(self, value): + # GUID:Offset + symbolName = value.split(':') + if len(symbolName) == 2 and self.dictFfsOffset.has_key(symbolName[0]): + value = (int(self.dictFfsOffset[symbolName[0]], 16) + int(symbolName[1], 16)) & 0xFFFFFFFF + else: + raise Exception("Unknown GUID %s !" % value) + return value + + def getSymbols(self, value): + if self.dictSymbolAddress.has_key(value): + # Module:Function + ret = int (self.dictSymbolAddress[value], 16) + else: + raise Exception("Unknown symbol %s !" % value) + return ret + + def evaluate(self, expression, isOffset): + self.index = 0 + self.synUsed = False + self.string = expression + value = self.getResult() + if isOffset: + if self.synUsed: + # Consider it as an address first + if (value >= self.fdBase) and (value < self.fdBase + self.fdSize): + value = value - self.fdBase + if value & 0x80000000: + # Consider it as a negative offset next + offset = (~value & 0xFFFFFFFF) + 1 + if offset < self.fdSize: + value = self.fdSize - offset + if value >= self.fdSize: + raise Exception("Invalid offset expression !") + return value & 0xFFFFFFFF + +def usage(): + print "Usage: \n\tPatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch \"Offset, Value\"" + +def main(): + # + # Parse the options and args + # + symTables = Symbols() + + if len(sys.argv) < 4: + Usage() + return 1 + + if symTables.createDicts(sys.argv[1], sys.argv[2]) != 0: + print "ERROR: Failed to create symbol dictionary!!" + return 2 + + fdFile = symTables.getFdFile() + fdSize = symTables.getFdSize() + + try: + comment = "" + for fvFile in sys.argv[3:]: + items = fvFile.split(",") + if len (items) < 2: + raise Exception("Expect more arguments for '%s'!" % fvFile) + + comment = "" + command = "" + params = [] + for item in items: + item = item.strip() + if item.startswith("@"): + comment = item[1:] + elif item.startswith("$"): + command = item[1:] + else: + if len(params) == 0: + isOffset = True + else : + isOffset = False + params.append (symTables.evaluate(item, isOffset)) + + if command == "": + # Patch a DWORD + if len (params) == 2: + offset = params[0] + value = params[1] + oldvalue = readDataFromFile(fdFile, offset, 4) + ret = patchDataInFile (fdFile, offset, value, 4) - 4 + else: + raise Exception ("Patch command needs 2 parameters !") + + if ret: + raise Exception ("Patch failed for offset 0x%08X" % offset) + else: + print "Patched offset 0x%08X:[%08X] with value 0x%08X # %s" % (offset, oldvalue, value, comment) + + elif command == "COPY": + # Copy binary block from source to destination + if len (params) == 3: + src = symTables.toOffset(params[0]) + dest = symTables.toOffset(params[1]) + clen = symTables.toOffset(params[2]) + if (dest + clen <= fdSize) and (src + clen <= fdSize): + oldvalue = readDataFromFile(fdFile, src, clen) + ret = patchDataInFile (fdFile, dest, oldvalue, clen) - clen + else: + raise Exception ("Copy command OFFSET or LENGTH parameter is invalid !") + else: + raise Exception ("Copy command needs 3 parameters !") + + if ret: + raise Exception ("Copy failed from offset 0x%08X to offset 0x%08X!" % (src, dest)) + else : + print "Copied %d bytes from offset 0x%08X ~ offset 0x%08X # %s" % (clen, src, dest, comment) + else: + raise Exception ("Unknown command %s!" % command) + return 0 + + except Exception as (ex): + print "ERROR: %s" % ex + return 1 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx b/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx new file mode 100644 index 0000000..e4da8e0 Binary files /dev/null and b/IntelFspPkg/Tools/UserManuals/GenCfgOptUserManual.docx differ diff --git a/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx b/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx new file mode 100644 index 0000000..ab1eda9 Binary files /dev/null and b/IntelFspPkg/Tools/UserManuals/PatchFvUserManual.docx differ -- cgit v1.1