To prevent the possibility that a library with a name like NULLTestLib is interpreted as a NULL linked library, use more explicit pattern matching to ensure that the library name follows the pattern NULL%d. Cc: Rebecca Cran <rebecca@bsdio.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Bob Feng <bob.c.feng@intel.com> Cc: Yuwei Chen <yuwei.chen@intel.com> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1135 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1135 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# process FFS generation from INF statement
 | 
						|
#
 | 
						|
#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
#  Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
#
 | 
						|
#  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
#
 | 
						|
 | 
						|
##
 | 
						|
# Import Modules
 | 
						|
#
 | 
						|
from __future__ import absolute_import
 | 
						|
from . import Rule
 | 
						|
import Common.LongFilePathOs as os
 | 
						|
from io import BytesIO
 | 
						|
from struct import *
 | 
						|
from .GenFdsGlobalVariable import GenFdsGlobalVariable
 | 
						|
from .Ffs import SectionSuffix,FdfFvFileTypeToFileType
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
from pathlib import Path
 | 
						|
from . import Section
 | 
						|
from . import RuleSimpleFile
 | 
						|
from . import RuleComplexFile
 | 
						|
from CommonDataClass.FdfClass import FfsInfStatementClassObject
 | 
						|
from Common.MultipleWorkspace import MultipleWorkspace as mws
 | 
						|
from Common.DataType import SUP_MODULE_USER_DEFINED
 | 
						|
from Common.DataType import SUP_MODULE_HOST_APPLICATION
 | 
						|
from Common.StringUtils import *
 | 
						|
from Common.Misc import PathClass
 | 
						|
from Common.Misc import GuidStructureByteArrayToGuidString
 | 
						|
from Common.Misc import ProcessDuplicatedInf
 | 
						|
from Common.Misc import GetVariableOffset
 | 
						|
from Common import EdkLogger
 | 
						|
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
 | 
						|
from Common.LongFilePathSupport import CopyLongFilePath
 | 
						|
from Common.LongFilePathSupport import OpenLongFilePath as open
 | 
						|
import Common.GlobalData as GlobalData
 | 
						|
from .DepexSection import DepexSection
 | 
						|
from Common.Misc import SaveFileOnChange
 | 
						|
from Common.Expression import *
 | 
						|
from Common.DataType import *
 | 
						|
 | 
						|
## generate FFS from INF
 | 
						|
#
 | 
						|
#
 | 
						|
class FfsInfStatement(FfsInfStatementClassObject):
 | 
						|
    ## The constructor
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #
 | 
						|
    def __init__(self):
 | 
						|
        FfsInfStatementClassObject.__init__(self)
 | 
						|
        self.TargetOverrideList = []
 | 
						|
        self.ShadowFromInfFile = None
 | 
						|
        self.KeepRelocFromRule = None
 | 
						|
        self.InDsc = True
 | 
						|
        self.OptRomDefs = {}
 | 
						|
        self.PiSpecVersion = '0x00000000'
 | 
						|
        self.InfModule = None
 | 
						|
        self.FinalTargetSuffixMap = {}
 | 
						|
        self.CurrentLineNum = None
 | 
						|
        self.CurrentLineContent = None
 | 
						|
        self.FileName = None
 | 
						|
        self.InfFileName = None
 | 
						|
        self.OverrideGuid = None
 | 
						|
        self.PatchedBinFile = ''
 | 
						|
        self.MacroDict = {}
 | 
						|
        self.Depex = False
 | 
						|
 | 
						|
    ## 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 != SUP_MODULE_USER_DEFINED and self.InfModule.ModuleType != SUP_MODULE_HOST_APPLICATION \
 | 
						|
                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 != SUP_MODULE_USER_DEFINED and ModuleType != SUP_MODULE_HOST_APPLICATION:
 | 
						|
                    for LibraryClass in PlatformDataBase.LibraryClasses.GetKeys():
 | 
						|
                        if LibraryClass.startswith("NULL") and LibraryClass[4:].isdigit() 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") and LibraryClass[4:].isdigit():
 | 
						|
                            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
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @param  Dict        dictionary contains macro and value pair
 | 
						|
    #
 | 
						|
    def __InfParse__(self, Dict = None, IsGenFfs=False):
 | 
						|
 | 
						|
        GenFdsGlobalVariable.VerboseLogger( " Begine parsing INf file : %s" %self.InfFileName)
 | 
						|
 | 
						|
        self.InfFileName = self.InfFileName.replace('$(WORKSPACE)', '')
 | 
						|
        if len(self.InfFileName) > 1 and self.InfFileName[0] == '\\' and self.InfFileName[1] == '\\':
 | 
						|
            pass
 | 
						|
        elif self.InfFileName[0] == '\\' or self.InfFileName[0] == '/' :
 | 
						|
            ws_path = Path(GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
            inf_path = Path(self.InfFileName)
 | 
						|
            if ws_path in inf_path.parents:
 | 
						|
                self.InfFileName = str(inf_path.relative_to(ws_path))
 | 
						|
            else:
 | 
						|
                self.InfFileName = self.InfFileName[1:]
 | 
						|
 | 
						|
        if self.InfFileName.find('$') == -1:
 | 
						|
            InfPath = NormPath(self.InfFileName)
 | 
						|
            if not os.path.exists(InfPath):
 | 
						|
                InfPath = GenFdsGlobalVariable.ReplaceWorkspaceMacro(InfPath)
 | 
						|
                if not os.path.exists(InfPath):
 | 
						|
                    EdkLogger.error("GenFds", GENFDS_ERROR, "Non-existant Module %s !" % (self.InfFileName))
 | 
						|
 | 
						|
        self.CurrentArch = self.GetCurrentArch()
 | 
						|
        #
 | 
						|
        # Get the InfClass object
 | 
						|
        #
 | 
						|
 | 
						|
        PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
        ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
 | 
						|
        if ErrorCode != 0:
 | 
						|
            EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
 | 
						|
 | 
						|
        #
 | 
						|
        # Cache lower case version of INF path before processing FILE_GUID override
 | 
						|
        #
 | 
						|
        InfLowerPath = str(PathClassObj).lower()
 | 
						|
        if self.OverrideGuid:
 | 
						|
            PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
        if self.CurrentArch is not None:
 | 
						|
 | 
						|
            Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
 | 
						|
            #
 | 
						|
            # Set Ffs BaseName, ModuleGuid, ModuleType, Version, OutputPath
 | 
						|
            #
 | 
						|
            self.BaseName = Inf.BaseName
 | 
						|
            self.ModuleGuid = Inf.Guid
 | 
						|
            self.ModuleType = Inf.ModuleType
 | 
						|
            if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
 | 
						|
                self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
 | 
						|
            if Inf.AutoGenVersion < 0x00010005:
 | 
						|
                self.ModuleType = Inf.ComponentType
 | 
						|
            self.VersionString = Inf.Version
 | 
						|
            self.BinFileList = Inf.Binaries
 | 
						|
            self.SourceFileList = Inf.Sources
 | 
						|
            if self.KeepReloc is None and Inf.Shadow:
 | 
						|
                self.ShadowFromInfFile = Inf.Shadow
 | 
						|
 | 
						|
        else:
 | 
						|
            Inf = GenFdsGlobalVariable.WorkSpace.BuildObject[PathClassObj, TAB_COMMON, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
 | 
						|
            self.BaseName = Inf.BaseName
 | 
						|
            self.ModuleGuid = Inf.Guid
 | 
						|
            self.ModuleType = Inf.ModuleType
 | 
						|
            if Inf.Specification is not None and 'PI_SPECIFICATION_VERSION' in Inf.Specification:
 | 
						|
                self.PiSpecVersion = Inf.Specification['PI_SPECIFICATION_VERSION']
 | 
						|
            self.VersionString = Inf.Version
 | 
						|
            self.BinFileList = Inf.Binaries
 | 
						|
            self.SourceFileList = Inf.Sources
 | 
						|
            if self.BinFileList == []:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR,
 | 
						|
                                "INF %s specified in FDF could not be found in build ARCH %s!" \
 | 
						|
                                % (self.InfFileName, GenFdsGlobalVariable.ArchList))
 | 
						|
 | 
						|
        if self.OverrideGuid:
 | 
						|
            self.ModuleGuid = self.OverrideGuid
 | 
						|
 | 
						|
        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 == SUP_MODULE_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 self.ModuleType == SUP_MODULE_MM_CORE_STANDALONE and int(self.PiSpecVersion, 16) < 0x00010032:
 | 
						|
            EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.InfFileName)
 | 
						|
 | 
						|
        if Inf._Defs is not None and len(Inf._Defs) > 0:
 | 
						|
            self.OptRomDefs.update(Inf._Defs)
 | 
						|
 | 
						|
        self.PatchPcds = []
 | 
						|
        InfPcds = Inf.Pcds
 | 
						|
        Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, self.CurrentArch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
 | 
						|
        FdfPcdDict = GenFdsGlobalVariable.FdfParser.Profile.PcdDict
 | 
						|
        PlatformPcds = Platform.Pcds
 | 
						|
 | 
						|
        # 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 != TAB_PCDS_PATCHABLE_IN_MODULE:
 | 
						|
                continue
 | 
						|
            # Override Patchable PCD value by the value from DSC
 | 
						|
            PatchPcd = None
 | 
						|
            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
 | 
						|
 | 
						|
            # Override Patchable PCD value by the value from Build Option
 | 
						|
            BuildOptionOverride = False
 | 
						|
            if GlobalData.BuildOptionPcd:
 | 
						|
                for pcd in GlobalData.BuildOptionPcd:
 | 
						|
                    if PcdKey == (pcd[1], pcd[0]):
 | 
						|
                        if pcd[2]:
 | 
						|
                            continue
 | 
						|
                        DefaultValue = pcd[3]
 | 
						|
                        BuildOptionOverride = True
 | 
						|
                        break
 | 
						|
 | 
						|
            if not DscOverride and not FdfOverride and not BuildOptionOverride:
 | 
						|
                continue
 | 
						|
 | 
						|
            # Support Flexible PCD format
 | 
						|
            if DefaultValue:
 | 
						|
                try:
 | 
						|
                    DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
 | 
						|
                except BadExpression:
 | 
						|
                    EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)
 | 
						|
 | 
						|
            if Pcd.InfDefaultValue:
 | 
						|
                try:
 | 
						|
                    Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
 | 
						|
                except BadExpression:
 | 
						|
                    EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue), File=self.InfFileName)
 | 
						|
 | 
						|
            # Check value, if value are equal, no need to patch
 | 
						|
            if Pcd.DatumType == TAB_VOID:
 | 
						|
                if Pcd.InfDefaultValue == DefaultValue or not DefaultValue:
 | 
						|
                    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 not Pcd.MaxDatumSize:
 | 
						|
                    Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))
 | 
						|
            else:
 | 
						|
                Base1 = Base2 = 10
 | 
						|
                if Pcd.InfDefaultValue.upper().startswith('0X'):
 | 
						|
                    Base1 = 16
 | 
						|
                if DefaultValue.upper().startswith('0X'):
 | 
						|
                    Base2 = 16
 | 
						|
                try:
 | 
						|
                    PcdValueInImg = int(Pcd.InfDefaultValue, Base1)
 | 
						|
                    PcdValueInDscOrFdf = int(DefaultValue, Base2)
 | 
						|
                    if PcdValueInImg == PcdValueInDscOrFdf:
 | 
						|
                        continue
 | 
						|
                except:
 | 
						|
                    continue
 | 
						|
            # Check the Pcd size and data type
 | 
						|
            if Pcd.DatumType == TAB_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 > MAX_VAL_TYPE[Pcd.DatumType] \
 | 
						|
                    or PcdValueInImg > MAX_VAL_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))
 | 
						|
            self.PatchPcds.append((Pcd, DefaultValue))
 | 
						|
 | 
						|
        self.InfModule = Inf
 | 
						|
        self.PcdIsDriver = Inf.PcdIsDriver
 | 
						|
        self.IsBinaryModule = Inf.IsBinaryModule
 | 
						|
        if len(Inf.Depex.data) > 0 and len(Inf.DepexExpression.data) > 0:
 | 
						|
            self.Depex = True
 | 
						|
 | 
						|
        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}+ ${ModuleName}\
 | 
						|
        #
 | 
						|
        if IsGenFfs:
 | 
						|
            Rule = self.__GetRule__()
 | 
						|
            if GlobalData.gGuidPatternEnd.match(Rule.NameGuid):
 | 
						|
                self.ModuleGuid = Rule.NameGuid
 | 
						|
        self.OutputPath = os.path.join(GenFdsGlobalVariable.FfsDir, \
 | 
						|
                                       self.ModuleGuid + self.BaseName)
 | 
						|
        if not os.path.exists(self.OutputPath) :
 | 
						|
            os.makedirs(self.OutputPath)
 | 
						|
 | 
						|
        self.EfiOutputPath, self.EfiDebugPath = 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, 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 != BINARY_FILE_TYPE_PE32 and self.ModuleType != SUP_MODULE_USER_DEFINED and self.ModuleType != SUP_MODULE_HOST_APPLICATION:
 | 
						|
            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)
 | 
						|
 | 
						|
        #
 | 
						|
        # 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)
 | 
						|
 | 
						|
        #
 | 
						|
        # Save the path of the patched output file
 | 
						|
        #
 | 
						|
        self.PatchedBinFile = Output
 | 
						|
 | 
						|
        #
 | 
						|
        # Return path to patched output file
 | 
						|
        #
 | 
						|
        return Output
 | 
						|
 | 
						|
    ## GenFfs() method
 | 
						|
    #
 | 
						|
    #   Generate FFS
 | 
						|
    #
 | 
						|
    #   @param  self         The object pointer
 | 
						|
    #   @param  Dict         dictionary contains macro and value pair
 | 
						|
    #   @param  FvChildAddr  Array of the inside FvImage base address
 | 
						|
    #   @param  FvParentAddr Parent Fv base address
 | 
						|
    #   @retval string       Generated FFS file name
 | 
						|
    #
 | 
						|
    def GenFfs(self, Dict = None, FvChildAddr = [], FvParentAddr=None, IsMakefile=False, FvName=None):
 | 
						|
        #
 | 
						|
        # Parse Inf file get Module related information
 | 
						|
        #
 | 
						|
        if Dict is None:
 | 
						|
            Dict = {}
 | 
						|
        self.__InfParse__(Dict, IsGenFfs=True)
 | 
						|
        Arch = self.GetCurrentArch()
 | 
						|
        SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName);
 | 
						|
        DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
 | 
						|
 | 
						|
        SrcFileDir = "."
 | 
						|
        SrcPath = os.path.dirname(SrcFile)
 | 
						|
        SrcFileName = os.path.basename(SrcFile)
 | 
						|
        SrcFileBase, SrcFileExt = os.path.splitext(SrcFileName)
 | 
						|
        DestPath = os.path.dirname(DestFile)
 | 
						|
        DestFileName = os.path.basename(DestFile)
 | 
						|
        DestFileBase, DestFileExt = os.path.splitext(DestFileName)
 | 
						|
        self.MacroDict = {
 | 
						|
            # source file
 | 
						|
            "${src}"      :   SrcFile,
 | 
						|
            "${s_path}"   :   SrcPath,
 | 
						|
            "${s_dir}"    :   SrcFileDir,
 | 
						|
            "${s_name}"   :   SrcFileName,
 | 
						|
            "${s_base}"   :   SrcFileBase,
 | 
						|
            "${s_ext}"    :   SrcFileExt,
 | 
						|
            # destination file
 | 
						|
            "${dst}"      :   DestFile,
 | 
						|
            "${d_path}"   :   DestPath,
 | 
						|
            "${d_name}"   :   DestFileName,
 | 
						|
            "${d_base}"   :   DestFileBase,
 | 
						|
            "${d_ext}"    :   DestFileExt
 | 
						|
        }
 | 
						|
        #
 | 
						|
        # Allow binary type module not specify override rule in FDF file.
 | 
						|
        #
 | 
						|
        if len(self.BinFileList) > 0:
 | 
						|
            if self.Rule is None or self.Rule == "":
 | 
						|
                self.Rule = "BINARY"
 | 
						|
 | 
						|
        if not IsMakefile and GenFdsGlobalVariable.EnableGenfdsMultiThread and self.Rule != 'BINARY':
 | 
						|
            IsMakefile = True
 | 
						|
        #
 | 
						|
        # Get the rule of how to generate Ffs file
 | 
						|
        #
 | 
						|
        Rule = self.__GetRule__()
 | 
						|
        GenFdsGlobalVariable.VerboseLogger( "Packing binaries from inf file : %s" %self.InfFileName)
 | 
						|
        #
 | 
						|
        # Convert Fv File Type for PI1.1 SMM driver.
 | 
						|
        #
 | 
						|
        if self.ModuleType == SUP_MODULE_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 == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
 | 
						|
            if Rule.FvFileType == 'SMM' or Rule.FvFileType == SUP_MODULE_SMM_CORE:
 | 
						|
                EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM or SMM_CORE FV file type", File=self.InfFileName)
 | 
						|
        #
 | 
						|
        # For the rule only has simpleFile
 | 
						|
        #
 | 
						|
        MakefilePath = None
 | 
						|
        if self.IsBinaryModule:
 | 
						|
            IsMakefile = False
 | 
						|
        if IsMakefile:
 | 
						|
            PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
            if self.OverrideGuid:
 | 
						|
                PathClassObj = ProcessDuplicatedInf(PathClassObj, self.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
            MakefilePath = PathClassObj.Path, Arch
 | 
						|
        if isinstance (Rule, RuleSimpleFile.RuleSimpleFile):
 | 
						|
            SectionOutputList = self.__GenSimpleFileSection__(Rule, IsMakefile=IsMakefile)
 | 
						|
            FfsOutput = self.__GenSimpleFileFfs__(Rule, SectionOutputList, MakefilePath=MakefilePath)
 | 
						|
            return FfsOutput
 | 
						|
        #
 | 
						|
        # For Rule has ComplexFile
 | 
						|
        #
 | 
						|
        elif isinstance(Rule, RuleComplexFile.RuleComplexFile):
 | 
						|
            InputSectList, InputSectAlignments = self.__GenComplexFileSection__(Rule, FvChildAddr, FvParentAddr, IsMakefile=IsMakefile)
 | 
						|
            FfsOutput = self.__GenComplexFileFfs__(Rule, InputSectList, InputSectAlignments, MakefilePath=MakefilePath)
 | 
						|
            return FfsOutput
 | 
						|
 | 
						|
    ## __ExtendMacro__() method
 | 
						|
    #
 | 
						|
    #   Replace macro with its value
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @param  String      The string to be replaced
 | 
						|
    #   @retval string      Macro replaced string
 | 
						|
    #
 | 
						|
    def __ExtendMacro__ (self, String):
 | 
						|
        MacroDict = {
 | 
						|
            '$(INF_OUTPUT)'  : self.EfiOutputPath,
 | 
						|
            '$(MODULE_NAME)' : self.BaseName,
 | 
						|
            '$(BUILD_NUMBER)': self.BuildNum,
 | 
						|
            '$(INF_VERSION)' : self.VersionString,
 | 
						|
            '$(NAMED_GUID)'  : self.ModuleGuid
 | 
						|
        }
 | 
						|
        String = GenFdsGlobalVariable.MacroExtend(String, MacroDict)
 | 
						|
        String = GenFdsGlobalVariable.MacroExtend(String, self.MacroDict)
 | 
						|
        return String
 | 
						|
 | 
						|
    ## __GetRule__() method
 | 
						|
    #
 | 
						|
    #   Get correct rule for generating FFS for this INF
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @retval Rule        Rule object
 | 
						|
    #
 | 
						|
    def __GetRule__ (self) :
 | 
						|
        CurrentArchList = []
 | 
						|
        if self.CurrentArch is None:
 | 
						|
            CurrentArchList = ['common']
 | 
						|
        else:
 | 
						|
            CurrentArchList.append(self.CurrentArch)
 | 
						|
 | 
						|
        for CurrentArch in CurrentArchList:
 | 
						|
            RuleName = 'RULE'              + \
 | 
						|
                       '.'                 + \
 | 
						|
                       CurrentArch.upper() + \
 | 
						|
                       '.'                 + \
 | 
						|
                       self.ModuleType.upper()
 | 
						|
            if self.Rule is not None:
 | 
						|
                RuleName = RuleName + \
 | 
						|
                           '.'      + \
 | 
						|
                           self.Rule.upper()
 | 
						|
 | 
						|
            Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
 | 
						|
            if Rule is not None:
 | 
						|
                GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
 | 
						|
                return Rule
 | 
						|
 | 
						|
        RuleName = 'RULE'      + \
 | 
						|
                   '.'         + \
 | 
						|
                   TAB_COMMON    + \
 | 
						|
                   '.'         + \
 | 
						|
                   self.ModuleType.upper()
 | 
						|
 | 
						|
        if self.Rule is not None:
 | 
						|
            RuleName = RuleName + \
 | 
						|
                       '.'      + \
 | 
						|
                       self.Rule.upper()
 | 
						|
 | 
						|
        GenFdsGlobalVariable.VerboseLogger ('Trying to apply common rule %s for INF %s' % (RuleName, self.InfFileName))
 | 
						|
 | 
						|
        Rule = GenFdsGlobalVariable.FdfParser.Profile.RuleDict.get(RuleName)
 | 
						|
        if Rule is not None:
 | 
						|
            GenFdsGlobalVariable.VerboseLogger ("Want To Find Rule Name is : " + RuleName)
 | 
						|
            return Rule
 | 
						|
 | 
						|
        if Rule is None :
 | 
						|
            EdkLogger.error("GenFds", GENFDS_ERROR, 'Don\'t Find common rule %s for INF %s' \
 | 
						|
                            % (RuleName, self.InfFileName))
 | 
						|
 | 
						|
    ## __GetPlatformArchList__() method
 | 
						|
    #
 | 
						|
    #   Get Arch list this INF built under
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @retval list        Arch list
 | 
						|
    #
 | 
						|
    def __GetPlatformArchList__(self):
 | 
						|
 | 
						|
        InfFileKey = os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
 | 
						|
        DscArchList = []
 | 
						|
        for Arch in GenFdsGlobalVariable.ArchList :
 | 
						|
            PlatformDataBase = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
 | 
						|
            if  PlatformDataBase is not None:
 | 
						|
                if InfFileKey in PlatformDataBase.Modules:
 | 
						|
                    DscArchList.append (Arch)
 | 
						|
                else:
 | 
						|
                    #
 | 
						|
                    # BaseTools support build same module more than once, the module path with FILE_GUID overridden has
 | 
						|
                    # the file name FILE_GUIDmodule.inf, then PlatformDataBase.Modules use FILE_GUIDmodule.inf as key,
 | 
						|
                    # but the path (self.MetaFile.Path) is the real path
 | 
						|
                    #
 | 
						|
                    for key in PlatformDataBase.Modules:
 | 
						|
                        if InfFileKey == str((PlatformDataBase.Modules[key]).MetaFile.Path):
 | 
						|
                            DscArchList.append (Arch)
 | 
						|
                            break
 | 
						|
 | 
						|
        return DscArchList
 | 
						|
 | 
						|
    ## GetCurrentArch() method
 | 
						|
    #
 | 
						|
    #   Get Arch list of the module from this INF is to be placed into flash
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @retval list        Arch list
 | 
						|
    #
 | 
						|
    def GetCurrentArch(self) :
 | 
						|
 | 
						|
        TargetArchList = GenFdsGlobalVariable.ArchList
 | 
						|
 | 
						|
        PlatformArchList = self.__GetPlatformArchList__()
 | 
						|
 | 
						|
        CurArchList = TargetArchList
 | 
						|
        if PlatformArchList != []:
 | 
						|
            CurArchList = list(set (TargetArchList) & set (PlatformArchList))
 | 
						|
        GenFdsGlobalVariable.VerboseLogger ("Valid target architecture(s) is : " + " ".join(CurArchList))
 | 
						|
 | 
						|
        ArchList = []
 | 
						|
        if self.KeyStringList != []:
 | 
						|
            for Key in self.KeyStringList:
 | 
						|
                Key = GenFdsGlobalVariable.MacroExtend(Key)
 | 
						|
                Target, Tag, Arch = Key.split('_')
 | 
						|
                if Arch in CurArchList:
 | 
						|
                    ArchList.append(Arch)
 | 
						|
                if Target not in self.TargetOverrideList:
 | 
						|
                    self.TargetOverrideList.append(Target)
 | 
						|
        else:
 | 
						|
            ArchList = CurArchList
 | 
						|
 | 
						|
        UseArchList = TargetArchList
 | 
						|
        if self.UseArch is not None:
 | 
						|
            UseArchList = []
 | 
						|
            UseArchList.append(self.UseArch)
 | 
						|
            ArchList = list(set (UseArchList) & set (ArchList))
 | 
						|
 | 
						|
        self.InfFileName = NormPath(self.InfFileName)
 | 
						|
        if len(PlatformArchList) == 0:
 | 
						|
            self.InDsc = False
 | 
						|
            PathClassObj = PathClass(self.InfFileName, GenFdsGlobalVariable.WorkSpaceDir)
 | 
						|
            ErrorCode, ErrorInfo = PathClassObj.Validate(".inf")
 | 
						|
            if ErrorCode != 0:
 | 
						|
                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
 | 
						|
        if len(ArchList) == 1:
 | 
						|
            Arch = ArchList[0]
 | 
						|
            return Arch
 | 
						|
        elif len(ArchList) > 1:
 | 
						|
            if len(PlatformArchList) == 0:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, "GenFds command line option has multiple ARCHs %s. Not able to determine which ARCH is valid for Module %s !" % (str(ArchList), self.InfFileName))
 | 
						|
            else:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, "Module built under multiple ARCHs %s. Not able to determine which output to put into flash for Module %s !" % (str(ArchList), self.InfFileName))
 | 
						|
        else:
 | 
						|
            EdkLogger.error("GenFds", GENFDS_ERROR, "Module %s appears under ARCH %s in platform %s, but current deduced ARCH is %s, so NO build output could be put into flash." \
 | 
						|
                            % (self.InfFileName, str(PlatformArchList), GenFdsGlobalVariable.ActivePlatform, str(set (UseArchList) & set (TargetArchList))))
 | 
						|
 | 
						|
    ## __GetEFIOutPutPath__() method
 | 
						|
    #
 | 
						|
    #   Get the output path for generated files
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @retval string      Path that output files from this INF go to
 | 
						|
    #
 | 
						|
    def __GetEFIOutPutPath__(self):
 | 
						|
        Arch = ''
 | 
						|
        OutputPath = ''
 | 
						|
        DebugPath = ''
 | 
						|
        (ModulePath, FileName) = os.path.split(self.InfFileName)
 | 
						|
        Index = FileName.rfind('.')
 | 
						|
        FileName = FileName[0:Index]
 | 
						|
        if self.OverrideGuid:
 | 
						|
            FileName = self.OverrideGuid
 | 
						|
        Arch = "NoneArch"
 | 
						|
        if self.CurrentArch is not None:
 | 
						|
            Arch = self.CurrentArch
 | 
						|
 | 
						|
        OutputPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
 | 
						|
                                  Arch,
 | 
						|
                                  ModulePath,
 | 
						|
                                  FileName,
 | 
						|
                                  'OUTPUT'
 | 
						|
                                  )
 | 
						|
        DebugPath = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch],
 | 
						|
                                  Arch,
 | 
						|
                                  ModulePath,
 | 
						|
                                  FileName,
 | 
						|
                                  'DEBUG'
 | 
						|
                                  )
 | 
						|
        OutputPath = os.path.abspath(OutputPath)
 | 
						|
        DebugPath = os.path.abspath(DebugPath)
 | 
						|
        return OutputPath, DebugPath
 | 
						|
 | 
						|
    ## __GenSimpleFileSection__() method
 | 
						|
    #
 | 
						|
    #   Generate section by specified file name or a list of files with file extension
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @param  Rule        The rule object used to generate section
 | 
						|
    #   @retval string      File name of the generated section file
 | 
						|
    #
 | 
						|
    def __GenSimpleFileSection__(self, Rule, IsMakefile = False):
 | 
						|
        #
 | 
						|
        # Prepare the parameter of GenSection
 | 
						|
        #
 | 
						|
        FileList = []
 | 
						|
        OutputFileList = []
 | 
						|
        GenSecInputFile = None
 | 
						|
        if Rule.FileName is not None:
 | 
						|
            GenSecInputFile = self.__ExtendMacro__(Rule.FileName)
 | 
						|
            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)
 | 
						|
 | 
						|
        Index = 1
 | 
						|
        SectionType = Rule.SectionType
 | 
						|
        #
 | 
						|
        # Convert Fv Section Type for PI1.1 SMM driver.
 | 
						|
        #
 | 
						|
        if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
 | 
						|
            if SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
 | 
						|
                SectionType = BINARY_FILE_TYPE_SMM_DEPEX
 | 
						|
        #
 | 
						|
        # Framework SMM Driver has no SMM_DEPEX section type
 | 
						|
        #
 | 
						|
        if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
 | 
						|
            if SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
 | 
						|
                EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
 | 
						|
        NoStrip = True
 | 
						|
        if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM):
 | 
						|
            if self.KeepReloc is not None:
 | 
						|
                NoStrip = self.KeepReloc
 | 
						|
            elif Rule.KeepReloc is not None:
 | 
						|
                NoStrip = Rule.KeepReloc
 | 
						|
            elif self.ShadowFromInfFile is not None:
 | 
						|
                NoStrip = self.ShadowFromInfFile
 | 
						|
 | 
						|
        if FileList != [] :
 | 
						|
            for File in FileList:
 | 
						|
 | 
						|
                SecNum = '%d' %Index
 | 
						|
                GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
 | 
						|
                              SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
 | 
						|
                Index = Index + 1
 | 
						|
                OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
 | 
						|
                File = GenFdsGlobalVariable.MacroExtend(File, Dict, self.CurrentArch)
 | 
						|
 | 
						|
                #Get PE Section alignment when align is set to AUTO
 | 
						|
                if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
 | 
						|
                    ImageObj = PeImageClass (File)
 | 
						|
                    if ImageObj.SectionAlignment < 0x400:
 | 
						|
                        self.Alignment = str (ImageObj.SectionAlignment)
 | 
						|
                    elif ImageObj.SectionAlignment < 0x100000:
 | 
						|
                        self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
 | 
						|
                    else:
 | 
						|
                        self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
 | 
						|
 | 
						|
                if not NoStrip:
 | 
						|
                    FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
 | 
						|
                    if not os.path.exists(FileBeforeStrip) or \
 | 
						|
                           (os.path.getmtime(File) > os.path.getmtime(FileBeforeStrip)):
 | 
						|
                        CopyLongFilePath(File, FileBeforeStrip)
 | 
						|
                    StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
 | 
						|
                    GenFdsGlobalVariable.GenerateFirmwareImage(
 | 
						|
                            StrippedFile,
 | 
						|
                            [File],
 | 
						|
                            Strip=True,
 | 
						|
                            IsMakefile=IsMakefile
 | 
						|
                        )
 | 
						|
                    File = StrippedFile
 | 
						|
 | 
						|
                if SectionType == BINARY_FILE_TYPE_TE:
 | 
						|
                    TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
 | 
						|
                    GenFdsGlobalVariable.GenerateFirmwareImage(
 | 
						|
                            TeFile,
 | 
						|
                            [File],
 | 
						|
                            Type='te',
 | 
						|
                            IsMakefile=IsMakefile
 | 
						|
                        )
 | 
						|
                    File = TeFile
 | 
						|
                GenFdsGlobalVariable.GenerateSection(OutputFile, [File], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
 | 
						|
                OutputFileList.append(OutputFile)
 | 
						|
        else:
 | 
						|
            SecNum = '%d' %Index
 | 
						|
            GenSecOutputFile= self.__ExtendMacro__(Rule.NameGuid) + \
 | 
						|
                              SectionSuffix[SectionType] + SUP_MODULE_SEC + SecNum
 | 
						|
            OutputFile = os.path.join(self.OutputPath, GenSecOutputFile)
 | 
						|
            GenSecInputFile = GenFdsGlobalVariable.MacroExtend(GenSecInputFile, Dict, self.CurrentArch)
 | 
						|
 | 
						|
            #Get PE Section alignment when align is set to AUTO
 | 
						|
            if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
 | 
						|
                ImageObj = PeImageClass (GenSecInputFile)
 | 
						|
                if ImageObj.SectionAlignment < 0x400:
 | 
						|
                    self.Alignment = str (ImageObj.SectionAlignment)
 | 
						|
                elif ImageObj.SectionAlignment < 0x100000:
 | 
						|
                    self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
 | 
						|
                else:
 | 
						|
                    self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
 | 
						|
 | 
						|
            if not NoStrip:
 | 
						|
                FileBeforeStrip = os.path.join(self.OutputPath, ModuleName + '.reloc')
 | 
						|
                if not os.path.exists(FileBeforeStrip) or \
 | 
						|
                       (os.path.getmtime(GenSecInputFile) > os.path.getmtime(FileBeforeStrip)):
 | 
						|
                    CopyLongFilePath(GenSecInputFile, FileBeforeStrip)
 | 
						|
 | 
						|
                StrippedFile = os.path.join(self.OutputPath, ModuleName + '.stipped')
 | 
						|
                GenFdsGlobalVariable.GenerateFirmwareImage(
 | 
						|
                        StrippedFile,
 | 
						|
                        [GenSecInputFile],
 | 
						|
                        Strip=True,
 | 
						|
                        IsMakefile=IsMakefile
 | 
						|
                    )
 | 
						|
                GenSecInputFile = StrippedFile
 | 
						|
 | 
						|
            if SectionType == BINARY_FILE_TYPE_TE:
 | 
						|
                TeFile = os.path.join( self.OutputPath, self.ModuleGuid + 'Te.raw')
 | 
						|
                GenFdsGlobalVariable.GenerateFirmwareImage(
 | 
						|
                        TeFile,
 | 
						|
                        [GenSecInputFile],
 | 
						|
                        Type='te',
 | 
						|
                        IsMakefile=IsMakefile
 | 
						|
                    )
 | 
						|
                GenSecInputFile = TeFile
 | 
						|
            GenFdsGlobalVariable.GenerateSection(OutputFile, [GenSecInputFile], Section.Section.SectionType[SectionType], IsMakefile=IsMakefile)
 | 
						|
            OutputFileList.append(OutputFile)
 | 
						|
 | 
						|
        return OutputFileList
 | 
						|
 | 
						|
    ## __GenSimpleFileFfs__() method
 | 
						|
    #
 | 
						|
    #   Generate FFS
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @param  Rule        The rule object used to generate section
 | 
						|
    #   @param  InputFileList        The output file list from GenSection
 | 
						|
    #   @retval string      Generated FFS file name
 | 
						|
    #
 | 
						|
    def __GenSimpleFileFfs__(self, Rule, InputFileList, MakefilePath = None):
 | 
						|
        FfsOutput = self.OutputPath                     + \
 | 
						|
                    os.sep                              + \
 | 
						|
                    self.__ExtendMacro__(Rule.NameGuid) + \
 | 
						|
                    '.ffs'
 | 
						|
 | 
						|
        GenFdsGlobalVariable.VerboseLogger(self.__ExtendMacro__(Rule.NameGuid))
 | 
						|
        InputSection = []
 | 
						|
        SectionAlignments = []
 | 
						|
        for InputFile in InputFileList:
 | 
						|
            InputSection.append(InputFile)
 | 
						|
            SectionAlignments.append(Rule.SectAlignment)
 | 
						|
 | 
						|
        if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
 | 
						|
            PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
 | 
						|
            if len(PcdValue) == 0:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
 | 
						|
                            % (Rule.NameGuid))
 | 
						|
            if PcdValue.startswith('{'):
 | 
						|
                PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
 | 
						|
            RegistryGuidStr = PcdValue
 | 
						|
            if len(RegistryGuidStr) == 0:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
 | 
						|
                            % (Rule.NameGuid))
 | 
						|
            self.ModuleGuid = RegistryGuidStr
 | 
						|
 | 
						|
            GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputSection,
 | 
						|
                                             FdfFvFileTypeToFileType[Rule.FvFileType],
 | 
						|
                                             self.ModuleGuid, Fixed=Rule.Fixed,
 | 
						|
                                             CheckSum=Rule.CheckSum, Align=Rule.Alignment,
 | 
						|
                                             SectionAlign=SectionAlignments,
 | 
						|
                                             MakefilePath=MakefilePath
 | 
						|
                                             )
 | 
						|
        return FfsOutput
 | 
						|
 | 
						|
    ## __GenComplexFileSection__() method
 | 
						|
    #
 | 
						|
    #   Generate section by sections in Rule
 | 
						|
    #
 | 
						|
    #   @param  self         The object pointer
 | 
						|
    #   @param  Rule         The rule object used to generate section
 | 
						|
    #   @param  FvChildAddr  Array of the inside FvImage base address
 | 
						|
    #   @param  FvParentAddr Parent Fv base address
 | 
						|
    #   @retval string       File name of the generated section file
 | 
						|
    #
 | 
						|
    def __GenComplexFileSection__(self, Rule, FvChildAddr, FvParentAddr, IsMakefile = False):
 | 
						|
        if self.ModuleType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE):
 | 
						|
            if Rule.KeepReloc is not None:
 | 
						|
                self.KeepRelocFromRule = Rule.KeepReloc
 | 
						|
        SectFiles = []
 | 
						|
        SectAlignments = []
 | 
						|
        Index = 1
 | 
						|
        HasGeneratedFlag = 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",
 | 
						|
                                                 IsMakefile = IsMakefile
 | 
						|
                                                 )
 | 
						|
            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",
 | 
						|
                                                IsMakefile = IsMakefile
 | 
						|
                                                )
 | 
						|
            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 == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) >= 0x0001000A:
 | 
						|
                if Sect.SectionType == BINARY_FILE_TYPE_DXE_DEPEX:
 | 
						|
                    Sect.SectionType = BINARY_FILE_TYPE_SMM_DEPEX
 | 
						|
            #
 | 
						|
            # Framework SMM Driver has no SMM_DEPEX section type
 | 
						|
            #
 | 
						|
            if self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER and int(self.PiSpecVersion, 16) < 0x0001000A:
 | 
						|
                if Sect.SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
 | 
						|
                    EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Framework SMM module doesn't support SMM_DEPEX section type", File=self.InfFileName)
 | 
						|
            #
 | 
						|
            # process the inside FvImage from FvSection or GuidSection
 | 
						|
            #
 | 
						|
            if FvChildAddr != []:
 | 
						|
                if isinstance(Sect, FvImageSection):
 | 
						|
                    Sect.FvAddr = FvChildAddr.pop(0)
 | 
						|
                elif isinstance(Sect, GuidSection):
 | 
						|
                    Sect.FvAddr = FvChildAddr
 | 
						|
            if FvParentAddr is not None and isinstance(Sect, GuidSection):
 | 
						|
                Sect.FvParentAddr = FvParentAddr
 | 
						|
 | 
						|
            if Rule.KeyStringList != []:
 | 
						|
                SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, Rule.KeyStringList, self, IsMakefile = IsMakefile)
 | 
						|
            else :
 | 
						|
                SectList, Align = Sect.GenSection(self.OutputPath, self.ModuleGuid, SecIndex, self.KeyStringList, self, IsMakefile = IsMakefile)
 | 
						|
 | 
						|
            if not HasGeneratedFlag:
 | 
						|
                UniVfrOffsetFileSection = ""
 | 
						|
                ModuleFileName = mws.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:
 | 
						|
                    if IsMakefile:
 | 
						|
                        if InfData.BuildType != 'UEFI_HII':
 | 
						|
                            UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
 | 
						|
                            UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
 | 
						|
                            UniVfrOffsetFileNameList = []
 | 
						|
                            UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
 | 
						|
                            TrimCmd = "Trim --Vfr-Uni-Offset -o %s --ModuleName=%s --DebugDir=%s " % (UniVfrOffsetFileName, self.BaseName, self.EfiDebugPath)
 | 
						|
                            GenFdsGlobalVariable.SecCmdList.append(TrimCmd)
 | 
						|
                            GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
 | 
						|
                                                                [UniVfrOffsetFileName],
 | 
						|
                                                                "EFI_SECTION_RAW",
 | 
						|
                                                                IsMakefile = True
 | 
						|
                                                                )
 | 
						|
                    else:
 | 
						|
                        VfrUniOffsetList = self.__GetBuildOutputMapFileVfrUniInfo(VfrUniBaseName)
 | 
						|
                        #
 | 
						|
                        # Generate the Raw data of raw section
 | 
						|
                        #
 | 
						|
                        if VfrUniOffsetList:
 | 
						|
                            UniVfrOffsetFileName = os.path.join(self.OutputPath, self.BaseName + '.offset')
 | 
						|
                            UniVfrOffsetFileSection = os.path.join(self.OutputPath, self.BaseName + 'Offset' + '.raw')
 | 
						|
                            FfsInfStatement.__GenUniVfrOffsetFile (VfrUniOffsetList, UniVfrOffsetFileName)
 | 
						|
                            UniVfrOffsetFileNameList = []
 | 
						|
                            UniVfrOffsetFileNameList.append(UniVfrOffsetFileName)
 | 
						|
                            """Call GenSection"""
 | 
						|
 | 
						|
                            GenFdsGlobalVariable.GenerateSection(UniVfrOffsetFileSection,
 | 
						|
                                                                 UniVfrOffsetFileNameList,
 | 
						|
                                                                 "EFI_SECTION_RAW"
 | 
						|
                                                                 )
 | 
						|
                            #os.remove(UniVfrOffsetFileName)
 | 
						|
                    if UniVfrOffsetFileSection:
 | 
						|
                        SectList.append(UniVfrOffsetFileSection)
 | 
						|
                        HasGeneratedFlag = True
 | 
						|
 | 
						|
            for SecName in  SectList :
 | 
						|
                SectFiles.append(SecName)
 | 
						|
                SectAlignments.append(Align)
 | 
						|
            Index = Index + 1
 | 
						|
        return SectFiles, SectAlignments
 | 
						|
 | 
						|
    ## __GenComplexFileFfs__() method
 | 
						|
    #
 | 
						|
    #   Generate FFS
 | 
						|
    #
 | 
						|
    #   @param  self        The object pointer
 | 
						|
    #   @param  Rule        The rule object used to generate section
 | 
						|
    #   @param  InputFileList        The output file list from GenSection
 | 
						|
    #   @retval string      Generated FFS file name
 | 
						|
    #
 | 
						|
    def __GenComplexFileFfs__(self, Rule, InputFile, Alignments, MakefilePath = None):
 | 
						|
 | 
						|
        if Rule.NameGuid is not None and Rule.NameGuid.startswith('PCD('):
 | 
						|
            PcdValue = GenFdsGlobalVariable.GetPcdValue(Rule.NameGuid)
 | 
						|
            if len(PcdValue) == 0:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \
 | 
						|
                            % (Rule.NameGuid))
 | 
						|
            if PcdValue.startswith('{'):
 | 
						|
                PcdValue = GuidStructureByteArrayToGuidString(PcdValue)
 | 
						|
            RegistryGuidStr = PcdValue
 | 
						|
            if len(RegistryGuidStr) == 0:
 | 
						|
                EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \
 | 
						|
                            % (Rule.NameGuid))
 | 
						|
            self.ModuleGuid = RegistryGuidStr
 | 
						|
 | 
						|
        FfsOutput = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
 | 
						|
        GenFdsGlobalVariable.GenerateFfs(FfsOutput, InputFile,
 | 
						|
                                             FdfFvFileTypeToFileType[Rule.FvFileType],
 | 
						|
                                             self.ModuleGuid, Fixed=Rule.Fixed,
 | 
						|
                                             CheckSum=Rule.CheckSum, Align=Rule.Alignment,
 | 
						|
                                             SectionAlign=Alignments,
 | 
						|
                                             MakefilePath=MakefilePath
 | 
						|
                                             )
 | 
						|
        return FfsOutput
 | 
						|
 | 
						|
    ## __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):
 | 
						|
        MapFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".map")
 | 
						|
        EfiFileName = os.path.join(self.EfiOutputPath, self.BaseName + ".efi")
 | 
						|
        return GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
 | 
						|
 | 
						|
    ## __GenUniVfrOffsetFile() method
 | 
						|
    #
 | 
						|
    #   Generate the offset file for the module which contain VFR or UNI file.
 | 
						|
    #
 | 
						|
    #   @param  VfrUniOffsetList        A list contain the VFR/UNI offsets in the EFI image file.
 | 
						|
    #   @param  UniVfrOffsetFileName    The output offset file name.
 | 
						|
    #
 | 
						|
    @staticmethod
 | 
						|
    def __GenUniVfrOffsetFile(VfrUniOffsetList, UniVfrOffsetFileName):
 | 
						|
 | 
						|
        # Use a instance of StringIO to cache data
 | 
						|
        fStringIO = BytesIO()
 | 
						|
 | 
						|
        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 = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
 | 
						|
                fStringIO.write(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 = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
 | 
						|
                fStringIO.write(VfrGuid)
 | 
						|
                type (Item[1])
 | 
						|
                VfrValue = pack ('Q', int (Item[1], 16))
 | 
						|
                fStringIO.write (VfrValue)
 | 
						|
 | 
						|
        #
 | 
						|
        # write data into file.
 | 
						|
        #
 | 
						|
        try :
 | 
						|
            SaveFileOnChange(UniVfrOffsetFileName, 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 ()
 | 
						|
 | 
						|
 |