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
45 import FfsFileStatement
47 from struct
import unpack
49 ## Version and Copyright
50 versionNumber
= "1.0" + ' ' + gBUILD_VERSION
51 __version__
= "%prog Version " + versionNumber
52 __copyright__
= "Copyright (c) 2007 - 2017, Intel Corporation All rights reserved."
54 ## Tool entrance method
56 # This method mainly dispatch specific methods per the command line options.
57 # If no error found, return zero value so the caller of this tool can know
58 # if it's executed successfully or not.
60 # @retval 0 Tool was successful
61 # @retval 1 Tool failed
65 Options
= myOptionParser()
72 EdkLogger
.Initialize()
74 if Options
.verbose
!= None:
75 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
76 GenFdsGlobalVariable
.VerboseMode
= True
78 if Options
.FixedAddress
!= None:
79 GenFdsGlobalVariable
.FixedLoadAddress
= True
81 if Options
.quiet
!= None:
82 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
83 if Options
.debug
!= None:
84 EdkLogger
.SetLevel(Options
.debug
+ 1)
85 GenFdsGlobalVariable
.DebugLevel
= Options
.debug
87 EdkLogger
.SetLevel(EdkLogger
.INFO
)
89 if (Options
.Workspace
== None):
90 EdkLogger
.error("GenFds", OPTION_MISSING
, "WORKSPACE not defined",
91 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
92 elif not os
.path
.exists(Options
.Workspace
):
93 EdkLogger
.error("GenFds", PARAMETER_INVALID
, "WORKSPACE is invalid",
94 ExtraData
="Please use '-w' switch to pass it or set the WORKSPACE environment variable.")
96 Workspace
= os
.path
.normcase(Options
.Workspace
)
97 GenFdsGlobalVariable
.WorkSpaceDir
= Workspace
98 if 'EDK_SOURCE' in os
.environ
.keys():
99 GenFdsGlobalVariable
.EdkSourceDir
= os
.path
.normcase(os
.environ
['EDK_SOURCE'])
101 GenFdsGlobalVariable
.VerboseLogger("Using Workspace:" + Workspace
)
102 os
.chdir(GenFdsGlobalVariable
.WorkSpaceDir
)
104 # set multiple workspace
105 PackagesPath
= os
.getenv("PACKAGES_PATH")
106 mws
.setWs(GenFdsGlobalVariable
.WorkSpaceDir
, PackagesPath
)
108 if (Options
.filename
):
109 FdfFilename
= Options
.filename
110 FdfFilename
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(FdfFilename
)
112 if FdfFilename
[0:2] == '..':
113 FdfFilename
= os
.path
.realpath(FdfFilename
)
114 if not os
.path
.isabs(FdfFilename
):
115 FdfFilename
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FdfFilename
)
116 if not os
.path
.exists(FdfFilename
):
117 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=FdfFilename
)
119 GenFdsGlobalVariable
.FdfFile
= FdfFilename
120 GenFdsGlobalVariable
.FdfFileTimeStamp
= os
.path
.getmtime(FdfFilename
)
122 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing FDF filename")
124 if (Options
.BuildTarget
):
125 GenFdsGlobalVariable
.TargetName
= Options
.BuildTarget
127 if (Options
.ToolChain
):
128 GenFdsGlobalVariable
.ToolChainTag
= Options
.ToolChain
130 if (Options
.activePlatform
):
131 ActivePlatform
= Options
.activePlatform
132 ActivePlatform
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(ActivePlatform
)
134 if ActivePlatform
[0:2] == '..':
135 ActivePlatform
= os
.path
.realpath(ActivePlatform
)
137 if not os
.path
.isabs (ActivePlatform
):
138 ActivePlatform
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ActivePlatform
)
140 if not os
.path
.exists(ActivePlatform
) :
141 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, "ActivePlatform doesn't exist!")
143 EdkLogger
.error("GenFds", OPTION_MISSING
, "Missing active platform")
145 GenFdsGlobalVariable
.ActivePlatform
= PathClass(NormPath(ActivePlatform
))
147 if (Options
.ConfDirectory
):
148 # Get alternate Conf location, if it is absolute, then just use the absolute directory name
149 ConfDirectoryPath
= os
.path
.normpath(Options
.ConfDirectory
)
150 if ConfDirectoryPath
.startswith('"'):
151 ConfDirectoryPath
= ConfDirectoryPath
[1:]
152 if ConfDirectoryPath
.endswith('"'):
153 ConfDirectoryPath
= ConfDirectoryPath
[:-1]
154 if not os
.path
.isabs(ConfDirectoryPath
):
155 # Since alternate directory name is not absolute, the alternate directory is located within the WORKSPACE
156 # This also handles someone specifying the Conf directory in the workspace. Using --conf=Conf
157 ConfDirectoryPath
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, ConfDirectoryPath
)
159 if "CONF_PATH" in os
.environ
.keys():
160 ConfDirectoryPath
= os
.path
.normcase(os
.environ
["CONF_PATH"])
162 # Get standard WORKSPACE/Conf, use the absolute path to the WORKSPACE/Conf
163 ConfDirectoryPath
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, 'Conf')
164 GenFdsGlobalVariable
.ConfDir
= ConfDirectoryPath
165 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, "target.txt"))
166 if os
.path
.isfile(BuildConfigurationFile
) == True:
167 TargetTxt
= TargetTxtClassObject
.TargetTxtClassObject()
168 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
169 # if no build target given in command line, get it from target.txt
170 if not GenFdsGlobalVariable
.TargetName
:
171 BuildTargetList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TARGET
]
172 if len(BuildTargetList
) != 1:
173 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for Target.")
174 GenFdsGlobalVariable
.TargetName
= BuildTargetList
[0]
176 # if no tool chain given in command line, get it from target.txt
177 if not GenFdsGlobalVariable
.ToolChainTag
:
178 ToolChainList
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_TAG
]
179 if ToolChainList
== None or len(ToolChainList
) == 0:
180 EdkLogger
.error("GenFds", RESOURCE_NOT_AVAILABLE
, ExtraData
="No toolchain given. Don't know how to build.")
181 if len(ToolChainList
) != 1:
182 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="Only allows one instance for ToolChain.")
183 GenFdsGlobalVariable
.ToolChainTag
= ToolChainList
[0]
185 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=BuildConfigurationFile
)
187 #Set global flag for build mode
188 GlobalData
.gIgnoreSource
= Options
.IgnoreSources
191 for Pair
in Options
.Macros
:
192 if Pair
.startswith('"'):
194 if Pair
.endswith('"'):
196 List
= Pair
.split('=')
198 if not List
[1].strip():
199 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
, ExtraData
="No Value given for Macro %s" %List
[0])
200 if List
[0].strip() == "EFI_SOURCE":
201 GlobalData
.gEfiSource
= List
[1].strip()
202 GlobalData
.gGlobalDefines
["EFI_SOURCE"] = GlobalData
.gEfiSource
204 elif List
[0].strip() == "EDK_SOURCE":
205 GlobalData
.gEdkSource
= List
[1].strip()
206 GlobalData
.gGlobalDefines
["EDK_SOURCE"] = GlobalData
.gEdkSource
208 elif List
[0].strip() in ["WORKSPACE", "TARGET", "TOOLCHAIN"]:
209 GlobalData
.gGlobalDefines
[List
[0].strip()] = List
[1].strip()
211 GlobalData
.gCommandLineDefines
[List
[0].strip()] = List
[1].strip()
213 GlobalData
.gCommandLineDefines
[List
[0].strip()] = "TRUE"
214 os
.environ
["WORKSPACE"] = Workspace
216 # Use the -t and -b option as gGlobalDefines's TOOLCHAIN and TARGET if they are not defined
217 if "TARGET" not in GlobalData
.gGlobalDefines
.keys():
218 GlobalData
.gGlobalDefines
["TARGET"] = GenFdsGlobalVariable
.TargetName
219 if "TOOLCHAIN" not in GlobalData
.gGlobalDefines
.keys():
220 GlobalData
.gGlobalDefines
["TOOLCHAIN"] = GenFdsGlobalVariable
.ToolChainTag
221 if "TOOL_CHAIN_TAG" not in GlobalData
.gGlobalDefines
.keys():
222 GlobalData
.gGlobalDefines
['TOOL_CHAIN_TAG'] = GenFdsGlobalVariable
.ToolChainTag
224 """call Workspace build create database"""
225 GlobalData
.gDatabasePath
= os
.path
.normpath(os
.path
.join(ConfDirectoryPath
, GlobalData
.gDatabasePath
))
226 BuildWorkSpace
= WorkspaceDatabase(GlobalData
.gDatabasePath
)
227 BuildWorkSpace
.InitDatabase()
230 # Get files real name in workspace dir
232 GlobalData
.gAllFiles
= DirCache(Workspace
)
233 GlobalData
.gWorkspace
= Workspace
235 if (Options
.archList
) :
236 ArchList
= Options
.archList
.split(',')
238 # EdkLogger.error("GenFds", OPTION_MISSING, "Missing build ARCH")
239 ArchList
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
241 TargetArchList
= set(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON', Options
.BuildTarget
, Options
.ToolChain
].SupArchList
) & set(ArchList
)
242 if len(TargetArchList
) == 0:
243 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Target ARCH %s not in platform supported ARCH %s" % (str(ArchList
), str(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, 'COMMON'].SupArchList
)))
245 for Arch
in ArchList
:
246 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = NormPath(BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].OutputDirectory
)
247 GenFdsGlobalVariable
.PlatformName
= BuildWorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, Options
.BuildTarget
, Options
.ToolChain
].PlatformName
249 if (Options
.outputDir
):
250 OutputDirFromCommandLine
= GenFdsGlobalVariable
.ReplaceWorkspaceMacro(Options
.outputDir
)
251 if not os
.path
.isabs (OutputDirFromCommandLine
):
252 OutputDirFromCommandLine
= os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, OutputDirFromCommandLine
)
253 for Arch
in ArchList
:
254 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = OutputDirFromCommandLine
256 for Arch
in ArchList
:
257 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.join(GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
], GenFdsGlobalVariable
.TargetName
+ '_' + GenFdsGlobalVariable
.ToolChainTag
)
259 for Key
in GenFdsGlobalVariable
.OutputDirDict
:
260 OutputDir
= GenFdsGlobalVariable
.OutputDirDict
[Key
]
261 if OutputDir
[0:2] == '..':
262 OutputDir
= os
.path
.realpath(OutputDir
)
264 if OutputDir
[1] != ':':
265 OutputDir
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, OutputDir
)
267 if not os
.path
.exists(OutputDir
):
268 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=OutputDir
)
269 GenFdsGlobalVariable
.OutputDirDict
[Key
] = OutputDir
271 """ Parse Fdf file, has to place after build Workspace as FDF may contain macros from DSC file """
272 FdfParserObj
= FdfParser
.FdfParser(FdfFilename
)
273 FdfParserObj
.ParseFile()
275 if FdfParserObj
.CycleReferenceCheck():
276 EdkLogger
.error("GenFds", FORMAT_NOT_SUPPORTED
, "Cycle Reference Detected in FDF file")
278 if (Options
.uiFdName
) :
279 if Options
.uiFdName
.upper() in FdfParserObj
.Profile
.FdDict
.keys():
280 GenFds
.OnlyGenerateThisFd
= Options
.uiFdName
282 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
283 "No such an FD in FDF file: %s" % Options
.uiFdName
)
285 if (Options
.uiFvName
) :
286 if Options
.uiFvName
.upper() in FdfParserObj
.Profile
.FvDict
.keys():
287 GenFds
.OnlyGenerateThisFv
= Options
.uiFvName
289 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
290 "No such an FV in FDF file: %s" % Options
.uiFvName
)
292 if (Options
.uiCapName
) :
293 if Options
.uiCapName
.upper() in FdfParserObj
.Profile
.CapsuleDict
.keys():
294 GenFds
.OnlyGenerateThisCap
= Options
.uiCapName
296 EdkLogger
.error("GenFds", OPTION_VALUE_INVALID
,
297 "No such a Capsule in FDF file: %s" % Options
.uiCapName
)
299 GenFdsGlobalVariable
.WorkSpace
= BuildWorkSpace
301 GenFdsGlobalVariable
.ArchList
= ArchList
303 if Options
.OptionPcd
:
304 GlobalData
.BuildOptionPcd
= Options
.OptionPcd
305 CheckBuildOptionPcd()
307 """Modify images from build output if the feature of loading driver at fixed address is on."""
308 if GenFdsGlobalVariable
.FixedLoadAddress
:
309 GenFds
.PreprocessImage(BuildWorkSpace
, GenFdsGlobalVariable
.ActivePlatform
)
311 # Record the FV Region info that may specific in the FD
312 if FdfParserObj
.Profile
.FvDict
and FdfParserObj
.Profile
.FdDict
:
313 for Fv
in FdfParserObj
.Profile
.FvDict
:
314 FvObj
= FdfParserObj
.Profile
.FvDict
[Fv
]
315 for Fd
in FdfParserObj
.Profile
.FdDict
:
316 FdObj
= FdfParserObj
.Profile
.FdDict
[Fd
]
317 for RegionObj
in FdObj
.RegionList
:
318 if RegionObj
.RegionType
!= 'FV':
320 for RegionData
in RegionObj
.RegionDataList
:
321 if FvObj
.UiFvName
.upper() == RegionData
.upper():
322 if FvObj
.FvRegionInFD
:
323 if FvObj
.FvRegionInFD
!= RegionObj
.Size
:
324 EdkLogger
.error("GenFds", FORMAT_INVALID
, "The FV %s's region is specified in multiple FD with different value." %FvObj
.UiFvName
)
326 FvObj
.FvRegionInFD
= RegionObj
.Size
327 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, FvObj
)
330 GenFds
.GenFd('', FdfParserObj
, BuildWorkSpace
, ArchList
)
332 """Generate GUID cross reference file"""
333 GenFds
.GenerateGuidXRefFile(BuildWorkSpace
, ArchList
, FdfParserObj
)
335 """Display FV space info."""
336 GenFds
.DisplayFvSpaceInfo(FdfParserObj
)
338 except FdfParser
.Warning, X
:
339 EdkLogger
.error(X
.ToolName
, FORMAT_INVALID
, File
=X
.FileName
, Line
=X
.LineNumber
, ExtraData
=X
.Message
, RaiseError
=False)
340 ReturnCode
= FORMAT_INVALID
341 except FatalError
, X
:
342 if Options
.debug
!= None:
344 EdkLogger
.quiet(traceback
.format_exc())
345 ReturnCode
= X
.args
[0]
351 "Tools code failure",
352 ExtraData
="Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!\n",
355 EdkLogger
.quiet(traceback
.format_exc())
356 ReturnCode
= CODE_ERROR
362 def SingleCheckCallback(option
, opt_str
, value
, parser
):
363 if option
not in gParamCheck
:
364 setattr(parser
.values
, option
.dest
, value
)
365 gParamCheck
.append(option
)
367 parser
.error("Option %s only allows one instance in command line!" % option
)
369 def CheckBuildOptionPcd():
370 for Arch
in GenFdsGlobalVariable
.ArchList
:
371 PkgList
= GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
)
372 for i
, pcd
in enumerate(GlobalData
.BuildOptionPcd
):
373 if type(pcd
) is tuple:
375 (pcdname
, pcdvalue
) = pcd
.split('=')
377 EdkLogger
.error('GenFds', OPTION_MISSING
, "No Value specified for the PCD %s." % (pcdname
))
379 (TokenSpaceGuidCName
, TokenCName
) = pcdname
.split('.')
383 TokenSpaceGuidCName
= ''
384 HasTokenSpace
= False
385 TokenSpaceGuidCNameList
= []
389 for package
in PkgList
:
390 for key
in package
.Pcds
:
391 PcdItem
= package
.Pcds
[key
]
393 if (PcdItem
.TokenCName
, PcdItem
.TokenSpaceGuidCName
) == (TokenCName
, TokenSpaceGuidCName
):
394 PcdDatumType
= PcdItem
.DatumType
395 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
398 if PcdItem
.TokenCName
== TokenCName
:
399 if not PcdItem
.TokenSpaceGuidCName
in TokenSpaceGuidCNameList
:
400 if len (TokenSpaceGuidCNameList
) < 1:
401 TokenSpaceGuidCNameList
.append(PcdItem
.TokenSpaceGuidCName
)
402 PcdDatumType
= PcdItem
.DatumType
403 TokenSpaceGuidCName
= PcdItem
.TokenSpaceGuidCName
404 NewValue
= BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, pcdvalue
)
409 PCD_VALIDATION_INFO_ERROR
,
410 "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName
, PcdItem
.TokenSpaceGuidCName
, TokenSpaceGuidCNameList
[0])
413 GlobalData
.BuildOptionPcd
[i
] = (TokenSpaceGuidCName
, TokenCName
, NewValue
)
418 # Find location of tools to process data
420 # @param KeyStringList Filter for inputs of section generation
421 # @param CurrentArchList Arch list
422 # @param NameGuid The Guid name
424 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
425 ToolDb
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
426 # if user not specify filter, try to deduce it from global data.
427 if KeyStringList
== None or KeyStringList
== []:
428 Target
= GenFdsGlobalVariable
.TargetName
429 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
430 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
431 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
432 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
433 for Arch
in CurrentArchList
:
434 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
435 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
437 if GenFdsGlobalVariable
.GuidToolDefinition
:
438 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
.keys():
439 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
441 ToolDefinition
= ToolDefClassObject
.ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
447 for ToolDef
in ToolDefinition
.items():
448 if NameGuid
== ToolDef
[1]:
449 KeyList
= ToolDef
[0].split('_')
455 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
456 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
457 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
458 ToolPath
= ToolDefinition
.get(ToolPathKey
)
459 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
460 if ToolPathTmp
== None:
461 ToolPathTmp
= ToolPath
463 if ToolPathTmp
!= ToolPath
:
464 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
467 for Arch
in CurrentArchList
:
468 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
469 # key is (ToolChainFamily, ToolChain, CodeBase)
470 for item
in Platform
.BuildOptions
:
471 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
472 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
473 if item
[1] not in BuildOption
:
474 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
476 ToolList
= [TAB_TOD_DEFINES_TARGET
, TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, TAB_TOD_DEFINES_TARGET_ARCH
]
477 for Index
in range(2, -1, -1):
478 for Key
in dict(BuildOption
):
479 List
= Key
.split('_')
480 if List
[Index
] == '*':
481 for String
in ToolDb
[ToolList
[Index
]]:
482 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
484 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
485 if NewKey
not in BuildOption
:
486 BuildOption
[NewKey
] = BuildOption
[Key
]
489 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
493 for Op
in BuildOption
:
494 if NameGuid
== BuildOption
[Op
]:
495 KeyList
= Op
.split('_')
496 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
497 if Key
in KeyStringList
and KeyList
[4] == 'GUID':
498 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
499 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
500 if ToolPathKey
in BuildOption
.keys():
501 ToolPathTmp
= BuildOption
.get(ToolPathKey
)
502 if ToolOptionKey
in BuildOption
.keys():
503 ToolOption
= BuildOption
.get(ToolOptionKey
)
505 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
506 return ToolPathTmp
, ToolOption
508 ## Parse command line options
510 # Using standard Python module optparse to parse command line option of this tool.
512 # @retval Opt A optparse.Values object containing the parsed options
513 # @retval Args Target of build command
515 def myOptionParser():
516 usage
= "%prog [options] -f input_file -a arch_list -b build_target -p active_platform -t tool_chain_tag -D \"MacroName [= MacroValue]\""
517 Parser
= OptionParser(usage
=usage
, description
=__copyright__
, version
="%prog " + str(versionNumber
))
518 Parser
.add_option("-f", "--file", dest
="filename", type="string", help="Name of FDF file to convert", action
="callback", callback
=SingleCheckCallback
)
519 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")
520 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
521 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed.")
522 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
523 Parser
.add_option("-p", "--platform", type="string", dest
="activePlatform", help="Set the ACTIVE_PLATFORM, overrides target.txt ACTIVE_PLATFORM setting.",
524 action
="callback", callback
=SingleCheckCallback
)
525 Parser
.add_option("-w", "--workspace", type="string", dest
="Workspace", default
=os
.environ
.get('WORKSPACE'), help="Set the WORKSPACE",
526 action
="callback", callback
=SingleCheckCallback
)
527 Parser
.add_option("-o", "--outputDir", type="string", dest
="outputDir", help="Name of Build Output directory",
528 action
="callback", callback
=SingleCheckCallback
)
529 Parser
.add_option("-r", "--rom_image", dest
="uiFdName", help="Build the image using the [FD] section named by FdUiName.")
530 Parser
.add_option("-i", "--FvImage", dest
="uiFvName", help="Build the FV image using the [FV] section named by UiFvName")
531 Parser
.add_option("-C", "--CapsuleImage", dest
="uiCapName", help="Build the Capsule image using the [Capsule] section named by UiCapName")
532 Parser
.add_option("-b", "--buildtarget", type="string", dest
="BuildTarget", help="Set the build TARGET, overrides target.txt TARGET setting.",
533 action
="callback", callback
=SingleCheckCallback
)
534 Parser
.add_option("-t", "--tagname", type="string", dest
="ToolChain", help="Using the tools: TOOL_CHAIN_TAG name to build the platform.",
535 action
="callback", callback
=SingleCheckCallback
)
536 Parser
.add_option("-D", "--define", action
="append", type="string", dest
="Macros", help="Macro: \"Name [= Value]\".")
537 Parser
.add_option("-s", "--specifyaddress", dest
="FixedAddress", action
="store_true", type=None, help="Specify driver load address.")
538 Parser
.add_option("--conf", action
="store", type="string", dest
="ConfDirectory", help="Specify the customized Conf directory.")
539 Parser
.add_option("--ignore-sources", action
="store_true", dest
="IgnoreSources", default
=False, help="Focus to a binary build and ignore all source files")
540 Parser
.add_option("--pcd", action
="append", dest
="OptionPcd", help="Set PCD value by command line. Format: \"PcdName=Value\" ")
542 (Options
, args
) = Parser
.parse_args()
545 ## The class implementing the EDK2 flash image generation process
547 # This process includes:
548 # 1. Collect workspace information, includes platform and module information
549 # 2. Call methods of Fd class to generate FD
550 # 3. Call methods of Fv class to generate FV that not belong to FD
554 # FvName, FdName, CapName in FDF, Image file name
556 OnlyGenerateThisFd
= None
557 OnlyGenerateThisFv
= None
558 OnlyGenerateThisCap
= None
562 # @param OutputDir Output directory
563 # @param FdfParser FDF contents parser
564 # @param Workspace The directory of workspace
565 # @param ArchList The Arch list of platform
567 def GenFd (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
568 GenFdsGlobalVariable
.SetDir ('', FdfParser
, WorkSpace
, ArchList
)
570 GenFdsGlobalVariable
.VerboseLogger(" Generate all Fd images and their required FV and Capsule images!")
571 if GenFds
.OnlyGenerateThisCap
!= None and GenFds
.OnlyGenerateThisCap
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
572 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.get(GenFds
.OnlyGenerateThisCap
.upper())
573 if CapsuleObj
!= None:
574 CapsuleObj
.GenCapsule()
577 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
578 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.get(GenFds
.OnlyGenerateThisFd
.upper())
582 elif GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisFv
== None:
583 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
584 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
587 GenFdsGlobalVariable
.VerboseLogger("\n Generate other FV images! ")
588 if GenFds
.OnlyGenerateThisFv
!= None and GenFds
.OnlyGenerateThisFv
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
589 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(GenFds
.OnlyGenerateThisFv
.upper())
591 Buffer
= StringIO
.StringIO()
592 FvObj
.AddToBuffer(Buffer
)
595 elif GenFds
.OnlyGenerateThisFv
== None:
596 for FvName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
597 Buffer
= StringIO
.StringIO('')
598 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[FvName
]
599 FvObj
.AddToBuffer(Buffer
)
602 if GenFds
.OnlyGenerateThisFv
== None and GenFds
.OnlyGenerateThisFd
== None and GenFds
.OnlyGenerateThisCap
== None:
603 if GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
!= {}:
604 GenFdsGlobalVariable
.VerboseLogger("\n Generate other Capsule images!")
605 for CapsuleName
in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
606 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[CapsuleName
]
607 CapsuleObj
.GenCapsule()
609 if GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
!= {}:
610 GenFdsGlobalVariable
.VerboseLogger("\n Generate all Option ROM!")
611 for DriverName
in GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
.keys():
612 OptRomObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.OptRomDict
[DriverName
]
613 OptRomObj
.AddToBuffer(None)
617 # @param FvObj Whose block size to get
618 # @retval int Block size value
620 def GetFvBlockSize(FvObj
):
621 DefaultBlockSize
= 0x1
623 if GenFds
.OnlyGenerateThisFd
!= None and GenFds
.OnlyGenerateThisFd
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
624 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[GenFds
.OnlyGenerateThisFd
.upper()]
626 for ElementFd
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.values():
627 for ElementRegion
in ElementFd
.RegionList
:
628 if ElementRegion
.RegionType
== 'FV':
629 for ElementRegionData
in ElementRegion
.RegionDataList
:
630 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
631 if FvObj
.BlockSizeList
!= []:
632 return FvObj
.BlockSizeList
[0][0]
634 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
635 if FvObj
.BlockSizeList
!= []:
636 return FvObj
.BlockSizeList
[0][0]
637 return DefaultBlockSize
639 for ElementRegion
in FdObj
.RegionList
:
640 if ElementRegion
.RegionType
== 'FV':
641 for ElementRegionData
in ElementRegion
.RegionDataList
:
642 if ElementRegionData
!= None and ElementRegionData
.upper() == FvObj
.UiFvName
:
643 if FvObj
.BlockSizeList
!= []:
644 return FvObj
.BlockSizeList
[0][0]
646 return ElementRegion
.BlockSizeOfRegion(ElementFd
.BlockSizeList
)
647 return DefaultBlockSize
649 ## DisplayFvSpaceInfo()
651 # @param FvObj Whose block size to get
654 def DisplayFvSpaceInfo(FdfParser
):
658 for FvName
in FdfParser
.Profile
.FvDict
:
659 if len(FvName
) > MaxFvNameLength
:
660 MaxFvNameLength
= len(FvName
)
661 FvSpaceInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, FvName
.upper() + '.Fv.map')
662 if os
.path
.exists(FvSpaceInfoFileName
):
663 FileLinesList
= linecache
.getlines(FvSpaceInfoFileName
)
670 for Line
in FileLinesList
:
671 NameValue
= Line
.split('=')
672 if len(NameValue
) == 2:
673 if NameValue
[0].strip() == 'EFI_FV_TOTAL_SIZE':
675 Total
= NameValue
[1].strip()
676 if NameValue
[0].strip() == 'EFI_FV_TAKEN_SIZE':
678 Used
= NameValue
[1].strip()
679 if NameValue
[0].strip() == 'EFI_FV_SPACE_SIZE':
681 Free
= NameValue
[1].strip()
683 if TotalFound
and UsedFound
and FreeFound
:
684 FvSpaceInfoList
.append((FvName
, Total
, Used
, Free
))
686 GenFdsGlobalVariable
.InfLogger('\nFV Space Information')
687 for FvSpaceInfo
in FvSpaceInfoList
:
688 Name
= FvSpaceInfo
[0]
689 TotalSizeValue
= long(FvSpaceInfo
[1], 0)
690 UsedSizeValue
= long(FvSpaceInfo
[2], 0)
691 FreeSizeValue
= long(FvSpaceInfo
[3], 0)
692 if UsedSizeValue
== TotalSizeValue
:
695 Percentage
= str((UsedSizeValue
+ 0.0) / TotalSizeValue
)[0:4].lstrip('0.')
697 GenFdsGlobalVariable
.InfLogger(Name
+ ' ' + '[' + Percentage
+ '%Full] ' + str(TotalSizeValue
) + ' total, ' + str(UsedSizeValue
) + ' used, ' + str(FreeSizeValue
) + ' free')
701 # @param BuildDb Database from build meta data files
702 # @param DscFile modules from dsc file will be preprocessed
705 def PreprocessImage(BuildDb
, DscFile
):
706 PcdDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Pcds
709 PcdObj
= PcdDict
[Key
]
710 if PcdObj
.TokenCName
== 'PcdBsBaseAddress':
711 PcdValue
= PcdObj
.DefaultValue
717 Int64PcdValue
= long(PcdValue
, 0)
718 if Int64PcdValue
== 0 or Int64PcdValue
< -1:
722 if Int64PcdValue
> 0:
723 TopAddress
= Int64PcdValue
725 ModuleDict
= BuildDb
.BuildObject
[DscFile
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].Modules
726 for Key
in ModuleDict
:
727 ModuleObj
= BuildDb
.BuildObject
[Key
, 'COMMON', GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
728 print ModuleObj
.BaseName
+ ' ' + ModuleObj
.ModuleType
730 def GenerateGuidXRefFile(BuildDb
, ArchList
, FdfParserObj
):
731 GuidXRefFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, "Guid.xref")
732 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 if Module
in ModuleList
:
743 ModuleList
.append(Module
)
744 GuidXRefFile
.write("%s %s\n" % (Module
.Guid
, Module
.BaseName
))
745 for key
, item
in Module
.Protocols
.items():
747 for key
, item
in Module
.Guids
.items():
749 for key
, item
in Module
.Ppis
.items():
751 for FvName
in FdfParserObj
.Profile
.FvDict
:
752 for FfsObj
in FdfParserObj
.Profile
.FvDict
[FvName
].FfsList
:
753 if not isinstance(FfsObj
, FfsFileStatement
.FileStatement
):
754 InfPath
= PathClass(NormPath(mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, FfsObj
.InfFileName
)))
755 FdfModule
= BuildDb
.BuildObject
[InfPath
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
756 if FdfModule
in ModuleList
:
759 ModuleList
.append(FdfModule
)
760 GuidXRefFile
.write("%s %s\n" % (FdfModule
.Guid
, FdfModule
.BaseName
))
761 for key
, item
in FdfModule
.Protocols
.items():
763 for key
, item
in FdfModule
.Guids
.items():
765 for key
, item
in FdfModule
.Ppis
.items():
768 FileStatementGuid
= FfsObj
.NameGuid
769 if FileStatementGuid
in FileGuidList
:
772 FileGuidList
.append(FileStatementGuid
)
774 FfsPath
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
775 FfsPath
= glob
.glob(os
.path
.join(FfsPath
, FileStatementGuid
) + '*')
778 if not os
.path
.exists(FfsPath
[0]):
781 ReFileEnds
= re
.compile('\S+(.ui)$|\S+(fv.sec.txt)$|\S+(.pe32.txt)$|\S+(.te.txt)$|\S+(.pic.txt)$|\S+(.raw.txt)$|\S+(.ffs.txt)$')
782 FileList
= os
.listdir(FfsPath
[0])
783 for File
in FileList
:
784 Match
= ReFileEnds
.search(File
)
786 for Index
in range(1, 8):
787 if Match
.group(Index
) and Match
.group(Index
) in MatchDict
:
788 MatchDict
[Match
.group(Index
)].append(File
)
789 elif Match
.group(Index
):
790 MatchDict
[Match
.group(Index
)] = [File
]
793 if '.ui' in MatchDict
:
794 for File
in MatchDict
['.ui']:
795 with
open(os
.path
.join(FfsPath
[0], File
), 'rb') as F
:
799 TmpStr
= unpack('%dh' % ((length
- 4) / 2), F
.read())
800 Name
= ''.join([chr(c
) for c
in TmpStr
[:-1]])
803 if 'fv.sec.txt' in MatchDict
:
804 FileList
= MatchDict
['fv.sec.txt']
805 elif '.pe32.txt' in MatchDict
:
806 FileList
= MatchDict
['.pe32.txt']
807 elif '.te.txt' in MatchDict
:
808 FileList
= MatchDict
['.te.txt']
809 elif '.pic.txt' in MatchDict
:
810 FileList
= MatchDict
['.pic.txt']
811 elif '.raw.txt' in MatchDict
:
812 FileList
= MatchDict
['.raw.txt']
813 elif '.ffs.txt' in MatchDict
:
814 FileList
= MatchDict
['.ffs.txt']
817 for File
in FileList
:
818 with
open(os
.path
.join(FfsPath
[0], File
), 'r') as F
:
819 Name
.append((F
.read().split()[-1]))
823 Name
= ' '.join(Name
) if type(Name
) == type([]) else Name
824 GuidXRefFile
.write("%s %s\n" %(FileStatementGuid
, Name
))
826 # Append GUIDs, Protocols, and PPIs to the Xref file
827 GuidXRefFile
.write("\n")
828 for key
, item
in GuidDict
.items():
829 GuidXRefFile
.write("%s %s\n" % (GuidStructureStringToGuidString(item
).upper(), key
))
831 if GuidXRefFile
.getvalue():
832 SaveFileOnChange(GuidXRefFileName
, GuidXRefFile
.getvalue(), False)
833 GenFdsGlobalVariable
.InfLogger("\nGUID cross reference file can be found at %s" % GuidXRefFileName
)
834 elif os
.path
.exists(GuidXRefFileName
):
835 os
.remove(GuidXRefFileName
)
838 ##Define GenFd as static function
839 GenFd
= staticmethod(GenFd
)
840 GetFvBlockSize
= staticmethod(GetFvBlockSize
)
841 DisplayFvSpaceInfo
= staticmethod(DisplayFvSpaceInfo
)
842 PreprocessImage
= staticmethod(PreprocessImage
)
843 GenerateGuidXRefFile
= staticmethod(GenerateGuidXRefFile
)
845 if __name__
== '__main__':
847 ## 0-127 is a safe return range, and 1 is a standard default error
848 if r
< 0 or r
> 127: r
= 1