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