diff options
Diffstat (limited to 'BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py')
-rw-r--r-- | BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py new file mode 100644 index 0000000000..e9eace9c39 --- /dev/null +++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py @@ -0,0 +1,497 @@ +## @file +# Global variables for GenFds +# +# Copyright (c) 2007 - 2010, 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 + +## 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 = '' + + SectionHeader = struct.Struct("3B 1B") + + ## 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].BsBaseAddress: + BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].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].RtBaseAddress: + RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].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): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + 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] + + 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 += ["-j", Ver] + SectionData = array.array('B', [0,0,0,0]) + SectionData.fromstring(Ver.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, 0x14) + SaveFileOnChange(Output, SectionData.tostring()) + else: + Cmd += ["-o", Output] + Cmd += Input + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section") + + @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): + if not GenFdsGlobalVariable.NeedsUpdate(Output, Input): + return + GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input)) + + 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]) + GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS") + + @staticmethod + def GenerateFirmwareVolume(Output, Input, BaseAddress=None, Capsule=False, Dump=False, + AddressFile=None, MapFile=None, FfsList=[]): + 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 Capsule: + Cmd += ["-c"] + if Dump: + Cmd += ["-p"] + if AddressFile not in [None, '']: + Cmd += ["-a", AddressFile] + if MapFile not in [None, '']: + Cmd += ["-m", MapFile] + 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(cmd, stdout=subprocess.PIPE, stderr= subprocess.PIPE) + 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 Platform in GenFdsGlobalVariable.WorkSpace.PlatformList: + 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.PackageList: + 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) |