From b21a13fbb61e0232ea98b0d7b305e24e67e50b0a Mon Sep 17 00:00:00 2001 From: Yonghong Zhu Date: Mon, 7 Dec 2015 08:27:53 +0000 Subject: [PATCH] BaseTools: Add support for INF statement in FD region FD region today can be file or data, but not a patched image.Add support for an INF statement in an FD region, so the binary from the INF can be patched prior to being added to the FD region. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu Reviewed-by: Liming Gao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19136 6f19259b-4bc3-4df7-8a09-765794883524 --- BaseTools/Source/Python/GenFds/FdfParser.py | 57 ++++++++++++------- .../Source/Python/GenFds/FfsInfStatement.py | 44 +++++++++++++- BaseTools/Source/Python/GenFds/Region.py | 21 ++++--- 3 files changed, 91 insertions(+), 31 deletions(-) diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py index 664bf8e87d..788190567e 100644 --- a/BaseTools/Source/Python/GenFds/FdfParser.py +++ b/BaseTools/Source/Python/GenFds/FdfParser.py @@ -1,7 +1,7 @@ ## @file # parse FDF file # -# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
# Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.
# # This program and the accompanying materials @@ -1846,7 +1846,7 @@ class FdfParser: if not self.__GetNextWord(): return True - if not self.__Token in ("SET", "FV", "FILE", "DATA", "CAPSULE"): + if not self.__Token in ("SET", "FV", "FILE", "DATA", "CAPSULE", "INF"): # # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]] # Or it might be next region's offset described by an expression which starts with a PCD. @@ -1887,17 +1887,27 @@ class FdfParser: elif self.__Token == "FILE": self.__UndoToken() - self.__GetRegionFileType( RegionObj) + self.__GetRegionFileType(RegionObj) + + elif self.__Token == "INF": + self.__UndoToken() + RegionObj.RegionType = "INF" + while self.__IsKeyword("INF"): + self.__UndoToken() + ffsInf = self.__ParseInfStatement() + if not ffsInf: + break + RegionObj.RegionDataList.append(ffsInf) elif self.__Token == "DATA": self.__UndoToken() - self.__GetRegionDataType( RegionObj) + self.__GetRegionDataType(RegionObj) else: self.__UndoToken() if self.__GetRegionLayout(Fd): return True raise Warning("A valid region type was not found. " - "Valid types are [SET, FV, CAPSULE, FILE, DATA]. This error occurred", + "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred", self.FileName, self.CurrentLineNumber) return True @@ -2426,23 +2436,12 @@ class FdfParser: FvObj.AprioriSectionList.append(AprSectionObj) return True - ## __GetInfStatement() method - # - # Get INF statements - # - # @param self The object pointer - # @param Obj for whom inf statement is got - # @param MacroDict dictionary used to replace macro - # @retval True Successfully find inf statement - # @retval False Not able to find inf statement - # - def __GetInfStatement(self, Obj, ForCapsule = False, MacroDict = {}): - - if not self.__IsKeyword( "INF"): - return False + def __ParseInfStatement(self): + if not self.__IsKeyword("INF"): + return None ffsInf = FfsInfStatement.FfsInfStatement() - self.__GetInfOptions( ffsInf) + self.__GetInfOptions(ffsInf) if not self.__GetNextToken(): raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber) @@ -2472,7 +2471,23 @@ class FdfParser: ffsInf.KeepReloc = True else: raise Warning("Unknown reloc strip flag '%s'" % self.__Token, self.FileName, self.CurrentLineNumber) - + return ffsInf + + ## __GetInfStatement() method + # + # Get INF statements + # + # @param self The object pointer + # @param Obj for whom inf statement is got + # @param MacroDict dictionary used to replace macro + # @retval True Successfully find inf statement + # @retval False Not able to find inf statement + # + def __GetInfStatement(self, Obj, ForCapsule=False, MacroDict={}): + ffsInf = self.__ParseInfStatement() + if not ffsInf: + return False + if ForCapsule: capsuleFfs = CapsuleData.CapsuleFfs() capsuleFfs.Ffs = ffsInf diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py index ed767d3fa6..7b221399b4 100644 --- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -331,25 +331,63 @@ class FfsInfStatement(FfsInfStatementClassObject): # If passed in file does not end with efi, return as is # def PatchEfiFile(self, EfiFile, FileType): + # + # If the module does not have any patches, then return path to input file + # if not self.PatchPcds: return EfiFile + + # + # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED + # if FileType != 'PE32' and self.ModuleType != "USER_DEFINED": return EfiFile + + # + # Generate path to patched output file + # + Basename = os.path.basename(EfiFile) + Output = os.path.normpath (os.path.join(self.OutputPath, Basename)) + + # + # If this file has already been patched, then return the path to the patched file + # + if self.PatchedBinFile == Output: + return Output + + # + # If a different file from the same module has already been patched, then generate an error + # if self.PatchedBinFile: EdkLogger.error("GenFds", GENFDS_ERROR, 'Only one binary file can be patched:\n' ' a binary file has been patched: %s\n' ' current file: %s' % (self.PatchedBinFile, EfiFile), File=self.InfFileName) - Basename = os.path.basename(EfiFile) - Output = os.path.join(self.OutputPath, Basename) + + # + # Copy unpatched file contents to output file location to perform patching + # CopyLongFilePath(EfiFile, Output) + + # + # Apply patches to patched output file + # for Pcd, Value in self.PatchPcds: RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize) if RetVal: EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName) - self.PatchedBinFile = os.path.normpath(EfiFile) + + # + # Save the path of the patched output file + # + self.PatchedBinFile = Output + + # + # Return path to patched output file + # return Output + ## GenFfs() method # # Generate FFS diff --git a/BaseTools/Source/Python/GenFds/Region.py b/BaseTools/Source/Python/GenFds/Region.py index 01e998e54c..8734635fda 100644 --- a/BaseTools/Source/Python/GenFds/Region.py +++ b/BaseTools/Source/Python/GenFds/Region.py @@ -1,7 +1,7 @@ ## @file # process FD Region generation # -# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2015, 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 @@ -202,13 +202,20 @@ class Region(RegionClassObject): for i in range(0, Size): Buffer.write(pack('B', PadData)) - if self.RegionType == 'FILE': + if self.RegionType in ('FILE', 'INF'): for RegionData in self.RegionDataList: - RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict) - if RegionData[1] != ':' : - RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData) - if not os.path.exists(RegionData): - EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData) + if self.RegionType == 'INF': + RegionData.__InfParse__(None) + if len(RegionData.BinFileList) != 1: + EdkLogger.error('GenFds', GENFDS_ERROR, 'INF in FD region can only contain one binary: %s' % RegionData) + File = RegionData.BinFileList[0] + RegionData = RegionData.PatchEfiFile(File.Path, File.Type) + else: + RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict) + if RegionData[1] != ':' : + RegionData = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData) + if not os.path.exists(RegionData): + EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=RegionData) # # Add the file image into FD buffer # -- 2.39.2