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 from io
import StringIO
31 import Common
.TargetTxtClassObject
as TargetTxtClassObject
32 import Common
.ToolDefClassObject
as ToolDefClassObject
33 from Common
.DataType
import *
34 import Common
.GlobalData
as GlobalData
35 from Common
import EdkLogger
36 from Common
.StringUtils
import *
37 from Common
.Misc
import DirCache
, PathClass
38 from Common
.Misc
import SaveFileOnChange
39 from Common
.Misc
import ClearDuplicatedInf
40 from Common
.Misc
import GuidStructureStringToGuidString
41 from Common
.BuildVersion
import gBUILD_VERSION
42 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
43 from . import FfsFileStatement
45 from struct
import unpack
46 from Common
.GlobalData
import gGuidPattern
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 not FvObj
.BaseAddress
:
325 FvObj
.BaseAddress
= '0x%x' % (int(FdObj
.BaseAddress
, 0) + RegionObj
.Offset
)
326 if FvObj
.FvRegionInFD
:
327 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
328 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
330 FvObj
.FvRegionInFD
= RegionObj
.Size
331 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
334 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
336 """Generate GUID cross reference file"""
337 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
339 """Display FV space info."""
340 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
342 except FdfParser
.Warning as X
:
343 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
344 ReturnCode
= FORMAT_INVALID
345 except FatalError
as X
:
346 if Options
.debug
is not None:
348 EdkLogger
.quiet(traceback
.format_exc())
349 ReturnCode
= X
.args
[0]
355 "Tools code failure",
356 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
359 EdkLogger
.quiet(traceback
.format_exc())
360 ReturnCode
= CODE_ERROR
366 def SingleCheckCallback(option
, opt_str
, value
, parser
):
367 if option
not in gParamCheck
:
368 setattr(parser
.values
, option
.dest
, value
)
369 gParamCheck
.append(option
)
371 parser
.error("Option %s only allows one instance in command line!" % option
)
373 ## Parse command line options
375 # Using standard Python module optparse to parse command line option of this tool.
377 # @retval Opt A optparse.Values object containing the parsed options
378 # @retval Args Target of build command
380 def myOptionParser():
381 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
382 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
383 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
384 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")
385 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
386 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
387 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
388 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
389 action
="callback", callback
=SingleCheckCallback
)
390 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
391 action
="callback", callback
=SingleCheckCallback
)
392 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
393 action
="callback", callback
=SingleCheckCallback
)
394 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
395 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
396 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
397 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
398 action
="callback", callback
=SingleCheckCallback
)
399 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
400 action
="callback", callback
=SingleCheckCallback
)
401 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
402 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
403 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
404 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
405 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
406 Parser
.add_option("--genfds-multi-thread", action
="store_true", dest
="GenfdsMultiThread", default
=False, help="Enable GenFds multi thread to generate ffs file.")
408 (Options
, args
) = Parser
.parse_args()
411 ## The class implementing the EDK2 flash image generation process
413 # This process includes:
414 # 1. Collect workspace information, includes platform and module information
415 # 2. Call methods of Fd class to generate FD
416 # 3. Call methods of Fv class to generate FV that not belong to FD
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
= int(FvSpaceInfo
[1], 0)
564 UsedSizeValue
= int(FvSpaceInfo
[2], 0)
565 FreeSizeValue
= int(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
= int(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
= StringIO('')
611 GuidPattern
= gGuidPattern
612 VariableGuidSet
= set()
613 for Arch
in ArchList
:
614 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
615 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
617 PkgGuidDict
.update(P
.Guids
)
618 for Name
, Guid
in sorted(PlatformDataBase
.Pcds
):
619 Pcd
= PlatformDataBase
.Pcds
[Name
, Guid
]
620 if Pcd
.Type
in [TAB_PCDS_DYNAMIC_HII
, TAB_PCDS_DYNAMIC_EX_HII
]:
621 for SkuId
in Pcd
.SkuInfoList
:
622 Sku
= Pcd
.SkuInfoList
[SkuId
]
623 if Sku
.VariableGuid
in VariableGuidSet
:
626 VariableGuidSet
.add(Sku
.VariableGuid
)
627 if Sku
.VariableGuid
and Sku
.VariableGuid
in PkgGuidDict
.keys():
628 GuidDict
[Sku
.VariableGuid
] = PkgGuidDict
[Sku
.VariableGuid
]
629 for ModuleFile
in PlatformDataBase
.Modules
:
630 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
631 if Module
in ModuleList
:
634 ModuleList
.append(Module
)
635 GuidMatch
= GuidPattern
.match(ModuleFile
.BaseName
)
636 if GuidMatch
is not None:
637 GuidXRefFile
.write("%s %s\n" % (ModuleFile
.BaseName
, Module
.BaseName
))
639 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
640 for key
, item
in Module
.Protocols
.items():
642 for key
, item
in Module
.Guids
.items():
644 for key
, item
in Module
.Ppis
.items():
646 for FvName
in FdfParserObj
.Profile
.FvDict
:
647 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
648 if not isinstance(FfsObj
, FfsFileStatement
.FileStatement
):
649 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
650 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
651 if FdfModule
in ModuleList
:
654 ModuleList
.append(FdfModule
)
655 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
656 for key
, item
in FdfModule
.Protocols
.items():
658 for key
, item
in FdfModule
.Guids
.items():
660 for key
, item
in FdfModule
.Ppis
.items():
663 FileStatementGuid
= FfsObj
.NameGuid
664 if FileStatementGuid
in FileGuidList
:
667 FileGuidList
.append(FileStatementGuid
)
669 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
670 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
673 if not os
.path
.exists(FfsPath
[0]):
676 ReFileEnds
= re
.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
677 FileList
= os
.listdir(FfsPath
[0])
678 for File
in FileList
:
679 Match
= ReFileEnds
.search(File
)
681 for Index
in range(1, 8):
682 if Match
.group(Index
) and Match
.group(Index
) in MatchDict
:
683 MatchDict
[Match
.group(Index
)].append(File
)
684 elif Match
.group(Index
):
685 MatchDict
[Match
.group(Index
)] = [File
]
688 if '.ui' in MatchDict
:
689 for File
in MatchDict
['.ui']:
690 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
694 TmpStr
= unpack('%dh' % ((length
- 4) // 2), F
.read())
695 Name
= ''.join(chr(c
) for c
in TmpStr
[:-1])
698 if 'fv.sec.txt' in MatchDict
:
699 FileList
= MatchDict
['fv.sec.txt']
700 elif '.pe32.txt' in MatchDict
:
701 FileList
= MatchDict
['.pe32.txt']
702 elif '.te.txt' in MatchDict
:
703 FileList
= MatchDict
['.te.txt']
704 elif '.pic.txt' in MatchDict
:
705 FileList
= MatchDict
['.pic.txt']
706 elif '.raw.txt' in MatchDict
:
707 FileList
= MatchDict
['.raw.txt']
708 elif '.ffs.txt' in MatchDict
:
709 FileList
= MatchDict
['.ffs.txt']
712 for File
in FileList
:
713 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
714 Name
.append((F
.read().split()[-1]))
718 Name
= ' '.join(Name
) if isinstance(Name
, type([])) else Name
719 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
721 # Append GUIDs, Protocols, and PPIs to the Xref file
722 GuidXRefFile
.write("\n")
723 for key
, item
in GuidDict
.items():
724 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
726 if GuidXRefFile
.getvalue():
727 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
728 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
729 elif os
.path
.exists(GuidXRefFileName
):
730 os
.remove(GuidXRefFileName
)
733 ##Define GenFd as static function
734 GenFd
= staticmethod(GenFd
)
735 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
736 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
737 PreprocessImage
= staticmethod(PreprocessImage
)
738 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
740 if __name__
== '__main__':
742 ## 0-127 is a safe return range, and 1 is a standard default error
743 if r
< 0 or r
> 127: r
= 1