diff options
Diffstat (limited to 'BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py')
| -rw-r--r-- | BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py | 2054 |
1 files changed, 1027 insertions, 1027 deletions
diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py index d7668ba681..a8830556aa 100644 --- a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py +++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py @@ -1,1027 +1,1027 @@ -## @file
-# Global variables for GenFds
-#
-# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-
-##
-# Import Modules
-#
-from __future__ import print_function
-from __future__ import absolute_import
-
-import Common.LongFilePathOs as os
-import sys
-from sys import stdout
-from subprocess import PIPE,Popen
-from struct import Struct
-from array import array
-
-from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR
-from Common import EdkLogger
-from Common.Misc import SaveFileOnChange
-
-from Common.TargetTxtClassObject import TargetTxtDict
-from Common.ToolDefClassObject import ToolDefDict,gDefaultToolsDefFile
-from AutoGen.BuildEngine import ToolBuildRule
-import Common.DataType as DataType
-from Common.Misc import PathClass,CreateDirectory
-from Common.LongFilePathSupport import OpenLongFilePath as open
-from Common.MultipleWorkspace import MultipleWorkspace as mws
-import Common.GlobalData as GlobalData
-from Common.BuildToolError import *
-from AutoGen.AutoGen import CalculatePriorityValue
-
-## Global variables
-#
-#
-class GenFdsGlobalVariable:
- FvDir = ''
- OutputDirDict = {}
- BinDir = ''
- # will be FvDir + os.sep + 'Ffs'
- FfsDir = ''
- FdfParser = None
- LibDir = ''
- WorkSpace = None
- WorkSpaceDir = ''
- ConfDir = ''
- OutputDirFromDscDict = {}
- TargetName = ''
- ToolChainTag = ''
- RuleDict = {}
- ArchList = None
- ActivePlatform = None
- FvAddressFileName = ''
- VerboseMode = False
- DebugLevel = -1
- SharpCounter = 0
- SharpNumberPerLine = 40
- FdfFile = ''
- FdfFileTimeStamp = 0
- FixedLoadAddress = False
- PlatformName = ''
-
- BuildRuleFamily = DataType.TAB_COMPILER_MSFT
- ToolChainFamily = DataType.TAB_COMPILER_MSFT
- __BuildRuleDatabase = None
- GuidToolDefinition = {}
- FfsCmdDict = {}
- SecCmdList = []
- CopyList = []
- ModuleFile = ''
- EnableGenfdsMultiThread = True
-
- #
- # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
- # At the beginning of each generation of FV, false flag is appended to the list,
- # after the call to GenerateSection returns, check the size of the output file,
- # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
- # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
- # At the end of generation of FV, pop the flag.
- # List is used as a stack to handle nested FV generation.
- #
- LargeFileInFvFlags = []
- EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
- LARGE_FILE_SIZE = 0x1000000
-
- SectionHeader = Struct("3B 1B")
-
- # FvName, FdName, CapName in FDF, Image file name
- ImageBinDict = {}
-
- ## LoadBuildRule
- #
- @staticmethod
- def _LoadBuildRule():
- if GenFdsGlobalVariable.__BuildRuleDatabase:
- return GenFdsGlobalVariable.__BuildRuleDatabase
- BuildRule = ToolBuildRule()
- GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule
- TargetObj = TargetTxtDict()
- ToolDefinitionFile = TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
- if ToolDefinitionFile == '':
- ToolDefinitionFile = os.path.join('Conf', gDefaultToolsDefFile)
- if os.path.isfile(ToolDefinitionFile):
- ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
- ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase
- if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
- and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
- and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
- GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]
-
- if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \
- and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \
- and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]:
- GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]
- return GenFdsGlobalVariable.__BuildRuleDatabase
-
- ## GetBuildRules
- # @param Inf: object of InfBuildData
- # @param Arch: current arch
- #
- @staticmethod
- def GetBuildRules(Inf, Arch):
- if not Arch:
- Arch = DataType.TAB_COMMON
-
- if not Arch in GenFdsGlobalVariable.OutputDirDict:
- return {}
-
- BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule()
- if not BuildRuleDatabase:
- return {}
-
- PathClassObj = PathClass(Inf.MetaFile.File,
- GenFdsGlobalVariable.WorkSpaceDir)
- BuildDir = os.path.join(
- GenFdsGlobalVariable.OutputDirDict[Arch],
- Arch,
- PathClassObj.SubDir,
- PathClassObj.BaseName
- )
- BinDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
- Macro = {
- "WORKSPACE":GenFdsGlobalVariable.WorkSpaceDir,
- "MODULE_NAME":Inf.BaseName,
- "MODULE_GUID":Inf.Guid,
- "MODULE_VERSION":Inf.Version,
- "MODULE_TYPE":Inf.ModuleType,
- "MODULE_FILE":str(PathClassObj),
- "MODULE_FILE_BASE_NAME":PathClassObj.BaseName,
- "MODULE_RELATIVE_DIR":PathClassObj.SubDir,
- "MODULE_DIR":PathClassObj.SubDir,
- "BASE_NAME":Inf.BaseName,
- "ARCH":Arch,
- "TOOLCHAIN":GenFdsGlobalVariable.ToolChainTag,
- "TOOLCHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
- "TOOL_CHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
- "TARGET":GenFdsGlobalVariable.TargetName,
- "BUILD_DIR":GenFdsGlobalVariable.OutputDirDict[Arch],
- "BIN_DIR":BinDir,
- "LIB_DIR":BinDir,
- "MODULE_BUILD_DIR":BuildDir,
- "OUTPUT_DIR":os.path.join(BuildDir, "OUTPUT"),
- "DEBUG_DIR":os.path.join(BuildDir, "DEBUG")
- }
-
- BuildRules = {}
- for Type in BuildRuleDatabase.FileTypeList:
- #first try getting build rule by BuildRuleFamily
- RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
- if not RuleObject:
- # build type is always module type, but ...
- if Inf.ModuleType != Inf.BuildType:
- RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
- #second try getting build rule by ToolChainFamily
- if not RuleObject:
- RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily]
- if not RuleObject:
- # build type is always module type, but ...
- if Inf.ModuleType != Inf.BuildType:
- RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily]
- if not RuleObject:
- continue
- RuleObject = RuleObject.Instantiate(Macro)
- BuildRules[Type] = RuleObject
- for Ext in RuleObject.SourceFileExtList:
- BuildRules[Ext] = RuleObject
- return BuildRules
-
- ## GetModuleCodaTargetList
- #
- # @param Inf: object of InfBuildData
- # @param Arch: current arch
- #
- @staticmethod
- def GetModuleCodaTargetList(Inf, Arch):
- BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch)
- if not BuildRules:
- return []
-
- TargetList = set()
- FileList = []
-
- if not Inf.IsBinaryModule:
- for File in Inf.Sources:
- if File.TagName in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainTag} and \
- File.ToolChainFamily in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainFamily}:
- FileList.append((File, DataType.TAB_UNKNOWN_FILE))
-
- for File in Inf.Binaries:
- if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}:
- FileList.append((File, File.Type))
-
- for File, FileType in FileList:
- LastTarget = None
- RuleChain = []
- SourceList = [File]
- Index = 0
- while Index < len(SourceList):
- Source = SourceList[Index]
- Index = Index + 1
-
- if File.IsBinary and File == Source and Inf.Binaries and File in Inf.Binaries:
- # Skip all files that are not binary libraries
- if not Inf.LibraryClass:
- continue
- RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE]
- elif FileType in BuildRules:
- RuleObject = BuildRules[FileType]
- elif Source.Ext in BuildRules:
- RuleObject = BuildRules[Source.Ext]
- else:
- # stop at no more rules
- if LastTarget:
- TargetList.add(str(LastTarget))
- break
-
- FileType = RuleObject.SourceFileType
-
- # stop at STATIC_LIBRARY for library
- if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY:
- if LastTarget:
- TargetList.add(str(LastTarget))
- break
-
- Target = RuleObject.Apply(Source)
- if not Target:
- if LastTarget:
- TargetList.add(str(LastTarget))
- break
- elif not Target.Outputs:
- # Only do build for target with outputs
- TargetList.add(str(Target))
-
- # to avoid cyclic rule
- if FileType in RuleChain:
- break
-
- RuleChain.append(FileType)
- SourceList.extend(Target.Outputs)
- LastTarget = Target
- FileType = DataType.TAB_UNKNOWN_FILE
- for Cmd in Target.Commands:
- if "$(CP)" == Cmd.split()[0]:
- CpTarget = Cmd.split()[2]
- TargetList.add(CpTarget)
-
- return list(TargetList)
-
- ## SetDir()
- #
- # @param OutputDir Output directory
- # @param FdfParser FDF contents parser
- # @param Workspace The directory of workspace
- # @param ArchList The Arch list of platform
- #
- @staticmethod
- def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
- GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir)
- GenFdsGlobalVariable.FdfParser = FdfParser
- GenFdsGlobalVariable.WorkSpace = WorkSpace
- GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
- if not os.path.exists(GenFdsGlobalVariable.FvDir):
- os.makedirs(GenFdsGlobalVariable.FvDir)
- GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
- if not os.path.exists(GenFdsGlobalVariable.FfsDir):
- os.makedirs(GenFdsGlobalVariable.FfsDir)
-
- #
- # Create FV Address inf file
- #
- GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
- FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
- #
- # Add [Options]
- #
- FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
- BsAddress = '0'
- for Arch in ArchList:
- if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress:
- BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress
- break
-
- FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
- BsAddress + \
- DataType.TAB_LINE_BREAK)
-
- RtAddress = '0'
- for Arch in reversed(ArchList):
- temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
- if temp:
- RtAddress = temp
- break
-
- FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
- RtAddress + \
- DataType.TAB_LINE_BREAK)
-
- FvAddressFile.close()
-
- @staticmethod
- def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData):
- GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile
- GenFdsGlobalVariable.FdfParser = FdfParser
- GenFdsGlobalVariable.WorkSpace = WorkSpace.Db
- GenFdsGlobalVariable.ArchList = ArchList
- GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]
- GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"]
- GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform
- GenFdsGlobalVariable.ConfDir = GlobalData.gConfDirectory
- GenFdsGlobalVariable.EnableGenfdsMultiThread = GlobalData.gEnableGenfdsMultiThread
- for Arch in ArchList:
- GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.normpath(
- os.path.join(GlobalData.gWorkspace,
- WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
- GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory,
- GlobalData.gGlobalDefines['TARGET'] +'_' + GlobalData.gGlobalDefines['TOOLCHAIN']))
- GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = os.path.normpath(
- WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
- GlobalData.gGlobalDefines['TARGET'], GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory)
- GenFdsGlobalVariable.PlatformName = WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
- GlobalData.gGlobalDefines['TARGET'],
- GlobalData.gGlobalDefines['TOOLCHAIN']].PlatformName
- GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
- if not os.path.exists(GenFdsGlobalVariable.FvDir):
- os.makedirs(GenFdsGlobalVariable.FvDir)
- GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
- if not os.path.exists(GenFdsGlobalVariable.FfsDir):
- os.makedirs(GenFdsGlobalVariable.FfsDir)
-
- #
- # Create FV Address inf file
- #
- GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
- FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
- #
- # Add [Options]
- #
- FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
- BsAddress = '0'
- for Arch in ArchList:
- BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
- GlobalData.gGlobalDefines['TARGET'],
- GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress
- if BsAddress:
- break
-
- FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
- BsAddress + \
- DataType.TAB_LINE_BREAK)
-
- RtAddress = '0'
- for Arch in reversed(ArchList):
- temp = GenFdsGlobalVariable.WorkSpace.BuildObject[
- GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
- GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress
- if temp:
- RtAddress = temp
- break
-
- FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
- RtAddress + \
- DataType.TAB_LINE_BREAK)
-
- FvAddressFile.close()
-
- ## ReplaceWorkspaceMacro()
- #
- # @param String String that may contain macro
- #
- @staticmethod
- def ReplaceWorkspaceMacro(String):
- String = mws.handleWsMacro(String)
- Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
- if os.path.exists(Str):
- if not os.path.isabs(Str):
- Str = os.path.abspath(Str)
- else:
- Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String)
- return os.path.normpath(Str)
-
- ## Check if the input files are newer than output files
- #
- # @param Output Path of output file
- # @param Input Path list of input files
- #
- # @retval True if Output doesn't exist, or any Input is newer
- # @retval False if all Input is older than Output
- #
- @staticmethod
- def NeedsUpdate(Output, Input):
- if not os.path.exists(Output):
- return True
- # always update "Output" if no "Input" given
- if not Input:
- return True
-
- # if fdf file is changed after the 'Output" is generated, update the 'Output'
- OutputTime = os.path.getmtime(Output)
- if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime:
- return True
-
- for F in Input:
- # always update "Output" if any "Input" doesn't exist
- if not os.path.exists(F):
- return True
- # always update "Output" if any "Input" is newer than "Output"
- if os.path.getmtime(F) > OutputTime:
- return True
- return False
-
- @staticmethod
- def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
- GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=[], BuildNumber=None, DummyFile=None, IsMakefile=False):
- Cmd = ["GenSec"]
- if Type:
- Cmd += ("-s", Type)
- if CompressionType:
- Cmd += ("-c", CompressionType)
- if Guid:
- Cmd += ("-g", Guid)
- if DummyFile:
- Cmd += ("--dummy", DummyFile)
- if GuidHdrLen:
- Cmd += ("-l", GuidHdrLen)
- #Add each guided attribute
- for Attr in GuidAttr:
- Cmd += ("-r", Attr)
- #Section Align is only for dummy section without section type
- for SecAlign in InputAlign:
- Cmd += ("--sectionalign", SecAlign)
-
- CommandFile = Output + '.txt'
- if Ui:
- if IsMakefile:
- if Ui == "$(MODULE_NAME)":
- Cmd += ('-n', Ui)
- else:
- Cmd += ("-n", '"' + Ui + '"')
- Cmd += ("-o", Output)
- if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
- else:
- SectionData = array('B', [0, 0, 0, 0])
- SectionData.fromlist(array('B',Ui.encode('utf-16-le')).tolist())
- SectionData.append(0)
- SectionData.append(0)
- Len = len(SectionData)
- GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
-
-
- DirName = os.path.dirname(Output)
- if not CreateDirectory(DirName):
- EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)
- else:
- if DirName == '':
- DirName = os.getcwd()
- if not os.access(DirName, os.W_OK):
- EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)
-
- try:
- with open(Output, "wb") as Fd:
- SectionData.tofile(Fd)
- Fd.flush()
- except IOError as X:
- EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)
-
- elif Ver:
- Cmd += ("-n", Ver)
- if BuildNumber:
- Cmd += ("-j", BuildNumber)
- Cmd += ("-o", Output)
-
- SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
- if IsMakefile:
- if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
- else:
- if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
- return
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
- else:
- Cmd += ("-o", Output)
- Cmd += Input
-
- SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
- if IsMakefile:
- if sys.platform == "win32":
- Cmd = ['if', 'exist', Input[0]] + Cmd
- else:
- Cmd = ['-test', '-e', Input[0], "&&"] + Cmd
- if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
- elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
- if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and
- GenFdsGlobalVariable.LargeFileInFvFlags):
- GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True
-
- @staticmethod
- def GetAlignment (AlignString):
- if not AlignString:
- return 0
- if AlignString.endswith('K'):
- return int (AlignString.rstrip('K')) * 1024
- if AlignString.endswith('M'):
- return int (AlignString.rstrip('M')) * 1024 * 1024
- if AlignString.endswith('G'):
- return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024
- return int (AlignString)
-
- @staticmethod
- def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
- SectionAlign=None, MakefilePath=None):
- Cmd = ["GenFfs", "-t", Type, "-g", Guid]
- mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
- if Fixed == True:
- Cmd.append("-x")
- if CheckSum:
- Cmd.append("-s")
- if Align:
- if Align not in mFfsValidAlign:
- Align = GenFdsGlobalVariable.GetAlignment (Align)
- for index in range(0, len(mFfsValidAlign) - 1):
- if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))):
- break
- Align = mFfsValidAlign[index + 1]
- Cmd += ("-a", Align)
-
- Cmd += ("-o", Output)
- for I in range(0, len(Input)):
- if MakefilePath:
- Cmd += ("-oi", Input[I])
- else:
- Cmd += ("-i", Input[I])
- if SectionAlign and SectionAlign[I]:
- Cmd += ("-n", SectionAlign[I])
-
- CommandFile = Output + '.txt'
- SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
-
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
- if MakefilePath:
- if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict:
- GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath
- GenFdsGlobalVariable.SecCmdList = []
- GenFdsGlobalVariable.CopyList = []
- else:
- if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
- return
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
-
- @staticmethod
- def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
- AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
- if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
- return
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
-
- Cmd = ["GenFv"]
- if BaseAddress:
- Cmd += ("-r", BaseAddress)
-
- if ForceRebase == False:
- Cmd += ("-F", "FALSE")
- elif ForceRebase == True:
- Cmd += ("-F", "TRUE")
-
- if Capsule:
- Cmd.append("-c")
- if Dump:
- Cmd.append("-p")
- if AddressFile:
- Cmd += ("-a", AddressFile)
- if MapFile:
- Cmd += ("-m", MapFile)
- if FileSystemGuid:
- Cmd += ("-g", FileSystemGuid)
- Cmd += ("-o", Output)
- for I in Input:
- Cmd += ("-i", I)
-
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
-
- @staticmethod
- def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
- Strip=False, Replace=False, TimeStamp=None, Join=False,
- Align=None, Padding=None, Convert=False, IsMakefile=False):
- if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
- return
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
-
- Cmd = ["GenFw"]
- if Type.lower() == "te":
- Cmd.append("-t")
- if SubType:
- Cmd += ("-e", SubType)
- if TimeStamp:
- Cmd += ("-s", TimeStamp)
- if Align:
- Cmd += ("-a", Align)
- if Padding:
- Cmd += ("-p", Padding)
- if Zero:
- Cmd.append("-z")
- if Strip:
- Cmd.append("-l")
- if Replace:
- Cmd.append("-r")
- if Join:
- Cmd.append("-j")
- if Convert:
- Cmd.append("-m")
- Cmd += ("-o", Output)
- Cmd += Input
- if IsMakefile:
- if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
- else:
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
-
- @staticmethod
- def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
- Revision=None, DeviceId=None, VendorId=None, IsMakefile=False):
- InputList = []
- Cmd = ["EfiRom"]
- if EfiInput:
-
- if Compress:
- Cmd.append("-ec")
- else:
- Cmd.append("-e")
-
- for EfiFile in EfiInput:
- Cmd.append(EfiFile)
- InputList.append (EfiFile)
-
- if BinaryInput:
- Cmd.append("-b")
- for BinFile in BinaryInput:
- Cmd.append(BinFile)
- InputList.append (BinFile)
-
- # Check List
- if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile:
- return
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
-
- if ClassCode:
- Cmd += ("-l", ClassCode)
- if Revision:
- Cmd += ("-r", Revision)
- if DeviceId:
- Cmd += ("-i", DeviceId)
- if VendorId:
- Cmd += ("-f", VendorId)
-
- Cmd += ("-o", Output)
- if IsMakefile:
- if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
- else:
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
-
- @staticmethod
- def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False):
- if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
- return
- GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
-
- Cmd = [ToolPath, ]
- Cmd += Options.split(' ')
- Cmd += ("-o", Output)
- Cmd += Input
- if IsMakefile:
- if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
- GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
- else:
- GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
-
- @staticmethod
- def CallExternalTool (cmd, errorMess, returnValue=[]):
-
- if type(cmd) not in (tuple, list):
- GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
-
- if GenFdsGlobalVariable.DebugLevel != -1:
- cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
- GenFdsGlobalVariable.InfLogger (cmd)
-
- if GenFdsGlobalVariable.VerboseMode:
- cmd += ('-v',)
- GenFdsGlobalVariable.InfLogger (cmd)
- else:
- stdout.write ('#')
- stdout.flush()
- GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
- if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
- stdout.write('\n')
-
- try:
- PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True)
- except Exception as X:
- EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
- (out, error) = PopenObject.communicate()
-
- while PopenObject.returncode is None:
- PopenObject.wait()
- if returnValue != [] and returnValue[0] != 0:
- #get command return value
- returnValue[0] = PopenObject.returncode
- return
- if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
- GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
- GenFdsGlobalVariable.InfLogger(out.decode(encoding='utf-8', errors='ignore'))
- GenFdsGlobalVariable.InfLogger(error.decode(encoding='utf-8', errors='ignore'))
- if PopenObject.returncode != 0:
- print("###", cmd)
- EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
-
- @staticmethod
- def VerboseLogger (msg):
- EdkLogger.verbose(msg)
-
- @staticmethod
- def InfLogger (msg):
- EdkLogger.info(msg)
-
- @staticmethod
- def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
- EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
-
- @staticmethod
- def DebugLogger (Level, msg):
- EdkLogger.debug(Level, msg)
-
- ## MacroExtend()
- #
- # @param Str String that may contain macro
- # @param MacroDict Dictionary that contains macro value pair
- #
- @staticmethod
- def MacroExtend (Str, MacroDict=None, Arch=DataType.TAB_COMMON):
- if Str is None:
- return None
-
- Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir,
-# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
- '$(TARGET)': GenFdsGlobalVariable.TargetName,
- '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag,
- '$(SPACE)': ' '
- }
-
- if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList:
- OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
- else:
- OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
-
- Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
-
- if MacroDict:
- Dict.update(MacroDict)
-
- for key in Dict:
- if Str.find(key) >= 0:
- Str = Str.replace (key, Dict[key])
-
- if Str.find('$(ARCH)') >= 0:
- if len(GenFdsGlobalVariable.ArchList) == 1:
- Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
- else:
- EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
-
- return Str
-
- ## GetPcdValue()
- #
- # @param PcdPattern pattern that labels a PCD.
- #
- @staticmethod
- def GetPcdValue (PcdPattern):
- if PcdPattern is None:
- return None
- if PcdPattern.startswith('PCD('):
- PcdPair = PcdPattern[4:].rstrip(')').strip().split('.')
- else:
- PcdPair = PcdPattern.strip().split('.')
- TokenSpace = PcdPair[0]
- TokenCName = PcdPair[1]
-
- for Arch in GenFdsGlobalVariable.ArchList:
- Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
- PcdDict = Platform.Pcds
- for Key in PcdDict:
- PcdObj = PcdDict[Key]
- if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
- if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
- EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
- if PcdObj.DatumType != DataType.TAB_VOID:
- EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
-
- return PcdObj.DefaultValue
-
- for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
- Arch,
- GenFdsGlobalVariable.TargetName,
- GenFdsGlobalVariable.ToolChainTag):
- PcdDict = Package.Pcds
- for Key in PcdDict:
- PcdObj = PcdDict[Key]
- if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
- if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
- EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
- if PcdObj.DatumType != DataType.TAB_VOID:
- EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
-
- return PcdObj.DefaultValue
-
- return ''
-
-## FindExtendTool()
-#
-# Find location of tools to process data
-#
-# @param KeyStringList Filter for inputs of section generation
-# @param CurrentArchList Arch list
-# @param NameGuid The Guid name
-#
-def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
- if GenFdsGlobalVariable.GuidToolDefinition:
- if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
- return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
-
- ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
- ToolDef = ToolDefObj.ToolDef
- ToolDb = ToolDef.ToolsDefTxtDatabase
- # if user not specify filter, try to deduce it from global data.
- if KeyStringList is None or KeyStringList == []:
- Target = GenFdsGlobalVariable.TargetName
- ToolChain = GenFdsGlobalVariable.ToolChainTag
- if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
- EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
- KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
- for Arch in CurrentArchList:
- if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
- KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
-
- ToolPathTmp = None
- ToolOption = None
- for Arch in CurrentArchList:
- MatchItem = None
- MatchPathItem = None
- MatchOptionsItem = None
- for KeyString in KeyStringList:
- KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
- if KeyStringArch != Arch:
- continue
- for Item in ToolDef.ToolsDefTxtDictionary:
- if len(Item.split('_')) < 5:
- continue
- ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
- if ItemTarget == DataType.TAB_STAR:
- ItemTarget = KeyStringBuildTarget
- if ItemToolChain == DataType.TAB_STAR:
- ItemToolChain = KeyStringToolChain
- if ItemArch == DataType.TAB_STAR:
- ItemArch = KeyStringArch
- if ItemTarget != KeyStringBuildTarget:
- continue
- if ItemToolChain != KeyStringToolChain:
- continue
- if ItemArch != KeyStringArch:
- continue
- if ItemAttr != DataType.TAB_GUID:
- # Not GUID attribute
- continue
- if ToolDef.ToolsDefTxtDictionary[Item].lower() != NameGuid.lower():
- # No GUID value match
- continue
- if MatchItem:
- if MatchItem.split('_')[3] == ItemTool:
- # Tool name is the same
- continue
- if CalculatePriorityValue(MatchItem) > CalculatePriorityValue(Item):
- # Current MatchItem is higher priority than new match item
- continue
- MatchItem = Item
- if not MatchItem:
- continue
- ToolName = MatchItem.split('_')[3]
- for Item in ToolDef.ToolsDefTxtDictionary:
- if len(Item.split('_')) < 5:
- continue
- ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
- if ItemTarget == DataType.TAB_STAR:
- ItemTarget = KeyStringBuildTarget
- if ItemToolChain == DataType.TAB_STAR:
- ItemToolChain = KeyStringToolChain
- if ItemArch == DataType.TAB_STAR:
- ItemArch = KeyStringArch
- if ItemTarget != KeyStringBuildTarget:
- continue
- if ItemToolChain != KeyStringToolChain:
- continue
- if ItemArch != KeyStringArch:
- continue
- if ItemTool != ToolName:
- continue
- if ItemAttr == 'PATH':
- if MatchPathItem:
- if CalculatePriorityValue(MatchPathItem) <= CalculatePriorityValue(Item):
- MatchPathItem = Item
- else:
- MatchPathItem = Item
- if ItemAttr == 'FLAGS':
- if MatchOptionsItem:
- if CalculatePriorityValue(MatchOptionsItem) <= CalculatePriorityValue(Item):
- MatchOptionsItem = Item
- else:
- MatchOptionsItem = Item
- if MatchPathItem:
- ToolPathTmp = ToolDef.ToolsDefTxtDictionary[MatchPathItem]
- if MatchOptionsItem:
- ToolOption = ToolDef.ToolsDefTxtDictionary[MatchOptionsItem]
-
- for Arch in CurrentArchList:
- MatchItem = None
- MatchPathItem = None
- MatchOptionsItem = None
- for KeyString in KeyStringList:
- KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
- if KeyStringArch != Arch:
- continue
- Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, KeyStringBuildTarget, KeyStringToolChain]
- for Item in Platform.BuildOptions:
- if len(Item[1].split('_')) < 5:
- continue
- ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
- if ItemTarget == DataType.TAB_STAR:
- ItemTarget = KeyStringBuildTarget
- if ItemToolChain == DataType.TAB_STAR:
- ItemToolChain = KeyStringToolChain
- if ItemArch == DataType.TAB_STAR:
- ItemArch = KeyStringArch
- if ItemTarget != KeyStringBuildTarget:
- continue
- if ItemToolChain != KeyStringToolChain:
- continue
- if ItemArch != KeyStringArch:
- continue
- if ItemAttr != DataType.TAB_GUID:
- # Not GUID attribute match
- continue
- if Platform.BuildOptions[Item].lower() != NameGuid.lower():
- # No GUID value match
- continue
- if MatchItem:
- if MatchItem[1].split('_')[3] == ItemTool:
- # Tool name is the same
- continue
- if CalculatePriorityValue(MatchItem[1]) > CalculatePriorityValue(Item[1]):
- # Current MatchItem is higher priority than new match item
- continue
- MatchItem = Item
- if not MatchItem:
- continue
- ToolName = MatchItem[1].split('_')[3]
- for Item in Platform.BuildOptions:
- if len(Item[1].split('_')) < 5:
- continue
- ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
- if ItemTarget == DataType.TAB_STAR:
- ItemTarget = KeyStringBuildTarget
- if ItemToolChain == DataType.TAB_STAR:
- ItemToolChain = KeyStringToolChain
- if ItemArch == DataType.TAB_STAR:
- ItemArch = KeyStringArch
- if ItemTarget != KeyStringBuildTarget:
- continue
- if ItemToolChain != KeyStringToolChain:
- continue
- if ItemArch != KeyStringArch:
- continue
- if ItemTool != ToolName:
- continue
- if ItemAttr == 'PATH':
- if MatchPathItem:
- if CalculatePriorityValue(MatchPathItem[1]) <= CalculatePriorityValue(Item[1]):
- MatchPathItem = Item
- else:
- MatchPathItem = Item
- if ItemAttr == 'FLAGS':
- if MatchOptionsItem:
- if CalculatePriorityValue(MatchOptionsItem[1]) <= CalculatePriorityValue(Item[1]):
- MatchOptionsItem = Item
- else:
- MatchOptionsItem = Item
- if MatchPathItem:
- ToolPathTmp = Platform.BuildOptions[MatchPathItem]
- if MatchOptionsItem:
- ToolOption = Platform.BuildOptions[MatchOptionsItem]
- GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
- return ToolPathTmp, ToolOption
+## @file +# Global variables for GenFds +# +# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## +# Import Modules +# +from __future__ import print_function +from __future__ import absolute_import + +import Common.LongFilePathOs as os +import sys +from sys import stdout +from subprocess import PIPE,Popen +from struct import Struct +from array import array + +from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR +from Common import EdkLogger +from Common.Misc import SaveFileOnChange + +from Common.TargetTxtClassObject import TargetTxtDict +from Common.ToolDefClassObject import ToolDefDict,gDefaultToolsDefFile +from AutoGen.BuildEngine import ToolBuildRule +import Common.DataType as DataType +from Common.Misc import PathClass,CreateDirectory +from Common.LongFilePathSupport import OpenLongFilePath as open +from Common.MultipleWorkspace import MultipleWorkspace as mws +import Common.GlobalData as GlobalData +from Common.BuildToolError import * +from AutoGen.AutoGen import CalculatePriorityValue + +## Global variables +# +# +class GenFdsGlobalVariable: + FvDir = '' + OutputDirDict = {} + BinDir = '' + # will be FvDir + os.sep + 'Ffs' + FfsDir = '' + FdfParser = None + LibDir = '' + WorkSpace = None + WorkSpaceDir = '' + ConfDir = '' + OutputDirFromDscDict = {} + TargetName = '' + ToolChainTag = '' + RuleDict = {} + ArchList = None + ActivePlatform = None + FvAddressFileName = '' + VerboseMode = False + DebugLevel = -1 + SharpCounter = 0 + SharpNumberPerLine = 40 + FdfFile = '' + FdfFileTimeStamp = 0 + FixedLoadAddress = False + PlatformName = '' + + BuildRuleFamily = DataType.TAB_COMPILER_MSFT + ToolChainFamily = DataType.TAB_COMPILER_MSFT + __BuildRuleDatabase = None + GuidToolDefinition = {} + FfsCmdDict = {} + SecCmdList = [] + CopyList = [] + ModuleFile = '' + EnableGenfdsMultiThread = True + + # + # The list whose element are flags to indicate if large FFS or SECTION files exist in FV. + # At the beginning of each generation of FV, false flag is appended to the list, + # after the call to GenerateSection returns, check the size of the output file, + # if it is greater than 0xFFFFFF, the tail flag in list is set to true, + # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv. + # At the end of generation of FV, pop the flag. + # List is used as a stack to handle nested FV generation. + # + LargeFileInFvFlags = [] + EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A' + LARGE_FILE_SIZE = 0x1000000 + + SectionHeader = Struct("3B 1B") + + # FvName, FdName, CapName in FDF, Image file name + ImageBinDict = {} + + ## LoadBuildRule + # + @staticmethod + def _LoadBuildRule(): + if GenFdsGlobalVariable.__BuildRuleDatabase: + return GenFdsGlobalVariable.__BuildRuleDatabase + BuildRule = ToolBuildRule() + GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule.ToolBuildRule + TargetObj = TargetTxtDict() + ToolDefinitionFile = TargetObj.Target.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF] + if ToolDefinitionFile == '': + ToolDefinitionFile = os.path.join('Conf', gDefaultToolsDefFile) + if os.path.isfile(ToolDefinitionFile): + ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf"))) + ToolDefinition = ToolDefObj.ToolDef.ToolsDefTxtDatabase + if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \ + and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \ + and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]: + GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag] + + if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \ + and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \ + and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]: + GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag] + return GenFdsGlobalVariable.__BuildRuleDatabase + + ## GetBuildRules + # @param Inf: object of InfBuildData + # @param Arch: current arch + # + @staticmethod + def GetBuildRules(Inf, Arch): + if not Arch: + Arch = DataType.TAB_COMMON + + if not Arch in GenFdsGlobalVariable.OutputDirDict: + return {} + + BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule() + if not BuildRuleDatabase: + return {} + + PathClassObj = PathClass(Inf.MetaFile.File, + GenFdsGlobalVariable.WorkSpaceDir) + BuildDir = os.path.join( + GenFdsGlobalVariable.OutputDirDict[Arch], + Arch, + PathClassObj.SubDir, + PathClassObj.BaseName + ) + BinDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) + Macro = { + "WORKSPACE":GenFdsGlobalVariable.WorkSpaceDir, + "MODULE_NAME":Inf.BaseName, + "MODULE_GUID":Inf.Guid, + "MODULE_VERSION":Inf.Version, + "MODULE_TYPE":Inf.ModuleType, + "MODULE_FILE":str(PathClassObj), + "MODULE_FILE_BASE_NAME":PathClassObj.BaseName, + "MODULE_RELATIVE_DIR":PathClassObj.SubDir, + "MODULE_DIR":PathClassObj.SubDir, + "BASE_NAME":Inf.BaseName, + "ARCH":Arch, + "TOOLCHAIN":GenFdsGlobalVariable.ToolChainTag, + "TOOLCHAIN_TAG":GenFdsGlobalVariable.ToolChainTag, + "TOOL_CHAIN_TAG":GenFdsGlobalVariable.ToolChainTag, + "TARGET":GenFdsGlobalVariable.TargetName, + "BUILD_DIR":GenFdsGlobalVariable.OutputDirDict[Arch], + "BIN_DIR":BinDir, + "LIB_DIR":BinDir, + "MODULE_BUILD_DIR":BuildDir, + "OUTPUT_DIR":os.path.join(BuildDir, "OUTPUT"), + "DEBUG_DIR":os.path.join(BuildDir, "DEBUG") + } + + BuildRules = {} + for Type in BuildRuleDatabase.FileTypeList: + #first try getting build rule by BuildRuleFamily + RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily] + if not RuleObject: + # build type is always module type, but ... + if Inf.ModuleType != Inf.BuildType: + RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily] + #second try getting build rule by ToolChainFamily + if not RuleObject: + RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily] + if not RuleObject: + # build type is always module type, but ... + if Inf.ModuleType != Inf.BuildType: + RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily] + if not RuleObject: + continue + RuleObject = RuleObject.Instantiate(Macro) + BuildRules[Type] = RuleObject + for Ext in RuleObject.SourceFileExtList: + BuildRules[Ext] = RuleObject + return BuildRules + + ## GetModuleCodaTargetList + # + # @param Inf: object of InfBuildData + # @param Arch: current arch + # + @staticmethod + def GetModuleCodaTargetList(Inf, Arch): + BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch) + if not BuildRules: + return [] + + TargetList = set() + FileList = [] + + if not Inf.IsBinaryModule: + for File in Inf.Sources: + if File.TagName in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainTag} and \ + File.ToolChainFamily in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainFamily}: + FileList.append((File, DataType.TAB_UNKNOWN_FILE)) + + for File in Inf.Binaries: + if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}: + FileList.append((File, File.Type)) + + for File, FileType in FileList: + LastTarget = None + RuleChain = [] + SourceList = [File] + Index = 0 + while Index < len(SourceList): + Source = SourceList[Index] + Index = Index + 1 + + if File.IsBinary and File == Source and Inf.Binaries and File in Inf.Binaries: + # Skip all files that are not binary libraries + if not Inf.LibraryClass: + continue + RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE] + elif FileType in BuildRules: + RuleObject = BuildRules[FileType] + elif Source.Ext in BuildRules: + RuleObject = BuildRules[Source.Ext] + else: + # stop at no more rules + if LastTarget: + TargetList.add(str(LastTarget)) + break + + FileType = RuleObject.SourceFileType + + # stop at STATIC_LIBRARY for library + if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY: + if LastTarget: + TargetList.add(str(LastTarget)) + break + + Target = RuleObject.Apply(Source) + if not Target: + if LastTarget: + TargetList.add(str(LastTarget)) + break + elif not Target.Outputs: + # Only do build for target with outputs + TargetList.add(str(Target)) + + # to avoid cyclic rule + if FileType in RuleChain: + break + + RuleChain.append(FileType) + SourceList.extend(Target.Outputs) + LastTarget = Target + FileType = DataType.TAB_UNKNOWN_FILE + for Cmd in Target.Commands: + if "$(CP)" == Cmd.split()[0]: + CpTarget = Cmd.split()[2] + TargetList.add(CpTarget) + + return list(TargetList) + + ## SetDir() + # + # @param OutputDir Output directory + # @param FdfParser FDF contents parser + # @param Workspace The directory of workspace + # @param ArchList The Arch list of platform + # + @staticmethod + def SetDir (OutputDir, FdfParser, WorkSpace, ArchList): + GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir) + GenFdsGlobalVariable.FdfParser = FdfParser + GenFdsGlobalVariable.WorkSpace = WorkSpace + GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY) + if not os.path.exists(GenFdsGlobalVariable.FvDir): + os.makedirs(GenFdsGlobalVariable.FvDir) + GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') + if not os.path.exists(GenFdsGlobalVariable.FfsDir): + os.makedirs(GenFdsGlobalVariable.FfsDir) + + # + # Create FV Address inf file + # + GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') + FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w') + # + # Add [Options] + # + FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK) + BsAddress = '0' + for Arch in ArchList: + if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress: + BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress + break + + FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \ + BsAddress + \ + DataType.TAB_LINE_BREAK) + + RtAddress = '0' + for Arch in reversed(ArchList): + temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress + if temp: + RtAddress = temp + break + + FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ + RtAddress + \ + DataType.TAB_LINE_BREAK) + + FvAddressFile.close() + + @staticmethod + def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData): + GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile + GenFdsGlobalVariable.FdfParser = FdfParser + GenFdsGlobalVariable.WorkSpace = WorkSpace.Db + GenFdsGlobalVariable.ArchList = ArchList + GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"] + GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"] + GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform + GenFdsGlobalVariable.ConfDir = GlobalData.gConfDirectory + GenFdsGlobalVariable.EnableGenfdsMultiThread = GlobalData.gEnableGenfdsMultiThread + for Arch in ArchList: + GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.normpath( + os.path.join(GlobalData.gWorkspace, + WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'], + GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory, + GlobalData.gGlobalDefines['TARGET'] +'_' + GlobalData.gGlobalDefines['TOOLCHAIN'])) + GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = os.path.normpath( + WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, + GlobalData.gGlobalDefines['TARGET'], GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory) + GenFdsGlobalVariable.PlatformName = WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, + GlobalData.gGlobalDefines['TARGET'], + GlobalData.gGlobalDefines['TOOLCHAIN']].PlatformName + GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY) + if not os.path.exists(GenFdsGlobalVariable.FvDir): + os.makedirs(GenFdsGlobalVariable.FvDir) + GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs') + if not os.path.exists(GenFdsGlobalVariable.FfsDir): + os.makedirs(GenFdsGlobalVariable.FfsDir) + + # + # Create FV Address inf file + # + GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') + FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w') + # + # Add [Options] + # + FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK) + BsAddress = '0' + for Arch in ArchList: + BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, + GlobalData.gGlobalDefines['TARGET'], + GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress + if BsAddress: + break + + FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \ + BsAddress + \ + DataType.TAB_LINE_BREAK) + + RtAddress = '0' + for Arch in reversed(ArchList): + temp = GenFdsGlobalVariable.WorkSpace.BuildObject[ + GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'], + GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress + if temp: + RtAddress = temp + break + + FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ + RtAddress + \ + DataType.TAB_LINE_BREAK) + + FvAddressFile.close() + + ## ReplaceWorkspaceMacro() + # + # @param String String that may contain macro + # + @staticmethod + def ReplaceWorkspaceMacro(String): + String = mws.handleWsMacro(String) + Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir) + if os.path.exists(Str): + if not os.path.isabs(Str): + Str = os.path.abspath(Str) + else: + Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String) + return os.path.normpath(Str) + + ## Check if the input files are newer than output files + # + # @param Output Path of output file + # @param Input Path list of input files + # + # @retval True if Output doesn't exist, or any Input is newer + # @retval False if all Input is older than Output + # + @staticmethod + def NeedsUpdate(Output, Input): + if not os.path.exists(Output): + return True + # always update "Output" if no "Input" given + if not Input: + return True + + # if fdf file is changed after the 'Output" is generated, update the 'Output' + OutputTime = os.path.getmtime(Output) + if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime: + return True + + for F in Input: + # always update "Output" if any "Input" doesn't exist + if not os.path.exists(F): + return True + # always update "Output" if any "Input" is newer than "Output" + if os.path.getmtime(F) > OutputTime: + return True + return False + + @staticmethod + def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None, + GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=[], BuildNumber=None, DummyFile=None, IsMakefile=False): + Cmd = ["GenSec"] + if Type: + Cmd += ("-s", Type) + if CompressionType: + Cmd += ("-c", CompressionType) + if Guid: + Cmd += ("-g", Guid) + if DummyFile: + Cmd += ("--dummy", DummyFile) + if GuidHdrLen: + Cmd += ("-l", GuidHdrLen) + #Add each guided attribute + for Attr in GuidAttr: + Cmd += ("-r", Attr) + #Section Align is only for dummy section without section type + for SecAlign in InputAlign: + Cmd += ("--sectionalign", SecAlign) + + CommandFile = Output + '.txt' + if Ui: + if IsMakefile: + if Ui == "$(MODULE_NAME)": + Cmd += ('-n', Ui) + else: + Cmd += ("-n", '"' + Ui + '"') + Cmd += ("-o", Output) + if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) + else: + SectionData = array('B', [0, 0, 0, 0]) + SectionData.fromlist(array('B',Ui.encode('utf-16-le')).tolist()) + SectionData.append(0) + SectionData.append(0) + Len = len(SectionData) + GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15) + + + DirName = os.path.dirname(Output) + if not CreateDirectory(DirName): + EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName) + else: + if DirName == '': + DirName = os.getcwd() + if not os.access(DirName, os.W_OK): + EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName) + + try: + with open(Output, "wb") as Fd: + SectionData.tofile(Fd) + Fd.flush() + except IOError as X: + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X) + + elif Ver: + Cmd += ("-n", Ver) + if BuildNumber: + Cmd += ("-j", BuildNumber) + Cmd += ("-o", Output) + + SaveFileOnChange(CommandFile, ' '.join(Cmd), False) + if IsMakefile: + if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) + else: + if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): + return + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") + else: + Cmd += ("-o", Output) + Cmd += Input + + SaveFileOnChange(CommandFile, ' '.join(Cmd), False) + if IsMakefile: + if sys.platform == "win32": + Cmd = ['if', 'exist', Input[0]] + Cmd + else: + Cmd = ['-test', '-e', Input[0], "&&"] + Cmd + if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip()) + elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") + if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and + GenFdsGlobalVariable.LargeFileInFvFlags): + GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True + + @staticmethod + def GetAlignment (AlignString): + if not AlignString: + return 0 + if AlignString.endswith('K'): + return int (AlignString.rstrip('K')) * 1024 + if AlignString.endswith('M'): + return int (AlignString.rstrip('M')) * 1024 * 1024 + if AlignString.endswith('G'): + return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024 + return int (AlignString) + + @staticmethod + def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None, + SectionAlign=None, MakefilePath=None): + Cmd = ["GenFfs", "-t", Type, "-g", Guid] + mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"] + if Fixed == True: + Cmd.append("-x") + if CheckSum: + Cmd.append("-s") + if Align: + if Align not in mFfsValidAlign: + Align = GenFdsGlobalVariable.GetAlignment (Align) + for index in range(0, len(mFfsValidAlign) - 1): + if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))): + break + Align = mFfsValidAlign[index + 1] + Cmd += ("-a", Align) + + Cmd += ("-o", Output) + for I in range(0, len(Input)): + if MakefilePath: + Cmd += ("-oi", Input[I]) + else: + Cmd += ("-i", Input[I]) + if SectionAlign and SectionAlign[I]: + Cmd += ("-n", SectionAlign[I]) + + CommandFile = Output + '.txt' + SaveFileOnChange(CommandFile, ' '.join(Cmd), False) + + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + if MakefilePath: + if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict: + GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath + GenFdsGlobalVariable.SecCmdList = [] + GenFdsGlobalVariable.CopyList = [] + else: + if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): + return + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS") + + @staticmethod + def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False, + AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenFv"] + if BaseAddress: + Cmd += ("-r", BaseAddress) + + if ForceRebase == False: + Cmd += ("-F", "FALSE") + elif ForceRebase == True: + Cmd += ("-F", "TRUE") + + if Capsule: + Cmd.append("-c") + if Dump: + Cmd.append("-p") + if AddressFile: + Cmd += ("-a", AddressFile) + if MapFile: + Cmd += ("-m", MapFile) + if FileSystemGuid: + Cmd += ("-g", FileSystemGuid) + Cmd += ("-o", Output) + for I in Input: + Cmd += ("-i", I) + + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV") + + @staticmethod + def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False, + Strip=False, Replace=False, TimeStamp=None, Join=False, + Align=None, Padding=None, Convert=False, IsMakefile=False): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile: + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = ["GenFw"] + if Type.lower() == "te": + Cmd.append("-t") + if SubType: + Cmd += ("-e", SubType) + if TimeStamp: + Cmd += ("-s", TimeStamp) + if Align: + Cmd += ("-a", Align) + if Padding: + Cmd += ("-p", Padding) + if Zero: + Cmd.append("-z") + if Strip: + Cmd.append("-l") + if Replace: + Cmd.append("-r") + if Join: + Cmd.append("-j") + if Convert: + Cmd.append("-m") + Cmd += ("-o", Output) + Cmd += Input + if IsMakefile: + if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) + else: + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image") + + @staticmethod + def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None, + Revision=None, DeviceId=None, VendorId=None, IsMakefile=False): + InputList = [] + Cmd = ["EfiRom"] + if EfiInput: + + if Compress: + Cmd.append("-ec") + else: + Cmd.append("-e") + + for EfiFile in EfiInput: + Cmd.append(EfiFile) + InputList.append (EfiFile) + + if BinaryInput: + Cmd.append("-b") + for BinFile in BinaryInput: + Cmd.append(BinFile) + InputList.append (BinFile) + + # Check List + if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile: + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList)) + + if ClassCode: + Cmd += ("-l", ClassCode) + if Revision: + Cmd += ("-r", Revision) + if DeviceId: + Cmd += ("-i", DeviceId) + if VendorId: + Cmd += ("-f", VendorId) + + Cmd += ("-o", Output) + if IsMakefile: + if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) + else: + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom") + + @staticmethod + def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile: + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + Cmd = [ToolPath, ] + Cmd += Options.split(' ') + Cmd += ("-o", Output) + Cmd += Input + if IsMakefile: + if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList: + GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip()) + else: + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue) + + @staticmethod + def CallExternalTool (cmd, errorMess, returnValue=[]): + + if type(cmd) not in (tuple, list): + GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool") + + if GenFdsGlobalVariable.DebugLevel != -1: + cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel)) + GenFdsGlobalVariable.InfLogger (cmd) + + if GenFdsGlobalVariable.VerboseMode: + cmd += ('-v',) + GenFdsGlobalVariable.InfLogger (cmd) + else: + stdout.write ('#') + stdout.flush() + GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1 + if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0: + stdout.write('\n') + + try: + PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True) + except Exception as X: + EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) + (out, error) = PopenObject.communicate() + + while PopenObject.returncode is None: + PopenObject.wait() + if returnValue != [] and returnValue[0] != 0: + #get command return value + returnValue[0] = PopenObject.returncode + return + if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1: + GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode) + GenFdsGlobalVariable.InfLogger(out.decode(encoding='utf-8', errors='ignore')) + GenFdsGlobalVariable.InfLogger(error.decode(encoding='utf-8', errors='ignore')) + if PopenObject.returncode != 0: + print("###", cmd) + EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess) + + @staticmethod + def VerboseLogger (msg): + EdkLogger.verbose(msg) + + @staticmethod + def InfLogger (msg): + EdkLogger.info(msg) + + @staticmethod + def ErrorLogger (msg, File=None, Line=None, ExtraData=None): + EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData) + + @staticmethod + def DebugLogger (Level, msg): + EdkLogger.debug(Level, msg) + + ## MacroExtend() + # + # @param Str String that may contain macro + # @param MacroDict Dictionary that contains macro value pair + # + @staticmethod + def MacroExtend (Str, MacroDict=None, Arch=DataType.TAB_COMMON): + if Str is None: + return None + + Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir, +# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc, + '$(TARGET)': GenFdsGlobalVariable.TargetName, + '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag, + '$(SPACE)': ' ' + } + + if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList: + OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch] + else: + OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]] + + Dict['$(OUTPUT_DIRECTORY)'] = OutputDir + + if MacroDict: + Dict.update(MacroDict) + + for key in Dict: + if Str.find(key) >= 0: + Str = Str.replace (key, Dict[key]) + + if Str.find('$(ARCH)') >= 0: + if len(GenFdsGlobalVariable.ArchList) == 1: + Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0]) + else: + EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str) + + return Str + + ## GetPcdValue() + # + # @param PcdPattern pattern that labels a PCD. + # + @staticmethod + def GetPcdValue (PcdPattern): + if PcdPattern is None: + return None + if PcdPattern.startswith('PCD('): + PcdPair = PcdPattern[4:].rstrip(')').strip().split('.') + else: + PcdPair = PcdPattern.strip().split('.') + TokenSpace = PcdPair[0] + TokenCName = PcdPair[1] + + for Arch in GenFdsGlobalVariable.ArchList: + Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag] + PcdDict = Platform.Pcds + for Key in PcdDict: + PcdObj = PcdDict[Key] + if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): + if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD: + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) + if PcdObj.DatumType != DataType.TAB_VOID: + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) + + return PcdObj.DefaultValue + + for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, + Arch, + GenFdsGlobalVariable.TargetName, + GenFdsGlobalVariable.ToolChainTag): + PcdDict = Package.Pcds + for Key in PcdDict: + PcdObj = PcdDict[Key] + if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace): + if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD: + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) + if PcdObj.DatumType != DataType.TAB_VOID: + EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) + + return PcdObj.DefaultValue + + return '' + +## FindExtendTool() +# +# Find location of tools to process data +# +# @param KeyStringList Filter for inputs of section generation +# @param CurrentArchList Arch list +# @param NameGuid The Guid name +# +def FindExtendTool(KeyStringList, CurrentArchList, NameGuid): + if GenFdsGlobalVariable.GuidToolDefinition: + if NameGuid in GenFdsGlobalVariable.GuidToolDefinition: + return GenFdsGlobalVariable.GuidToolDefinition[NameGuid] + + ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf"))) + ToolDef = ToolDefObj.ToolDef + ToolDb = ToolDef.ToolsDefTxtDatabase + # if user not specify filter, try to deduce it from global data. + if KeyStringList is None or KeyStringList == []: + Target = GenFdsGlobalVariable.TargetName + ToolChain = GenFdsGlobalVariable.ToolChainTag + if ToolChain not in ToolDb['TOOL_CHAIN_TAG']: + EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain) + KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]] + for Arch in CurrentArchList: + if Target + '_' + ToolChain + '_' + Arch not in KeyStringList: + KeyStringList.append(Target + '_' + ToolChain + '_' + Arch) + + ToolPathTmp = None + ToolOption = None + for Arch in CurrentArchList: + MatchItem = None + MatchPathItem = None + MatchOptionsItem = None + for KeyString in KeyStringList: + KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_') + if KeyStringArch != Arch: + continue + for Item in ToolDef.ToolsDefTxtDictionary: + if len(Item.split('_')) < 5: + continue + ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_') + if ItemTarget == DataType.TAB_STAR: + ItemTarget = KeyStringBuildTarget + if ItemToolChain == DataType.TAB_STAR: + ItemToolChain = KeyStringToolChain + if ItemArch == DataType.TAB_STAR: + ItemArch = KeyStringArch + if ItemTarget != KeyStringBuildTarget: + continue + if ItemToolChain != KeyStringToolChain: + continue + if ItemArch != KeyStringArch: + continue + if ItemAttr != DataType.TAB_GUID: + # Not GUID attribute + continue + if ToolDef.ToolsDefTxtDictionary[Item].lower() != NameGuid.lower(): + # No GUID value match + continue + if MatchItem: + if MatchItem.split('_')[3] == ItemTool: + # Tool name is the same + continue + if CalculatePriorityValue(MatchItem) > CalculatePriorityValue(Item): + # Current MatchItem is higher priority than new match item + continue + MatchItem = Item + if not MatchItem: + continue + ToolName = MatchItem.split('_')[3] + for Item in ToolDef.ToolsDefTxtDictionary: + if len(Item.split('_')) < 5: + continue + ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_') + if ItemTarget == DataType.TAB_STAR: + ItemTarget = KeyStringBuildTarget + if ItemToolChain == DataType.TAB_STAR: + ItemToolChain = KeyStringToolChain + if ItemArch == DataType.TAB_STAR: + ItemArch = KeyStringArch + if ItemTarget != KeyStringBuildTarget: + continue + if ItemToolChain != KeyStringToolChain: + continue + if ItemArch != KeyStringArch: + continue + if ItemTool != ToolName: + continue + if ItemAttr == 'PATH': + if MatchPathItem: + if CalculatePriorityValue(MatchPathItem) <= CalculatePriorityValue(Item): + MatchPathItem = Item + else: + MatchPathItem = Item + if ItemAttr == 'FLAGS': + if MatchOptionsItem: + if CalculatePriorityValue(MatchOptionsItem) <= CalculatePriorityValue(Item): + MatchOptionsItem = Item + else: + MatchOptionsItem = Item + if MatchPathItem: + ToolPathTmp = ToolDef.ToolsDefTxtDictionary[MatchPathItem] + if MatchOptionsItem: + ToolOption = ToolDef.ToolsDefTxtDictionary[MatchOptionsItem] + + for Arch in CurrentArchList: + MatchItem = None + MatchPathItem = None + MatchOptionsItem = None + for KeyString in KeyStringList: + KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_') + if KeyStringArch != Arch: + continue + Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, KeyStringBuildTarget, KeyStringToolChain] + for Item in Platform.BuildOptions: + if len(Item[1].split('_')) < 5: + continue + ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_') + if ItemTarget == DataType.TAB_STAR: + ItemTarget = KeyStringBuildTarget + if ItemToolChain == DataType.TAB_STAR: + ItemToolChain = KeyStringToolChain + if ItemArch == DataType.TAB_STAR: + ItemArch = KeyStringArch + if ItemTarget != KeyStringBuildTarget: + continue + if ItemToolChain != KeyStringToolChain: + continue + if ItemArch != KeyStringArch: + continue + if ItemAttr != DataType.TAB_GUID: + # Not GUID attribute match + continue + if Platform.BuildOptions[Item].lower() != NameGuid.lower(): + # No GUID value match + continue + if MatchItem: + if MatchItem[1].split('_')[3] == ItemTool: + # Tool name is the same + continue + if CalculatePriorityValue(MatchItem[1]) > CalculatePriorityValue(Item[1]): + # Current MatchItem is higher priority than new match item + continue + MatchItem = Item + if not MatchItem: + continue + ToolName = MatchItem[1].split('_')[3] + for Item in Platform.BuildOptions: + if len(Item[1].split('_')) < 5: + continue + ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_') + if ItemTarget == DataType.TAB_STAR: + ItemTarget = KeyStringBuildTarget + if ItemToolChain == DataType.TAB_STAR: + ItemToolChain = KeyStringToolChain + if ItemArch == DataType.TAB_STAR: + ItemArch = KeyStringArch + if ItemTarget != KeyStringBuildTarget: + continue + if ItemToolChain != KeyStringToolChain: + continue + if ItemArch != KeyStringArch: + continue + if ItemTool != ToolName: + continue + if ItemAttr == 'PATH': + if MatchPathItem: + if CalculatePriorityValue(MatchPathItem[1]) <= CalculatePriorityValue(Item[1]): + MatchPathItem = Item + else: + MatchPathItem = Item + if ItemAttr == 'FLAGS': + if MatchOptionsItem: + if CalculatePriorityValue(MatchOptionsItem[1]) <= CalculatePriorityValue(Item[1]): + MatchOptionsItem = Item + else: + MatchOptionsItem = Item + if MatchPathItem: + ToolPathTmp = Platform.BuildOptions[MatchPathItem] + if MatchOptionsItem: + ToolOption = Platform.BuildOptions[MatchOptionsItem] + GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption) + return ToolPathTmp, ToolOption |
