]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/GenFds.py
BaseTools: Fix the bug for CArray PCD override in command line
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / GenFds.py
1 ## @file
2 # generate flash image
3 #
4 # Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
5 #
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
10 #
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 #
14
15 ##
16 # Import Modules
17 #
18 from optparse import OptionParser
19 import sys
20 import Common.LongFilePathOs as os
21 import linecache
22 import FdfParser
23 import Common.BuildToolError as BuildToolError
24 from GenFdsGlobalVariable import GenFdsGlobalVariable
25 from Workspace.WorkspaceDatabase import WorkspaceDatabase
26 from Workspace.BuildClassObject import PcdClassObject
27 from Workspace.BuildClassObject import ModuleBuildClassObject
28 import RuleComplexFile
29 from EfiSection import EfiSection
30 import StringIO
31 import Common.TargetTxtClassObject as TargetTxtClassObject
32 import Common.ToolDefClassObject as ToolDefClassObject
33 from Common.DataType import *
34 import Common.GlobalData as GlobalData
35 from Common import EdkLogger
36 from Common.String import *
37 from Common.Misc import DirCache, PathClass
38 from Common.Misc import SaveFileOnChange
39 from Common.Misc import ClearDuplicatedInf
40 from Common.Misc import GuidStructureStringToGuidString
41 from Common.Misc import CheckPcdDatum
42 from Common.Misc import BuildOptionPcdValueFormat
43 from Common.BuildVersion import gBUILD_VERSION
44 from Common.MultipleWorkspace import MultipleWorkspace as mws
45
46 ## Version and Copyright
47 versionNumber = "1.0" + ' ' + gBUILD_VERSION
48 __version__ = "%prog Version " + versionNumber
49 __copyright__ = "Copyright (c) 2007 - 2017, Intel Corporation All rights reserved."
50
51 ## Tool entrance method
52 #
53 # This method mainly dispatch specific methods per the command line options.
54 # If no error found, return zero value so the caller of this tool can know
55 # if it's executed successfully or not.
56 #
57 # @retval 0 Tool was successful
58 # @retval 1 Tool failed
59 #
60 def main():
61 global Options
62 Options = myOptionParser()
63
64 global Workspace
65 Workspace = ""
66 ArchList = None
67 ReturnCode = 0
68
69 EdkLogger.Initialize()
70 try:
71 if Options.verbose != None:
72 EdkLogger.SetLevel(EdkLogger.VERBOSE)
73 GenFdsGlobalVariable.VerboseMode = True
74
75 if Options.FixedAddress != None:
76 GenFdsGlobalVariable.FixedLoadAddress = True
77
78 if Options.quiet != None:
79 EdkLogger.SetLevel(EdkLogger.QUIET)
80 if Options.debug != None:
81 EdkLogger.SetLevel(Options.debug + 1)
82 GenFdsGlobalVariable.DebugLevel = Options.debug
83 else:
84 EdkLogger.SetLevel(EdkLogger.INFO)
85
86 if (Options.Workspace == None):
87 EdkLogger.error("GenFds", OPTION_MISSING, "WORKSPACE not defined",
88 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
89 elif not os.path.exists(Options.Workspace):
90 EdkLogger.error("GenFds", PARAMETER_INVALID, "WORKSPACE is invalid",
91 ExtraData="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
92 else:
93 Workspace = os.path.normcase(Options.Workspace)
94 GenFdsGlobalVariable.WorkSpaceDir = Workspace
95 if 'EDK_SOURCE' in os.environ.keys():
96 GenFdsGlobalVariable.EdkSourceDir = os.path.normcase(os.environ['EDK_SOURCE'])
97 if (Options.debug):
98 GenFdsGlobalVariable.VerboseLogger("Using Workspace:" + Workspace)
99 os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
100
101 # set multiple workspace
102 PackagesPath = os.getenv("PACKAGES_PATH")
103 mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
104
105 if (Options.filename):
106 FdfFilename = Options.filename
107 FdfFilename = GenFdsGlobalVariable.ReplaceWorkspaceMacro(FdfFilename)
108
109 if FdfFilename[0:2] == '..':
110 FdfFilename = os.path.realpath(FdfFilename)
111 if not os.path.isabs(FdfFilename):
112 FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, FdfFilename)
113 if not os.path.exists(FdfFilename):
114 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=FdfFilename)
115
116 GenFdsGlobalVariable.FdfFile = FdfFilename
117 GenFdsGlobalVariable.FdfFileTimeStamp = os.path.getmtime(FdfFilename)
118 else:
119 EdkLogger.error("GenFds", OPTION_MISSING, "Missing FDF filename")
120
121 if (Options.BuildTarget):
122 GenFdsGlobalVariable.TargetName = Options.BuildTarget
123
124 if (Options.ToolChain):
125 GenFdsGlobalVariable.ToolChainTag = Options.ToolChain
126
127 if (Options.activePlatform):
128 ActivePlatform = Options.activePlatform
129 ActivePlatform = GenFdsGlobalVariable.ReplaceWorkspaceMacro(ActivePlatform)
130
131 if ActivePlatform[0:2] == '..':
132 ActivePlatform = os.path.realpath(ActivePlatform)
133
134 if not os.path.isabs (ActivePlatform):
135 ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)
136
137 if not os.path.exists(ActivePlatform) :
138 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform doesn't exist!")
139 else:
140 EdkLogger.error("GenFds", OPTION_MISSING, "Missing active platform")
141
142 GenFdsGlobalVariable.ActivePlatform = PathClass(NormPath(ActivePlatform))
143
144 if (Options.ConfDirectory):
145 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
146 ConfDirectoryPath = os.path.normpath(Options.ConfDirectory)
147 if ConfDirectoryPath.startswith('"'):
148 ConfDirectoryPath = ConfDirectoryPath[1:]
149 if ConfDirectoryPath.endswith('"'):
150 ConfDirectoryPath = ConfDirectoryPath[:-1]
151 if not os.path.isabs(ConfDirectoryPath):
152 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
153 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
154 ConfDirectoryPath = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath)
155 else:
156 if "CONF_PATH" in os.environ.keys():
157 ConfDirectoryPath = os.path.normcase(os.environ["CONF_PATH"])
158 else:
159 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
160 ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')
161 GenFdsGlobalVariable.ConfDir = ConfDirectoryPath
162 BuildConfigurationFile = os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
163 if os.path.isfile(BuildConfigurationFile) == True:
164 TargetTxt = TargetTxtClassObject.TargetTxtClassObject()
165 TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
166 # if no build target given in command line, get it from target.txt
167 if not GenFdsGlobalVariable.TargetName:
168 BuildTargetList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TARGET]
169 if len(BuildTargetList) != 1:
170 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for Target.")
171 GenFdsGlobalVariable.TargetName = BuildTargetList[0]
172
173 # if no tool chain given in command line, get it from target.txt
174 if not GenFdsGlobalVariable.ToolChainTag:
175 ToolChainList = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_TAG]
176 if ToolChainList == None or len(ToolChainList) == 0:
177 EdkLogger.error("GenFds", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.")
178 if len(ToolChainList) != 1:
179 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="Only allows one instance for ToolChain.")
180 GenFdsGlobalVariable.ToolChainTag = ToolChainList[0]
181 else:
182 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=BuildConfigurationFile)
183
184 #Set global flag for build mode
185 GlobalData.gIgnoreSource = Options.IgnoreSources
186
187 if Options.Macros:
188 for Pair in Options.Macros:
189 if Pair.startswith('"'):
190 Pair = Pair[1:]
191 if Pair.endswith('"'):
192 Pair = Pair[:-1]
193 List = Pair.split('=')
194 if len(List) == 2:
195 if not List[1].strip():
196 EdkLogger.error("GenFds", OPTION_VALUE_INVALID, ExtraData="No Value given for Macro %s" %List[0])
197 if List[0].strip() == "EFI_SOURCE":
198 GlobalData.gEfiSource = List[1].strip()
199 GlobalData.gGlobalDefines["EFI_SOURCE"] = GlobalData.gEfiSource
200 continue
201 elif List[0].strip() == "EDK_SOURCE":
202 GlobalData.gEdkSource = List[1].strip()
203 GlobalData.gGlobalDefines["EDK_SOURCE"] = GlobalData.gEdkSource
204 continue
205 elif List[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
206 GlobalData.gGlobalDefines[List[0].strip()] = List[1].strip()
207 else:
208 GlobalData.gCommandLineDefines[List[0].strip()] = List[1].strip()
209 else:
210 GlobalData.gCommandLineDefines[List[0].strip()] = "TRUE"
211 os.environ["WORKSPACE"] = Workspace
212
213 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
214 if "TARGET" not in GlobalData.gGlobalDefines.keys():
215 GlobalData.gGlobalDefines["TARGET"] = GenFdsGlobalVariable.TargetName
216 if "TOOLCHAIN" not in GlobalData.gGlobalDefines.keys():
217 GlobalData.gGlobalDefines["TOOLCHAIN"] = GenFdsGlobalVariable.ToolChainTag
218 if "TOOL_CHAIN_TAG" not in GlobalData.gGlobalDefines.keys():
219 GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable.ToolChainTag
220
221 """call Workspace build create database"""
222 GlobalData.gDatabasePath = os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
223 BuildWorkSpace = WorkspaceDatabase(GlobalData.gDatabasePath)
224 BuildWorkSpace.InitDatabase()
225
226 #
227 # Get files real name in workspace dir
228 #
229 GlobalData.gAllFiles = DirCache(Workspace)
230 GlobalData.gWorkspace = Workspace
231
232 if (Options.archList) :
233 ArchList = Options.archList.split(',')
234 else:
235 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
236 ArchList = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON', Options.BuildTarget, Options.ToolChain].SupArchList
237
238 TargetArchList = set(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON', Options.BuildTarget, Options.ToolChain].SupArchList) & set(ArchList)
239 if len(TargetArchList) == 0:
240 EdkLogger.error("GenFds", GENFDS_ERROR, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList), str(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 'COMMON'].SupArchList)))
241
242 for Arch in ArchList:
243 GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = NormPath(BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].OutputDirectory)
244 GenFdsGlobalVariable.PlatformName = BuildWorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, Options.BuildTarget, Options.ToolChain].PlatformName
245
246 if (Options.outputDir):
247 OutputDirFromCommandLine = GenFdsGlobalVariable.ReplaceWorkspaceMacro(Options.outputDir)
248 if not os.path.isabs (OutputDirFromCommandLine):
249 OutputDirFromCommandLine = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, OutputDirFromCommandLine)
250 for Arch in ArchList:
251 GenFdsGlobalVariable.OutputDirDict[Arch] = OutputDirFromCommandLine
252 else:
253 for Arch in ArchList:
254 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.join(GenFdsGlobalVariable.OutputDirFromDscDict[Arch], GenFdsGlobalVariable.TargetName + '_' + GenFdsGlobalVariable.ToolChainTag)
255
256 for Key in GenFdsGlobalVariable.OutputDirDict:
257 OutputDir = GenFdsGlobalVariable.OutputDirDict[Key]
258 if OutputDir[0:2] == '..':
259 OutputDir = os.path.realpath(OutputDir)
260
261 if OutputDir[1] != ':':
262 OutputDir = os.path.join (GenFdsGlobalVariable.WorkSpaceDir, OutputDir)
263
264 if not os.path.exists(OutputDir):
265 EdkLogger.error("GenFds", FILE_NOT_FOUND, ExtraData=OutputDir)
266 GenFdsGlobalVariable.OutputDirDict[Key] = OutputDir
267
268 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
269 FdfParserObj = FdfParser.FdfParser(FdfFilename)
270 FdfParserObj.ParseFile()
271
272 if FdfParserObj.CycleReferenceCheck():
273 EdkLogger.error("GenFds", FORMAT_NOT_SUPPORTED, "Cycle Reference Detected in FDF file")
274
275 if (Options.uiFdName) :
276 if Options.uiFdName.upper() in FdfParserObj.Profile.FdDict.keys():
277 GenFds.OnlyGenerateThisFd = Options.uiFdName
278 else:
279 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
280 "No such an FD in FDF file: %s" % Options.uiFdName)
281
282 if (Options.uiFvName) :
283 if Options.uiFvName.upper() in FdfParserObj.Profile.FvDict.keys():
284 GenFds.OnlyGenerateThisFv = Options.uiFvName
285 else:
286 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
287 "No such an FV in FDF file: %s" % Options.uiFvName)
288
289 if (Options.uiCapName) :
290 if Options.uiCapName.upper() in FdfParserObj.Profile.CapsuleDict.keys():
291 GenFds.OnlyGenerateThisCap = Options.uiCapName
292 else:
293 EdkLogger.error("GenFds", OPTION_VALUE_INVALID,
294 "No such a Capsule in FDF file: %s" % Options.uiCapName)
295
296 GenFdsGlobalVariable.WorkSpace = BuildWorkSpace
297 if ArchList != None:
298 GenFdsGlobalVariable.ArchList = ArchList
299
300 if Options.OptionPcd:
301 GlobalData.BuildOptionPcd = Options.OptionPcd
302 CheckBuildOptionPcd()
303
304 """Modify images from build output if the feature of loading driver at fixed address is on."""
305 if GenFdsGlobalVariable.FixedLoadAddress:
306 GenFds.PreprocessImage(BuildWorkSpace, GenFdsGlobalVariable.ActivePlatform)
307
308 # Record the FV Region info that may specific in the FD
309 if FdfParserObj.Profile.FvDict and FdfParserObj.Profile.FdDict:
310 for Fv in FdfParserObj.Profile.FvDict:
311 FvObj = FdfParserObj.Profile.FvDict[Fv]
312 for Fd in FdfParserObj.Profile.FdDict:
313 FdObj = FdfParserObj.Profile.FdDict[Fd]
314 for RegionObj in FdObj.RegionList:
315 if RegionObj.RegionType != 'FV':
316 continue
317 for RegionData in RegionObj.RegionDataList:
318 if FvObj.UiFvName.upper() == RegionData.upper():
319 if FvObj.FvRegionInFD:
320 if FvObj.FvRegionInFD != RegionObj.Size:
321 EdkLogger.error("GenFds", FORMAT_INVALID, "The FV %s's region is specified in multiple FD with different value." %FvObj.UiFvName)
322 else:
323 FvObj.FvRegionInFD = RegionObj.Size
324 RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, FvObj)
325
326 """Call GenFds"""
327 GenFds.GenFd('', FdfParserObj, BuildWorkSpace, ArchList)
328
329 """Generate GUID cross reference file"""
330 GenFds.GenerateGuidXRefFile(BuildWorkSpace, ArchList)
331
332 """Display FV space info."""
333 GenFds.DisplayFvSpaceInfo(FdfParserObj)
334
335 except FdfParser.Warning, X:
336 EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
337 ReturnCode = FORMAT_INVALID
338 except FatalError, X:
339 if Options.debug != None:
340 import traceback
341 EdkLogger.quiet(traceback.format_exc())
342 ReturnCode = X.args[0]
343 except:
344 import traceback
345 EdkLogger.error(
346 "\nPython",
347 CODE_ERROR,
348 "Tools code failure",
349 ExtraData="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
350 RaiseError=False
351 )
352 EdkLogger.quiet(traceback.format_exc())
353 ReturnCode = CODE_ERROR
354 finally:
355 ClearDuplicatedInf()
356 return ReturnCode
357
358 gParamCheck = []
359 def SingleCheckCallback(option, opt_str, value, parser):
360 if option not in gParamCheck:
361 setattr(parser.values, option.dest, value)
362 gParamCheck.append(option)
363 else:
364 parser.error("Option %s only allows one instance in command line!" % option)
365
366 def CheckBuildOptionPcd():
367 for Arch in GenFdsGlobalVariable.ArchList:
368 PkgList = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag)
369 for i, pcd in enumerate(GlobalData.BuildOptionPcd):
370 if type(pcd) is tuple:
371 continue
372 (pcdname, pcdvalue) = pcd.split('=')
373 if not pcdvalue:
374 EdkLogger.error('GenFds', OPTION_MISSING, "No Value specified for the PCD %s." % (pcdname))
375 if '.' in pcdname:
376 (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')
377 HasTokenSpace = True
378 else:
379 TokenCName = pcdname
380 TokenSpaceGuidCName = ''
381 HasTokenSpace = False
382 TokenSpaceGuidCNameList = []
383 FoundFlag = False
384 PcdDatumType = ''
385 NewValue = ''
386 for package in PkgList:
387 for key in package.Pcds:
388 PcdItem = package.Pcds[key]
389 if HasTokenSpace:
390 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
391 PcdDatumType = PcdItem.DatumType
392 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
393 FoundFlag = True
394 else:
395 if PcdItem.TokenCName == TokenCName:
396 if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
397 if len (TokenSpaceGuidCNameList) < 1:
398 TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
399 PcdDatumType = PcdItem.DatumType
400 TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
401 NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
402 FoundFlag = True
403 else:
404 EdkLogger.error(
405 'GenFds',
406 PCD_VALIDATION_INFO_ERROR,
407 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
408 )
409
410 GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)
411
412
413 ## FindExtendTool()
414 #
415 # Find location of tools to process data
416 #
417 # @param KeyStringList Filter for inputs of section generation
418 # @param CurrentArchList Arch list
419 # @param NameGuid The Guid name
420 #
421 def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
422 ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
423 # if user not specify filter, try to deduce it from global data.
424 if KeyStringList == None or KeyStringList == []:
425 Target = GenFdsGlobalVariable.TargetName
426 ToolChain = GenFdsGlobalVariable.ToolChainTag
427 if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
428 EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
429 KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
430 for Arch in CurrentArchList:
431 if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
432 KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
433
434 if GenFdsGlobalVariable.GuidToolDefinition:
435 if NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys():
436 return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
437
438 ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
439 ToolPathTmp = None
440 ToolOption = None
441 ToolPathKey = None
442 ToolOptionKey = None
443 KeyList = None
444 for ToolDef in ToolDefinition.items():
445 if NameGuid == ToolDef[1]:
446 KeyList = ToolDef[0].split('_')
447 Key = KeyList[0] + \
448 '_' + \
449 KeyList[1] + \
450 '_' + \
451 KeyList[2]
452 if Key in KeyStringList and KeyList[4] == 'GUID':
453 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
454 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
455 ToolPath = ToolDefinition.get(ToolPathKey)
456 ToolOption = ToolDefinition.get(ToolOptionKey)
457 if ToolPathTmp == None:
458 ToolPathTmp = ToolPath
459 else:
460 if ToolPathTmp != ToolPath:
461 EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
462
463 BuildOption = {}
464 for Arch in CurrentArchList:
465 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
466 # key is (ToolChainFamily, ToolChain, CodeBase)
467 for item in Platform.BuildOptions:
468 if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]:
469 if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]):
470 if item[1] not in BuildOption:
471 BuildOption[item[1]] = Platform.BuildOptions[item]
472 if BuildOption:
473 ToolList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH]
474 for Index in range(2, -1, -1):
475 for Key in dict(BuildOption):
476 List = Key.split('_')
477 if List[Index] == '*':
478 for String in ToolDb[ToolList[Index]]:
479 if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]:
480 List[Index] = String
481 NewKey = '%s_%s_%s_%s_%s' % tuple(List)
482 if NewKey not in BuildOption:
483 BuildOption[NewKey] = BuildOption[Key]
484 continue
485 del BuildOption[Key]
486 elif List[Index] not in ToolDb[ToolList[Index]]:
487 del BuildOption[Key]
488 if BuildOption:
489 if not KeyList:
490 for Op in BuildOption:
491 if NameGuid == BuildOption[Op]:
492 KeyList = Op.split('_')
493 Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2]
494 if Key in KeyStringList and KeyList[4] == 'GUID':
495 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
496 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
497 if ToolPathKey in BuildOption.keys():
498 ToolPathTmp = BuildOption.get(ToolPathKey)
499 if ToolOptionKey in BuildOption.keys():
500 ToolOption = BuildOption.get(ToolOptionKey)
501
502 GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
503 return ToolPathTmp, ToolOption
504
505 ## Parse command line options
506 #
507 # Using standard Python module optparse to parse command line option of this tool.
508 #
509 # @retval Opt A optparse.Values object containing the parsed options
510 # @retval Args Target of build command
511 #
512 def myOptionParser():
513 usage = "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
514 Parser = OptionParser(usage=usage, description=__copyright__, version="%prog " + str(versionNumber))
515 Parser.add_option("-f", "--file", dest="filename", type="string", help="Name of FDF file to convert", action="callback", callback=SingleCheckCallback)
516 Parser.add_option("-a", "--arch", dest="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM, AARCH64 or EBC which should be built, overrides target.txt?s TARGET_ARCH")
517 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
518 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed.")
519 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
520 Parser.add_option("-p", "--platform", type="string", dest="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
521 action="callback", callback=SingleCheckCallback)
522 Parser.add_option("-w", "--workspace", type="string", dest="Workspace", default=os.environ.get('WORKSPACE'), help="Set the WORKSPACE",
523 action="callback", callback=SingleCheckCallback)
524 Parser.add_option("-o", "--outputDir", type="string", dest="outputDir", help="Name of Build Output directory",
525 action="callback", callback=SingleCheckCallback)
526 Parser.add_option("-r", "--rom_image", dest="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
527 Parser.add_option("-i", "--FvImage", dest="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
528 Parser.add_option("-C", "--CapsuleImage", dest="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
529 Parser.add_option("-b", "--buildtarget", type="string", dest="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
530 action="callback", callback=SingleCheckCallback)
531 Parser.add_option("-t", "--tagname", type="string", dest="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
532 action="callback", callback=SingleCheckCallback)
533 Parser.add_option("-D", "--define", action="append", type="string", dest="Macros", help="Macro: \"Name [= Value]\".")
534 Parser.add_option("-s", "--specifyaddress", dest="FixedAddress", action="store_true", type=None, help="Specify driver load address.")
535 Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")
536 Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")
537 Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
538
539 (Options, args) = Parser.parse_args()
540 return Options
541
542 ## The class implementing the EDK2 flash image generation process
543 #
544 # This process includes:
545 # 1. Collect workspace information, includes platform and module information
546 # 2. Call methods of Fd class to generate FD
547 # 3. Call methods of Fv class to generate FV that not belong to FD
548 #
549 class GenFds :
550 FdfParsef = None
551 # FvName, FdName, CapName in FDF, Image file name
552 ImageBinDict = {}
553 OnlyGenerateThisFd = None
554 OnlyGenerateThisFv = None
555 OnlyGenerateThisCap = None
556
557 ## GenFd()
558 #
559 # @param OutputDir Output directory
560 # @param FdfParser FDF contents parser
561 # @param Workspace The directory of workspace
562 # @param ArchList The Arch list of platform
563 #
564 def GenFd (OutputDir, FdfParser, WorkSpace, ArchList):
565 GenFdsGlobalVariable.SetDir ('', FdfParser, WorkSpace, ArchList)
566
567 GenFdsGlobalVariable.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
568 if GenFds.OnlyGenerateThisCap != None and GenFds.OnlyGenerateThisCap.upper() in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.keys():
569 CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.get(GenFds.OnlyGenerateThisCap.upper())
570 if CapsuleObj != None:
571 CapsuleObj.GenCapsule()
572 return
573
574 if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
575 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(GenFds.OnlyGenerateThisFd.upper())
576 if FdObj != None:
577 FdObj.GenFd()
578 return
579 elif GenFds.OnlyGenerateThisFd == None and GenFds.OnlyGenerateThisFv == None:
580 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
581 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]
582 FdObj.GenFd()
583
584 GenFdsGlobalVariable.VerboseLogger("\n Generate other FV images! ")
585 if GenFds.OnlyGenerateThisFv != None and GenFds.OnlyGenerateThisFv.upper() in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():
586 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(GenFds.OnlyGenerateThisFv.upper())
587 if FvObj != None:
588 Buffer = StringIO.StringIO()
589 FvObj.AddToBuffer(Buffer)
590 Buffer.close()
591 return
592 elif GenFds.OnlyGenerateThisFv == None:
593 for FvName in GenFdsGlobalVariable.FdfParser.Profile.FvDict.keys():
594 Buffer = StringIO.StringIO('')
595 FvObj = GenFdsGlobalVariable.FdfParser.Profile.FvDict[FvName]
596 FvObj.AddToBuffer(Buffer)
597 Buffer.close()
598
599 if GenFds.OnlyGenerateThisFv == None and GenFds.OnlyGenerateThisFd == None and GenFds.OnlyGenerateThisCap == None:
600 if GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict != {}:
601 GenFdsGlobalVariable.VerboseLogger("\n Generate other Capsule images!")
602 for CapsuleName in GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict.keys():
603 CapsuleObj = GenFdsGlobalVariable.FdfParser.Profile.CapsuleDict[CapsuleName]
604 CapsuleObj.GenCapsule()
605
606 if GenFdsGlobalVariable.FdfParser.Profile.OptRomDict != {}:
607 GenFdsGlobalVariable.VerboseLogger("\n Generate all Option ROM!")
608 for DriverName in GenFdsGlobalVariable.FdfParser.Profile.OptRomDict.keys():
609 OptRomObj = GenFdsGlobalVariable.FdfParser.Profile.OptRomDict[DriverName]
610 OptRomObj.AddToBuffer(None)
611
612 ## GetFvBlockSize()
613 #
614 # @param FvObj Whose block size to get
615 # @retval int Block size value
616 #
617 def GetFvBlockSize(FvObj):
618 DefaultBlockSize = 0x1
619 FdObj = None
620 if GenFds.OnlyGenerateThisFd != None and GenFds.OnlyGenerateThisFd.upper() in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
621 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[GenFds.OnlyGenerateThisFd.upper()]
622 if FdObj == None:
623 for ElementFd in GenFdsGlobalVariable.FdfParser.Profile.FdDict.values():
624 for ElementRegion in ElementFd.RegionList:
625 if ElementRegion.RegionType == 'FV':
626 for ElementRegionData in ElementRegion.RegionDataList:
627 if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:
628 if FvObj.BlockSizeList != []:
629 return FvObj.BlockSizeList[0][0]
630 else:
631 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
632 if FvObj.BlockSizeList != []:
633 return FvObj.BlockSizeList[0][0]
634 return DefaultBlockSize
635 else:
636 for ElementRegion in FdObj.RegionList:
637 if ElementRegion.RegionType == 'FV':
638 for ElementRegionData in ElementRegion.RegionDataList:
639 if ElementRegionData != None and ElementRegionData.upper() == FvObj.UiFvName:
640 if FvObj.BlockSizeList != []:
641 return FvObj.BlockSizeList[0][0]
642 else:
643 return ElementRegion.BlockSizeOfRegion(ElementFd.BlockSizeList)
644 return DefaultBlockSize
645
646 ## DisplayFvSpaceInfo()
647 #
648 # @param FvObj Whose block size to get
649 # @retval None
650 #
651 def DisplayFvSpaceInfo(FdfParser):
652
653 FvSpaceInfoList = []
654 MaxFvNameLength = 0
655 for FvName in FdfParser.Profile.FvDict:
656 if len(FvName) > MaxFvNameLength:
657 MaxFvNameLength = len(FvName)
658 FvSpaceInfoFileName = os.path.join(GenFdsGlobalVariable.FvDir, FvName.upper() + '.Fv.map')
659 if os.path.exists(FvSpaceInfoFileName):
660 FileLinesList = linecache.getlines(FvSpaceInfoFileName)
661 TotalFound = False
662 Total = ''
663 UsedFound = False
664 Used = ''
665 FreeFound = False
666 Free = ''
667 for Line in FileLinesList:
668 NameValue = Line.split('=')
669 if len(NameValue) == 2:
670 if NameValue[0].strip() == 'EFI_FV_TOTAL_SIZE':
671 TotalFound = True
672 Total = NameValue[1].strip()
673 if NameValue[0].strip() == 'EFI_FV_TAKEN_SIZE':
674 UsedFound = True
675 Used = NameValue[1].strip()
676 if NameValue[0].strip() == 'EFI_FV_SPACE_SIZE':
677 FreeFound = True
678 Free = NameValue[1].strip()
679
680 if TotalFound and UsedFound and FreeFound:
681 FvSpaceInfoList.append((FvName, Total, Used, Free))
682
683 GenFdsGlobalVariable.InfLogger('\nFV Space Information')
684 for FvSpaceInfo in FvSpaceInfoList:
685 Name = FvSpaceInfo[0]
686 TotalSizeValue = long(FvSpaceInfo[1], 0)
687 UsedSizeValue = long(FvSpaceInfo[2], 0)
688 FreeSizeValue = long(FvSpaceInfo[3], 0)
689 if UsedSizeValue == TotalSizeValue:
690 Percentage = '100'
691 else:
692 Percentage = str((UsedSizeValue + 0.0) / TotalSizeValue)[0:4].lstrip('0.')
693
694 GenFdsGlobalVariable.InfLogger(Name + ' ' + '[' + Percentage + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free')
695
696 ## PreprocessImage()
697 #
698 # @param BuildDb Database from build meta data files
699 # @param DscFile modules from dsc file will be preprocessed
700 # @retval None
701 #
702 def PreprocessImage(BuildDb, DscFile):
703 PcdDict = BuildDb.BuildObject[DscFile, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Pcds
704 PcdValue = ''
705 for Key in PcdDict:
706 PcdObj = PcdDict[Key]
707 if PcdObj.TokenCName == 'PcdBsBaseAddress':
708 PcdValue = PcdObj.DefaultValue
709 break
710
711 if PcdValue == '':
712 return
713
714 Int64PcdValue = long(PcdValue, 0)
715 if Int64PcdValue == 0 or Int64PcdValue < -1:
716 return
717
718 TopAddress = 0
719 if Int64PcdValue > 0:
720 TopAddress = Int64PcdValue
721
722 ModuleDict = BuildDb.BuildObject[DscFile, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].Modules
723 for Key in ModuleDict:
724 ModuleObj = BuildDb.BuildObject[Key, 'COMMON', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
725 print ModuleObj.BaseName + ' ' + ModuleObj.ModuleType
726
727 def GenerateGuidXRefFile(BuildDb, ArchList):
728 GuidXRefFileName = os.path.join(GenFdsGlobalVariable.FvDir, "Guid.xref")
729 GuidXRefFile = StringIO.StringIO('')
730 GuidDict = {}
731 for Arch in ArchList:
732 PlatformDataBase = BuildDb.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
733 for ModuleFile in PlatformDataBase.Modules:
734 Module = BuildDb.BuildObject[ModuleFile, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
735 GuidXRefFile.write("%s %s\n" % (Module.Guid, Module.BaseName))
736 for key, item in Module.Protocols.items():
737 GuidDict[key] = item
738 for key, item in Module.Guids.items():
739 GuidDict[key] = item
740 for key, item in Module.Ppis.items():
741 GuidDict[key] = item
742 # Append GUIDs, Protocols, and PPIs to the Xref file
743 GuidXRefFile.write("\n")
744 for key, item in GuidDict.items():
745 GuidXRefFile.write("%s %s\n" % (GuidStructureStringToGuidString(item).upper(), key))
746
747 if GuidXRefFile.getvalue():
748 SaveFileOnChange(GuidXRefFileName, GuidXRefFile.getvalue(), False)
749 GenFdsGlobalVariable.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName)
750 elif os.path.exists(GuidXRefFileName):
751 os.remove(GuidXRefFileName)
752 GuidXRefFile.close()
753
754 ##Define GenFd as static function
755 GenFd = staticmethod(GenFd)
756 GetFvBlockSize = staticmethod(GetFvBlockSize)
757 DisplayFvSpaceInfo = staticmethod(DisplayFvSpaceInfo)
758 PreprocessImage = staticmethod(PreprocessImage)
759 GenerateGuidXRefFile = staticmethod(GenerateGuidXRefFile)
760
761 if __name__ == '__main__':
762 r = main()
763 ## 0-127 is a safe return range, and 1 is a standard default error
764 if r < 0 or r > 127: r = 1
765 sys.exit(r)
766