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 <yonghong.zhu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19136 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
				
			|||||||
## @file
 | 
					## @file
 | 
				
			||||||
# parse FDF file
 | 
					# parse FDF file
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
					#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
				
			||||||
#  Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
 | 
					#  Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  This program and the accompanying materials
 | 
					#  This program and the accompanying materials
 | 
				
			||||||
@@ -1846,7 +1846,7 @@ class FdfParser:
 | 
				
			|||||||
        if not self.__GetNextWord():
 | 
					        if not self.__GetNextWord():
 | 
				
			||||||
            return True
 | 
					            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]]
 | 
					            # 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.
 | 
					            # 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":
 | 
					        elif self.__Token == "FILE":
 | 
				
			||||||
            self.__UndoToken()
 | 
					            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":
 | 
					        elif self.__Token == "DATA":
 | 
				
			||||||
            self.__UndoToken()
 | 
					            self.__UndoToken()
 | 
				
			||||||
            self.__GetRegionDataType( RegionObj)
 | 
					            self.__GetRegionDataType(RegionObj)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.__UndoToken()
 | 
					            self.__UndoToken()
 | 
				
			||||||
            if self.__GetRegionLayout(Fd):
 | 
					            if self.__GetRegionLayout(Fd):
 | 
				
			||||||
                return True
 | 
					                return True
 | 
				
			||||||
            raise Warning("A valid region type was not found. "
 | 
					            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)
 | 
					                          self.FileName, self.CurrentLineNumber)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
@@ -2426,23 +2436,12 @@ class FdfParser:
 | 
				
			|||||||
        FvObj.AprioriSectionList.append(AprSectionObj)
 | 
					        FvObj.AprioriSectionList.append(AprSectionObj)
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ## __GetInfStatement() method
 | 
					    def __ParseInfStatement(self):
 | 
				
			||||||
    #
 | 
					        if not self.__IsKeyword("INF"):
 | 
				
			||||||
    #   Get INF statements
 | 
					            return None
 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    #   @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
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ffsInf = FfsInfStatement.FfsInfStatement()
 | 
					        ffsInf = FfsInfStatement.FfsInfStatement()
 | 
				
			||||||
        self.__GetInfOptions( ffsInf)
 | 
					        self.__GetInfOptions(ffsInf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not self.__GetNextToken():
 | 
					        if not self.__GetNextToken():
 | 
				
			||||||
            raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
 | 
					            raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
 | 
				
			||||||
@@ -2472,6 +2471,22 @@ class FdfParser:
 | 
				
			|||||||
                ffsInf.KeepReloc = True
 | 
					                ffsInf.KeepReloc = True
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                raise Warning("Unknown reloc strip flag '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
 | 
					                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:
 | 
					        if ForCapsule:
 | 
				
			||||||
            capsuleFfs = CapsuleData.CapsuleFfs()
 | 
					            capsuleFfs = CapsuleData.CapsuleFfs()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -331,25 +331,63 @@ class FfsInfStatement(FfsInfStatementClassObject):
 | 
				
			|||||||
    #           If passed in file does not end with efi, return as is
 | 
					    #           If passed in file does not end with efi, return as is
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    def PatchEfiFile(self, EfiFile, FileType):
 | 
					    def PatchEfiFile(self, EfiFile, FileType):
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # If the module does not have any patches, then return path to input file
 | 
				
			||||||
 | 
					        #  
 | 
				
			||||||
        if not self.PatchPcds:
 | 
					        if not self.PatchPcds:
 | 
				
			||||||
            return EfiFile
 | 
					            return EfiFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # Only patch file if FileType is PE32 or ModuleType is USER_DEFINED
 | 
				
			||||||
 | 
					        #  
 | 
				
			||||||
        if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":
 | 
					        if FileType != 'PE32' and self.ModuleType != "USER_DEFINED":
 | 
				
			||||||
            return EfiFile
 | 
					            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:
 | 
					        if self.PatchedBinFile:
 | 
				
			||||||
            EdkLogger.error("GenFds", GENFDS_ERROR,
 | 
					            EdkLogger.error("GenFds", GENFDS_ERROR,
 | 
				
			||||||
                            'Only one binary file can be patched:\n'
 | 
					                            'Only one binary file can be patched:\n'
 | 
				
			||||||
                            '  a binary file has been patched: %s\n'
 | 
					                            '  a binary file has been patched: %s\n'
 | 
				
			||||||
                            '  current file: %s' % (self.PatchedBinFile, EfiFile),
 | 
					                            '  current file: %s' % (self.PatchedBinFile, EfiFile),
 | 
				
			||||||
                            File=self.InfFileName)
 | 
					                            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)
 | 
					        CopyLongFilePath(EfiFile, Output)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # Apply patches to patched output file
 | 
				
			||||||
 | 
					        #  
 | 
				
			||||||
        for Pcd, Value in self.PatchPcds:
 | 
					        for Pcd, Value in self.PatchPcds:
 | 
				
			||||||
            RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
 | 
					            RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Value, Pcd.MaxDatumSize)
 | 
				
			||||||
            if RetVal:
 | 
					            if RetVal:
 | 
				
			||||||
                EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName)
 | 
					                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
 | 
					        return Output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ## GenFfs() method
 | 
					    ## GenFfs() method
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    #   Generate FFS
 | 
					    #   Generate FFS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
## @file
 | 
					## @file
 | 
				
			||||||
# process FD Region generation
 | 
					# process FD Region generation
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
					#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#  This program and the accompanying materials
 | 
					#  This program and the accompanying materials
 | 
				
			||||||
#  are licensed and made available under the terms and conditions of the BSD License
 | 
					#  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):
 | 
					                for i in range(0, Size):
 | 
				
			||||||
                    Buffer.write(pack('B', PadData))
 | 
					                    Buffer.write(pack('B', PadData))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.RegionType == 'FILE':
 | 
					        if self.RegionType in ('FILE', 'INF'):
 | 
				
			||||||
            for RegionData in self.RegionDataList:
 | 
					            for RegionData in self.RegionDataList:
 | 
				
			||||||
                RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, MacroDict)
 | 
					                if self.RegionType == 'INF':
 | 
				
			||||||
                if RegionData[1] != ':' :
 | 
					                    RegionData.__InfParse__(None)
 | 
				
			||||||
                    RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, RegionData)
 | 
					                    if len(RegionData.BinFileList) != 1:
 | 
				
			||||||
                if not os.path.exists(RegionData):
 | 
					                        EdkLogger.error('GenFds', GENFDS_ERROR, 'INF in FD region can only contain one binary: %s' % RegionData)
 | 
				
			||||||
                    EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=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
 | 
					                # Add the file image into FD buffer
 | 
				
			||||||
                #
 | 
					                #
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user