4 # Copyright (c) 2007 - 2017, 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 from Workspace
.BuildClassObject
import ModuleBuildClassObject
28 import RuleComplexFile
29 from EfiSection
import EfiSection
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
.String
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
.Misc
import CheckPcdDatum
42 from Common
.Misc
import BuildOptionPcdValueFormat
43 from Common
.BuildVersion
import gBUILD_VERSION
44 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
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
!= None:
72 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
73 GenFdsGlobalVariable
.VerboseMode
= True
75 if Options
.FixedAddress
!= None:
76 GenFdsGlobalVariable
.FixedLoadAddress
= True
78 if Options
.quiet
!= None:
79 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
80 if Options
.debug
!= None:
81 EdkLogger
.SetLevel(Options
.debug
+ 1)
82 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
84 EdkLogger
.SetLevel(EdkLogger
.INFO
)
86 if (Options
.Workspace
== 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 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
101 # set multiple workspace
102 PackagesPath
= os
.getenv("PACKAGES_PATH")
103 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
105 if (Options
.filename
):
106 FdfFilename
= Options
.filename
107 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
109 if FdfFilename
[0:2] == '..':
110 FdfFilename
= os
.path
.realpath(FdfFilename
)
111 if not os
.path
.isabs(FdfFilename
):
112 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
113 if not os
.path
.exists(FdfFilename
):
114 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
116 GenFdsGlobalVariable
.FdfFile
= FdfFilename
117 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
119 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
121 if (Options
.BuildTarget
):
122 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
124 if (Options
.ToolChain
):
125 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
127 if (Options
.activePlatform
):
128 ActivePlatform
= Options
.activePlatform
129 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
131 if ActivePlatform
[0:2] == '..':
132 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
134 if not os
.path
.isabs (ActivePlatform
):
135 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
137 if not os
.path
.exists(ActivePlatform
) :
138 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
140 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
142 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
144 if (Options
.ConfDirectory
):
145 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
146 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
147 if ConfDirectoryPath
.startswith('"'):
148 ConfDirectoryPath
= ConfDirectoryPath
[1:]
149 if ConfDirectoryPath
.endswith('"'):
150 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
151 if not os
.path
.isabs(ConfDirectoryPath
):
152 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
153 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
154 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
156 if "CONF_PATH" in os
.environ
.keys():
157 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
159 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
160 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
161 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
162 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
163 if os
.path
.isfile(BuildConfigurationFile
) == True:
164 TargetTxt
= TargetTxtClassObject
.TargetTxtClassObject()
165 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
166 # if no build target given in command line, get it from target.txt
167 if not GenFdsGlobalVariable
.TargetName
:
168 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
169 if len(BuildTargetList
) != 1:
170 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
171 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
173 # if no tool chain given in command line, get it from target.txt
174 if not GenFdsGlobalVariable
.ToolChainTag
:
175 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
176 if ToolChainList
== None or len(ToolChainList
) == 0:
177 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
178 if len(ToolChainList
) != 1:
179 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
180 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
182 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
184 #Set global flag for build mode
185 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
188 for Pair
in Options
.Macros
:
189 if Pair
.startswith('"'):
191 if Pair
.endswith('"'):
193 List
= Pair
.split('=')
195 if not List
[1].strip():
196 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
197 if List
[0].strip() == "EFI_SOURCE":
198 GlobalData
.gEfiSource
= List
[1].strip()
199 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
201 elif List
[0].strip() == "EDK_SOURCE":
202 GlobalData
.gEdkSource
= List
[1].strip()
203 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
205 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
206 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
208 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
210 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
211 os
.environ
["WORKSPACE"] = Workspace
213 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
214 if "TARGET" not in GlobalData
.gGlobalDefines
.keys():
215 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
216 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
.keys():
217 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
218 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
.keys():
219 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
221 """call Workspace build create database"""
222 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
223 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
224 BuildWorkSpace
.InitDatabase()
227 # Get files real name in workspace dir
229 GlobalData
.gAllFiles
= DirCache(Workspace
)
230 GlobalData
.gWorkspace
= Workspace
232 if (Options
.archList
) :
233 ArchList
= Options
.archList
.split(',')
235 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
236 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
238 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
239 if len(TargetArchList
) == 0:
240 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList
), str(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON'].SupArchList
)))
242 for Arch
in ArchList
:
243 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
244 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].PlatformName
246 if (Options
.outputDir
):
247 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
248 if not os
.path
.isabs (OutputDirFromCommandLine
):
249 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
250 for Arch
in ArchList
:
251 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
253 for Arch
in ArchList
:
254 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
256 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
257 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
258 if OutputDir
[0:2] == '..':
259 OutputDir
= os
.path
.realpath(OutputDir
)
261 if OutputDir
[1] != ':':
262 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
264 if not os
.path
.exists(OutputDir
):
265 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
266 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
268 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
269 FdfParserObj
= FdfParser
.FdfParser(FdfFilename
)
270 FdfParserObj
.ParseFile()
272 if FdfParserObj
.CycleReferenceCheck():
273 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
275 if (Options
.uiFdName
) :
276 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
.keys():
277 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
279 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
280 "No such an FD in FDF file: %s" % Options
.uiFdName
)
282 if (Options
.uiFvName
) :
283 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
.keys():
284 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
286 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
287 "No such an FV in FDF file: %s" % Options
.uiFvName
)
289 if (Options
.uiCapName
) :
290 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
.keys():
291 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
293 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
294 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
296 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
298 GenFdsGlobalVariable
.ArchList
= ArchList
300 if Options
.OptionPcd
:
301 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
302 CheckBuildOptionPcd()
304 """Modify images from build output if the feature of loading driver at fixed address is on."""
305 if GenFdsGlobalVariable
.FixedLoadAddress
:
306 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
308 # Record the FV Region info that may specific in the FD
309 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
310 for Fv
in FdfParserObj
.Profile
.FvDict
:
311 FvObj
= FdfParserObj
.Profile
.FvDict
[Fv
]
312 for Fd
in FdfParserObj
.Profile
.FdDict
:
313 FdObj
= FdfParserObj
.Profile
.FdDict
[Fd
]
314 for RegionObj
in FdObj
.RegionList
:
315 if RegionObj
.RegionType
!= 'FV':
317 for RegionData
in RegionObj
.RegionDataList
:
318 if FvObj
.UiFvName
.upper() == RegionData
.upper():
319 if FvObj
.FvRegionInFD
:
320 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
321 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
323 FvObj
.FvRegionInFD
= RegionObj
.Size
324 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
327 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
329 """Generate GUID cross reference file"""
330 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
)
332 """Display FV space info."""
333 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
335 except FdfParser
.Warning, X
:
336 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
337 ReturnCode
= FORMAT_INVALID
338 except FatalError
, X
:
339 if Options
.debug
!= None:
341 EdkLogger
.quiet(traceback
.format_exc())
342 ReturnCode
= X
.args
[0]
348 "Tools code failure",
349 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
352 EdkLogger
.quiet(traceback
.format_exc())
353 ReturnCode
= CODE_ERROR
359 def SingleCheckCallback(option
, opt_str
, value
, parser
):
360 if option
not in gParamCheck
:
361 setattr(parser
.values
, option
.dest
, value
)
362 gParamCheck
.append(option
)
364 parser
.error("Option %s only allows one instance in command line!" % option
)
366 def CheckBuildOptionPcd():
367 for Arch
in GenFdsGlobalVariable
.ArchList
:
368 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
369 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
370 if type(pcd
) is tuple:
372 (pcdname
, pcdvalue
) = pcd
.split('=')
374 EdkLogger
.error('GenFds', OPTION_MISSING
, "No Value specified for the PCD %s." % (pcdname
))
376 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
380 TokenSpaceGuidCName
= ''
381 HasTokenSpace
= False
382 TokenSpaceGuidCNameList
= []
386 for package
in PkgList
:
387 for key
in package
.Pcds
:
388 PcdItem
= package
.Pcds
[key
]
390 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
391 PcdDatumType
= PcdItem
.DatumType
392 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
395 if PcdItem
.TokenCName
== TokenCName
:
396 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
397 if len (TokenSpaceGuidCNameList
) < 1:
398 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
399 PcdDatumType
= PcdItem
.DatumType
400 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
401 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
406 PCD_VALIDATION_INFO_ERROR
,
407 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
410 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
415 # Find location of tools to process data
417 # @param KeyStringList Filter for inputs of section generation
418 # @param CurrentArchList Arch list
419 # @param NameGuid The Guid name
421 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
422 ToolDb
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
423 # if user not specify filter, try to deduce it from global data.
424 if KeyStringList
== None or KeyStringList
== []:
425 Target
= GenFdsGlobalVariable
.TargetName
426 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
427 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
428 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
429 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
430 for Arch
in CurrentArchList
:
431 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
432 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
434 if GenFdsGlobalVariable
.GuidToolDefinition
:
435 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
.keys():
436 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
438 ToolDefinition
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
444 for ToolDef
in ToolDefinition
.items():
445 if NameGuid
== ToolDef
[1]:
446 KeyList
= ToolDef
[0].split('_')
452 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
453 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
454 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
455 ToolPath
= ToolDefinition
.get(ToolPathKey
)
456 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
457 if ToolPathTmp
== None:
458 ToolPathTmp
= ToolPath
460 if ToolPathTmp
!= ToolPath
:
461 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
464 for Arch
in CurrentArchList
:
465 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
466 # key is (ToolChainFamily, ToolChain, CodeBase)
467 for item
in Platform
.BuildOptions
:
468 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
469 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
470 if item
[1] not in BuildOption
:
471 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
473 ToolList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
]
474 for Index
in range(2, -1, -1):
475 for Key
in dict(BuildOption
):
476 List
= Key
.split('_')
477 if List
[Index
] == '*':
478 for String
in ToolDb
[ToolList
[Index
]]:
479 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
481 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
482 if NewKey
not in BuildOption
:
483 BuildOption
[NewKey
] = BuildOption
[Key
]
486 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
490 for Op
in BuildOption
:
491 if NameGuid
== BuildOption
[Op
]:
492 KeyList
= Op
.split('_')
493 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
494 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
495 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
496 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
497 if ToolPathKey
in BuildOption
.keys():
498 ToolPathTmp
= BuildOption
.get(ToolPathKey
)
499 if ToolOptionKey
in BuildOption
.keys():
500 ToolOption
= BuildOption
.get(ToolOptionKey
)
502 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
503 return ToolPathTmp
, ToolOption
505 ## Parse command line options
507 # Using standard Python module optparse to parse command line option of this tool.
509 # @retval Opt A optparse.Values object containing the parsed options
510 # @retval Args Target of build command
512 def myOptionParser():
513 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
514 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
515 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
516 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")
517 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
518 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
519 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
520 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
521 action
="callback", callback
=SingleCheckCallback
)
522 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
523 action
="callback", callback
=SingleCheckCallback
)
524 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
525 action
="callback", callback
=SingleCheckCallback
)
526 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
527 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
528 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
529 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
530 action
="callback", callback
=SingleCheckCallback
)
531 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
532 action
="callback", callback
=SingleCheckCallback
)
533 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
534 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
535 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
536 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
537 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
539 (Options
, args
) = Parser
.parse_args()
542 ## The class implementing the EDK2 flash image generation process
544 # This process includes:
545 # 1. Collect workspace information, includes platform and module information
546 # 2. Call methods of Fd class to generate FD
547 # 3. Call methods of Fv class to generate FV that not belong to FD
551 # FvName, FdName, CapName in FDF, Image file name
553 OnlyGenerateThisFd
= None
554 OnlyGenerateThisFv
= None
555 OnlyGenerateThisCap
= None
559 # @param OutputDir Output directory
560 # @param FdfParser FDF contents parser
561 # @param Workspace The directory of workspace
562 # @param ArchList The Arch list of platform
564 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
565 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
567 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
568 if GenFds
.OnlyGenerateThisCap
!= None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
569 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.get(GenFds
.OnlyGenerateThisCap
.upper())
570 if CapsuleObj
!= None:
571 CapsuleObj
.GenCapsule()
574 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
575 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.get(GenFds
.OnlyGenerateThisFd
.upper())
579 elif GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisFv
== None:
580 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
581 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
584 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
585 if GenFds
.OnlyGenerateThisFv
!= None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
586 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(GenFds
.OnlyGenerateThisFv
.upper())
588 Buffer
= StringIO
.StringIO()
589 FvObj
.AddToBuffer(Buffer
)
592 elif GenFds
.OnlyGenerateThisFv
== None:
593 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
594 Buffer
= StringIO
.StringIO('')
595 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
596 FvObj
.AddToBuffer(Buffer
)
599 if GenFds
.OnlyGenerateThisFv
== None and GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisCap
== None:
600 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
601 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
602 for CapsuleName
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
603 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[CapsuleName
]
604 CapsuleObj
.GenCapsule()
606 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
607 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
608 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
609 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
610 OptRomObj
.AddToBuffer(None)
614 # @param FvObj Whose block size to get
615 # @retval int Block size value
617 def GetFvBlockSize(FvObj
):
618 DefaultBlockSize
= 0x1
620 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
621 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
623 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
624 for ElementRegion
in ElementFd
.RegionList
:
625 if ElementRegion
.RegionType
== 'FV':
626 for ElementRegionData
in ElementRegion
.RegionDataList
:
627 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
628 if FvObj
.BlockSizeList
!= []:
629 return FvObj
.BlockSizeList
[0][0]
631 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
632 if FvObj
.BlockSizeList
!= []:
633 return FvObj
.BlockSizeList
[0][0]
634 return DefaultBlockSize
636 for ElementRegion
in FdObj
.RegionList
:
637 if ElementRegion
.RegionType
== 'FV':
638 for ElementRegionData
in ElementRegion
.RegionDataList
:
639 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
640 if FvObj
.BlockSizeList
!= []:
641 return FvObj
.BlockSizeList
[0][0]
643 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
644 return DefaultBlockSize
646 ## DisplayFvSpaceInfo()
648 # @param FvObj Whose block size to get
651 def DisplayFvSpaceInfo(FdfParser
):
655 for FvName
in FdfParser
.Profile
.FvDict
:
656 if len(FvName
) > MaxFvNameLength
:
657 MaxFvNameLength
= len(FvName
)
658 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
659 if os
.path
.exists(FvSpaceInfoFileName
):
660 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
667 for Line
in FileLinesList
:
668 NameValue
= Line
.split('=')
669 if len(NameValue
) == 2:
670 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
672 Total
= NameValue
[1].strip()
673 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
675 Used
= NameValue
[1].strip()
676 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
678 Free
= NameValue
[1].strip()
680 if TotalFound
and UsedFound
and FreeFound
:
681 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
683 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
684 for FvSpaceInfo
in FvSpaceInfoList
:
685 Name
= FvSpaceInfo
[0]
686 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
687 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
688 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
689 if UsedSizeValue
== TotalSizeValue
:
692 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
694 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
698 # @param BuildDb Database from build meta data files
699 # @param DscFile modules from dsc file will be preprocessed
702 def PreprocessImage(BuildDb
, DscFile
):
703 PcdDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
706 PcdObj
= PcdDict
[Key
]
707 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
708 PcdValue
= PcdObj
.DefaultValue
714 Int64PcdValue
= long(PcdValue
, 0)
715 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
719 if Int64PcdValue
> 0:
720 TopAddress
= Int64PcdValue
722 ModuleDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
723 for Key
in ModuleDict
:
724 ModuleObj
= BuildDb
.BuildObject
[Key
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
725 print ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
727 def GenerateGuidXRefFile(BuildDb
, ArchList
):
728 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
729 GuidXRefFile
= StringIO
.StringIO('')
731 for Arch
in ArchList
:
732 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
733 for ModuleFile
in PlatformDataBase
.Modules
:
734 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
735 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
736 for key
, item
in Module
.Protocols
.items():
738 for key
, item
in Module
.Guids
.items():
740 for key
, item
in Module
.Ppis
.items():
742 # Append GUIDs, Protocols, and PPIs to the Xref file
743 GuidXRefFile
.write("\n")
744 for key
, item
in GuidDict
.items():
745 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
747 if GuidXRefFile
.getvalue():
748 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
749 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
750 elif os
.path
.exists(GuidXRefFileName
):
751 os
.remove(GuidXRefFileName
)
754 ##Define GenFd as static function
755 GenFd
= staticmethod(GenFd
)
756 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
757 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
758 PreprocessImage
= staticmethod(PreprocessImage
)
759 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
761 if __name__
== '__main__':
763 ## 0-127 is a safe return range, and 1 is a standard default error
764 if r
< 0 or r
> 127: r
= 1