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 optparse
import OptionParser
20 import Common
.LongFilePathOs
as os
22 from . import FdfParser
23 import Common
.BuildToolError
as BuildToolError
24 from .GenFdsGlobalVariable
import GenFdsGlobalVariable
25 from Workspace
.WorkspaceDatabase
import WorkspaceDatabase
26 from Workspace
.BuildClassObject
import PcdClassObject
27 from . import RuleComplexFile
28 from .EfiSection
import EfiSection
29 from io
import BytesIO
30 import Common
.TargetTxtClassObject
as TargetTxtClassObject
31 import Common
.ToolDefClassObject
as ToolDefClassObject
32 from Common
.DataType
import *
33 import Common
.GlobalData
as GlobalData
34 from Common
import EdkLogger
35 from Common
.StringUtils
import *
36 from Common
.Misc
import DirCache
, PathClass
37 from Common
.Misc
import SaveFileOnChange
38 from Common
.Misc
import ClearDuplicatedInf
39 from Common
.Misc
import GuidStructureStringToGuidString
40 from Common
.BuildVersion
import gBUILD_VERSION
41 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
42 from . import FfsFileStatement
44 from struct
import unpack
45 from Common
.GlobalData
import gGuidPattern
47 ## Version and Copyright
48 versionNumber
= "1.0" + ' ' + gBUILD_VERSION
49 __version__
= "%prog Version " + versionNumber
50 __copyright__
= "Copyright (c) 2007 - 2018, Intel Corporation All rights reserved."
52 ## Tool entrance method
54 # This method mainly dispatch specific methods per the command line options.
55 # If no error found, return zero value so the caller of this tool can know
56 # if it's executed successfully or not.
58 # @retval 0 Tool was successful
59 # @retval 1 Tool failed
63 Options
= myOptionParser()
70 EdkLogger
.Initialize()
72 if Options
.verbose
is not None:
73 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
74 GenFdsGlobalVariable
.VerboseMode
= True
76 if Options
.FixedAddress
is not None:
77 GenFdsGlobalVariable
.FixedLoadAddress
= True
79 if Options
.quiet
is not None:
80 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
81 if Options
.debug
is not None:
82 EdkLogger
.SetLevel(Options
.debug
+ 1)
83 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
85 EdkLogger
.SetLevel(EdkLogger
.INFO
)
87 if (Options
.Workspace
is None):
88 EdkLogger
.error("GenFds", OPTION_MISSING
, "WORKSPACE not defined",
89 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
90 elif not os
.path
.exists(Options
.Workspace
):
91 EdkLogger
.error("GenFds", PARAMETER_INVALID
, "WORKSPACE is invalid",
92 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
94 Workspace
= os
.path
.normcase(Options
.Workspace
)
95 GenFdsGlobalVariable
.WorkSpaceDir
= Workspace
96 if 'EDK_SOURCE' in os
.environ
:
97 GenFdsGlobalVariable
.EdkSourceDir
= os
.path
.normcase(os
.environ
['EDK_SOURCE'])
99 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
100 if Options
.GenfdsMultiThread
:
101 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= True
102 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
104 # set multiple workspace
105 PackagesPath
= os
.getenv("PACKAGES_PATH")
106 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
108 if (Options
.filename
):
109 FdfFilename
= Options
.filename
110 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
112 if FdfFilename
[0:2] == '..':
113 FdfFilename
= os
.path
.realpath(FdfFilename
)
114 if not os
.path
.isabs(FdfFilename
):
115 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
116 if not os
.path
.exists(FdfFilename
):
117 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
119 GenFdsGlobalVariable
.FdfFile
= FdfFilename
120 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
122 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
124 if (Options
.BuildTarget
):
125 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
127 if (Options
.ToolChain
):
128 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
130 if (Options
.activePlatform
):
131 ActivePlatform
= Options
.activePlatform
132 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
134 if ActivePlatform
[0:2] == '..':
135 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
137 if not os
.path
.isabs (ActivePlatform
):
138 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
140 if not os
.path
.exists(ActivePlatform
) :
141 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
143 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
145 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
if Options
.OptionPcd
else {}
146 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
148 if (Options
.ConfDirectory
):
149 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
150 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
151 if ConfDirectoryPath
.startswith('"'):
152 ConfDirectoryPath
= ConfDirectoryPath
[1:]
153 if ConfDirectoryPath
.endswith('"'):
154 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
155 if not os
.path
.isabs(ConfDirectoryPath
):
156 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
157 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
158 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
160 if "CONF_PATH" in os
.environ
:
161 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
163 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
164 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
165 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
166 if not GlobalData
.gConfDirectory
:
167 GlobalData
.gConfDirectory
= GenFdsGlobalVariable
.ConfDir
168 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
169 if os
.path
.isfile(BuildConfigurationFile
) == True:
170 TargetTxt
= TargetTxtClassObject
.TargetTxtClassObject()
171 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
172 # if no build target given in command line, get it from target.txt
173 if not GenFdsGlobalVariable
.TargetName
:
174 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
175 if len(BuildTargetList
) != 1:
176 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
177 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
179 # if no tool chain given in command line, get it from target.txt
180 if not GenFdsGlobalVariable
.ToolChainTag
:
181 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
182 if ToolChainList
is None or len(ToolChainList
) == 0:
183 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
184 if len(ToolChainList
) != 1:
185 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
186 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
188 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
190 #Set global flag for build mode
191 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
194 for Pair
in Options
.Macros
:
195 if Pair
.startswith('"'):
197 if Pair
.endswith('"'):
199 List
= Pair
.split('=')
201 if not List
[1].strip():
202 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
203 if List
[0].strip() == "EFI_SOURCE":
204 GlobalData
.gEfiSource
= List
[1].strip()
205 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
207 elif List
[0].strip() == "EDK_SOURCE":
208 GlobalData
.gEdkSource
= List
[1].strip()
209 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
211 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
212 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
214 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
216 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
217 os
.environ
["WORKSPACE"] = Workspace
219 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
220 if "TARGET" not in GlobalData
.gGlobalDefines
:
221 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
222 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
:
223 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
224 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
:
225 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
227 """call Workspace build create database"""
228 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
229 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
230 BuildWorkSpace
.InitDatabase()
233 # Get files real name in workspace dir
235 GlobalData
.gAllFiles
= DirCache(Workspace
)
236 GlobalData
.gWorkspace
= Workspace
238 if (Options
.archList
) :
239 ArchList
= Options
.archList
.split(',')
241 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
242 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
244 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, TAB_COMMON
, Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
245 if len(TargetArchList
) == 0:
246 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 for Arch
in ArchList
:
249 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
250 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].PlatformName
252 if (Options
.outputDir
):
253 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
254 if not os
.path
.isabs (OutputDirFromCommandLine
):
255 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
256 for Arch
in ArchList
:
257 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
259 for Arch
in ArchList
:
260 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
262 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
263 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
264 if OutputDir
[0:2] == '..':
265 OutputDir
= os
.path
.realpath(OutputDir
)
267 if OutputDir
[1] != ':':
268 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
270 if not os
.path
.exists(OutputDir
):
271 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
272 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
274 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
275 FdfParserObj
= FdfParser
.FdfParser(FdfFilename
)
276 FdfParserObj
.ParseFile()
278 if FdfParserObj
.CycleReferenceCheck():
279 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
281 if (Options
.uiFdName
) :
282 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
:
283 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
285 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
286 "No such an FD in FDF file: %s" % Options
.uiFdName
)
288 if (Options
.uiFvName
) :
289 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
:
290 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
292 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
293 "No such an FV in FDF file: %s" % Options
.uiFvName
)
295 if (Options
.uiCapName
) :
296 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
:
297 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
299 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
300 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
302 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
303 if ArchList
is not None:
304 GenFdsGlobalVariable
.ArchList
= ArchList
306 # Dsc Build Data will handle Pcd Settings from CommandLine.
308 """Modify images from build output if the feature of loading driver at fixed address is on."""
309 if GenFdsGlobalVariable
.FixedLoadAddress
:
310 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
312 # Record the FV Region info that may specific in the FD
313 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
314 for Fv
in FdfParserObj
.Profile
.FvDict
:
315 FvObj
= FdfParserObj
.Profile
.FvDict
[Fv
]
316 for Fd
in FdfParserObj
.Profile
.FdDict
:
317 FdObj
= FdfParserObj
.Profile
.FdDict
[Fd
]
318 for RegionObj
in FdObj
.RegionList
:
319 if RegionObj
.RegionType
!= BINARY_FILE_TYPE_FV
:
321 for RegionData
in RegionObj
.RegionDataList
:
322 if FvObj
.UiFvName
.upper() == RegionData
.upper():
323 if FvObj
.FvRegionInFD
:
324 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
325 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
327 FvObj
.FvRegionInFD
= RegionObj
.Size
328 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
331 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
333 """Generate GUID cross reference file"""
334 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
336 """Display FV space info."""
337 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
339 except FdfParser
.Warning as X
:
340 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
341 ReturnCode
= FORMAT_INVALID
342 except FatalError
as X
:
343 if Options
.debug
is not None:
345 EdkLogger
.quiet(traceback
.format_exc())
346 ReturnCode
= X
.args
[0]
352 "Tools code failure",
353 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
356 EdkLogger
.quiet(traceback
.format_exc())
357 ReturnCode
= CODE_ERROR
363 def SingleCheckCallback(option
, opt_str
, value
, parser
):
364 if option
not in gParamCheck
:
365 setattr(parser
.values
, option
.dest
, value
)
366 gParamCheck
.append(option
)
368 parser
.error("Option %s only allows one instance in command line!" % option
)
370 ## Parse command line options
372 # Using standard Python module optparse to parse command line option of this tool.
374 # @retval Opt A optparse.Values object containing the parsed options
375 # @retval Args Target of build command
377 def myOptionParser():
378 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
379 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
380 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
381 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")
382 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
383 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
384 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
385 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
386 action
="callback", callback
=SingleCheckCallback
)
387 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
388 action
="callback", callback
=SingleCheckCallback
)
389 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
390 action
="callback", callback
=SingleCheckCallback
)
391 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
392 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
393 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
394 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
395 action
="callback", callback
=SingleCheckCallback
)
396 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
397 action
="callback", callback
=SingleCheckCallback
)
398 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
399 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
400 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
401 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
402 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
403 Parser
.add_option("--genfds-multi-thread", action
="store_true", dest
="GenfdsMultiThread", default
=False, help="Enable GenFds multi thread to generate ffs file.")
405 (Options
, args
) = Parser
.parse_args()
408 ## The class implementing the EDK2 flash image generation process
410 # This process includes:
411 # 1. Collect workspace information, includes platform and module information
412 # 2. Call methods of Fd class to generate FD
413 # 3. Call methods of Fv class to generate FV that not belong to FD
417 OnlyGenerateThisFd
= None
418 OnlyGenerateThisFv
= None
419 OnlyGenerateThisCap
= None
423 # @param OutputDir Output directory
424 # @param FdfParser FDF contents parser
425 # @param Workspace The directory of workspace
426 # @param ArchList The Arch list of platform
428 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
429 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
431 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
432 if GenFds
.OnlyGenerateThisCap
is not None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
433 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[GenFds
.OnlyGenerateThisCap
.upper()]
434 if CapsuleObj
is not None:
435 CapsuleObj
.GenCapsule()
438 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
439 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
440 if FdObj
is not None:
443 elif GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisFv
is None:
444 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
447 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
448 if GenFds
.OnlyGenerateThisFv
is not None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
449 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[GenFds
.OnlyGenerateThisFv
.upper()]
450 if FvObj
is not None:
452 FvObj
.AddToBuffer(Buffer
)
455 elif GenFds
.OnlyGenerateThisFv
is None:
456 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
458 FvObj
.AddToBuffer(Buffer
)
461 if GenFds
.OnlyGenerateThisFv
is None and GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisCap
is None:
462 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
463 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
464 for CapsuleObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.values():
465 CapsuleObj
.GenCapsule()
467 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
468 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
469 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
470 OptRomObj
.AddToBuffer(None)
472 def GenFfsMakefile(OutputDir
, FdfParser
, WorkSpace
, ArchList
, GlobalData
):
473 GenFdsGlobalVariable
.SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
)
474 for FdObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
475 FdObj
.GenFd(Flag
=True)
477 for FvObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.values():
478 FvObj
.AddToBuffer(Buffer
=None, Flag
=True)
480 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
481 for OptRomObj
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.values():
482 OptRomObj
.AddToBuffer(Buffer
=None, Flag
=True)
484 return GenFdsGlobalVariable
.FfsCmdDict
488 # @param FvObj Whose block size to get
489 # @retval int Block size value
491 def GetFvBlockSize(FvObj
):
492 DefaultBlockSize
= 0x1
494 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
:
495 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
497 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
498 for ElementRegion
in ElementFd
.RegionList
:
499 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
500 for ElementRegionData
in ElementRegion
.RegionDataList
:
501 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
502 if FvObj
.BlockSizeList
!= []:
503 return FvObj
.BlockSizeList
[0][0]
505 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
506 if FvObj
.BlockSizeList
!= []:
507 return FvObj
.BlockSizeList
[0][0]
508 return DefaultBlockSize
510 for ElementRegion
in FdObj
.RegionList
:
511 if ElementRegion
.RegionType
== BINARY_FILE_TYPE_FV
:
512 for ElementRegionData
in ElementRegion
.RegionDataList
:
513 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
514 if FvObj
.BlockSizeList
!= []:
515 return FvObj
.BlockSizeList
[0][0]
517 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
518 return DefaultBlockSize
520 ## DisplayFvSpaceInfo()
522 # @param FvObj Whose block size to get
525 def DisplayFvSpaceInfo(FdfParser
):
529 for FvName
in FdfParser
.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
= linecache
.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
576 def PreprocessImage(BuildDb
, DscFile
):
577 PcdDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
580 PcdObj
= PcdDict
[Key
]
581 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
582 PcdValue
= PcdObj
.DefaultValue
588 Int64PcdValue
= long(PcdValue
, 0)
589 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
593 if Int64PcdValue
> 0:
594 TopAddress
= Int64PcdValue
596 ModuleDict
= BuildDb
.BuildObject
[DscFile
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
597 for Key
in ModuleDict
:
598 ModuleObj
= BuildDb
.BuildObject
[Key
, TAB_COMMON
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
599 print(ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
)
601 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
602 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
603 GuidXRefFile
= BytesIO('')
608 GuidPattern
= gGuidPattern
609 for Arch
in ArchList
:
610 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
611 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
613 PkgGuidDict
.update(P
.Guids
)
614 for Name
, Guid
in PlatformDataBase
.Pcds
:
615 Pcd
= PlatformDataBase
.Pcds
[Name
, Guid
]
616 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_HII
, TAB_PCDS_DYNAMIC_EX_HII
]:
617 for SkuId
in Pcd
.SkuInfoList
:
618 Sku
= Pcd
.SkuInfoList
[SkuId
]
619 if Sku
.VariableGuid
and Sku
.VariableGuid
in PkgGuidDict
.keys():
620 GuidDict
[Sku
.VariableGuid
] = PkgGuidDict
[Sku
.VariableGuid
]
621 for ModuleFile
in PlatformDataBase
.Modules
:
622 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
623 if Module
in ModuleList
:
626 ModuleList
.append(Module
)
627 GuidMatch
= GuidPattern
.match(ModuleFile
.BaseName
)
628 if GuidMatch
is not None:
629 GuidXRefFile
.write("%s %s\n" % (ModuleFile
.BaseName
, Module
.BaseName
))
631 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
632 for key
, item
in Module
.Protocols
.items():
634 for key
, item
in Module
.Guids
.items():
636 for key
, item
in Module
.Ppis
.items():
638 for FvName
in FdfParserObj
.Profile
.FvDict
:
639 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
640 if not isinstance(FfsObj
, FfsFileStatement
.FileStatement
):
641 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
642 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
643 if FdfModule
in ModuleList
:
646 ModuleList
.append(FdfModule
)
647 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
648 for key
, item
in FdfModule
.Protocols
.items():
650 for key
, item
in FdfModule
.Guids
.items():
652 for key
, item
in FdfModule
.Ppis
.items():
655 FileStatementGuid
= FfsObj
.NameGuid
656 if FileStatementGuid
in FileGuidList
:
659 FileGuidList
.append(FileStatementGuid
)
661 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
662 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
665 if not os
.path
.exists(FfsPath
[0]):
668 ReFileEnds
= re
.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
669 FileList
= os
.listdir(FfsPath
[0])
670 for File
in FileList
:
671 Match
= ReFileEnds
.search(File
)
673 for Index
in range(1, 8):
674 if Match
.group(Index
) and Match
.group(Index
) in MatchDict
:
675 MatchDict
[Match
.group(Index
)].append(File
)
676 elif Match
.group(Index
):
677 MatchDict
[Match
.group(Index
)] = [File
]
680 if '.ui' in MatchDict
:
681 for File
in MatchDict
['.ui']:
682 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
686 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
687 Name
= ''.join(chr(c
) for c
in TmpStr
[:-1])
690 if 'fv.sec.txt' in MatchDict
:
691 FileList
= MatchDict
['fv.sec.txt']
692 elif '.pe32.txt' in MatchDict
:
693 FileList
= MatchDict
['.pe32.txt']
694 elif '.te.txt' in MatchDict
:
695 FileList
= MatchDict
['.te.txt']
696 elif '.pic.txt' in MatchDict
:
697 FileList
= MatchDict
['.pic.txt']
698 elif '.raw.txt' in MatchDict
:
699 FileList
= MatchDict
['.raw.txt']
700 elif '.ffs.txt' in MatchDict
:
701 FileList
= MatchDict
['.ffs.txt']
704 for File
in FileList
:
705 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
706 Name
.append((F
.read().split()[-1]))
710 Name
= ' '.join(Name
) if isinstance(Name
, type([])) else Name
711 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
713 # Append GUIDs, Protocols, and PPIs to the Xref file
714 GuidXRefFile
.write("\n")
715 for key
, item
in GuidDict
.items():
716 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
718 if GuidXRefFile
.getvalue():
719 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
720 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
721 elif os
.path
.exists(GuidXRefFileName
):
722 os
.remove(GuidXRefFileName
)
725 ##Define GenFd as static function
726 GenFd
= staticmethod(GenFd
)
727 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
728 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
729 PreprocessImage
= staticmethod(PreprocessImage
)
730 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
732 if __name__
== '__main__':
734 ## 0-127 is a safe return range, and 1 is a standard default error
735 if r
< 0 or r
> 127: r
= 1