X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;ds=sidebyside;f=BaseTools%2FSource%2FPython%2FGenFds%2FFfsInfStatement.py;h=feab8c84a097f326c0157dbd861b3df08879c8a2;hb=2bc3256ca6d439ebf5d85d5e74e5f3e68df14130;hp=b00e5a21788410fdebc19dfe2c99b5985e5f5cdf;hpb=52302d4dee589a5df43a464420c9fe68ba83937d;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py index b00e5a2178..feab8c84a0 100644 --- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py +++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py @@ -1,9 +1,9 @@ ## @file # process FFS generation from INF statement # -# Copyright (c) 2007 - 2010, Intel Corporation +# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.
# -# All rights reserved. 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 # which accompanies this distribution. The full text of the license may be found at # http://opensource.org/licenses/bsd-license.php @@ -18,6 +18,8 @@ import Rule import os import shutil +import StringIO +from struct import * from GenFdsGlobalVariable import GenFdsGlobalVariable import Ffs import subprocess @@ -34,11 +36,15 @@ from Common.BuildToolError import * from GuidSection import GuidSection from FvImageSection import FvImageSection from Common.Misc import PeImageClass +from AutoGen.GenDepex import DependencyExpression +from PatchPcdValue.PatchPcdValue import PatchBinaryFile ## generate FFS from INF # # class FfsInfStatement(FfsInfStatementClassObject): + ## The mapping dictionary from datum type to its maximum number. + _MAX_SIZE_TYPE = {"BOOLEAN":0x01, "UINT8":0xFF, "UINT16":0xFFFF, "UINT32":0xFFFFFFFF, "UINT64":0xFFFFFFFFFFFFFFFF} ## The constructor # # @param self The object pointer @@ -50,8 +56,82 @@ class FfsInfStatement(FfsInfStatementClassObject): self.KeepRelocFromRule = None self.InDsc = True self.OptRomDefs = {} - self.PiSpecVersion = 0 - + self.PiSpecVersion = '0x00000000' + self.InfModule = None + self.FinalTargetSuffixMap = {} + self.CurrentLineNum = None + self.CurrentLineContent = None + self.FileName = None + self.InfFileName = None + + ## GetFinalTargetSuffixMap() method + # + # Get final build target list + def GetFinalTargetSuffixMap(self): + if not self.InfModule or not self.CurrentArch: + return [] + if not self.FinalTargetSuffixMap: + FinalBuildTargetList = GenFdsGlobalVariable.GetModuleCodaTargetList(self.InfModule, self.CurrentArch) + for File in FinalBuildTargetList: + self.FinalTargetSuffixMap.setdefault(os.path.splitext(File)[1], []).append(File) + + # Check if current INF module has DEPEX + if '.depex' not in self.FinalTargetSuffixMap and self.InfModule.ModuleType != "USER_DEFINED" \ + and not self.InfModule.DxsFile and not self.InfModule.LibraryClass: + ModuleType = self.InfModule.ModuleType + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] + + if ModuleType != DataType.SUP_MODULE_USER_DEFINED: + for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys(): + if LibraryClass.startswith("NULL") and PlatformDataBase.LibraryClasses[LibraryClass, ModuleType]: + self.InfModule.LibraryClasses[LibraryClass] = PlatformDataBase.LibraryClasses[LibraryClass, ModuleType] + + StrModule = str(self.InfModule) + PlatformModule = None + if StrModule in PlatformDataBase.Modules: + PlatformModule = PlatformDataBase.Modules[StrModule] + for LibraryClass in PlatformModule.LibraryClasses: + if LibraryClass.startswith("NULL"): + self.InfModule.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass] + + DependencyList = [self.InfModule] + LibraryInstance = {} + DepexList = [] + while len(DependencyList) > 0: + Module = DependencyList.pop(0) + if not Module: + continue + for Dep in Module.Depex[self.CurrentArch, ModuleType]: + if DepexList != []: + DepexList.append('AND') + DepexList.append('(') + DepexList.extend(Dep) + if DepexList[-1] == 'END': # no need of a END at this time + DepexList.pop() + DepexList.append(')') + if 'BEFORE' in DepexList or 'AFTER' in DepexList: + break + for LibName in Module.LibraryClasses: + if LibName in LibraryInstance: + continue + if PlatformModule and LibName in PlatformModule.LibraryClasses: + LibraryPath = PlatformModule.LibraryClasses[LibName] + else: + LibraryPath = PlatformDataBase.LibraryClasses[LibName, ModuleType] + if not LibraryPath: + LibraryPath = Module.LibraryClasses[LibName] + if not LibraryPath: + continue + LibraryModule = GenFdsGlobalVariable.WorkSpace.BuildObject[LibraryPath, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] + LibraryInstance[LibName] = LibraryModule + DependencyList.append(LibraryModule) + if DepexList: + Dpx = DependencyExpression(DepexList, ModuleType, True) + if len(Dpx.PostfixNotation) != 0: + # It means this module has DEPEX + self.FinalTargetSuffixMap['.depex'] = [os.path.join(self.EfiOutputPath, self.BaseName) + '.depex'] + return self.FinalTargetSuffixMap + ## __InfParse() method # # Parse inf file to get module information @@ -80,13 +160,13 @@ class FfsInfStatement(FfsInfStatementClassObject): # PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) - ErrorCode, ErrorInfo = PathClassObj.Validate() + ErrorCode, ErrorInfo = PathClassObj.Validate(".inf") if ErrorCode != 0: EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) if self.CurrentArch != None: - Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch] + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] # # Set Ffs BaseName, MdouleGuid, ModuleType, Version, OutputPath # @@ -104,7 +184,7 @@ class FfsInfStatement(FfsInfStatementClassObject): self.ShadowFromInfFile = Inf.Shadow else: - Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON'] + Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] self.BaseName = Inf.BaseName self.ModuleGuid = Inf.Guid self.ModuleType = Inf.ModuleType @@ -121,17 +201,99 @@ class FfsInfStatement(FfsInfStatementClassObject): if len(self.SourceFileList) != 0 and not self.InDsc: EdkLogger.warn("GenFds", GENFDS_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % (self.InfFileName)) - if self.ModuleType == 'SMM_CORE' and self.PiSpecVersion < 0x0001000A: + if self.ModuleType == 'SMM_CORE' and int(self.PiSpecVersion, 16) < 0x0001000A: EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.InfFileName) if Inf._Defs != None and len(Inf._Defs) > 0: self.OptRomDefs.update(Inf._Defs) - - GenFdsGlobalVariable.VerboseLogger( "BaseName : %s" %self.BaseName) - GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" %self.ModuleGuid) - GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" %self.ModuleType) - GenFdsGlobalVariable.VerboseLogger("VersionString : %s" %self.VersionString) - GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" %self.InfFileName) + + self.PatchPcds = [] + InfPcds = Inf.Pcds + Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] + FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict + + # Workaround here: both build and GenFds tool convert the workspace path to lower case + # But INF file path in FDF and DSC file may have real case characters. + # Try to convert the path to lower case to see if PCDs value are override by DSC. + DscModules = {} + for DscModule in Platform.Modules: + DscModules[str(DscModule).lower()] = Platform.Modules[DscModule] + for PcdKey in InfPcds: + Pcd = InfPcds[PcdKey] + if not hasattr(Pcd, 'Offset'): + continue + if Pcd.Type != 'PatchableInModule': + continue + # Override Patchable PCD value by the value from DSC + PatchPcd = None + InfLowerPath = str(PathClassObj).lower() + if InfLowerPath in DscModules and PcdKey in DscModules[InfLowerPath].Pcds: + PatchPcd = DscModules[InfLowerPath].Pcds[PcdKey] + elif PcdKey in Platform.Pcds: + PatchPcd = Platform.Pcds[PcdKey] + DscOverride = False + if PatchPcd and Pcd.Type == PatchPcd.Type: + DefaultValue = PatchPcd.DefaultValue + DscOverride = True + + # Override Patchable PCD value by the value from FDF + FdfOverride = False + if PcdKey in FdfPcdDict: + DefaultValue = FdfPcdDict[PcdKey] + FdfOverride = True + + if not DscOverride and not FdfOverride: + continue + # Check value, if value are equal, no need to patch + if Pcd.DatumType == "VOID*": + if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']: + continue + # Get the string size from FDF or DSC + if DefaultValue[0] == 'L': + # Remove L"", but the '\0' must be appended + MaxDatumSize = str((len(DefaultValue) - 2) * 2) + elif DefaultValue[0] == '{': + MaxDatumSize = str(len(DefaultValue.split(','))) + else: + MaxDatumSize = str(len(DefaultValue) - 1) + if DscOverride: + Pcd.MaxDatumSize = PatchPcd.MaxDatumSize + # If no defined the maximum size in DSC, try to get current size from INF + if Pcd.MaxDatumSize in ['', None]: + Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(','))) + else: + Base1 = Base2 = 10 + if Pcd.DefaultValue.upper().startswith('0X'): + Base1 = 16 + if DefaultValue.upper().startswith('0X'): + Base2 = 16 + try: + PcdValueInImg = int(Pcd.DefaultValue, Base1) + PcdValueInDscOrFdf = int(DefaultValue, Base2) + if PcdValueInImg == PcdValueInDscOrFdf: + continue + except: + continue + # Check the Pcd size and data type + if Pcd.DatumType == "VOID*": + if int(MaxDatumSize) > int(Pcd.MaxDatumSize): + EdkLogger.error("GenFds", GENFDS_ERROR, "The size of VOID* type PCD '%s.%s' exceeds its maximum size %d bytes." \ + % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, int(MaxDatumSize) - int(Pcd.MaxDatumSize))) + else: + if PcdValueInDscOrFdf > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType] \ + or PcdValueInImg > FfsInfStatement._MAX_SIZE_TYPE[Pcd.DatumType]: + EdkLogger.error("GenFds", GENFDS_ERROR, "The size of %s type PCD '%s.%s' doesn't match its data type." \ + % (Pcd.DatumType, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)) + Pcd.DefaultValue = DefaultValue + self.PatchPcds.append(Pcd) + self.InfModule = Inf + self.PcdIsDriver = Inf.PcdIsDriver + self.IsBinaryModule = Inf.IsBinaryModule + GenFdsGlobalVariable.VerboseLogger("BaseName : %s" % self.BaseName) + GenFdsGlobalVariable.VerboseLogger("ModuleGuid : %s" % self.ModuleGuid) + GenFdsGlobalVariable.VerboseLogger("ModuleType : %s" % self.ModuleType) + GenFdsGlobalVariable.VerboseLogger("VersionString : %s" % self.VersionString) + GenFdsGlobalVariable.VerboseLogger("InfFileName :%s" % self.InfFileName) # # Set OutputPath = ${WorkSpace}\Build\Fv\Ffs\${ModuleGuid}+ ${MdouleName}\ @@ -145,6 +307,27 @@ class FfsInfStatement(FfsInfStatementClassObject): self.EfiOutputPath = self.__GetEFIOutPutPath__() GenFdsGlobalVariable.VerboseLogger( "ModuelEFIPath: " + self.EfiOutputPath) +## PatchEfiFile + # + # Patch EFI file with patch PCD + # + # @param EfiFile: EFI file needs to be patched. + # @retval: Full path of patched EFI file: self.OutputPath + EfiFile base name + # If passed in file does not end with efi, return as is + # + def PatchEfiFile(self, EfiFile): + if os.path.splitext(EfiFile)[1].lower() != '.efi': + return EfiFile + if not self.PatchPcds: + return EfiFile + Basename = os.path.basename(EfiFile) + Output = os.path.join(self.OutputPath, Basename) + shutil.copy(EfiFile, Output) + for Pcd in self.PatchPcds: + RetVal, RetStr = PatchBinaryFile(Output, int(Pcd.Offset, 0), Pcd.DatumType, Pcd.DefaultValue, Pcd.MaxDatumSize) + if RetVal: + EdkLogger.error("GenFds", GENFDS_ERROR, RetStr, File=self.InfFileName) + return Output ## GenFfs() method # # Generate FFS @@ -161,6 +344,14 @@ class FfsInfStatement(FfsInfStatementClassObject): # self.__InfParse__(Dict) + + # + # Allow binary type module not specify override rule in FDF file. + # + if len(self.BinFileList) >0 and not self.InDsc: + if self.Rule == None or self.Rule == "": + self.Rule = "BINARY" + # # Get the rule of how to generate Ffs file # @@ -169,13 +360,13 @@ class FfsInfStatement(FfsInfStatementClassObject): # # Convert Fv File Type for PI1.1 SMM driver. # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion >= 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A: if Rule.FvFileType == 'DRIVER': Rule.FvFileType = 'SMM' # # Framework SMM Driver has no SMM FV file type # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion < 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A: if Rule.FvFileType == 'SMM' or Rule.FvFileType == 'SMM_CORE': EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName) # @@ -276,31 +467,36 @@ class FfsInfStatement(FfsInfStatementClassObject): InfFileKey = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)) DscArchList = [] - PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32'] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] if PlatformDataBase != None: if InfFileKey in PlatformDataBase.Modules: DscArchList.append ('IA32') - PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64'] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'X64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] if PlatformDataBase != None: if InfFileKey in PlatformDataBase.Modules: DscArchList.append ('X64') - PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF'] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'IPF', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] if PlatformDataBase != None: if InfFileKey in (PlatformDataBase.Modules): DscArchList.append ('IPF') - PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM'] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'ARM', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] if PlatformDataBase != None: if InfFileKey in (PlatformDataBase.Modules): DscArchList.append ('ARM') - PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC'] + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'EBC', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] if PlatformDataBase != None: if InfFileKey in (PlatformDataBase.Modules): DscArchList.append ('EBC') + PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'AARCH64', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] + if PlatformDataBase != None: + if InfFileKey in (PlatformDataBase.Modules): + DscArchList.append ('AARCH64') + return DscArchList ## GetCurrentArch() method @@ -343,7 +539,7 @@ class FfsInfStatement(FfsInfStatementClassObject): if len(PlatformArchList) == 0: self.InDsc = False PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir) - ErrorCode, ErrorInfo = PathClassObj.Validate() + ErrorCode, ErrorInfo = PathClassObj.Validate(".inf") if ErrorCode != 0: EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo) if len(ArchList) == 1: @@ -369,7 +565,7 @@ class FfsInfStatement(FfsInfStatementClassObject): Arch = '' OutputPath = '' (ModulePath, FileName) = os.path.split(self.InfFileName) - Index = FileName.find('.') + Index = FileName.rfind('.') FileName = FileName[0:Index] Arch = "NoneArch" if self.CurrentArch != None: @@ -401,9 +597,9 @@ class FfsInfStatement(FfsInfStatementClassObject): GenSecInputFile = None if Rule.FileName != None: GenSecInputFile = self.__ExtendMacro__(Rule.FileName) - if os.path.isabs(GenSecInputFile): - GenSecInputFile = os.path.normpath(GenSecInputFile) - else: + if os.path.isabs(GenSecInputFile): + GenSecInputFile = os.path.normpath(GenSecInputFile) + else: GenSecInputFile = os.path.normpath(os.path.join(self.EfiOutputPath, GenSecInputFile)) else: FileList, IsSect = Section.Section.GetFileList(self, '', Rule.FileExtension) @@ -413,13 +609,13 @@ class FfsInfStatement(FfsInfStatementClassObject): # # Convert Fv Section Type for PI1.1 SMM driver. # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion >= 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A: if SectionType == 'DXE_DEPEX': SectionType = 'SMM_DEPEX' # # Framework SMM Driver has no SMM_DEPEX section type # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion < 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A: if SectionType == 'SMM_DEPEX': EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName) NoStrip = True @@ -575,19 +771,44 @@ class FfsInfStatement(FfsInfStatementClassObject): SectFiles = [] SectAlignments = [] Index = 1 + HasGneratedFlag = False + if self.PcdIsDriver == 'PEI_PCD_DRIVER': + if self.IsBinaryModule: + PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "PEIPcdDataBase.raw") + else: + PcdExDbFileName = os.path.join(self.EfiOutputPath, "PEIPcdDataBase.raw") + PcdExDbSecName = os.path.join(self.OutputPath, "PEIPcdDataBaseSec.raw") + GenFdsGlobalVariable.GenerateSection(PcdExDbSecName, + [PcdExDbFileName], + "EFI_SECTION_RAW", + ) + SectFiles.append(PcdExDbSecName) + SectAlignments.append(None) + elif self.PcdIsDriver == 'DXE_PCD_DRIVER': + if self.IsBinaryModule: + PcdExDbFileName = os.path.join(GenFdsGlobalVariable.FvDir, "DXEPcdDataBase.raw") + else: + PcdExDbFileName = os.path.join(self.EfiOutputPath, "DXEPcdDataBase.raw") + PcdExDbSecName = os.path.join(self.OutputPath, "DXEPcdDataBaseSec.raw") + GenFdsGlobalVariable.GenerateSection(PcdExDbSecName, + [PcdExDbFileName], + "EFI_SECTION_RAW", + ) + SectFiles.append(PcdExDbSecName) + SectAlignments.append(None) for Sect in Rule.SectionList: SecIndex = '%d' %Index SectList = [] # # Convert Fv Section Type for PI1.1 SMM driver. # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion >= 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) >= 0x0001000A: if Sect.SectionType == 'DXE_DEPEX': Sect.SectionType = 'SMM_DEPEX' # # Framework SMM Driver has no SMM_DEPEX section type # - if self.ModuleType == 'DXE_SMM_DRIVER' and self.PiSpecVersion < 0x0001000A: + if self.ModuleType == 'DXE_SMM_DRIVER' and int(self.PiSpecVersion, 16) < 0x0001000A: if Sect.SectionType == 'SMM_DEPEX': EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName) # @@ -605,6 +826,51 @@ class FfsInfStatement(FfsInfStatementClassObject): SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, Rule.KeyStringList, self) else : SectList, Align = Sect.GenSection(self.OutputPath , self.ModuleGuid, SecIndex, self.KeyStringList, self) + + if not HasGneratedFlag: + UniVfrOffsetFileSection = "" + ModuleFileName = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName) + InfData = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), self.CurrentArch] + # + # Search the source list in InfData to find if there are .vfr file exist. + # + VfrUniBaseName = {} + VfrUniOffsetList = [] + for SourceFile in InfData.Sources: + if SourceFile.Type.upper() == ".VFR" : + # + # search the .map file to find the offset of vfr binary in the PE32+/TE file. + # + VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin") + if SourceFile.Type.upper() == ".UNI" : + # + # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. + # + VfrUniBaseName["UniOffsetName"] = (self.BaseName + "Strings") + + + if len(VfrUniBaseName) > 0: + VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName) + # + # Generate the Raw data of raw section + # + os.path.join( self.OutputPath, self.BaseName + '.offset') + UniVfrOffsetFileName = os.path.join( self.OutputPath, self.BaseName + '.offset') + UniVfrOffsetFileSection = os.path.join( self.OutputPath, self.BaseName + 'Offset' + '.raw') + + self.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName) + + UniVfrOffsetFileNameList = [] + UniVfrOffsetFileNameList.append(UniVfrOffsetFileName) + """Call GenSection""" + GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection, + UniVfrOffsetFileNameList, + "EFI_SECTION_RAW" + ) + os.remove(UniVfrOffsetFileName) + SectList.append(UniVfrOffsetFileSection) + HasGneratedFlag = True + for SecName in SectList : SectFiles.append(SecName) SectAlignments.append(Align) @@ -664,3 +930,116 @@ class FfsInfStatement(FfsInfStatementClassObject): result += ('-a', Rule.Alignment) return result + + ## __GetBuildOutputMapFileVfrUniInfo() method + # + # Find the offset of UNI/INF object offset in the EFI image file. + # + # @param self The object pointer + # @param VfrUniBaseName A name list contain the UNI/INF object name. + # @retval RetValue A list contain offset of UNI/INF object. + # + def __GetBuildOutputMapFileVfrUniInfo(self, VfrUniBaseName): + + RetValue = [] + + MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map") + try: + fInputfile = open(MapFileName, "r", 0) + try: + FileLinesList = fInputfile.readlines() + except: + EdkLogger.error("GenFds", FILE_READ_FAILURE, "File read failed for %s" %MapFileName,None) + finally: + fInputfile.close() + except: + EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %MapFileName,None) + + IsHex = False + for eachLine in FileLinesList: + for eachName in VfrUniBaseName.values(): + if eachLine.find(eachName) != -1: + eachLine = eachLine.strip() + Element = eachLine.split() + # + # MSFT/ICC/EBC map file + # + if (len(Element) == 4): + try: + int (Element[2], 16) + IsHex = True + except: + IsHex = False + + if IsHex: + RetValue.append((eachName, Element[2])) + IsHex = False + # + # GCC map file + # + elif (len(Element) == 2) and Element[0].startswith("0x"): + RetValue.append((eachName, Element[0])) + + return RetValue + + ## __GenUniVfrOffsetFile() method + # + # Generate the offset file for the module which contain VFR or UNI file. + # + # @param self The object pointer + # @param VfrUniOffsetList A list contain the VFR/UNI offsets in the EFI image file. + # @param UniVfrOffsetFileName The output offset file name. + # + def __GenUniVfrOffsetFile(self, VfrUniOffsetList, UniVfrOffsetFileName): + + try: + fInputfile = open(UniVfrOffsetFileName, "wb+", 0) + except: + EdkLogger.error("GenFds", FILE_OPEN_FAILURE, "File open failed for %s" %UniVfrOffsetFileName,None) + + # Use a instance of StringIO to cache data + fStringIO = StringIO.StringIO('') + + for Item in VfrUniOffsetList: + if (Item[0].find("Strings") != -1): + # + # UNI offset in image. + # GUID + Offset + # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } } + # + UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66] + UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid] + fStringIO.write(''.join(UniGuid)) + UniValue = pack ('Q', int (Item[1], 16)) + fStringIO.write (UniValue) + else: + # + # VFR binary offset in image. + # GUID + Offset + # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }; + # + VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2] + VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid] + fStringIO.write(''.join(VfrGuid)) + type (Item[1]) + VfrValue = pack ('Q', int (Item[1], 16)) + fStringIO.write (VfrValue) + + # + # write data into file. + # + try : + fInputfile.write (fStringIO.getvalue()) + except: + EdkLogger.error("GenFds", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %UniVfrOffsetFileName,None) + + fStringIO.close () + fInputfile.close () + + + + + + + +