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