Files
slimbootloader/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
T

921 lines
40 KiB
Python
Raw Normal View History

2018-09-13 16:11:07 -07:00
## @file
# Global variables for GenFds
#
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
2018-09-13 16:11:07 -07:00
#
##
# Import Modules
#
from __future__ import print_function
from __future__ import absolute_import
2018-09-13 16:11:07 -07:00
import Common.LongFilePathOs as os
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
2018-09-13 16:11:07 -07:00
from Common import EdkLogger
from Common.Misc import SaveFileOnChange
from Common.TargetTxtClassObject import TargetTxtClassObject
from Common.ToolDefClassObject import ToolDefClassObject, ToolDefDict
2018-09-13 16:11:07 -07:00
from AutoGen.BuildEngine import BuildRule
import Common.DataType as DataType
from Common.Misc import PathClass
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.MultipleWorkspace import MultipleWorkspace as mws
import Common.GlobalData as GlobalData
2018-09-13 16:11:07 -07:00
## 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
2018-09-13 16:11:07 -07:00
__BuildRuleDatabase = None
GuidToolDefinition = {}
FfsCmdDict = {}
SecCmdList = []
CopyList = []
ModuleFile = ''
EnableGenfdsMultiThread = False
2018-09-13 16:11:07 -07:00
#
# 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 = {}
2018-09-13 16:11:07 -07:00
## LoadBuildRule
#
@staticmethod
def _LoadBuildRule():
2018-09-13 16:11:07 -07:00
if GenFdsGlobalVariable.__BuildRuleDatabase:
return GenFdsGlobalVariable.__BuildRuleDatabase
BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.ConfDir, "target.txt"))
TargetTxt = TargetTxtClassObject()
if os.path.isfile(BuildConfigurationFile) == True:
TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
if DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
BuildRuleFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF]
if not BuildRuleFile:
2018-09-13 16:11:07 -07:00
BuildRuleFile = 'Conf/build_rule.txt'
GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule(BuildRuleFile)
ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
if ToolDefinitionFile == '':
ToolDefinitionFile = "Conf/tools_def.txt"
if os.path.isfile(ToolDefinitionFile):
ToolDef = ToolDefClassObject()
ToolDef.LoadToolDefFile(ToolDefinitionFile)
ToolDefinition = 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]
2018-09-13 16:11:07 -07:00
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
2018-09-13 16:11:07 -07:00
if not Arch in GenFdsGlobalVariable.OutputDirDict:
return {}
BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule()
2018-09-13 16:11:07 -07:00
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")
}
2018-09-13 16:11:07 -07:00
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}:
2018-09-13 16:11:07 -07:00
FileList.append((File, DataType.TAB_UNKNOWN_FILE))
for File in Inf.Binaries:
if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}:
2018-09-13 16:11:07 -07:00
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:
2018-09-13 16:11:07 -07:00
# Skip all files that are not binary libraries
if not Inf.LibraryClass:
continue
2018-09-13 16:11:07 -07:00
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
2018-09-13 16:11:07 -07:00
FileType = RuleObject.SourceFileType
2018-09-13 16:11:07 -07:00
# stop at STATIC_LIBRARY for library
if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY:
if LastTarget:
TargetList.add(str(LastTarget))
break
2018-09-13 16:11:07 -07:00
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))
2018-09-13 16:11:07 -07:00
# to avoid cyclic rule
if FileType in RuleChain:
break
2018-09-13 16:11:07 -07:00
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
2018-09-13 16:11:07 -07:00
def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir)
2018-09-13 16:11:07 -07:00
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):
2018-09-13 16:11:07 -07:00
os.makedirs(GenFdsGlobalVariable.FvDir)
GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
if not os.path.exists(GenFdsGlobalVariable.FfsDir):
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
RtAddress = '0'
for Arch in reversed(ArchList):
temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
if temp:
RtAddress = temp
break
2018-09-13 16:11:07 -07:00
FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
RtAddress + \
DataType.TAB_LINE_BREAK)
2018-09-13 16:11:07 -07:00
FvAddressFile.close()
@staticmethod
2018-09-13 16:11:07 -07:00
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'],
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
RtAddress = '0'
for Arch in reversed(ArchList):
temp = GenFdsGlobalVariable.WorkSpace.BuildObject[
2018-09-13 16:11:07 -07:00
GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress
if temp:
RtAddress = temp
break
2018-09-13 16:11:07 -07:00
FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
RtAddress + \
DataType.TAB_LINE_BREAK)
2018-09-13 16:11:07 -07:00
FvAddressFile.close()
## ReplaceWorkspaceMacro()
#
# @param String String that may contain macro
#
@staticmethod
2018-09-13 16:11:07 -07:00
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:
2018-09-13 16:11:07 -07:00
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):
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
CommandFile = Output + '.txt'
if Ui:
2018-09-13 16:11:07 -07:00
if IsMakefile:
if Ui == "$(MODULE_NAME)":
Cmd += ('-n', Ui)
else:
Cmd += ("-n", '"' + Ui + '"')
Cmd += ("-o", Output)
2018-09-13 16:11:07 -07:00
if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
else:
SectionData = array('B', [0, 0, 0, 0])
2018-09-13 16:11:07 -07:00
SectionData.fromstring(Ui.encode("utf_16_le"))
SectionData.append(0)
SectionData.append(0)
Len = len(SectionData)
GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
SaveFileOnChange(Output, SectionData.tostring())
elif Ver:
Cmd += ("-n", Ver)
2018-09-13 16:11:07 -07:00
if BuildNumber:
Cmd += ("-j", BuildNumber)
Cmd += ("-o", Output)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
Cmd += Input
SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
if IsMakefile:
if GlobalData.gGlobalDefines.get("FAMILY") == "MSFT":
Cmd = ['if', 'exist', Input[0]] + Cmd
else:
Cmd = ['test', '-e', Input[0], "&&"] + Cmd
2018-09-13 16:11:07 -07:00
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:
2018-09-13 16:11:07 -07:00
return 0
if AlignString.endswith('K'):
2018-09-13 16:11:07 -07:00
return int (AlignString.rstrip('K')) * 1024
if AlignString.endswith('M'):
2018-09-13 16:11:07 -07:00
return int (AlignString.rstrip('M')) * 1024 * 1024
if AlignString.endswith('G'):
return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024
return int (AlignString)
2018-09-13 16:11:07 -07:00
@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")
2018-09-13 16:11:07 -07:00
if CheckSum:
Cmd.append("-s")
if Align:
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
Cmd += ("-o", Output)
2018-09-13 16:11:07 -07:00
for I in range(0, len(Input)):
if MakefilePath:
Cmd += ("-oi", Input[I])
else:
Cmd += ("-i", Input[I])
if SectionAlign and SectionAlign[I]:
2018-09-13 16:11:07 -07:00
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:
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
if ForceRebase == False:
Cmd += ("-F", "FALSE")
2018-09-13 16:11:07 -07:00
elif ForceRebase == True:
Cmd += ("-F", "TRUE")
2018-09-13 16:11:07 -07:00
if Capsule:
Cmd.append("-c")
2018-09-13 16:11:07 -07:00
if Dump:
Cmd.append("-p")
if AddressFile:
Cmd += ("-a", AddressFile)
if MapFile:
Cmd += ("-m", MapFile)
2018-09-13 16:11:07 -07:00
if FileSystemGuid:
Cmd += ("-g", FileSystemGuid)
Cmd += ("-o", Output)
2018-09-13 16:11:07 -07:00
for I in Input:
Cmd += ("-i", I)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
if Zero:
Cmd.append("-z")
2018-09-13 16:11:07 -07:00
if Strip:
Cmd.append("-l")
2018-09-13 16:11:07 -07:00
if Replace:
Cmd.append("-r")
2018-09-13 16:11:07 -07:00
if Join:
Cmd.append("-j")
2018-09-13 16:11:07 -07:00
if Convert:
Cmd.append("-m")
Cmd += ("-o", Output)
2018-09-13 16:11:07 -07:00
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 = []
2018-09-13 16:11:07 -07:00
Cmd = ["EfiRom"]
if EfiInput:
2018-09-13 16:11:07 -07:00
if Compress:
Cmd.append("-ec")
2018-09-13 16:11:07 -07:00
else:
Cmd.append("-e")
2018-09-13 16:11:07 -07:00
for EfiFile in EfiInput:
Cmd.append(EfiFile)
2018-09-13 16:11:07 -07:00
InputList.append (EfiFile)
if BinaryInput:
Cmd.append("-b")
2018-09-13 16:11:07 -07:00
for BinFile in BinaryInput:
Cmd.append(BinFile)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
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)
2018-09-13 16:11:07 -07:00
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
2018-09-13 16:11:07 -07:00
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()
2018-09-13 16:11:07 -07:00
GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
stdout.write('\n')
2018-09-13 16:11:07 -07:00
try:
PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True)
except Exception as X:
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
(out, error) = PopenObject.communicate()
while PopenObject.returncode is None:
2018-09-13 16:11:07 -07:00
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'))
2018-09-13 16:11:07 -07:00
if PopenObject.returncode != 0:
print("###", cmd)
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
@staticmethod
2018-09-13 16:11:07 -07:00
def VerboseLogger (msg):
EdkLogger.verbose(msg)
@staticmethod
2018-09-13 16:11:07 -07:00
def InfLogger (msg):
EdkLogger.info(msg)
@staticmethod
2018-09-13 16:11:07 -07:00
def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
@staticmethod
2018-09-13 16:11:07 -07:00
def DebugLogger (Level, msg):
EdkLogger.debug(Level, msg)
## MacroExtend()
2018-09-13 16:11:07 -07:00
#
# @param Str String that may contain macro
# @param MacroDict Dictionary that contains macro value pair
#
@staticmethod
def MacroExtend (Str, MacroDict={}, Arch=DataType.TAB_COMMON):
if Str is None:
2018-09-13 16:11:07 -07:00
return None
Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir,
2018-09-13 16:11:07 -07:00
# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
'$(TARGET)': GenFdsGlobalVariable.TargetName,
'$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag,
'$(SPACE)': ' '
2018-09-13 16:11:07 -07:00
}
if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList:
2018-09-13 16:11:07 -07:00
OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
else:
OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
2018-09-13 16:11:07 -07:00
Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
if MacroDict:
2018-09-13 16:11:07 -07:00
Dict.update(MacroDict)
for key in Dict:
if Str.find(key) >= 0:
2018-09-13 16:11:07 -07:00
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
2018-09-13 16:11:07 -07:00
def GetPcdValue (PcdPattern):
if PcdPattern is None:
2018-09-13 16:11:07 -07:00
return None
PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').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:
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
if PcdObj.DatumType != DataType.TAB_VOID:
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
return PcdObj.DefaultValue
2018-09-13 16:11:07 -07:00
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:
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
if PcdObj.DatumType != DataType.TAB_VOID:
2018-09-13 16:11:07 -07:00
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
return PcdObj.DefaultValue
2018-09-13 16:11:07 -07:00
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):
ToolDb = ToolDefDict(GenFdsGlobalVariable.ConfDir).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)
if GenFdsGlobalVariable.GuidToolDefinition:
if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
ToolDefinition = ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
ToolPathTmp = None
ToolOption = None
ToolPathKey = None
ToolOptionKey = None
KeyList = None
for ToolDef in ToolDefinition.items():
if NameGuid.lower() == ToolDef[1].lower():
KeyList = ToolDef[0].split('_')
Key = KeyList[0] + \
'_' + \
KeyList[1] + \
'_' + \
KeyList[2]
if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
ToolPath = ToolDefinition.get(ToolPathKey)
ToolOption = ToolDefinition.get(ToolOptionKey)
if ToolPathTmp is None:
ToolPathTmp = ToolPath
else:
if ToolPathTmp != ToolPath:
EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
BuildOption = {}
for Arch in CurrentArchList:
Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
# key is (ToolChainFamily, ToolChain, CodeBase)
for item in Platform.BuildOptions:
if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]:
if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]):
if item[1] not in BuildOption:
BuildOption[item[1]] = Platform.BuildOptions[item]
if BuildOption:
ToolList = [DataType.TAB_TOD_DEFINES_TARGET, DataType.TAB_TOD_DEFINES_TOOL_CHAIN_TAG, DataType.TAB_TOD_DEFINES_TARGET_ARCH]
for Index in range(2, -1, -1):
for Key in list(BuildOption.keys()):
List = Key.split('_')
if List[Index] == DataType.TAB_STAR:
for String in ToolDb[ToolList[Index]]:
if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]:
List[Index] = String
NewKey = '%s_%s_%s_%s_%s' % tuple(List)
if NewKey not in BuildOption:
BuildOption[NewKey] = BuildOption[Key]
continue
del BuildOption[Key]
elif List[Index] not in ToolDb[ToolList[Index]]:
del BuildOption[Key]
if BuildOption:
if not KeyList:
for Op in BuildOption:
if NameGuid == BuildOption[Op]:
KeyList = Op.split('_')
Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2]
if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
if ToolPathKey in BuildOption:
ToolPathTmp = BuildOption[ToolPathKey]
if ToolOptionKey in BuildOption:
ToolOption = BuildOption[ToolOptionKey]
GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
return ToolPathTmp, ToolOption