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
23 import Common
.BuildToolError
as BuildToolError
24 from GenFdsGlobalVariable
import GenFdsGlobalVariable
25 from Workspace
.WorkspaceDatabase
import WorkspaceDatabase
26 from Workspace
.BuildClassObject
import PcdClassObject
27 import RuleComplexFile
28 from EfiSection
import EfiSection
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
.String
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 import FfsFileStatement
44 from struct
import unpack
46 ## Version and Copyright
47 versionNumber
= "1.0" + ' ' + gBUILD_VERSION
48 __version__
= "%prog Version " + versionNumber
49 __copyright__
= "Copyright (c) 2007 - 2017, Intel Corporation All rights reserved."
51 ## Tool entrance method
53 # This method mainly dispatch specific methods per the command line options.
54 # If no error found, return zero value so the caller of this tool can know
55 # if it's executed successfully or not.
57 # @retval 0 Tool was successful
58 # @retval 1 Tool failed
62 Options
= myOptionParser()
69 EdkLogger
.Initialize()
71 if Options
.verbose
is not None:
72 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
73 GenFdsGlobalVariable
.VerboseMode
= True
75 if Options
.FixedAddress
is not None:
76 GenFdsGlobalVariable
.FixedLoadAddress
= True
78 if Options
.quiet
is not None:
79 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
80 if Options
.debug
is not None:
81 EdkLogger
.SetLevel(Options
.debug
+ 1)
82 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
84 EdkLogger
.SetLevel(EdkLogger
.INFO
)
86 if (Options
.Workspace
is None):
87 EdkLogger
.error("GenFds", OPTION_MISSING
, "WORKSPACE not defined",
88 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
89 elif not os
.path
.exists(Options
.Workspace
):
90 EdkLogger
.error("GenFds", PARAMETER_INVALID
, "WORKSPACE is invalid",
91 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
93 Workspace
= os
.path
.normcase(Options
.Workspace
)
94 GenFdsGlobalVariable
.WorkSpaceDir
= Workspace
95 if 'EDK_SOURCE' in os
.environ
.keys():
96 GenFdsGlobalVariable
.EdkSourceDir
= os
.path
.normcase(os
.environ
['EDK_SOURCE'])
98 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
99 if Options
.GenfdsMultiThread
:
100 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= True
101 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
103 # set multiple workspace
104 PackagesPath
= os
.getenv("PACKAGES_PATH")
105 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
107 if (Options
.filename
):
108 FdfFilename
= Options
.filename
109 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
111 if FdfFilename
[0:2] == '..':
112 FdfFilename
= os
.path
.realpath(FdfFilename
)
113 if not os
.path
.isabs(FdfFilename
):
114 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
115 if not os
.path
.exists(FdfFilename
):
116 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
118 GenFdsGlobalVariable
.FdfFile
= FdfFilename
119 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
121 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
123 if (Options
.BuildTarget
):
124 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
126 if (Options
.ToolChain
):
127 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
129 if (Options
.activePlatform
):
130 ActivePlatform
= Options
.activePlatform
131 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
133 if ActivePlatform
[0:2] == '..':
134 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
136 if not os
.path
.isabs (ActivePlatform
):
137 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
139 if not os
.path
.exists(ActivePlatform
) :
140 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
142 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
144 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
if Options
.OptionPcd
else {}
145 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
147 if (Options
.ConfDirectory
):
148 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
149 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
150 if ConfDirectoryPath
.startswith('"'):
151 ConfDirectoryPath
= ConfDirectoryPath
[1:]
152 if ConfDirectoryPath
.endswith('"'):
153 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
154 if not os
.path
.isabs(ConfDirectoryPath
):
155 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
156 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
157 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
159 if "CONF_PATH" in os
.environ
.keys():
160 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
162 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
163 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
164 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
165 if not GlobalData
.gConfDirectory
:
166 GlobalData
.gConfDirectory
= GenFdsGlobalVariable
.ConfDir
167 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
168 if os
.path
.isfile(BuildConfigurationFile
) == True:
169 TargetTxt
= TargetTxtClassObject
.TargetTxtClassObject()
170 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
171 # if no build target given in command line, get it from target.txt
172 if not GenFdsGlobalVariable
.TargetName
:
173 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
174 if len(BuildTargetList
) != 1:
175 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
176 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
178 # if no tool chain given in command line, get it from target.txt
179 if not GenFdsGlobalVariable
.ToolChainTag
:
180 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
181 if ToolChainList
is None or len(ToolChainList
) == 0:
182 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
183 if len(ToolChainList
) != 1:
184 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
185 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
187 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
189 #Set global flag for build mode
190 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
193 for Pair
in Options
.Macros
:
194 if Pair
.startswith('"'):
196 if Pair
.endswith('"'):
198 List
= Pair
.split('=')
200 if not List
[1].strip():
201 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
202 if List
[0].strip() == "EFI_SOURCE":
203 GlobalData
.gEfiSource
= List
[1].strip()
204 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
206 elif List
[0].strip() == "EDK_SOURCE":
207 GlobalData
.gEdkSource
= List
[1].strip()
208 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
210 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
211 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
213 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
215 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
216 os
.environ
["WORKSPACE"] = Workspace
218 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
219 if "TARGET" not in GlobalData
.gGlobalDefines
.keys():
220 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
221 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
.keys():
222 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
223 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
.keys():
224 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
226 """call Workspace build create database"""
227 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
228 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
229 BuildWorkSpace
.InitDatabase()
232 # Get files real name in workspace dir
234 GlobalData
.gAllFiles
= DirCache(Workspace
)
235 GlobalData
.gWorkspace
= Workspace
237 if (Options
.archList
) :
238 ArchList
= Options
.archList
.split(',')
240 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
241 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
243 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
244 if len(TargetArchList
) == 0:
245 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList
), str(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON'].SupArchList
)))
247 for Arch
in ArchList
:
248 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
249 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].PlatformName
251 if (Options
.outputDir
):
252 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
253 if not os
.path
.isabs (OutputDirFromCommandLine
):
254 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
255 for Arch
in ArchList
:
256 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
258 for Arch
in ArchList
:
259 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
261 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
262 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
263 if OutputDir
[0:2] == '..':
264 OutputDir
= os
.path
.realpath(OutputDir
)
266 if OutputDir
[1] != ':':
267 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
269 if not os
.path
.exists(OutputDir
):
270 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
271 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
273 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
274 FdfParserObj
= FdfParser
.FdfParser(FdfFilename
)
275 FdfParserObj
.ParseFile()
277 if FdfParserObj
.CycleReferenceCheck():
278 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
280 if (Options
.uiFdName
) :
281 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
.keys():
282 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
284 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
285 "No such an FD in FDF file: %s" % Options
.uiFdName
)
287 if (Options
.uiFvName
) :
288 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
.keys():
289 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
291 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
292 "No such an FV in FDF file: %s" % Options
.uiFvName
)
294 if (Options
.uiCapName
) :
295 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
.keys():
296 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
298 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
299 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
301 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
302 if ArchList
is not None:
303 GenFdsGlobalVariable
.ArchList
= ArchList
305 # Dsc Build Data will handle Pcd Settings from CommandLine.
307 """Modify images from build output if the feature of loading driver at fixed address is on."""
308 if GenFdsGlobalVariable
.FixedLoadAddress
:
309 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
311 # Record the FV Region info that may specific in the FD
312 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
313 for Fv
in FdfParserObj
.Profile
.FvDict
:
314 FvObj
= FdfParserObj
.Profile
.FvDict
[Fv
]
315 for Fd
in FdfParserObj
.Profile
.FdDict
:
316 FdObj
= FdfParserObj
.Profile
.FdDict
[Fd
]
317 for RegionObj
in FdObj
.RegionList
:
318 if RegionObj
.RegionType
!= 'FV':
320 for RegionData
in RegionObj
.RegionDataList
:
321 if FvObj
.UiFvName
.upper() == RegionData
.upper():
322 if FvObj
.FvRegionInFD
:
323 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
324 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
326 FvObj
.FvRegionInFD
= RegionObj
.Size
327 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
330 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
332 """Generate GUID cross reference file"""
333 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
335 """Display FV space info."""
336 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
338 except FdfParser
.Warning, X
:
339 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
340 ReturnCode
= FORMAT_INVALID
341 except FatalError
, X
:
342 if Options
.debug
is not None:
344 EdkLogger
.quiet(traceback
.format_exc())
345 ReturnCode
= X
.args
[0]
351 "Tools code failure",
352 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
355 EdkLogger
.quiet(traceback
.format_exc())
356 ReturnCode
= CODE_ERROR
362 def SingleCheckCallback(option
, opt_str
, value
, parser
):
363 if option
not in gParamCheck
:
364 setattr(parser
.values
, option
.dest
, value
)
365 gParamCheck
.append(option
)
367 parser
.error("Option %s only allows one instance in command line!" % option
)
371 # Find location of tools to process data
373 # @param KeyStringList Filter for inputs of section generation
374 # @param CurrentArchList Arch list
375 # @param NameGuid The Guid name
377 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
378 ToolDb
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
379 # if user not specify filter, try to deduce it from global data.
380 if KeyStringList
is None or KeyStringList
== []:
381 Target
= GenFdsGlobalVariable
.TargetName
382 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
383 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
384 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
385 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
386 for Arch
in CurrentArchList
:
387 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
388 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
390 if GenFdsGlobalVariable
.GuidToolDefinition
:
391 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
.keys():
392 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
394 ToolDefinition
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
400 for ToolDef
in ToolDefinition
.items():
401 if NameGuid
.lower() == ToolDef
[1].lower() :
402 KeyList
= ToolDef
[0].split('_')
408 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
409 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
410 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
411 ToolPath
= ToolDefinition
.get(ToolPathKey
)
412 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
413 if ToolPathTmp
is None:
414 ToolPathTmp
= ToolPath
416 if ToolPathTmp
!= ToolPath
:
417 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
420 for Arch
in CurrentArchList
:
421 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
422 # key is (ToolChainFamily, ToolChain, CodeBase)
423 for item
in Platform
.BuildOptions
:
424 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
425 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
426 if item
[1] not in BuildOption
:
427 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
429 ToolList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
]
430 for Index
in range(2, -1, -1):
431 for Key
in dict(BuildOption
):
432 List
= Key
.split('_')
433 if List
[Index
] == '*':
434 for String
in ToolDb
[ToolList
[Index
]]:
435 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
437 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
438 if NewKey
not in BuildOption
:
439 BuildOption
[NewKey
] = BuildOption
[Key
]
442 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
446 for Op
in BuildOption
:
447 if NameGuid
== BuildOption
[Op
]:
448 KeyList
= Op
.split('_')
449 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
450 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
451 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
452 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
453 if ToolPathKey
in BuildOption
.keys():
454 ToolPathTmp
= BuildOption
.get(ToolPathKey
)
455 if ToolOptionKey
in BuildOption
.keys():
456 ToolOption
= BuildOption
.get(ToolOptionKey
)
458 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
459 return ToolPathTmp
, ToolOption
461 ## Parse command line options
463 # Using standard Python module optparse to parse command line option of this tool.
465 # @retval Opt A optparse.Values object containing the parsed options
466 # @retval Args Target of build command
468 def myOptionParser():
469 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
470 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
471 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
472 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")
473 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
474 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
475 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
476 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
477 action
="callback", callback
=SingleCheckCallback
)
478 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
479 action
="callback", callback
=SingleCheckCallback
)
480 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
481 action
="callback", callback
=SingleCheckCallback
)
482 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
483 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
484 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
485 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
486 action
="callback", callback
=SingleCheckCallback
)
487 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
488 action
="callback", callback
=SingleCheckCallback
)
489 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
490 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
491 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
492 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
493 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
494 Parser
.add_option("--genfds-multi-thread", action
="store_true", dest
="GenfdsMultiThread", default
=False, help="Enable GenFds multi thread to generate ffs file.")
496 (Options
, args
) = Parser
.parse_args()
499 ## The class implementing the EDK2 flash image generation process
501 # This process includes:
502 # 1. Collect workspace information, includes platform and module information
503 # 2. Call methods of Fd class to generate FD
504 # 3. Call methods of Fv class to generate FV that not belong to FD
508 # FvName, FdName, CapName in FDF, Image file name
510 OnlyGenerateThisFd
= None
511 OnlyGenerateThisFv
= None
512 OnlyGenerateThisCap
= None
516 # @param OutputDir Output directory
517 # @param FdfParser FDF contents parser
518 # @param Workspace The directory of workspace
519 # @param ArchList The Arch list of platform
521 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
522 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
524 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
525 if GenFds
.OnlyGenerateThisCap
is not None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
526 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.get(GenFds
.OnlyGenerateThisCap
.upper())
527 if CapsuleObj
is not None:
528 CapsuleObj
.GenCapsule()
531 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
532 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.get(GenFds
.OnlyGenerateThisFd
.upper())
533 if FdObj
is not None:
536 elif GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisFv
is None:
537 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
538 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
541 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
542 if GenFds
.OnlyGenerateThisFv
is not None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
543 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(GenFds
.OnlyGenerateThisFv
.upper())
544 if FvObj
is not None:
545 Buffer
= StringIO
.StringIO()
546 FvObj
.AddToBuffer(Buffer
)
549 elif GenFds
.OnlyGenerateThisFv
is None:
550 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
551 Buffer
= StringIO
.StringIO('')
552 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
553 FvObj
.AddToBuffer(Buffer
)
556 if GenFds
.OnlyGenerateThisFv
is None and GenFds
.OnlyGenerateThisFd
is None and GenFds
.OnlyGenerateThisCap
is None:
557 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
558 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
559 for CapsuleName
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
560 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[CapsuleName
]
561 CapsuleObj
.GenCapsule()
563 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
564 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
565 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
566 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
567 OptRomObj
.AddToBuffer(None)
569 def GenFfsMakefile(OutputDir
, FdfParser
, WorkSpace
, ArchList
, GlobalData
):
570 GenFdsGlobalVariable
.SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
)
571 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
572 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
573 FdObj
.GenFd(Flag
=True)
575 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
576 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
577 FvObj
.AddToBuffer(Buffer
=None, Flag
=True)
579 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
580 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
581 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
582 OptRomObj
.AddToBuffer(Buffer
=None, Flag
=True)
584 return GenFdsGlobalVariable
.FfsCmdDict
588 # @param FvObj Whose block size to get
589 # @retval int Block size value
591 def GetFvBlockSize(FvObj
):
592 DefaultBlockSize
= 0x1
594 if GenFds
.OnlyGenerateThisFd
is not None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
595 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
597 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
598 for ElementRegion
in ElementFd
.RegionList
:
599 if ElementRegion
.RegionType
== 'FV':
600 for ElementRegionData
in ElementRegion
.RegionDataList
:
601 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
602 if FvObj
.BlockSizeList
!= []:
603 return FvObj
.BlockSizeList
[0][0]
605 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
606 if FvObj
.BlockSizeList
!= []:
607 return FvObj
.BlockSizeList
[0][0]
608 return DefaultBlockSize
610 for ElementRegion
in FdObj
.RegionList
:
611 if ElementRegion
.RegionType
== 'FV':
612 for ElementRegionData
in ElementRegion
.RegionDataList
:
613 if ElementRegionData
is not None and ElementRegionData
.upper() == FvObj
.UiFvName
:
614 if FvObj
.BlockSizeList
!= []:
615 return FvObj
.BlockSizeList
[0][0]
617 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
618 return DefaultBlockSize
620 ## DisplayFvSpaceInfo()
622 # @param FvObj Whose block size to get
625 def DisplayFvSpaceInfo(FdfParser
):
629 for FvName
in FdfParser
.Profile
.FvDict
:
630 if len(FvName
) > MaxFvNameLength
:
631 MaxFvNameLength
= len(FvName
)
632 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
633 if os
.path
.exists(FvSpaceInfoFileName
):
634 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
641 for Line
in FileLinesList
:
642 NameValue
= Line
.split('=')
643 if len(NameValue
) == 2:
644 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
646 Total
= NameValue
[1].strip()
647 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
649 Used
= NameValue
[1].strip()
650 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
652 Free
= NameValue
[1].strip()
654 if TotalFound
and UsedFound
and FreeFound
:
655 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
657 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
658 for FvSpaceInfo
in FvSpaceInfoList
:
659 Name
= FvSpaceInfo
[0]
660 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
661 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
662 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
663 if UsedSizeValue
== TotalSizeValue
:
666 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
668 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
672 # @param BuildDb Database from build meta data files
673 # @param DscFile modules from dsc file will be preprocessed
676 def PreprocessImage(BuildDb
, DscFile
):
677 PcdDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
680 PcdObj
= PcdDict
[Key
]
681 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
682 PcdValue
= PcdObj
.DefaultValue
688 Int64PcdValue
= long(PcdValue
, 0)
689 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
693 if Int64PcdValue
> 0:
694 TopAddress
= Int64PcdValue
696 ModuleDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
697 for Key
in ModuleDict
:
698 ModuleObj
= BuildDb
.BuildObject
[Key
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
699 print ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
701 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
702 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
703 GuidXRefFile
= StringIO
.StringIO('')
707 for Arch
in ArchList
:
708 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
709 for ModuleFile
in PlatformDataBase
.Modules
:
710 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
711 if Module
in ModuleList
:
714 ModuleList
.append(Module
)
715 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
716 for key
, item
in Module
.Protocols
.items():
718 for key
, item
in Module
.Guids
.items():
720 for key
, item
in Module
.Ppis
.items():
722 for FvName
in FdfParserObj
.Profile
.FvDict
:
723 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
724 if not isinstance(FfsObj
, FfsFileStatement
.FileStatement
):
725 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
726 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
727 if FdfModule
in ModuleList
:
730 ModuleList
.append(FdfModule
)
731 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
732 for key
, item
in FdfModule
.Protocols
.items():
734 for key
, item
in FdfModule
.Guids
.items():
736 for key
, item
in FdfModule
.Ppis
.items():
739 FileStatementGuid
= FfsObj
.NameGuid
740 if FileStatementGuid
in FileGuidList
:
743 FileGuidList
.append(FileStatementGuid
)
745 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
746 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
749 if not os
.path
.exists(FfsPath
[0]):
752 ReFileEnds
= re
.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
753 FileList
= os
.listdir(FfsPath
[0])
754 for File
in FileList
:
755 Match
= ReFileEnds
.search(File
)
757 for Index
in range(1, 8):
758 if Match
.group(Index
) and Match
.group(Index
) in MatchDict
:
759 MatchDict
[Match
.group(Index
)].append(File
)
760 elif Match
.group(Index
):
761 MatchDict
[Match
.group(Index
)] = [File
]
764 if '.ui' in MatchDict
:
765 for File
in MatchDict
['.ui']:
766 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
770 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
771 Name
= ''.join([chr(c
) for c
in TmpStr
[:-1]])
774 if 'fv.sec.txt' in MatchDict
:
775 FileList
= MatchDict
['fv.sec.txt']
776 elif '.pe32.txt' in MatchDict
:
777 FileList
= MatchDict
['.pe32.txt']
778 elif '.te.txt' in MatchDict
:
779 FileList
= MatchDict
['.te.txt']
780 elif '.pic.txt' in MatchDict
:
781 FileList
= MatchDict
['.pic.txt']
782 elif '.raw.txt' in MatchDict
:
783 FileList
= MatchDict
['.raw.txt']
784 elif '.ffs.txt' in MatchDict
:
785 FileList
= MatchDict
['.ffs.txt']
788 for File
in FileList
:
789 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
790 Name
.append((F
.read().split()[-1]))
794 Name
= ' '.join(Name
) if type(Name
) == type([]) else Name
795 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
797 # Append GUIDs, Protocols, and PPIs to the Xref file
798 GuidXRefFile
.write("\n")
799 for key
, item
in GuidDict
.items():
800 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
802 if GuidXRefFile
.getvalue():
803 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
804 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
805 elif os
.path
.exists(GuidXRefFileName
):
806 os
.remove(GuidXRefFileName
)
809 ##Define GenFd as static function
810 GenFd
= staticmethod(GenFd
)
811 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
812 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
813 PreprocessImage
= staticmethod(PreprocessImage
)
814 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
816 if __name__
== '__main__':
818 ## 0-127 is a safe return range, and 1 is a standard default error
819 if r
< 0 or r
> 127: r
= 1