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 # Record the FV Region info that may specific in the FD
308 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
309 for Fv
in FdfParserObj
.Profile
.FvDict
:
310 FvObj
= FdfParserObj
.Profile
.FvDict
[Fv
]
311 for Fd
in FdfParserObj
.Profile
.FdDict
:
312 FdObj
= FdfParserObj
.Profile
.FdDict
[Fd
]
313 for RegionObj
in FdObj
.RegionList
:
314 if RegionObj
.RegionType
!= 'FV':
316 for RegionData
in RegionObj
.RegionDataList
:
317 if FvObj
.UiFvName
.upper() == RegionData
.upper():
318 if FvObj
.FvRegionInFD
:
319 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
320 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
322 FvObj
.FvRegionInFD
= RegionObj
.Size
323 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
326 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
328 """Generate GUID cross reference file"""
329 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
)
331 """Display FV space info."""
332 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
334 except FdfParser
.Warning, X
:
335 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
336 ReturnCode
= FORMAT_INVALID
337 except FatalError
, X
:
338 if Options
.debug
!= None:
340 EdkLogger
.quiet(traceback
.format_exc())
341 ReturnCode
= X
.args
[0]
347 "Tools code failure",
348 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
351 EdkLogger
.quiet(traceback
.format_exc())
352 ReturnCode
= CODE_ERROR
358 def SingleCheckCallback(option
, opt_str
, value
, parser
):
359 if option
not in gParamCheck
:
360 setattr(parser
.values
, option
.dest
, value
)
361 gParamCheck
.append(option
)
363 parser
.error("Option %s only allows one instance in command line!" % option
)
365 def CheckBuildOptionPcd():
366 for Arch
in GenFdsGlobalVariable
.ArchList
:
367 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
368 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
369 if type(pcd
) is tuple:
371 (pcdname
, pcdvalue
) = pcd
.split('=')
373 EdkLogger
.error('GenFds', OPTION_MISSING
, "No Value specified for the PCD %s." % (pcdname
))
375 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
379 TokenSpaceGuidCName
= ''
380 HasTokenSpace
= False
381 TokenSpaceGuidCNameList
= []
385 for package
in PkgList
:
386 for key
in package
.Pcds
:
387 PcdItem
= package
.Pcds
[key
]
389 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
390 PcdDatumType
= PcdItem
.DatumType
391 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
394 if PcdItem
.TokenCName
== TokenCName
:
395 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
396 if len (TokenSpaceGuidCNameList
) < 1:
397 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
398 PcdDatumType
= PcdItem
.DatumType
399 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
400 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
405 PCD_VALIDATION_INFO_ERROR
,
406 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
409 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
411 def BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, Value
):
412 if PcdDatumType
== 'VOID*':
413 if Value
.startswith('L'):
415 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"{...}"')
416 Value
= Value
[0] + '"' + Value
[1:] + '"'
417 elif Value
.startswith('B'):
419 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"{...}"')
423 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"{...}"')
424 Value
= '"' + Value
+ '"'
426 IsValid
, Cause
= CheckPcdDatum(PcdDatumType
, Value
)
428 EdkLogger
.error('build', FORMAT_INVALID
, Cause
, ExtraData
="%s.%s" % (TokenSpaceGuidCName
, TokenCName
))
429 if PcdDatumType
== 'BOOLEAN':
430 Value
= Value
.upper()
431 if Value
== 'TRUE' or Value
== '1':
433 elif Value
== 'FALSE' or Value
== '0':
439 # Find location of tools to process data
441 # @param KeyStringList Filter for inputs of section generation
442 # @param CurrentArchList Arch list
443 # @param NameGuid The Guid name
445 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
446 ToolDb
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
447 # if user not specify filter, try to deduce it from global data.
448 if KeyStringList
== None or KeyStringList
== []:
449 Target
= GenFdsGlobalVariable
.TargetName
450 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
451 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
452 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
453 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
454 for Arch
in CurrentArchList
:
455 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
456 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
458 if GenFdsGlobalVariable
.GuidToolDefinition
:
459 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
.keys():
460 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
462 ToolDefinition
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
468 for ToolDef
in ToolDefinition
.items():
469 if NameGuid
== ToolDef
[1]:
470 KeyList
= ToolDef
[0].split('_')
476 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
477 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
478 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
479 ToolPath
= ToolDefinition
.get(ToolPathKey
)
480 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
481 if ToolPathTmp
== None:
482 ToolPathTmp
= ToolPath
484 if ToolPathTmp
!= ToolPath
:
485 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
488 for Arch
in CurrentArchList
:
489 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
490 # key is (ToolChainFamily, ToolChain, CodeBase)
491 for item
in Platform
.BuildOptions
:
492 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
493 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
494 if item
[1] not in BuildOption
:
495 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
497 ToolList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
]
498 for Index
in range(2, -1, -1):
499 for Key
in dict(BuildOption
):
500 List
= Key
.split('_')
501 if List
[Index
] == '*':
502 for String
in ToolDb
[ToolList
[Index
]]:
503 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
505 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
506 if NewKey
not in BuildOption
:
507 BuildOption
[NewKey
] = BuildOption
[Key
]
510 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
514 for Op
in BuildOption
:
515 if NameGuid
== BuildOption
[Op
]:
516 KeyList
= Op
.split('_')
517 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
518 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
519 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
520 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
521 if ToolPathKey
in BuildOption
.keys():
522 ToolPathTmp
= BuildOption
.get(ToolPathKey
)
523 if ToolOptionKey
in BuildOption
.keys():
524 ToolOption
= BuildOption
.get(ToolOptionKey
)
526 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
527 return ToolPathTmp
, ToolOption
529 ## Parse command line options
531 # Using standard Python module optparse to parse command line option of this tool.
533 # @retval Opt A optparse.Values object containing the parsed options
534 # @retval Args Target of build command
536 def myOptionParser():
537 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
538 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
539 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
540 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")
541 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
542 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
543 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
544 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
545 action
="callback", callback
=SingleCheckCallback
)
546 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
547 action
="callback", callback
=SingleCheckCallback
)
548 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
549 action
="callback", callback
=SingleCheckCallback
)
550 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
551 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
552 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
553 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
554 action
="callback", callback
=SingleCheckCallback
)
555 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
556 action
="callback", callback
=SingleCheckCallback
)
557 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
558 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
559 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
560 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
561 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
563 (Options
, args
) = Parser
.parse_args()
566 ## The class implementing the EDK2 flash image generation process
568 # This process includes:
569 # 1. Collect workspace information, includes platform and module information
570 # 2. Call methods of Fd class to generate FD
571 # 3. Call methods of Fv class to generate FV that not belong to FD
575 # FvName, FdName, CapName in FDF, Image file name
577 OnlyGenerateThisFd
= None
578 OnlyGenerateThisFv
= None
579 OnlyGenerateThisCap
= None
583 # @param OutputDir Output directory
584 # @param FdfParser FDF contents parser
585 # @param Workspace The directory of workspace
586 # @param ArchList The Arch list of platform
588 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
589 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
591 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
592 if GenFds
.OnlyGenerateThisCap
!= None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
593 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.get(GenFds
.OnlyGenerateThisCap
.upper())
594 if CapsuleObj
!= None:
595 CapsuleObj
.GenCapsule()
598 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
599 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.get(GenFds
.OnlyGenerateThisFd
.upper())
603 elif GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisFv
== None:
604 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
605 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
608 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
609 if GenFds
.OnlyGenerateThisFv
!= None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
610 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(GenFds
.OnlyGenerateThisFv
.upper())
612 Buffer
= StringIO
.StringIO()
613 FvObj
.AddToBuffer(Buffer
)
616 elif GenFds
.OnlyGenerateThisFv
== None:
617 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
618 Buffer
= StringIO
.StringIO('')
619 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
620 FvObj
.AddToBuffer(Buffer
)
623 if GenFds
.OnlyGenerateThisFv
== None and GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisCap
== None:
624 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
625 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
626 for CapsuleName
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
627 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[CapsuleName
]
628 CapsuleObj
.GenCapsule()
630 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
631 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
632 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
633 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
634 OptRomObj
.AddToBuffer(None)
638 # @param FvObj Whose block size to get
639 # @retval int Block size value
641 def GetFvBlockSize(FvObj
):
642 DefaultBlockSize
= 0x1
644 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
645 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
647 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
648 for ElementRegion
in ElementFd
.RegionList
:
649 if ElementRegion
.RegionType
== 'FV':
650 for ElementRegionData
in ElementRegion
.RegionDataList
:
651 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
652 if FvObj
.BlockSizeList
!= []:
653 return FvObj
.BlockSizeList
[0][0]
655 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
656 if FvObj
.BlockSizeList
!= []:
657 return FvObj
.BlockSizeList
[0][0]
658 return DefaultBlockSize
660 for ElementRegion
in FdObj
.RegionList
:
661 if ElementRegion
.RegionType
== 'FV':
662 for ElementRegionData
in ElementRegion
.RegionDataList
:
663 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
664 if FvObj
.BlockSizeList
!= []:
665 return FvObj
.BlockSizeList
[0][0]
667 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
668 return DefaultBlockSize
670 ## DisplayFvSpaceInfo()
672 # @param FvObj Whose block size to get
675 def DisplayFvSpaceInfo(FdfParser
):
679 for FvName
in FdfParser
.Profile
.FvDict
:
680 if len(FvName
) > MaxFvNameLength
:
681 MaxFvNameLength
= len(FvName
)
682 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
683 if os
.path
.exists(FvSpaceInfoFileName
):
684 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
691 for Line
in FileLinesList
:
692 NameValue
= Line
.split('=')
693 if len(NameValue
) == 2:
694 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
696 Total
= NameValue
[1].strip()
697 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
699 Used
= NameValue
[1].strip()
700 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
702 Free
= NameValue
[1].strip()
704 if TotalFound
and UsedFound
and FreeFound
:
705 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
707 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
708 for FvSpaceInfo
in FvSpaceInfoList
:
709 Name
= FvSpaceInfo
[0]
710 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
711 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
712 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
713 if UsedSizeValue
== TotalSizeValue
:
716 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
718 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
722 # @param BuildDb Database from build meta data files
723 # @param DscFile modules from dsc file will be preprocessed
726 def PreprocessImage(BuildDb
, DscFile
):
727 PcdDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
730 PcdObj
= PcdDict
[Key
]
731 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
732 PcdValue
= PcdObj
.DefaultValue
738 Int64PcdValue
= long(PcdValue
, 0)
739 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
743 if Int64PcdValue
> 0:
744 TopAddress
= Int64PcdValue
746 ModuleDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
747 for Key
in ModuleDict
:
748 ModuleObj
= BuildDb
.BuildObject
[Key
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
749 print ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
751 def GenerateGuidXRefFile(BuildDb
, ArchList
):
752 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
753 GuidXRefFile
= StringIO
.StringIO('')
755 for Arch
in ArchList
:
756 PlatformDataBase
= BuildDb
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
757 for ModuleFile
in PlatformDataBase
.Modules
:
758 Module
= BuildDb
.BuildObject
[ModuleFile
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
759 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
760 for key
, item
in Module
.Protocols
.items():
762 for key
, item
in Module
.Guids
.items():
764 for key
, item
in Module
.Ppis
.items():
766 # Append GUIDs, Protocols, and PPIs to the Xref file
767 GuidXRefFile
.write("\n")
768 for key
, item
in GuidDict
.items():
769 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
771 if GuidXRefFile
.getvalue():
772 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
773 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
774 elif os
.path
.exists(GuidXRefFileName
):
775 os
.remove(GuidXRefFileName
)
778 ##Define GenFd as static function
779 GenFd
= staticmethod(GenFd
)
780 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
781 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
782 PreprocessImage
= staticmethod(PreprocessImage
)
783 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
785 if __name__
== '__main__':
787 ## 0-127 is a safe return range, and 1 is a standard default error
788 if r
< 0 or r
> 127: r
= 1