summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py')
-rw-r--r--BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py472
1 files changed, 472 insertions, 0 deletions
diff --git a/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
new file mode 100644
index 000000000..d556ce7ad
--- /dev/null
+++ b/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
@@ -0,0 +1,472 @@
+## @file
+# Global variables for GenFds
+#
+# Copyright (c) 2007, Intel Corporation
+#
+# All rights reserved. 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
+
+ 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=None, Ui=None, Ver=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 GuidAttr not in [None, '']:
+ Cmd += ["-r", GuidAttr]
+
+ 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 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):
+# if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
+# return
+# GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+
+ Cmd = ["EfiRom"]
+ if len(EfiInput) > 0:
+
+ if Compress:
+ Cmd += ["-ec"]
+ else:
+ Cmd += ["-e"]
+
+ for EfiFile in EfiInput:
+ Cmd += [EfiFile]
+
+ if len(BinaryInput) > 0:
+ Cmd += ["-b"]
+ for BinFile in BinaryInput:
+ Cmd += [BinFile]
+
+ 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=''):
+ if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
+ return
+ GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
+
+ Cmd = [ToolPath, Options]
+ Cmd += ["-o", Output]
+ Cmd += Input
+
+ GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath)
+
+ def CallExternalTool (cmd, errorMess):
+
+ 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", BuildToolError.COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
+ (out, error) = PopenObject.communicate()
+
+ while PopenObject.returncode == None :
+ PopenObject.wait()
+ 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", BuildToolError.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', BuildToolError.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)