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
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."
53 ## Tool entrance method
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.
59 # @retval 0 Tool was successful
60 # @retval 1 Tool failed
64 Options
= myOptionParser()
71 EdkLogger
.Initialize()
73 if Options
.verbose
is not None:
74 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
75 GenFdsGlobalVariable
.VerboseMode
= True
77 if Options
.FixedAddress
is not None:
78 GenFdsGlobalVariable
.FixedLoadAddress
= True
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
86 EdkLogger
.SetLevel(EdkLogger
.INFO
)
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.")
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'])
100 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
101 if Options
.GenfdsMultiThread
:
102 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= True
103 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
105 # set multiple workspace
106 PackagesPath
= os
.getenv("PACKAGES_PATH")
107 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
109 if (Options
.filename
):
110 FdfFilename
= Options
.filename
111 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
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
)
120 GenFdsGlobalVariable
.FdfFile
= FdfFilename
121 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
123 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
125 if (Options
.BuildTarget
):
126 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
128 if (Options
.ToolChain
):
129 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
131 if (Options
.activePlatform
):
132 ActivePlatform
= Options
.activePlatform
133 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
135 if ActivePlatform
[0:2] == '..':
136 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
138 if not os
.path
.isabs (ActivePlatform
):
139 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
141 if not os
.path
.exists(ActivePlatform
) :
142 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
144 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
146 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
if Options
.OptionPcd
else {}
147 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
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
)
161 if "CONF_PATH" in os
.environ
:
162 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
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]
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]
189 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
191 #Set global flag for build mode
192 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
195 for Pair
in Options
.Macros
:
196 if Pair
.startswith('"'):
198 if Pair
.endswith('"'):
200 List
= Pair
.split('=')
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
208 elif List
[0].strip() == "EDK_SOURCE":
209 GlobalData
.gEdkSource
= List
[1].strip()
210 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
212 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
213 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
215 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
217 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
218 os
.environ
["WORKSPACE"] = Workspace
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
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()
234 # Get files real name in workspace dir
236 GlobalData
.gAllFiles
= DirCache(Workspace
)
237 GlobalData
.gWorkspace
= Workspace
239 if (Options
.archList
) :
240 ArchList
= Options
.archList
.split(',')
242 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
243 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
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
)))
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
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
260 for Arch
in ArchList
:
261 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
263 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
264 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
265 if OutputDir
[0:2] == '..':
266 OutputDir
= os
.path
.realpath(OutputDir
)
268 if OutputDir
[1] != ':':
269 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
271 if not os
.path
.exists(OutputDir
):
272 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
273 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
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()
279 if FdfParserObj
.CycleReferenceCheck():
280 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
282 if (Options
.uiFdName
) :
283 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
:
284 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
286 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
287 "No such an FD in FDF file: %s" % Options
.uiFdName
)
289 if (Options
.uiFvName
) :
290 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
:
291 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
293 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
294 "No such an FV in FDF file: %s" % Options
.uiFvName
)
296 if (Options
.uiCapName
) :
297 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
:
298 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
300 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
301 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
303 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
304 if ArchList
is not None:
305 GenFdsGlobalVariable
.ArchList
= ArchList
307 # Dsc Build Data will handle Pcd Settings from CommandLine.
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
)
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
:
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
)
328 FvObj
.FvRegionInFD
= RegionObj
.Size
329 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
332 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
334 """Generate GUID cross reference file"""
335 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
337 """Display FV space info."""
338 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
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:
346 EdkLogger
.quiet(traceback
.format_exc())
347 ReturnCode
= X
.args
[0]
353 "Tools code failure",
354 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
357 EdkLogger
.quiet(traceback
.format_exc())
358 ReturnCode
= CODE_ERROR
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
)
369 parser
.error("Option %s only allows one instance in command line!" % option
)
371 ## Parse command line options
373 # Using standard Python module optparse to parse command line option of this tool.
375 # @retval Opt A optparse.Values object containing the parsed options
376 # @retval Args Target of build command
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.")
406 (Options
, args
) = Parser
.parse_args()
409 ## The class implementing the EDK2 flash image generation process
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
418 # FvName, FdName, CapName in FDF, Image file name
420 OnlyGenerateThisFd
= None
421 OnlyGenerateThisFv
= None
422 OnlyGenerateThisCap
= None
426 # @param OutputDir Output directory
427 # @param FdfParser FDF contents parser
428 # @param Workspace The directory of workspace
429 # @param ArchList The Arch list of platform
431 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
432 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
434 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
435 if GenFds
.OnlyGenerateThisCap
is not None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
436 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[GenFds
.OnlyGenerateThisCap
.upper()]
437 if CapsuleObj
is not None:
438 CapsuleObj
.GenCapsule()
441 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
442 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
443 if FdObj
is not None:
446 elif GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisFv
is None:
447 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
450 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
451 if GenFds
.OnlyGenerateThisFv
is not None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
452 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[GenFds
.OnlyGenerateThisFv
.upper()]
453 if FvObj
is not None:
455 FvObj
.AddToBuffer(Buffer
)
458 elif GenFds
.OnlyGenerateThisFv
is None:
459 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
461 FvObj
.AddToBuffer(Buffer
)
464 if GenFds
.OnlyGenerateThisFv
is None and GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisCap
is None:
465 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
466 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
467 for CapsuleObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.values():
468 CapsuleObj
.GenCapsule()
470 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
471 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
472 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
473 OptRomObj
.AddToBuffer(None)
475 def GenFfsMakefile(OutputDir
, FdfParser
, WorkSpace
, ArchList
, GlobalData
):
476 GenFdsGlobalVariable
.SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
)
477 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
478 FdObj
.GenFd(Flag
=True)
480 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
481 FvObj
.AddToBuffer(Buffer
=None, Flag
=True)
483 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
484 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
485 OptRomObj
.AddToBuffer(Buffer
=None, Flag
=True)
487 return GenFdsGlobalVariable
.FfsCmdDict
491 # @param FvObj Whose block size to get
492 # @retval int Block size value
494 def GetFvBlockSize(FvObj
):
495 DefaultBlockSize
= 0x1
497 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
498 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
500 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
501 for ElementRegion
in ElementFd
.RegionList
:
502 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
503 for ElementRegionData
in ElementRegion
.RegionDataList
:
504 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
505 if FvObj
.BlockSizeList
!= []:
506 return FvObj
.BlockSizeList
[0][0]
508 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
509 if FvObj
.BlockSizeList
!= []:
510 return FvObj
.BlockSizeList
[0][0]
511 return DefaultBlockSize
513 for ElementRegion
in FdObj
.RegionList
:
514 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
515 for ElementRegionData
in ElementRegion
.RegionDataList
:
516 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
517 if FvObj
.BlockSizeList
!= []:
518 return FvObj
.BlockSizeList
[0][0]
520 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
521 return DefaultBlockSize
523 ## DisplayFvSpaceInfo()
525 # @param FvObj Whose block size to get
528 def DisplayFvSpaceInfo(FdfParser
):
532 for FvName
in FdfParser
.Profile
.FvDict
:
533 if len(FvName
) > MaxFvNameLength
:
534 MaxFvNameLength
= len(FvName
)
535 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
536 if os
.path
.exists(FvSpaceInfoFileName
):
537 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
544 for Line
in FileLinesList
:
545 NameValue
= Line
.split('=')
546 if len(NameValue
) == 2:
547 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
549 Total
= NameValue
[1].strip()
550 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
552 Used
= NameValue
[1].strip()
553 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
555 Free
= NameValue
[1].strip()
557 if TotalFound
and UsedFound
and FreeFound
:
558 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
560 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
561 for FvSpaceInfo
in FvSpaceInfoList
:
562 Name
= FvSpaceInfo
[0]
563 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
564 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
565 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
566 if UsedSizeValue
== TotalSizeValue
:
569 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
571 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
575 # @param BuildDb Database from build meta data files
576 # @param DscFile modules from dsc file will be preprocessed
579 def PreprocessImage(BuildDb
, DscFile
):
580 PcdDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
583 PcdObj
= PcdDict
[Key
]
584 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
585 PcdValue
= PcdObj
.DefaultValue
591 Int64PcdValue
= long(PcdValue
, 0)
592 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
596 if Int64PcdValue
> 0:
597 TopAddress
= Int64PcdValue
599 ModuleDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
600 for Key
in ModuleDict
:
601 ModuleObj
= BuildDb
.BuildObject
[Key
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
602 print(ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
)
604 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
605 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
606 GuidXRefFile
= BytesIO('')
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 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
619 for key
, item
in Module
.Protocols
.items():
621 for key
, item
in Module
.Guids
.items():
623 for key
, item
in Module
.Ppis
.items():
625 for FvName
in FdfParserObj
.Profile
.FvDict
:
626 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
627 if not isinstance(FfsObj
, FfsFileStatement
.FileStatement
):
628 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
629 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
630 if FdfModule
in ModuleList
:
633 ModuleList
.append(FdfModule
)
634 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
635 for key
, item
in FdfModule
.Protocols
.items():
637 for key
, item
in FdfModule
.Guids
.items():
639 for key
, item
in FdfModule
.Ppis
.items():
642 FileStatementGuid
= FfsObj
.NameGuid
643 if FileStatementGuid
in FileGuidList
:
646 FileGuidList
.append(FileStatementGuid
)
648 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
649 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
652 if not os
.path
.exists(FfsPath
[0]):
655 ReFileEnds
= re
.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
656 FileList
= os
.listdir(FfsPath
[0])
657 for File
in FileList
:
658 Match
= ReFileEnds
.search(File
)
660 for Index
in range(1, 8):
661 if Match
.group(Index
) and Match
.group(Index
) in MatchDict
:
662 MatchDict
[Match
.group(Index
)].append(File
)
663 elif Match
.group(Index
):
664 MatchDict
[Match
.group(Index
)] = [File
]
667 if '.ui' in MatchDict
:
668 for File
in MatchDict
['.ui']:
669 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
673 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
674 Name
= ''.join(chr(c
) for c
in TmpStr
[:-1])
677 if 'fv.sec.txt' in MatchDict
:
678 FileList
= MatchDict
['fv.sec.txt']
679 elif '.pe32.txt' in MatchDict
:
680 FileList
= MatchDict
['.pe32.txt']
681 elif '.te.txt' in MatchDict
:
682 FileList
= MatchDict
['.te.txt']
683 elif '.pic.txt' in MatchDict
:
684 FileList
= MatchDict
['.pic.txt']
685 elif '.raw.txt' in MatchDict
:
686 FileList
= MatchDict
['.raw.txt']
687 elif '.ffs.txt' in MatchDict
:
688 FileList
= MatchDict
['.ffs.txt']
691 for File
in FileList
:
692 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
693 Name
.append((F
.read().split()[-1]))
697 Name
= ' '.join(Name
) if isinstance(Name
, type([])) else Name
698 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
700 # Append GUIDs, Protocols, and PPIs to the Xref file
701 GuidXRefFile
.write("\n")
702 for key
, item
in GuidDict
.items():
703 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
705 if GuidXRefFile
.getvalue():
706 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
707 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
708 elif os
.path
.exists(GuidXRefFileName
):
709 os
.remove(GuidXRefFileName
)
712 ##Define GenFd as static function
713 GenFd
= staticmethod(GenFd
)
714 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
715 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
716 PreprocessImage
= staticmethod(PreprocessImage
)
717 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
719 if __name__
== '__main__':
721 ## 0-127 is a safe return range, and 1 is a standard default error
722 if r
< 0 or r
> 127: r
= 1