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