4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
18 from __future__
import print_function
19 from __future__
import absolute_import
20 from optparse
import OptionParser
22 import Common
.LongFilePathOs
as os
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
46 from struct
import unpack
47 from Common
.GlobalData
import gGuidPattern
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."
54 ## Tool entrance method
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.
60 # @retval 0 Tool was successful
61 # @retval 1 Tool failed
65 Options
= myOptionParser()
72 EdkLogger
.Initialize()
74 if Options
.verbose
is not None:
75 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
76 GenFdsGlobalVariable
.VerboseMode
= True
78 if Options
.FixedAddress
is not None:
79 GenFdsGlobalVariable
.FixedLoadAddress
= True
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
87 EdkLogger
.SetLevel(EdkLogger
.INFO
)
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.")
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'])
101 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
102 if Options
.GenfdsMultiThread
:
103 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= True
104 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
106 # set multiple workspace
107 PackagesPath
= os
.getenv("PACKAGES_PATH")
108 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
110 if (Options
.filename
):
111 FdfFilename
= Options
.filename
112 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
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
)
121 GenFdsGlobalVariable
.FdfFile
= FdfFilename
122 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
124 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
126 if (Options
.BuildTarget
):
127 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
129 if (Options
.ToolChain
):
130 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
132 if (Options
.activePlatform
):
133 ActivePlatform
= Options
.activePlatform
134 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
136 if ActivePlatform
[0:2] == '..':
137 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
139 if not os
.path
.isabs (ActivePlatform
):
140 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
142 if not os
.path
.exists(ActivePlatform
) :
143 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
145 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
147 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
if Options
.OptionPcd
else {}
148 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
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
)
162 if "CONF_PATH" in os
.environ
:
163 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
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]
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]
190 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
192 #Set global flag for build mode
193 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
196 for Pair
in Options
.Macros
:
197 if Pair
.startswith('"'):
199 if Pair
.endswith('"'):
201 List
= Pair
.split('=')
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
209 elif List
[0].strip() == "EDK_SOURCE":
210 GlobalData
.gEdkSource
= List
[1].strip()
211 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
213 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
214 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
216 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
218 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
219 os
.environ
["WORKSPACE"] = Workspace
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
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()
235 # Get files real name in workspace dir
237 GlobalData
.gAllFiles
= DirCache(Workspace
)
238 GlobalData
.gWorkspace
= Workspace
240 if (Options
.archList
) :
241 ArchList
= Options
.archList
.split(',')
243 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
244 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
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
)))
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
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
261 for Arch
in ArchList
:
262 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
264 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
265 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
266 if OutputDir
[0:2] == '..':
267 OutputDir
= os
.path
.realpath(OutputDir
)
269 if OutputDir
[1] != ':':
270 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
272 if not os
.path
.exists(OutputDir
):
273 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
274 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
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()
280 if FdfParserObj
.CycleReferenceCheck():
281 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
283 if (Options
.uiFdName
) :
284 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
:
285 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
287 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
288 "No such an FD in FDF file: %s" % Options
.uiFdName
)
290 if (Options
.uiFvName
) :
291 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
:
292 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
294 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
295 "No such an FV in FDF file: %s" % Options
.uiFvName
)
297 if (Options
.uiCapName
) :
298 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
:
299 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
301 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
302 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
304 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
305 if ArchList
is not None:
306 GenFdsGlobalVariable
.ArchList
= ArchList
308 # Dsc Build Data will handle Pcd Settings from CommandLine.
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
)
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
:
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
)
329 FvObj
.FvRegionInFD
= RegionObj
.Size
330 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
333 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
335 """Generate GUID cross reference file"""
336 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
338 """Display FV space info."""
339 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
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:
347 EdkLogger
.quiet(traceback
.format_exc())
348 ReturnCode
= X
.args
[0]
354 "Tools code failure",
355 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
358 EdkLogger
.quiet(traceback
.format_exc())
359 ReturnCode
= CODE_ERROR
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
)
370 parser
.error("Option %s only allows one instance in command line!" % option
)
372 ## Parse command line options
374 # Using standard Python module optparse to parse command line option of this tool.
376 # @retval Opt A optparse.Values object containing the parsed options
377 # @retval Args Target of build command
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.")
407 (Options
, args
) = Parser
.parse_args()
410 ## The class implementing the EDK2 flash image generation process
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
419 OnlyGenerateThisFd
= None
420 OnlyGenerateThisFv
= None
421 OnlyGenerateThisCap
= None
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
430 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
431 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
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()
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:
445 elif GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisFv
is None:
446 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
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:
454 FvObj
.AddToBuffer(Buffer
)
457 elif GenFds
.OnlyGenerateThisFv
is None:
458 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
460 FvObj
.AddToBuffer(Buffer
)
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()
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)
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)
479 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
480 FvObj
.AddToBuffer(Buffer
=None, Flag
=True)
482 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
483 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
484 OptRomObj
.AddToBuffer(Buffer
=None, Flag
=True)
486 return GenFdsGlobalVariable
.FfsCmdDict
490 # @param FvObj Whose block size to get
491 # @retval int Block size value
493 def GetFvBlockSize(FvObj
):
494 DefaultBlockSize
= 0x1
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()]
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]
507 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
508 if FvObj
.BlockSizeList
!= []:
509 return FvObj
.BlockSizeList
[0][0]
510 return DefaultBlockSize
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]
519 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
520 return DefaultBlockSize
522 ## DisplayFvSpaceInfo()
524 # @param FvObj Whose block size to get
527 def DisplayFvSpaceInfo(FdfParser
):
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
)
543 for Line
in FileLinesList
:
544 NameValue
= Line
.split('=')
545 if len(NameValue
) == 2:
546 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
548 Total
= NameValue
[1].strip()
549 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
551 Used
= NameValue
[1].strip()
552 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
554 Free
= NameValue
[1].strip()
556 if TotalFound
and UsedFound
and FreeFound
:
557 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
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
:
568 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
570 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
574 # @param BuildDb Database from build meta data files
575 # @param DscFile modules from dsc file will be preprocessed
578 def PreprocessImage(BuildDb
, DscFile
):
579 PcdDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
582 PcdObj
= PcdDict
[Key
]
583 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
584 PcdValue
= PcdObj
.DefaultValue
590 Int64PcdValue
= long(PcdValue
, 0)
591 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
595 if Int64PcdValue
> 0:
596 TopAddress
= Int64PcdValue
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
)
603 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
604 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
605 GuidXRefFile
= BytesIO('')
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
:
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
))
622 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
623 for key
, item
in Module
.Protocols
.items():
625 for key
, item
in Module
.Guids
.items():
627 for key
, item
in Module
.Ppis
.items():
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
:
637 ModuleList
.append(FdfModule
)
638 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
639 for key
, item
in FdfModule
.Protocols
.items():
641 for key
, item
in FdfModule
.Guids
.items():
643 for key
, item
in FdfModule
.Ppis
.items():
646 FileStatementGuid
= FfsObj
.NameGuid
647 if FileStatementGuid
in FileGuidList
:
650 FileGuidList
.append(FileStatementGuid
)
652 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
653 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
656 if not os
.path
.exists(FfsPath
[0]):
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
)
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
]
671 if '.ui' in MatchDict
:
672 for File
in MatchDict
['.ui']:
673 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
677 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
678 Name
= ''.join(chr(c
) for c
in TmpStr
[:-1])
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']
695 for File
in FileList
:
696 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
697 Name
.append((F
.read().split()[-1]))
701 Name
= ' '.join(Name
) if isinstance(Name
, type([])) else Name
702 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
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
))
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
)
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
)
723 if __name__
== '__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