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