## @file | |
# Global variables for GenFds | |
# | |
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> | |
# | |
# This program and the accompanying materials | |
# are licensed and made available under the terms and conditions of the BSD License | |
# which accompanies this distribution. The full text of the license may be found at | |
# http://opensource.org/licenses/bsd-license.php | |
# | |
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
# | |
## | |
# Import Modules | |
# | |
import Common.LongFilePathOs as os | |
import sys | |
import subprocess | |
import struct | |
import array | |
from Common.BuildToolError import * | |
from Common import EdkLogger | |
from Common.Misc import SaveFileOnChange | |
from Common.TargetTxtClassObject import TargetTxtClassObject | |
from Common.ToolDefClassObject import ToolDefClassObject | |
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 | |
## Global variables | |
# | |
# | |
class GenFdsGlobalVariable: | |
FvDir = '' | |
OutputDirDict = {} | |
BinDir = '' | |
# will be FvDir + os.sep + 'Ffs' | |
FfsDir = '' | |
FdfParser = None | |
LibDir = '' | |
WorkSpace = None | |
WorkSpaceDir = '' | |
ConfDir = '' | |
EdkSourceDir = '' | |
OutputDirFromDscDict = {} | |
TargetName = '' | |
ToolChainTag = '' | |
RuleDict = {} | |
ArchList = None | |
VtfDict = {} | |
ActivePlatform = None | |
FvAddressFileName = '' | |
VerboseMode = False | |
DebugLevel = -1 | |
SharpCounter = 0 | |
SharpNumberPerLine = 40 | |
FdfFile = '' | |
FdfFileTimeStamp = 0 | |
FixedLoadAddress = False | |
PlatformName = '' | |
BuildRuleFamily = "MSFT" | |
ToolChainFamily = "MSFT" | |
__BuildRuleDatabase = None | |
GuidToolDefinition = {} | |
# | |
# 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.Struct("3B 1B") | |
## LoadBuildRule | |
# | |
@staticmethod | |
def __LoadBuildRule(): | |
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 BuildRuleFile in [None, '']: | |
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] | |
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 = 'COMMON' | |
if not Arch in GenFdsGlobalVariable.OutputDirDict: | |
return {} | |
BuildRuleDatabase = GenFdsGlobalVariable.__LoadBuildRule() | |
if not BuildRuleDatabase: | |
return {} | |
PathClassObj = PathClass(Inf.MetaFile.File, | |
GenFdsGlobalVariable.WorkSpaceDir) | |
Macro = {} | |
Macro["WORKSPACE" ] = GenFdsGlobalVariable.WorkSpaceDir | |
Macro["MODULE_NAME" ] = Inf.BaseName | |
Macro["MODULE_GUID" ] = Inf.Guid | |
Macro["MODULE_VERSION" ] = Inf.Version | |
Macro["MODULE_TYPE" ] = Inf.ModuleType | |
Macro["MODULE_FILE" ] = str(PathClassObj) | |
Macro["MODULE_FILE_BASE_NAME" ] = PathClassObj.BaseName | |
Macro["MODULE_RELATIVE_DIR" ] = PathClassObj.SubDir | |
Macro["MODULE_DIR" ] = PathClassObj.SubDir | |
Macro["BASE_NAME" ] = Inf.BaseName | |
Macro["ARCH" ] = Arch | |
Macro["TOOLCHAIN" ] = GenFdsGlobalVariable.ToolChainTag | |
Macro["TOOLCHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag | |
Macro["TOOL_CHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag | |
Macro["TARGET" ] = GenFdsGlobalVariable.TargetName | |
Macro["BUILD_DIR" ] = GenFdsGlobalVariable.OutputDirDict[Arch] | |
Macro["BIN_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) | |
Macro["LIB_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch) | |
BuildDir = os.path.join( | |
GenFdsGlobalVariable.OutputDirDict[Arch], | |
Arch, | |
PathClassObj.SubDir, | |
PathClassObj.BaseName | |
) | |
Macro["MODULE_BUILD_DIR" ] = BuildDir | |
Macro["OUTPUT_DIR" ] = os.path.join(BuildDir, "OUTPUT") | |
Macro["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 ("", "*", GenFdsGlobalVariable.ToolChainTag) and \ | |
File.ToolChainFamily in ("", "*", GenFdsGlobalVariable.ToolChainFamily): | |
FileList.append((File, DataType.TAB_UNKNOWN_FILE)) | |
for File in Inf.Binaries: | |
if File.Target in ['COMMON', '*', 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 != None 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 | |
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 | |
# | |
def SetDir (OutputDir, FdfParser, WorkSpace, ArchList): | |
GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir) | |
# GenFdsGlobalVariable.OutputDirDict = OutputDir | |
GenFdsGlobalVariable.FdfParser = FdfParser | |
GenFdsGlobalVariable.WorkSpace = WorkSpace | |
GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], 'FV') | |
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) | |
T_CHAR_LF = '\n' | |
# | |
# Create FV Address inf file | |
# | |
GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf') | |
FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w') | |
# | |
# Add [Options] | |
# | |
FvAddressFile.writelines("[options]" + T_CHAR_LF) | |
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 + \ | |
T_CHAR_LF) | |
RtAddress = '0' | |
for Arch in ArchList: | |
if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress: | |
RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress | |
FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \ | |
RtAddress + \ | |
T_CHAR_LF) | |
FvAddressFile.close() | |
## ReplaceWorkspaceMacro() | |
# | |
# @param String String that may contain macro | |
# | |
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 Input == None or len(Input) == 0: | |
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=None, BuildNumber=None): | |
Cmd = ["GenSec"] | |
if Type not in [None, '']: | |
Cmd += ["-s", Type] | |
if CompressionType not in [None, '']: | |
Cmd += ["-c", CompressionType] | |
if Guid != None: | |
Cmd += ["-g", Guid] | |
if GuidHdrLen not in [None, '']: | |
Cmd += ["-l", GuidHdrLen] | |
if len(GuidAttr) != 0: | |
#Add each guided attribute | |
for Attr in GuidAttr: | |
Cmd += ["-r", Attr] | |
if InputAlign != None: | |
#Section Align is only for dummy section without section type | |
for SecAlign in InputAlign: | |
Cmd += ["--sectionalign", SecAlign] | |
CommandFile = Output + '.txt' | |
if Ui not in [None, '']: | |
#Cmd += ["-n", '"' + Ui + '"'] | |
SectionData = array.array('B', [0, 0, 0, 0]) | |
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 not in [None, '']: | |
Cmd += ["-n", Ver] | |
if BuildNumber: | |
Cmd += ["-j", BuildNumber] | |
Cmd += ["-o", Output] | |
SaveFileOnChange(CommandFile, ' '.join(Cmd), False) | |
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 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 AlignString == None: | |
return 0 | |
if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K"): | |
return int (AlignString.rstrip('K')) * 1024 | |
else: | |
return int (AlignString) | |
@staticmethod | |
def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None, | |
SectionAlign=None): | |
Cmd = ["GenFfs", "-t", Type, "-g", Guid] | |
mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K"] | |
if Fixed == True: | |
Cmd += ["-x"] | |
if CheckSum: | |
Cmd += ["-s"] | |
if Align not in [None, '']: | |
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)): | |
Cmd += ("-i", Input[I]) | |
if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']: | |
Cmd += ("-n", SectionAlign[I]) | |
CommandFile = Output + '.txt' | |
SaveFileOnChange(CommandFile, ' '.join(Cmd), False) | |
if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]): | |
return | |
GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) | |
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 not in [None, '']: | |
Cmd += ["-r", BaseAddress] | |
if ForceRebase == False: | |
Cmd += ["-F", "FALSE"] | |
elif ForceRebase == True: | |
Cmd += ["-F", "TRUE"] | |
if Capsule: | |
Cmd += ["-c"] | |
if Dump: | |
Cmd += ["-p"] | |
if AddressFile not in [None, '']: | |
Cmd += ["-a", AddressFile] | |
if MapFile not in [None, '']: | |
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 GenerateVtf(Output, Input, BaseAddress=None, FvSize=None): | |
if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): | |
return | |
GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) | |
Cmd = ["GenVtf"] | |
if BaseAddress not in [None, ''] and FvSize not in [None, ''] \ | |
and len(BaseAddress) == len(FvSize): | |
for I in range(0, len(BaseAddress)): | |
Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]] | |
Cmd += ["-o", Output] | |
for F in Input: | |
Cmd += ["-f", F] | |
GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF") | |
@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): | |
if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): | |
return | |
GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) | |
Cmd = ["GenFw"] | |
if Type.lower() == "te": | |
Cmd += ["-t"] | |
if SubType not in [None, '']: | |
Cmd += ["-e", SubType] | |
if TimeStamp not in [None, '']: | |
Cmd += ["-s", TimeStamp] | |
if Align not in [None, '']: | |
Cmd += ["-a", Align] | |
if Padding not in [None, '']: | |
Cmd += ["-p", Padding] | |
if Zero: | |
Cmd += ["-z"] | |
if Strip: | |
Cmd += ["-l"] | |
if Replace: | |
Cmd += ["-r"] | |
if Join: | |
Cmd += ["-j"] | |
if Convert: | |
Cmd += ["-m"] | |
Cmd += ["-o", Output] | |
Cmd += Input | |
GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image") | |
@staticmethod | |
def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None, | |
Revision=None, DeviceId=None, VendorId=None): | |
InputList = [] | |
Cmd = ["EfiRom"] | |
if len(EfiInput) > 0: | |
if Compress: | |
Cmd += ["-ec"] | |
else: | |
Cmd += ["-e"] | |
for EfiFile in EfiInput: | |
Cmd += [EfiFile] | |
InputList.append (EfiFile) | |
if len(BinaryInput) > 0: | |
Cmd += ["-b"] | |
for BinFile in BinaryInput: | |
Cmd += [BinFile] | |
InputList.append (BinFile) | |
# Check List | |
if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList): | |
return | |
GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList)) | |
if ClassCode != None: | |
Cmd += ["-l", ClassCode] | |
if Revision != None: | |
Cmd += ["-r", Revision] | |
if DeviceId != None: | |
Cmd += ["-i", DeviceId] | |
if VendorId != None: | |
Cmd += ["-f", VendorId] | |
Cmd += ["-o", Output] | |
GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom") | |
@staticmethod | |
def GuidTool(Output, Input, ToolPath, Options='', returnValue=[]): | |
if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): | |
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 | |
GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue) | |
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: | |
sys.stdout.write ('#') | |
sys.stdout.flush() | |
GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1 | |
if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0: | |
sys.stdout.write('\n') | |
try: | |
PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) | |
except Exception, X: | |
EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0])) | |
(out, error) = PopenObject.communicate() | |
while PopenObject.returncode == 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) | |
GenFdsGlobalVariable.InfLogger (error) | |
if PopenObject.returncode != 0: | |
print "###", cmd | |
EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess) | |
def VerboseLogger (msg): | |
EdkLogger.verbose(msg) | |
def InfLogger (msg): | |
EdkLogger.info(msg) | |
def ErrorLogger (msg, File=None, Line=None, ExtraData=None): | |
EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData) | |
def DebugLogger (Level, msg): | |
EdkLogger.debug(Level, msg) | |
## ReplaceWorkspaceMacro() | |
# | |
# @param Str String that may contain macro | |
# @param MacroDict Dictionary that contains macro value pair | |
# | |
def MacroExtend (Str, MacroDict={}, Arch='COMMON'): | |
if Str == None : | |
return None | |
Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir, | |
'$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir, | |
# '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc, | |
'$(TARGET)' : GenFdsGlobalVariable.TargetName, | |
'$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag, | |
'$(SPACE)' : ' ' | |
} | |
OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]] | |
if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList: | |
OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch] | |
Dict['$(OUTPUT_DIRECTORY)'] = OutputDir | |
if MacroDict != None and len (MacroDict) != 0: | |
Dict.update(MacroDict) | |
for key in Dict.keys(): | |
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. | |
# | |
def GetPcdValue (PcdPattern): | |
if PcdPattern == None : | |
return None | |
PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.') | |
TokenSpace = PcdPair[0] | |
TokenCName = PcdPair[1] | |
PcdValue = '' | |
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 != 'FixedAtBuild': | |
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) | |
if PcdObj.DatumType != 'VOID*': | |
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) | |
PcdValue = PcdObj.DefaultValue | |
return PcdValue | |
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 != 'FixedAtBuild': | |
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern) | |
if PcdObj.DatumType != 'VOID*': | |
EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern) | |
PcdValue = PcdObj.DefaultValue | |
return PcdValue | |
return PcdValue | |
SetDir = staticmethod(SetDir) | |
ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro) | |
CallExternalTool = staticmethod(CallExternalTool) | |
VerboseLogger = staticmethod(VerboseLogger) | |
InfLogger = staticmethod(InfLogger) | |
ErrorLogger = staticmethod(ErrorLogger) | |
DebugLogger = staticmethod(DebugLogger) | |
MacroExtend = staticmethod (MacroExtend) | |
GetPcdValue = staticmethod(GetPcdValue) |