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