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 re
import compile
21 from optparse
import OptionParser
24 from struct
import unpack
25 from linecache
import getlines
26 from io
import BytesIO
28 import Common
.LongFilePathOs
as os
29 from Common
.TargetTxtClassObject
import TargetTxtClassObject
30 from Common
.DataType
import *
31 import Common
.GlobalData
as GlobalData
32 from Common
import EdkLogger
33 from Common
.StringUtils
import NormPath
34 from Common
.Misc
import DirCache
, PathClass
, GuidStructureStringToGuidString
35 from Common
.Misc
import SaveFileOnChange
, ClearDuplicatedInf
36 from Common
.BuildVersion
import gBUILD_VERSION
37 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
38 from Common
.BuildToolError
import FatalError
, GENFDS_ERROR
, CODE_ERROR
, FORMAT_INVALID
, RESOURCE_NOT_AVAILABLE
, FILE_NOT_FOUND
, OPTION_MISSING
, FORMAT_NOT_SUPPORTED
,OPTION_VALUE_INVALID
39 from Workspace
.WorkspaceDatabase
import WorkspaceDatabase
41 from .FdfParser
import FdfParser
, Warning
42 from .GenFdsGlobalVariable
import GenFdsGlobalVariable
43 from .FfsFileStatement
import FileStatement
45 ## Version and Copyright
46 versionNumber
= "1.0" + ' ' + gBUILD_VERSION
47 __version__
= "%prog Version " + versionNumber
48 __copyright__
= "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."
50 ## Tool entrance method
52 # This method mainly dispatch specific methods per the command line options.
53 # If no error found, return zero value so the caller of this tool can know
54 # if it's executed successfully or not.
56 # @retval 0 Tool was successful
57 # @retval 1 Tool failed
61 Options
= myOptionParser()
68 EdkLogger
.Initialize()
71 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
72 GenFdsGlobalVariable
.VerboseMode
= True
74 if Options
.FixedAddress
:
75 GenFdsGlobalVariable
.FixedLoadAddress
= True
78 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
80 EdkLogger
.SetLevel(Options
.debug
+ 1)
81 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
83 EdkLogger
.SetLevel(EdkLogger
.INFO
)
85 if not Options
.Workspace
:
86 EdkLogger
.error("GenFds", OPTION_MISSING
, "WORKSPACE not defined",
87 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
88 elif not os
.path
.exists(Options
.Workspace
):
89 EdkLogger
.error("GenFds", PARAMETER_INVALID
, "WORKSPACE is invalid",
90 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
92 Workspace
= os
.path
.normcase(Options
.Workspace
)
93 GenFdsGlobalVariable
.WorkSpaceDir
= Workspace
94 if 'EDK_SOURCE' in os
.environ
:
95 GenFdsGlobalVariable
.EdkSourceDir
= os
.path
.normcase(os
.environ
['EDK_SOURCE'])
97 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
98 if Options
.GenfdsMultiThread
:
99 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= True
100 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
102 # set multiple workspace
103 PackagesPath
= os
.getenv("PACKAGES_PATH")
104 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
107 FdfFilename
= Options
.filename
108 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
110 if FdfFilename
[0:2] == '..':
111 FdfFilename
= os
.path
.realpath(FdfFilename
)
112 if not os
.path
.isabs(FdfFilename
):
113 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
114 if not os
.path
.exists(FdfFilename
):
115 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
117 GenFdsGlobalVariable
.FdfFile
= FdfFilename
118 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
120 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
122 if Options
.BuildTarget
:
123 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
125 if Options
.ToolChain
:
126 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
128 if Options
.activePlatform
:
129 ActivePlatform
= Options
.activePlatform
130 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
132 if ActivePlatform
[0:2] == '..':
133 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
135 if not os
.path
.isabs (ActivePlatform
):
136 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
138 if not os
.path
.exists(ActivePlatform
):
139 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
141 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
143 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
if Options
.OptionPcd
else {}
144 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
146 if Options
.ConfDirectory
:
147 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
148 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
149 if ConfDirectoryPath
.startswith('"'):
150 ConfDirectoryPath
= ConfDirectoryPath
[1:]
151 if ConfDirectoryPath
.endswith('"'):
152 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
153 if not os
.path
.isabs(ConfDirectoryPath
):
154 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
155 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
156 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
158 if "CONF_PATH" in os
.environ
:
159 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
161 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
162 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
163 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
164 if not GlobalData
.gConfDirectory
:
165 GlobalData
.gConfDirectory
= GenFdsGlobalVariable
.ConfDir
166 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
167 if os
.path
.isfile(BuildConfigurationFile
) == True:
168 TargetTxt
= TargetTxtClassObject()
169 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
170 # if no build target given in command line, get it from target.txt
171 if not GenFdsGlobalVariable
.TargetName
:
172 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
173 if len(BuildTargetList
) != 1:
174 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
175 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
177 # if no tool chain given in command line, get it from target.txt
178 if not GenFdsGlobalVariable
.ToolChainTag
:
179 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
180 if ToolChainList
is None or len(ToolChainList
) == 0:
181 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
182 if len(ToolChainList
) != 1:
183 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
184 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
186 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
188 #Set global flag for build mode
189 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
192 for Pair
in Options
.Macros
:
193 if Pair
.startswith('"'):
195 if Pair
.endswith('"'):
197 List
= Pair
.split('=')
199 if not List
[1].strip():
200 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
201 if List
[0].strip() == "EFI_SOURCE":
202 GlobalData
.gEfiSource
= List
[1].strip()
203 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
205 elif List
[0].strip() == "EDK_SOURCE":
206 GlobalData
.gEdkSource
= List
[1].strip()
207 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
209 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
210 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
212 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
214 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
215 os
.environ
["WORKSPACE"] = Workspace
217 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
218 if "TARGET" not in GlobalData
.gGlobalDefines
:
219 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
220 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
:
221 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
222 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
:
223 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
225 """call Workspace build create database"""
226 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
227 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
228 BuildWorkSpace
.InitDatabase()
231 # Get files real name in workspace dir
233 GlobalData
.gAllFiles
= DirCache(Workspace
)
234 GlobalData
.gWorkspace
= Workspace
237 ArchList
= Options
.archList
.split(',')
239 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
241 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
242 if len(TargetArchList
) == 0:
243 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList
), str(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
].SupArchList
)))
245 for Arch
in ArchList
:
246 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
248 # assign platform name based on last entry in ArchList
249 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, ArchList
[-1], Options
.BuildTarget
, Options
.ToolChain
].PlatformName
251 if Options
.outputDir
:
252 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
253 if not os
.path
.isabs (OutputDirFromCommandLine
):
254 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
255 for Arch
in ArchList
:
256 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
258 for Arch
in ArchList
:
259 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
261 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
262 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
263 if OutputDir
[0:2] == '..':
264 OutputDir
= os
.path
.realpath(OutputDir
)
266 if OutputDir
[1] != ':':
267 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
269 if not os
.path
.exists(OutputDir
):
270 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
271 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
273 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
274 FdfParserObj
= FdfParser(FdfFilename
)
275 FdfParserObj
.ParseFile()
277 if FdfParserObj
.CycleReferenceCheck():
278 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
281 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
:
282 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
284 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
285 "No such an FD in FDF file: %s" % Options
.uiFdName
)
288 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
:
289 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
291 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
292 "No such an FV in FDF file: %s" % Options
.uiFvName
)
294 if Options
.uiCapName
:
295 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
:
296 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
298 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
299 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
301 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
303 GenFdsGlobalVariable
.ArchList
= ArchList
305 # Dsc Build Data will handle Pcd Settings from CommandLine.
307 """Modify images from build output if the feature of loading driver at fixed address is on."""
308 if GenFdsGlobalVariable
.FixedLoadAddress
:
309 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
311 # Record the FV Region info that may specific in the FD
312 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
313 for FvObj
in FdfParserObj
.Profile
.FvDict
.values():
314 for FdObj
in FdfParserObj
.Profile
.FdDict
.values():
315 for RegionObj
in FdObj
.RegionList
:
316 if RegionObj
.RegionType
!= BINARY_FILE_TYPE_FV
:
318 for RegionData
in RegionObj
.RegionDataList
:
319 if FvObj
.UiFvName
.upper() == RegionData
.upper():
320 if FvObj
.FvRegionInFD
:
321 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
322 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
324 FvObj
.FvRegionInFD
= RegionObj
.Size
325 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
328 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
330 """Generate GUID cross reference file"""
331 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
333 """Display FV space info."""
334 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
337 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
338 ReturnCode
= FORMAT_INVALID
339 except FatalError
as X
:
340 if Options
.debug
is not None:
342 EdkLogger
.quiet(traceback
.format_exc())
343 ReturnCode
= X
.args
[0]
349 "Tools code failure",
350 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
353 EdkLogger
.quiet(traceback
.format_exc())
354 ReturnCode
= CODE_ERROR
360 def SingleCheckCallback(option
, opt_str
, value
, parser
):
361 if option
not in gParamCheck
:
362 setattr(parser
.values
, option
.dest
, value
)
363 gParamCheck
.append(option
)
365 parser
.error("Option %s only allows one instance in command line!" % option
)
367 ## Parse command line options
369 # Using standard Python module optparse to parse command line option of this tool.
371 # @retval Opt A optparse.Values object containing the parsed options
373 def myOptionParser():
374 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
375 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
376 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
377 Parser
.add_option("-a", "--arch", dest
="archList", help="comma separated list containing one or more of: IA32, X64, IPF, ARM, AARCH64 or EBC which should be built, overrides target.txt?s TARGET_ARCH")
378 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
379 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
380 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
381 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
382 action
="callback", callback
=SingleCheckCallback
)
383 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
384 action
="callback", callback
=SingleCheckCallback
)
385 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
386 action
="callback", callback
=SingleCheckCallback
)
387 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
388 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
389 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
390 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
391 action
="callback", callback
=SingleCheckCallback
)
392 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
393 action
="callback", callback
=SingleCheckCallback
)
394 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
395 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
396 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
397 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
398 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
399 Parser
.add_option("--genfds-multi-thread", action
="store_true", dest
="GenfdsMultiThread", default
=False, help="Enable GenFds multi thread to generate ffs file.")
401 Options
, _
= Parser
.parse_args()
404 ## The class implementing the EDK2 flash image generation process
406 # This process includes:
407 # 1. Collect workspace information, includes platform and module information
408 # 2. Call methods of Fd class to generate FD
409 # 3. Call methods of Fv class to generate FV that not belong to FD
411 class GenFds(object):
413 OnlyGenerateThisFd
= None
414 OnlyGenerateThisFv
= None
415 OnlyGenerateThisCap
= None
419 # @param OutputDir Output directory
420 # @param FdfParserObject FDF contents parser
421 # @param Workspace The directory of workspace
422 # @param ArchList The Arch list of platform
425 def GenFd (OutputDir
, FdfParserObject
, WorkSpace
, ArchList
):
426 GenFdsGlobalVariable
.SetDir ('', FdfParserObject
, WorkSpace
, ArchList
)
428 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
429 if GenFds
.OnlyGenerateThisCap
is not None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
430 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[GenFds
.OnlyGenerateThisCap
.upper()]
431 if CapsuleObj
is not None:
432 CapsuleObj
.GenCapsule()
435 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
436 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
437 if FdObj
is not None:
440 elif GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisFv
is None:
441 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
444 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
445 if GenFds
.OnlyGenerateThisFv
is not None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
446 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[GenFds
.OnlyGenerateThisFv
.upper()]
447 if FvObj
is not None:
449 FvObj
.AddToBuffer(Buffer
)
452 elif GenFds
.OnlyGenerateThisFv
is None:
453 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
455 FvObj
.AddToBuffer(Buffer
)
458 if GenFds
.OnlyGenerateThisFv
is None and GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisCap
is None:
459 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
460 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
461 for CapsuleObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.values():
462 CapsuleObj
.GenCapsule()
464 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
465 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
466 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
467 OptRomObj
.AddToBuffer(None)
470 def GenFfsMakefile(OutputDir
, FdfParserObject
, WorkSpace
, ArchList
, GlobalData
):
471 GenFdsGlobalVariable
.SetEnv(FdfParserObject
, WorkSpace
, ArchList
, GlobalData
)
472 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
473 FdObj
.GenFd(Flag
=True)
475 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
476 FvObj
.AddToBuffer(Buffer
=None, Flag
=True)
478 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
479 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
480 OptRomObj
.AddToBuffer(Buffer
=None, Flag
=True)
482 return GenFdsGlobalVariable
.FfsCmdDict
486 # @param FvObj Whose block size to get
487 # @retval int Block size value
490 def GetFvBlockSize(FvObj
):
491 DefaultBlockSize
= 0x1
493 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
494 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
496 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
497 for ElementRegion
in ElementFd
.RegionList
:
498 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
499 for ElementRegionData
in ElementRegion
.RegionDataList
:
500 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
501 if FvObj
.BlockSizeList
!= []:
502 return FvObj
.BlockSizeList
[0][0]
504 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
505 if FvObj
.BlockSizeList
!= []:
506 return FvObj
.BlockSizeList
[0][0]
507 return DefaultBlockSize
509 for ElementRegion
in FdObj
.RegionList
:
510 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
511 for ElementRegionData
in ElementRegion
.RegionDataList
:
512 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
513 if FvObj
.BlockSizeList
!= []:
514 return FvObj
.BlockSizeList
[0][0]
516 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
517 return DefaultBlockSize
519 ## DisplayFvSpaceInfo()
521 # @param FvObj Whose block size to get
525 def DisplayFvSpaceInfo(FdfParserObject
):
529 for FvName
in FdfParserObject
.Profile
.FvDict
:
530 if len(FvName
) > MaxFvNameLength
:
531 MaxFvNameLength
= len(FvName
)
532 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
533 if os
.path
.exists(FvSpaceInfoFileName
):
534 FileLinesList
= getlines(FvSpaceInfoFileName
)
541 for Line
in FileLinesList
:
542 NameValue
= Line
.split('=')
543 if len(NameValue
) == 2:
544 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
546 Total
= NameValue
[1].strip()
547 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
549 Used
= NameValue
[1].strip()
550 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
552 Free
= NameValue
[1].strip()
554 if TotalFound
and UsedFound
and FreeFound
:
555 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
557 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
558 for FvSpaceInfo
in FvSpaceInfoList
:
559 Name
= FvSpaceInfo
[0]
560 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
561 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
562 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
563 if UsedSizeValue
== TotalSizeValue
:
566 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
568 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
572 # @param BuildDb Database from build meta data files
573 # @param DscFile modules from dsc file will be preprocessed
577 def PreprocessImage(BuildDb
, DscFile
):
578 PcdDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
581 PcdObj
= PcdDict
[Key
]
582 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
583 PcdValue
= PcdObj
.DefaultValue
589 Int64PcdValue
= long(PcdValue
, 0)
590 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
594 if Int64PcdValue
> 0:
595 TopAddress
= Int64PcdValue
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
)
603 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
604 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
605 GuidXRefFile
= BytesIO('')
610 for Arch
in ArchList
:
611 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
612 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
614 PkgGuidDict
.update(P
.Guids
)
615 for Name
, Guid
in PlatformDataBase
.Pcds
:
616 Pcd
= PlatformDataBase
.Pcds
[Name
, Guid
]
617 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_HII
, TAB_PCDS_DYNAMIC_EX_HII
]:
618 for SkuId
in Pcd
.SkuInfoList
:
619 Sku
= Pcd
.SkuInfoList
[SkuId
]
620 if Sku
.VariableGuid
and Sku
.VariableGuid
in PkgGuidDict
.keys():
621 GuidDict
[Sku
.VariableGuid
] = PkgGuidDict
[Sku
.VariableGuid
]
622 for ModuleFile
in PlatformDataBase
.Modules
:
623 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
624 if Module
in ModuleList
:
627 ModuleList
.append(Module
)
628 if GlobalData
.gGuidPattern
.match(ModuleFile
.BaseName
):
629 GuidXRefFile
.write("%s %s\n" % (ModuleFile
.BaseName
, Module
.BaseName
))
631 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
632 GuidDict
.update(Module
.Protocols
)
633 GuidDict
.update(Module
.Guids
)
634 GuidDict
.update(Module
.Ppis
)
635 for FvName
in FdfParserObj
.Profile
.FvDict
:
636 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
637 if not isinstance(FfsObj
, FileStatement
):
638 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
639 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
640 if FdfModule
in ModuleList
:
643 ModuleList
.append(FdfModule
)
644 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
645 GuidDict
.update(FdfModule
.Protocols
)
646 GuidDict
.update(FdfModule
.Guids
)
647 GuidDict
.update(FdfModule
.Ppis
)
649 FileStatementGuid
= FfsObj
.NameGuid
650 if FileStatementGuid
in FileGuidList
:
653 FileGuidList
.append(FileStatementGuid
)
655 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
656 FfsPath
= glob(os
.path
.join(FfsPath
, FileStatementGuid
) + TAB_STAR
)
659 if not os
.path
.exists(FfsPath
[0]):
662 ReFileEnds
= compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
663 FileList
= os
.listdir(FfsPath
[0])
664 for File
in FileList
:
665 Match
= ReFileEnds
.search(File
)
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
]
674 if '.ui' in MatchDict
:
675 for File
in MatchDict
['.ui']:
676 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
680 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
681 Name
= ''.join(chr(c
) for c
in TmpStr
[:-1])
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']
698 for File
in FileList
:
699 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
700 Name
.append((F
.read().split()[-1]))
704 Name
= ' '.join(Name
) if isinstance(Name
, type([])) else Name
705 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
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
))
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
)
719 if __name__
== '__main__':
721 ## 0-127 is a safe return range, and 1 is a standard default error