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