X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FGenFds%2FGenFds.py;h=c19dc4075793b8c9ea0b10df3b1cbd2952c54125;hb=5e9256cd7f54;hp=4fa4eda04a5fd7a8a8c36b49a9fad8d8d1b1c7ab;hpb=47fea6afd74af76c7e2a2b03d319b7ac035ac26a;p=mirror_edk2.git
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index 4fa4eda04a..c19dc40757 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -1,7 +1,7 @@
## @file
# generate flash image
#
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2017, 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
@@ -30,7 +30,7 @@ from EfiSection import EfiSection
import StringIO
import Common.TargetTxtClassObject as TargetTxtClassObject
import Common.ToolDefClassObject as ToolDefClassObject
-import Common.DataType
+from Common.DataType import *
import Common.GlobalData as GlobalData
from Common import EdkLogger
from Common.String import *
@@ -38,13 +38,18 @@ from Common.Misc import DirCache, PathClass
from Common.Misc import SaveFileOnChange
from Common.Misc import ClearDuplicatedInf
from Common.Misc import GuidStructureStringToGuidString
+from Common.Misc import CheckPcdDatum
+from Common.Misc import BuildOptionPcdValueFormat
from Common.BuildVersion import gBUILD_VERSION
from Common.MultipleWorkspace import MultipleWorkspace as mws
+import FfsFileStatement
+import glob
+from struct import unpack
## Version and Copyright
versionNumber = "1.0" + ' ' + gBUILD_VERSION
__version__ = "%prog Version " + versionNumber
-__copyright__ = "Copyright (c) 2007 - 2014, Intel Corporation All rights reserved."
+__copyright__ = "Copyright (c) 2007 - 2017, Intel Corporation All rights reserved."
## Tool entrance method
#
@@ -118,13 +123,9 @@ def main():
if (Options.BuildTarget):
GenFdsGlobalVariable.TargetName = Options.BuildTarget
- else:
- EdkLogger.error("GenFds", OPTION_MISSING, "Missing build target")
if (Options.ToolChain):
GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
- else:
- EdkLogger.error("GenFds", OPTION_MISSING, "Missing tool chain tag")
if (Options.activePlatform):
ActivePlatform = Options.activePlatform
@@ -138,18 +139,10 @@ def main():
if not os.path.exists(ActivePlatform) :
EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
-
- if os.path.normcase (ActivePlatform).find(Workspace) == 0:
- ActivePlatform = mws.relpath(ActivePlatform, Workspace)
- if len(ActivePlatform) > 0 :
- if ActivePlatform[0] == '\\' or ActivePlatform[0] == '/':
- ActivePlatform = ActivePlatform[1:]
- else:
- EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
else:
EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
- GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform), Workspace)
+ GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
if (Options.ConfDirectory):
# Get alternate Conf location, if it is absolute, then just use the absolute directory name
@@ -163,12 +156,31 @@ def main():
# This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
ConfDirectoryPath = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath)
else:
- # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
- ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')
+ if "CONF_PATH" in os.environ.keys():
+ ConfDirectoryPath = os.path.normcase(os.environ["CONF_PATH"])
+ else:
+ # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
+ ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')
GenFdsGlobalVariable.ConfDir = ConfDirectoryPath
BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
if os.path.isfile(BuildConfigurationFile) == True:
- TargetTxtClassObject.TargetTxtClassObject(BuildConfigurationFile)
+ TargetTxt = TargetTxtClassObject.TargetTxtClassObject()
+ TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
+ # if no build target given in command line, get it from target.txt
+ if not GenFdsGlobalVariable.TargetName:
+ BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
+ if len(BuildTargetList) != 1:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
+ GenFdsGlobalVariable.TargetName = BuildTargetList[0]
+
+ # if no tool chain given in command line, get it from target.txt
+ if not GenFdsGlobalVariable.ToolChainTag:
+ ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
+ if ToolChainList == None or len(ToolChainList) == 0:
+ EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
+ if len(ToolChainList) != 1:
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for ToolChain.")
+ GenFdsGlobalVariable.ToolChainTag = ToolChainList[0]
else:
EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
@@ -183,6 +195,8 @@ def main():
Pair = Pair[:-1]
List = Pair.split('=')
if len(List) == 2:
+ if not List[1].strip():
+ EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="No Value given for Macro %s" %List[0])
if List[0].strip() == "EFI_SOURCE":
GlobalData.gEfiSource = List[1].strip()
GlobalData.gGlobalDefines["EFI_SOURCE"] = GlobalData.gEfiSource
@@ -199,6 +213,14 @@ def main():
GlobalData.gCommandLineDefines[List[0].strip()] = "TRUE"
os.environ["WORKSPACE"] = Workspace
+ # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
+ if "TARGET" not in GlobalData.gGlobalDefines.keys():
+ GlobalData.gGlobalDefines["TARGET"] = GenFdsGlobalVariable.TargetName
+ if "TOOLCHAIN" not in GlobalData.gGlobalDefines.keys():
+ GlobalData.gGlobalDefines["TOOLCHAIN"] = GenFdsGlobalVariable.ToolChainTag
+ if "TOOL_CHAIN_TAG" not in GlobalData.gGlobalDefines.keys():
+ GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable.ToolChainTag
+
"""call Workspace build create database"""
GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
@@ -274,14 +296,41 @@ def main():
EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
"No such a Capsule in FDF file: %s" % Options.uiCapName)
+ GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
+ if ArchList != None:
+ GenFdsGlobalVariable.ArchList = ArchList
+
+ if Options.OptionPcd:
+ GlobalData.BuildOptionPcd = Options.OptionPcd
+ CheckBuildOptionPcd()
+
"""Modify images from build output if the feature of loading driver at fixed address is on."""
if GenFdsGlobalVariable.FixedLoadAddress:
GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform)
+
+ # Record the FV Region info that may specific in the FD
+ if FdfParserObj.Profile.FvDict and FdfParserObj.Profile.FdDict:
+ for Fv in FdfParserObj.Profile.FvDict:
+ FvObj = FdfParserObj.Profile.FvDict[Fv]
+ for Fd in FdfParserObj.Profile.FdDict:
+ FdObj = FdfParserObj.Profile.FdDict[Fd]
+ for RegionObj in FdObj.RegionList:
+ if RegionObj.RegionType != 'FV':
+ continue
+ for RegionData in RegionObj.RegionDataList:
+ if FvObj.UiFvName.upper() == RegionData.upper():
+ if FvObj.FvRegionInFD:
+ if FvObj.FvRegionInFD != RegionObj.Size:
+ EdkLogger.error("GenFds", FORMAT_INVALID, "The FV %s's region is specified in multiple FD with different value." %FvObj.UiFvName)
+ else:
+ FvObj.FvRegionInFD = RegionObj.Size
+ RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, FvObj)
+
"""Call GenFds"""
GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)
"""Generate GUID cross reference file"""
- GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList)
+ GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList, FdfParserObj)
"""Display FV space info."""
GenFds.DisplayFvSpaceInfo(FdfParserObj)
@@ -300,7 +349,7 @@ def main():
"\nPython",
CODE_ERROR,
"Tools code failure",
- ExtraData="Please send email to edk2-devel@lists.sourceforge.net for help, attaching following call stack trace!\n",
+ ExtraData="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
RaiseError=False
)
EdkLogger.quiet(traceback.format_exc())
@@ -316,7 +365,146 @@ def SingleCheckCallback(option, opt_str, value, parser):
gParamCheck.append(option)
else:
parser.error("Option %s only allows one instance in command line!" % option)
-
+
+def CheckBuildOptionPcd():
+ for Arch in GenFdsGlobalVariable.ArchList:
+ PkgList = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag)
+ for i, pcd in enumerate(GlobalData.BuildOptionPcd):
+ if type(pcd) is tuple:
+ continue
+ (pcdname, pcdvalue) = pcd.split('=')
+ if not pcdvalue:
+ EdkLogger.error('GenFds', OPTION_MISSING, "No Value specified for the PCD %s." % (pcdname))
+ if '.' in pcdname:
+ (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')
+ HasTokenSpace = True
+ else:
+ TokenCName = pcdname
+ TokenSpaceGuidCName = ''
+ HasTokenSpace = False
+ TokenSpaceGuidCNameList = []
+ FoundFlag = False
+ PcdDatumType = ''
+ NewValue = ''
+ for package in PkgList:
+ for key in package.Pcds:
+ PcdItem = package.Pcds[key]
+ if HasTokenSpace:
+ if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
+ PcdDatumType = PcdItem.DatumType
+ NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
+ FoundFlag = True
+ else:
+ if PcdItem.TokenCName == TokenCName:
+ if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
+ if len (TokenSpaceGuidCNameList) < 1:
+ TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
+ PcdDatumType = PcdItem.DatumType
+ TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
+ NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
+ FoundFlag = True
+ else:
+ EdkLogger.error(
+ 'GenFds',
+ PCD_VALIDATION_INFO_ERROR,
+ "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
+ )
+
+ GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)
+
+
+## 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 = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
+ # if user not specify filter, try to deduce it from global data.
+ if KeyStringList == 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.keys():
+ return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
+
+ ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
+ ToolPathTmp = None
+ ToolOption = None
+ ToolPathKey = None
+ ToolOptionKey = None
+ KeyList = None
+ for ToolDef in ToolDefinition.items():
+ if NameGuid == ToolDef[1]:
+ KeyList = ToolDef[0].split('_')
+ Key = KeyList[0] + \
+ '_' + \
+ KeyList[1] + \
+ '_' + \
+ KeyList[2]
+ if Key in KeyStringList and KeyList[4] == 'GUID':
+ ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
+ ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
+ ToolPath = ToolDefinition.get(ToolPathKey)
+ ToolOption = ToolDefinition.get(ToolOptionKey)
+ if ToolPathTmp == 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 = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH]
+ for Index in range(2, -1, -1):
+ for Key in dict(BuildOption):
+ List = Key.split('_')
+ if List[Index] == '*':
+ 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] == 'GUID':
+ ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
+ ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
+ if ToolPathKey in BuildOption.keys():
+ ToolPathTmp = BuildOption.get(ToolPathKey)
+ if ToolOptionKey in BuildOption.keys():
+ ToolOption = BuildOption.get(ToolOptionKey)
+
+ GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
+ return ToolPathTmp, ToolOption
+
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
@@ -349,6 +537,7 @@ def myOptionParser():
Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.")
Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
+ Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
(Options, args) = Parser.parse_args()
return Options
@@ -538,14 +727,20 @@ class GenFds :
ModuleObj = BuildDb.BuildObject[Key, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
print ModuleObj.BaseName + ' ' + ModuleObj.ModuleType
- def GenerateGuidXRefFile(BuildDb, ArchList):
+ def GenerateGuidXRefFile(BuildDb, ArchList, FdfParserObj):
GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref")
GuidXRefFile = StringIO.StringIO('')
GuidDict = {}
+ ModuleList = []
+ FileGuidList = []
for Arch in ArchList:
PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
for ModuleFile in PlatformDataBase.Modules:
Module = BuildDb.BuildObject[ModuleFile, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ if Module in ModuleList:
+ continue
+ else:
+ ModuleList.append(Module)
GuidXRefFile.write("%s %s\n" % (Module.Guid, Module.BaseName))
for key, item in Module.Protocols.items():
GuidDict[key] = item
@@ -553,6 +748,81 @@ class GenFds :
GuidDict[key] = item
for key, item in Module.Ppis.items():
GuidDict[key] = item
+ for FvName in FdfParserObj.Profile.FvDict:
+ for FfsObj in FdfParserObj.Profile.FvDict[FvName].FfsList:
+ if not isinstance(FfsObj, FfsFileStatement.FileStatement):
+ InfPath = PathClass(NormPath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, FfsObj.InfFileName)))
+ FdfModule = BuildDb.BuildObject[InfPath, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
+ if FdfModule in ModuleList:
+ continue
+ else:
+ ModuleList.append(FdfModule)
+ GuidXRefFile.write("%s %s\n" % (FdfModule.Guid, FdfModule.BaseName))
+ for key, item in FdfModule.Protocols.items():
+ GuidDict[key] = item
+ for key, item in FdfModule.Guids.items():
+ GuidDict[key] = item
+ for key, item in FdfModule.Ppis.items():
+ GuidDict[key] = item
+ else:
+ FileStatementGuid = FfsObj.NameGuid
+ if FileStatementGuid in FileGuidList:
+ continue
+ else:
+ FileGuidList.append(FileStatementGuid)
+ Name = []
+ FfsPath = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
+ FfsPath = glob.glob(os.path.join(FfsPath, FileStatementGuid) + '*')
+ if not FfsPath:
+ continue
+ if not os.path.exists(FfsPath[0]):
+ continue
+ MatchDict = {}
+ ReFileEnds = re.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
+ FileList = os.listdir(FfsPath[0])
+ for File in FileList:
+ Match = ReFileEnds.search(File)
+ if Match:
+ for Index in range(1, 8):
+ if Match.group(Index) and Match.group(Index) in MatchDict:
+ MatchDict[Match.group(Index)].append(File)
+ elif Match.group(Index):
+ MatchDict[Match.group(Index)] = [File]
+ if not MatchDict:
+ continue
+ if '.ui' in MatchDict:
+ for File in MatchDict['.ui']:
+ with open(os.path.join(FfsPath[0], File), 'rb') as F:
+ F.read()
+ length = F.tell()
+ F.seek(4)
+ TmpStr = unpack('%dh' % ((length - 4) / 2), F.read())
+ Name = ''.join([chr(c) for c in TmpStr[:-1]])
+ else:
+ FileList = []
+ if 'fv.sec.txt' in MatchDict:
+ FileList = MatchDict['fv.sec.txt']
+ elif '.pe32.txt' in MatchDict:
+ FileList = MatchDict['.pe32.txt']
+ elif '.te.txt' in MatchDict:
+ FileList = MatchDict['.te.txt']
+ elif '.pic.txt' in MatchDict:
+ FileList = MatchDict['.pic.txt']
+ elif '.raw.txt' in MatchDict:
+ FileList = MatchDict['.raw.txt']
+ elif '.ffs.txt' in MatchDict:
+ FileList = MatchDict['.ffs.txt']
+ else:
+ pass
+ for File in FileList:
+ with open(os.path.join(FfsPath[0], File), 'r') as F:
+ Name.append((F.read().split()[-1]))
+ if not Name:
+ continue
+
+ Name = ' '.join(Name) if type(Name) == type([]) else Name
+ GuidXRefFile.write("%s %s\n" %(FileStatementGuid, Name))
+
# Append GUIDs, Protocols, and PPIs to the Xref file
GuidXRefFile.write("\n")
for key, item in GuidDict.items():