mirror of https://github.com/acidanthera/audk.git
723 lines
30 KiB
Python
723 lines
30 KiB
Python
## @file
|
|
# Global variables for GenFds
|
|
#
|
|
# Copyright (c) 2007 - 2012, 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 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
|
|
|
|
## Global variables
|
|
#
|
|
#
|
|
class GenFdsGlobalVariable:
|
|
FvDir = ''
|
|
OutputDirDict = {}
|
|
BinDir = ''
|
|
# will be FvDir + os.sep + 'Ffs'
|
|
FfsDir = ''
|
|
FdfParser = None
|
|
LibDir = ''
|
|
WorkSpace = None
|
|
WorkSpaceDir = ''
|
|
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
|
|
|
|
#
|
|
# 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.WorkSpaceDir, "Conf/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 = []
|
|
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)
|
|
if ArchList != None:
|
|
GenFdsGlobalVariable.ArchList = ArchList
|
|
|
|
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):
|
|
Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
|
|
if os.path.exists(Str):
|
|
if not os.path.isabs(Str):
|
|
Str = os.path.abspath(Str)
|
|
else:
|
|
Str = os.path.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]
|
|
if Fixed == True:
|
|
Cmd += ["-x"]
|
|
if CheckSum:
|
|
Cmd += ["-s"]
|
|
if Align not in [None, '']:
|
|
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
|
|
}
|
|
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)
|