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
.BuildVersion
import gBUILD_VERSION
43 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
45 ## Version and Copyright
46 versionNumber
= "1.0" + ' ' + gBUILD_VERSION
47 __version__
= "%prog Version " + versionNumber
48 __copyright__
= "Copyright (c) 2007 - 2017, Intel Corporation All rights reserved."
50 ## Tool entrance method
52 # This method mainly dispatch specific methods per the command line options.
53 # If no error found, return zero value so the caller of this tool can know
54 # if it's executed successfully or not.
56 # @retval 0 Tool was successful
57 # @retval 1 Tool failed
61 Options
= myOptionParser()
68 EdkLogger
.Initialize()
70 if Options
.verbose
!= None:
71 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
72 GenFdsGlobalVariable
.VerboseMode
= True
74 if Options
.FixedAddress
!= None:
75 GenFdsGlobalVariable
.FixedLoadAddress
= True
77 if Options
.quiet
!= None:
78 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
79 if Options
.debug
!= None:
80 EdkLogger
.SetLevel(Options
.debug
+ 1)
81 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
83 EdkLogger
.SetLevel(EdkLogger
.INFO
)
85 if (Options
.Workspace
== None):
86 EdkLogger
.error("GenFds", OPTION_MISSING
, "WORKSPACE not defined",
87 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
88 elif not os
.path
.exists(Options
.Workspace
):
89 EdkLogger
.error("GenFds", PARAMETER_INVALID
, "WORKSPACE is invalid",
90 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
92 Workspace
= os
.path
.normcase(Options
.Workspace
)
93 GenFdsGlobalVariable
.WorkSpaceDir
= Workspace
94 if 'EDK_SOURCE' in os
.environ
.keys():
95 GenFdsGlobalVariable
.EdkSourceDir
= os
.path
.normcase(os
.environ
['EDK_SOURCE'])
97 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
98 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
100 # set multiple workspace
101 PackagesPath
= os
.getenv("PACKAGES_PATH")
102 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
104 if (Options
.filename
):
105 FdfFilename
= Options
.filename
106 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
108 if FdfFilename
[0:2] == '..':
109 FdfFilename
= os
.path
.realpath(FdfFilename
)
110 if not os
.path
.isabs(FdfFilename
):
111 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
112 if not os
.path
.exists(FdfFilename
):
113 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
115 GenFdsGlobalVariable
.FdfFile
= FdfFilename
116 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
118 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
120 if (Options
.BuildTarget
):
121 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
123 if (Options
.ToolChain
):
124 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
126 if (Options
.activePlatform
):
127 ActivePlatform
= Options
.activePlatform
128 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
130 if ActivePlatform
[0:2] == '..':
131 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
133 if not os
.path
.isabs (ActivePlatform
):
134 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
136 if not os
.path
.exists(ActivePlatform
) :
137 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
139 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
141 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
143 if (Options
.ConfDirectory
):
144 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
145 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
146 if ConfDirectoryPath
.startswith('"'):
147 ConfDirectoryPath
= ConfDirectoryPath
[1:]
148 if ConfDirectoryPath
.endswith('"'):
149 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
150 if not os
.path
.isabs(ConfDirectoryPath
):
151 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
152 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
153 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
155 if "CONF_PATH" in os
.environ
.keys():
156 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
158 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
159 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
160 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
161 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
162 if os
.path
.isfile(BuildConfigurationFile
) == True:
163 TargetTxt
= TargetTxtClassObject
.TargetTxtClassObject()
164 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
165 # if no build target given in command line, get it from target.txt
166 if not GenFdsGlobalVariable
.TargetName
:
167 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
168 if len(BuildTargetList
) != 1:
169 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
170 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
172 # if no tool chain given in command line, get it from target.txt
173 if not GenFdsGlobalVariable
.ToolChainTag
:
174 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
175 if ToolChainList
== None or len(ToolChainList
) == 0:
176 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
177 if len(ToolChainList
) != 1:
178 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
179 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
181 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
183 #Set global flag for build mode
184 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
187 for Pair
in Options
.Macros
:
188 if Pair
.startswith('"'):
190 if Pair
.endswith('"'):
192 List
= Pair
.split('=')
194 if not List
[1].strip():
195 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
196 if List
[0].strip() == "EFI_SOURCE":
197 GlobalData
.gEfiSource
= List
[1].strip()
198 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
200 elif List
[0].strip() == "EDK_SOURCE":
201 GlobalData
.gEdkSource
= List
[1].strip()
202 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
204 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
205 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
207 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
209 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
210 os
.environ
["WORKSPACE"] = Workspace
212 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
213 if "TARGET" not in GlobalData
.gGlobalDefines
.keys():
214 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
215 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
.keys():
216 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
217 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
.keys():
218 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
220 """call Workspace build create database"""
221 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
222 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
223 BuildWorkSpace
.InitDatabase()
226 # Get files real name in workspace dir
228 GlobalData
.gAllFiles
= DirCache(Workspace
)
229 GlobalData
.gWorkspace
= Workspace
231 if (Options
.archList
) :
232 ArchList
= Options
.archList
.split(',')
234 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
235 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
237 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
238 if len(TargetArchList
) == 0:
239 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList
), str(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON'].SupArchList
)))
241 for Arch
in ArchList
:
242 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
243 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].PlatformName
245 if (Options
.outputDir
):
246 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
247 if not os
.path
.isabs (OutputDirFromCommandLine
):
248 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
249 for Arch
in ArchList
:
250 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
252 for Arch
in ArchList
:
253 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
255 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
256 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
257 if OutputDir
[0:2] == '..':
258 OutputDir
= os
.path
.realpath(OutputDir
)
260 if OutputDir
[1] != ':':
261 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
263 if not os
.path
.exists(OutputDir
):
264 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
265 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
267 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
268 FdfParserObj
= FdfParser
.FdfParser(FdfFilename
)
269 FdfParserObj
.ParseFile()
271 if FdfParserObj
.CycleReferenceCheck():
272 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
274 if (Options
.uiFdName
) :
275 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
.keys():
276 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
278 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
279 "No such an FD in FDF file: %s" % Options
.uiFdName
)
281 if (Options
.uiFvName
) :
282 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
.keys():
283 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
285 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
286 "No such an FV in FDF file: %s" % Options
.uiFvName
)
288 if (Options
.uiCapName
) :
289 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
.keys():
290 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
292 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
293 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
295 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
297 GenFdsGlobalVariable
.ArchList
= ArchList
299 if Options
.OptionPcd
:
300 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
301 CheckBuildOptionPcd()
303 """Modify images from build output if the feature of loading driver at fixed address is on."""
304 if GenFdsGlobalVariable
.FixedLoadAddress
:
305 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
307 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
309 """Generate GUID cross reference file"""
310 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
)
312 """Display FV space info."""
313 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
315 except FdfParser
.Warning, X
:
316 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
317 ReturnCode
= FORMAT_INVALID
318 except FatalError
, X
:
319 if Options
.debug
!= None:
321 EdkLogger
.quiet(traceback
.format_exc())
322 ReturnCode
= X
.args
[0]
328 "Tools code failure",
329 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
332 EdkLogger
.quiet(traceback
.format_exc())
333 ReturnCode
= CODE_ERROR
339 def SingleCheckCallback(option
, opt_str
, value
, parser
):
340 if option
not in gParamCheck
:
341 setattr(parser
.values
, option
.dest
, value
)
342 gParamCheck
.append(option
)
344 parser
.error("Option %s only allows one instance in command line!" % option
)
346 def CheckBuildOptionPcd():
347 for Arch
in GenFdsGlobalVariable
.ArchList
:
348 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
349 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
350 if type(pcd
) is tuple:
352 (pcdname
, pcdvalue
) = pcd
.split('=')
354 EdkLogger
.error('GenFds', OPTION_MISSING
, "No Value specified for the PCD %s." % (pcdname
))
356 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
360 TokenSpaceGuidCName
= ''
361 HasTokenSpace
= False
362 TokenSpaceGuidCNameList
= []
366 for package
in PkgList
:
367 for key
in package
.Pcds
:
368 PcdItem
= package
.Pcds
[key
]
370 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
371 PcdDatumType
= PcdItem
.DatumType
372 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
375 if PcdItem
.TokenCName
== TokenCName
:
376 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
377 if len (TokenSpaceGuidCNameList
) < 1:
378 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
379 PcdDatumType
= PcdItem
.DatumType
380 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
381 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
386 PCD_VALIDATION_INFO_ERROR
,
387 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
390 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
392 def BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, Value
):
393 if PcdDatumType
== 'VOID*':
394 if Value
.startswith('L'):
396 EdkLogger
.error('GenFds', OPTION_VALUE_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')
397 Value
= Value
[0] + '"' + Value
[1:] + '"'
398 elif Value
.startswith('B'):
400 EdkLogger
.error('GenFds', OPTION_VALUE_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')
404 EdkLogger
.error('GenFds', OPTION_VALUE_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')
405 Value
= '"' + Value
+ '"'
407 IsValid
, Cause
= CheckPcdDatum(PcdDatumType
, Value
)
409 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, ExtraData
="%s.%s" % (TokenSpaceGuidCName
, TokenCName
))
410 if PcdDatumType
== 'BOOLEAN':
411 Value
= Value
.upper()
412 if Value
== 'TRUE' or Value
== '1':
414 elif Value
== 'FALSE' or Value
== '0':
420 # Find location of tools to process data
422 # @param KeyStringList Filter for inputs of section generation
423 # @param CurrentArchList Arch list
424 # @param NameGuid The Guid name
426 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
427 ToolDb
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
428 # if user not specify filter, try to deduce it from global data.
429 if KeyStringList
== None or KeyStringList
== []:
430 Target
= GenFdsGlobalVariable
.TargetName
431 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
432 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
433 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
434 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
435 for Arch
in CurrentArchList
:
436 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
437 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
439 if GenFdsGlobalVariable
.GuidToolDefinition
:
440 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
.keys():
441 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
443 ToolDefinition
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
449 for ToolDef
in ToolDefinition
.items():
450 if NameGuid
== ToolDef
[1]:
451 KeyList
= ToolDef
[0].split('_')
457 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
458 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
459 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
460 ToolPath
= ToolDefinition
.get(ToolPathKey
)
461 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
462 if ToolPathTmp
== None:
463 ToolPathTmp
= ToolPath
465 if ToolPathTmp
!= ToolPath
:
466 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
469 for Arch
in CurrentArchList
:
470 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
471 # key is (ToolChainFamily, ToolChain, CodeBase)
472 for item
in Platform
.BuildOptions
:
473 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
474 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
475 if item
[1] not in BuildOption
:
476 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
478 ToolList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
]
479 for Index
in range(2, -1, -1):
480 for Key
in dict(BuildOption
):
481 List
= Key
.split('_')
482 if List
[Index
] == '*':
483 for String
in ToolDb
[ToolList
[Index
]]:
484 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
486 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
487 if NewKey
not in BuildOption
:
488 BuildOption
[NewKey
] = BuildOption
[Key
]
491 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
495 for Op
in BuildOption
:
496 if NameGuid
== BuildOption
[Op
]:
497 KeyList
= Op
.split('_')
498 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
499 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
500 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
501 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
502 if ToolPathKey
in BuildOption
.keys():
503 ToolPathTmp
= BuildOption
.get(ToolPathKey
)
504 if ToolOptionKey
in BuildOption
.keys():
505 ToolOption
= BuildOption
.get(ToolOptionKey
)
507 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
508 return ToolPathTmp
, ToolOption
510 ## Parse command line options
512 # Using standard Python module optparse to parse command line option of this tool.
514 # @retval Opt A optparse.Values object containing the parsed options
515 # @retval Args Target of build command
517 def myOptionParser():
518 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
519 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
520 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
521 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")
522 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
523 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
524 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
525 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
526 action
="callback", callback
=SingleCheckCallback
)
527 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
528 action
="callback", callback
=SingleCheckCallback
)
529 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
530 action
="callback", callback
=SingleCheckCallback
)
531 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
532 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
533 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
534 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
535 action
="callback", callback
=SingleCheckCallback
)
536 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
537 action
="callback", callback
=SingleCheckCallback
)
538 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
539 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
540 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
541 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
542 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
544 (Options
, args
) = Parser
.parse_args()
547 ## The class implementing the EDK2 flash image generation process
549 # This process includes:
550 # 1. Collect workspace information, includes platform and module information
551 # 2. Call methods of Fd class to generate FD
552 # 3. Call methods of Fv class to generate FV that not belong to FD
556 # FvName, FdName, CapName in FDF, Image file name
558 OnlyGenerateThisFd
= None
559 OnlyGenerateThisFv
= None
560 OnlyGenerateThisCap
= None
564 # @param OutputDir Output directory
565 # @param FdfParser FDF contents parser
566 # @param Workspace The directory of workspace
567 # @param ArchList The Arch list of platform
569 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
570 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
572 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
573 if GenFds
.OnlyGenerateThisCap
!= None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
574 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.get(GenFds
.OnlyGenerateThisCap
.upper())
575 if CapsuleObj
!= None:
576 CapsuleObj
.GenCapsule()
579 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
580 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.get(GenFds
.OnlyGenerateThisFd
.upper())
584 elif GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisFv
== None:
585 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
586 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
589 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
590 if GenFds
.OnlyGenerateThisFv
!= None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
591 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(GenFds
.OnlyGenerateThisFv
.upper())
593 Buffer
= StringIO
.StringIO()
594 FvObj
.AddToBuffer(Buffer
)
597 elif GenFds
.OnlyGenerateThisFv
== None:
598 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
599 Buffer
= StringIO
.StringIO('')
600 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
601 FvObj
.AddToBuffer(Buffer
)
604 if GenFds
.OnlyGenerateThisFv
== None and GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisCap
== None:
605 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
606 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
607 for CapsuleName
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
608 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[CapsuleName
]
609 CapsuleObj
.GenCapsule()
611 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
612 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
613 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
614 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
615 OptRomObj
.AddToBuffer(None)
619 # @param FvObj Whose block size to get
620 # @retval int Block size value
622 def GetFvBlockSize(FvObj
):
623 DefaultBlockSize
= 0x1
625 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
626 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
628 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
629 for ElementRegion
in ElementFd
.RegionList
:
630 if ElementRegion
.RegionType
== 'FV':
631 for ElementRegionData
in ElementRegion
.RegionDataList
:
632 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
633 if FvObj
.BlockSizeList
!= []:
634 return FvObj
.BlockSizeList
[0][0]
636 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
637 if FvObj
.BlockSizeList
!= []:
638 return FvObj
.BlockSizeList
[0][0]
639 return DefaultBlockSize
641 for ElementRegion
in FdObj
.RegionList
:
642 if ElementRegion
.RegionType
== 'FV':
643 for ElementRegionData
in ElementRegion
.RegionDataList
:
644 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
645 if FvObj
.BlockSizeList
!= []:
646 return FvObj
.BlockSizeList
[0][0]
648 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
649 return DefaultBlockSize
651 ## DisplayFvSpaceInfo()
653 # @param FvObj Whose block size to get
656 def DisplayFvSpaceInfo(FdfParser
):
660 for FvName
in FdfParser
.Profile
.FvDict
:
661 if len(FvName
) > MaxFvNameLength
:
662 MaxFvNameLength
= len(FvName
)
663 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
664 if os
.path
.exists(FvSpaceInfoFileName
):
665 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
672 for Line
in FileLinesList
:
673 NameValue
= Line
.split('=')
674 if len(NameValue
) == 2:
675 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
677 Total
= NameValue
[1].strip()
678 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
680 Used
= NameValue
[1].strip()
681 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
683 Free
= NameValue
[1].strip()
685 if TotalFound
and UsedFound
and FreeFound
:
686 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
688 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
689 for FvSpaceInfo
in FvSpaceInfoList
:
690 Name
= FvSpaceInfo
[0]
691 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
692 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
693 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
694 if UsedSizeValue
== TotalSizeValue
:
697 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
699 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
703 # @param BuildDb Database from build meta data files
704 # @param DscFile modules from dsc file will be preprocessed
707 def PreprocessImage(BuildDb
, DscFile
):
708 PcdDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
711 PcdObj
= PcdDict
[Key
]
712 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
713 PcdValue
= PcdObj
.DefaultValue
719 Int64PcdValue
= long(PcdValue
, 0)
720 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
724 if Int64PcdValue
> 0:
725 TopAddress
= Int64PcdValue
727 ModuleDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
728 for Key
in ModuleDict
:
729 ModuleObj
= BuildDb
.BuildObject
[Key
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
730 print ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
732 def GenerateGuidXRefFile(BuildDb
, ArchList
):
733 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
734 GuidXRefFile
= StringIO
.StringIO('')
736 for Arch
in ArchList
:
737 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
738 for ModuleFile
in PlatformDataBase
.Modules
:
739 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
740 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
741 for key
, item
in Module
.Protocols
.items():
743 for key
, item
in Module
.Guids
.items():
745 for key
, item
in Module
.Ppis
.items():
747 # Append GUIDs, Protocols, and PPIs to the Xref file
748 GuidXRefFile
.write("\n")
749 for key
, item
in GuidDict
.items():
750 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
752 if GuidXRefFile
.getvalue():
753 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
754 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
755 elif os
.path
.exists(GuidXRefFileName
):
756 os
.remove(GuidXRefFileName
)
759 ##Define GenFd as static function
760 GenFd
= staticmethod(GenFd
)
761 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
762 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
763 PreprocessImage
= staticmethod(PreprocessImage
)
764 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
766 if __name__
== '__main__':
768 ## 0-127 is a safe return range, and 1 is a standard default error
769 if r
< 0 or r
> 127: r
= 1