2 # Global variables for GenFds
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
24 from Common
.BuildToolError
import *
25 from Common
import EdkLogger
26 from Common
.Misc
import SaveFileOnChange
28 from Common
.TargetTxtClassObject
import TargetTxtClassObject
29 from Common
.ToolDefClassObject
import ToolDefClassObject
, ToolDefDict
30 from AutoGen
.BuildEngine
import BuildRule
31 import Common
.DataType
as DataType
32 from Common
.Misc
import PathClass
33 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
34 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
39 class GenFdsGlobalVariable
:
43 # will be FvDir + os.sep + 'Ffs'
51 OutputDirFromDscDict
= {}
58 FvAddressFileName
= ''
62 SharpNumberPerLine
= 40
65 FixedLoadAddress
= False
68 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
69 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
70 __BuildRuleDatabase
= None
71 GuidToolDefinition
= {}
76 EnableGenfdsMultiThread
= False
79 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
80 # At the beginning of each generation of FV, false flag is appended to the list,
81 # after the call to GenerateSection returns, check the size of the output file,
82 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
83 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
84 # At the end of generation of FV, pop the flag.
85 # List is used as a stack to handle nested FV generation.
87 LargeFileInFvFlags
= []
88 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
89 LARGE_FILE_SIZE
= 0x1000000
91 SectionHeader
= struct
.Struct("3B 1B")
93 # FvName, FdName, CapName in FDF, Image file name
99 def __LoadBuildRule():
100 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
101 return GenFdsGlobalVariable
.__BuildRuleDatabase
102 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
103 TargetTxt
= TargetTxtClassObject()
104 if os
.path
.isfile(BuildConfigurationFile
) == True:
105 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
106 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
107 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
108 if not BuildRuleFile
:
109 BuildRuleFile
= 'Conf/build_rule.txt'
110 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
111 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
112 if ToolDefinitionFile
== '':
113 ToolDefinitionFile
= "Conf/tools_def.txt"
114 if os
.path
.isfile(ToolDefinitionFile
):
115 ToolDef
= ToolDefClassObject()
116 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
117 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
118 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
119 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
120 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
121 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
123 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
124 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
125 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
126 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
127 return GenFdsGlobalVariable
.__BuildRuleDatabase
130 # @param Inf: object of InfBuildData
131 # @param Arch: current arch
134 def GetBuildRules(Inf
, Arch
):
136 Arch
= DataType
.TAB_COMMON
138 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
141 BuildRuleDatabase
= GenFdsGlobalVariable
.__LoadBuildRule
()
142 if not BuildRuleDatabase
:
145 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
146 GenFdsGlobalVariable
.WorkSpaceDir
)
148 Macro
["WORKSPACE" ] = GenFdsGlobalVariable
.WorkSpaceDir
149 Macro
["MODULE_NAME" ] = Inf
.BaseName
150 Macro
["MODULE_GUID" ] = Inf
.Guid
151 Macro
["MODULE_VERSION" ] = Inf
.Version
152 Macro
["MODULE_TYPE" ] = Inf
.ModuleType
153 Macro
["MODULE_FILE" ] = str(PathClassObj
)
154 Macro
["MODULE_FILE_BASE_NAME" ] = PathClassObj
.BaseName
155 Macro
["MODULE_RELATIVE_DIR" ] = PathClassObj
.SubDir
156 Macro
["MODULE_DIR" ] = PathClassObj
.SubDir
158 Macro
["BASE_NAME" ] = Inf
.BaseName
160 Macro
["ARCH" ] = Arch
161 Macro
["TOOLCHAIN" ] = GenFdsGlobalVariable
.ToolChainTag
162 Macro
["TOOLCHAIN_TAG" ] = GenFdsGlobalVariable
.ToolChainTag
163 Macro
["TOOL_CHAIN_TAG" ] = GenFdsGlobalVariable
.ToolChainTag
164 Macro
["TARGET" ] = GenFdsGlobalVariable
.TargetName
166 Macro
["BUILD_DIR" ] = GenFdsGlobalVariable
.OutputDirDict
[Arch
]
167 Macro
["BIN_DIR" ] = os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
168 Macro
["LIB_DIR" ] = os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
169 BuildDir
= os
.path
.join(
170 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
173 PathClassObj
.BaseName
175 Macro
["MODULE_BUILD_DIR" ] = BuildDir
176 Macro
["OUTPUT_DIR" ] = os
.path
.join(BuildDir
, "OUTPUT")
177 Macro
["DEBUG_DIR" ] = os
.path
.join(BuildDir
, "DEBUG")
180 for Type
in BuildRuleDatabase
.FileTypeList
:
181 #first try getting build rule by BuildRuleFamily
182 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
184 # build type is always module type, but ...
185 if Inf
.ModuleType
!= Inf
.BuildType
:
186 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
187 #second try getting build rule by ToolChainFamily
189 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
191 # build type is always module type, but ...
192 if Inf
.ModuleType
!= Inf
.BuildType
:
193 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
196 RuleObject
= RuleObject
.Instantiate(Macro
)
197 BuildRules
[Type
] = RuleObject
198 for Ext
in RuleObject
.SourceFileExtList
:
199 BuildRules
[Ext
] = RuleObject
202 ## GetModuleCodaTargetList
204 # @param Inf: object of InfBuildData
205 # @param Arch: current arch
208 def GetModuleCodaTargetList(Inf
, Arch
):
209 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
216 if not Inf
.IsBinaryModule
:
217 for File
in Inf
.Sources
:
218 if File
.TagName
in ("", "*", GenFdsGlobalVariable
.ToolChainTag
) and \
219 File
.ToolChainFamily
in ("", "*", GenFdsGlobalVariable
.ToolChainFamily
):
220 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
222 for File
in Inf
.Binaries
:
223 if File
.Target
in [DataType
.TAB_COMMON
, '*', GenFdsGlobalVariable
.TargetName
]:
224 FileList
.append((File
, File
.Type
))
226 for File
, FileType
in FileList
:
231 while Index
< len(SourceList
):
232 Source
= SourceList
[Index
]
235 if File
.IsBinary
and File
== Source
and Inf
.Binaries
is not None and File
in Inf
.Binaries
:
236 # Skip all files that are not binary libraries
237 if not Inf
.LibraryClass
:
239 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
240 elif FileType
in BuildRules
:
241 RuleObject
= BuildRules
[FileType
]
242 elif Source
.Ext
in BuildRules
:
243 RuleObject
= BuildRules
[Source
.Ext
]
245 # stop at no more rules
247 TargetList
.add(str(LastTarget
))
250 FileType
= RuleObject
.SourceFileType
252 # stop at STATIC_LIBRARY for library
253 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
255 TargetList
.add(str(LastTarget
))
258 Target
= RuleObject
.Apply(Source
)
261 TargetList
.add(str(LastTarget
))
263 elif not Target
.Outputs
:
264 # Only do build for target with outputs
265 TargetList
.add(str(Target
))
267 # to avoid cyclic rule
268 if FileType
in RuleChain
:
271 RuleChain
.append(FileType
)
272 SourceList
.extend(Target
.Outputs
)
274 FileType
= DataType
.TAB_UNKNOWN_FILE
275 for Cmd
in Target
.Commands
:
276 if "$(CP)" == Cmd
.split()[0]:
277 CpTarget
= Cmd
.split()[2]
278 TargetList
.add(CpTarget
)
280 return list(TargetList
)
284 # @param OutputDir Output directory
285 # @param FdfParser FDF contents parser
286 # @param Workspace The directory of workspace
287 # @param ArchList The Arch list of platform
289 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
290 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir
)
291 # GenFdsGlobalVariable.OutputDirDict = OutputDir
292 GenFdsGlobalVariable
.FdfParser
= FdfParser
293 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
294 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
295 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
) :
296 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
297 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
298 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
) :
299 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
303 # Create FV Address inf file
305 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
306 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
310 FvAddressFile
.writelines("[options]" + T_CHAR_LF
)
312 for Arch
in ArchList
:
313 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
314 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
317 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
322 for Arch
in ArchList
:
323 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
:
324 RtAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
326 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
330 FvAddressFile
.close()
332 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
333 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
334 GenFdsGlobalVariable
.FdfParser
= FdfParser
335 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
336 GenFdsGlobalVariable
.ArchList
= ArchList
337 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
338 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
339 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
340 GenFdsGlobalVariable
.EdkSourceDir
= GlobalData
.gGlobalDefines
["EDK_SOURCE"]
341 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
342 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
343 for Arch
in ArchList
:
344 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
345 os
.path
.join(GlobalData
.gWorkspace
,
346 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
347 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
348 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
349 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
350 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
351 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
352 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
353 GlobalData
.gGlobalDefines
['TARGET'],
354 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
355 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
356 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
357 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
358 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
359 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
360 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
364 # Create FV Address inf file
366 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
367 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
371 FvAddressFile
.writelines("[options]" + T_CHAR_LF
)
373 for Arch
in ArchList
:
374 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
375 GlobalData
.gGlobalDefines
['TARGET'],
376 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
380 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
385 for Arch
in ArchList
:
386 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
387 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
388 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
:
389 RtAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
390 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
391 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
393 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
397 FvAddressFile
.close()
399 ## ReplaceWorkspaceMacro()
401 # @param String String that may contain macro
403 def ReplaceWorkspaceMacro(String
):
404 String
= mws
.handleWsMacro(String
)
405 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
406 if os
.path
.exists(Str
):
407 if not os
.path
.isabs(Str
):
408 Str
= os
.path
.abspath(Str
)
410 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
411 return os
.path
.normpath(Str
)
413 ## Check if the input files are newer than output files
415 # @param Output Path of output file
416 # @param Input Path list of input files
418 # @retval True if Output doesn't exist, or any Input is newer
419 # @retval False if all Input is older than Output
422 def NeedsUpdate(Output
, Input
):
423 if not os
.path
.exists(Output
):
425 # always update "Output" if no "Input" given
426 if Input
is None or len(Input
) == 0:
429 # if fdf file is changed after the 'Output" is generated, update the 'Output'
430 OutputTime
= os
.path
.getmtime(Output
)
431 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
435 # always update "Output" if any "Input" doesn't exist
436 if not os
.path
.exists(F
):
438 # always update "Output" if any "Input" is newer than "Output"
439 if os
.path
.getmtime(F
) > OutputTime
:
444 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
445 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
450 Cmd
+= ("-c", CompressionType
)
453 if DummyFile
is not None:
454 Cmd
+= ("--dummy", DummyFile
)
456 Cmd
+= ("-l", GuidHdrLen
)
457 #Add each guided attribute
458 for Attr
in GuidAttr
:
460 #Section Align is only for dummy section without section type
461 for SecAlign
in InputAlign
:
462 Cmd
+= ("--sectionalign", SecAlign
)
464 CommandFile
= Output
+ '.txt'
467 if Ui
== "$(MODULE_NAME)":
470 Cmd
+= ("-n", '"' + Ui
+ '"')
471 Cmd
+= ("-o", Output
)
472 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
473 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
475 SectionData
= array
.array('B', [0, 0, 0, 0])
476 SectionData
.fromstring(Ui
.encode("utf_16_le"))
477 SectionData
.append(0)
478 SectionData
.append(0)
479 Len
= len(SectionData
)
480 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
481 SaveFileOnChange(Output
, SectionData
.tostring())
486 Cmd
+= ("-j", BuildNumber
)
487 Cmd
+= ("-o", Output
)
489 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
491 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
492 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
494 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
496 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
498 Cmd
+= ("-o", Output
)
501 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
503 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
504 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
505 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
506 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
507 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
508 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
509 GenFdsGlobalVariable
.LargeFileInFvFlags
):
510 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
513 def GetAlignment (AlignString
):
516 if AlignString
.endswith('K'):
517 return int (AlignString
.rstrip('K')) * 1024
518 if AlignString
.endswith('M'):
519 return int (AlignString
.rstrip('M')) * 1024 * 1024
520 if AlignString
.endswith('G'):
521 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
522 return int (AlignString
)
525 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
526 SectionAlign
=None, MakefilePath
=None):
527 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
528 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
534 if Align
not in mFfsValidAlign
:
535 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
536 for index
in range(0, len(mFfsValidAlign
) - 1):
537 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
539 Align
= mFfsValidAlign
[index
+ 1]
542 Cmd
+= ("-o", Output
)
543 for I
in range(0, len(Input
)):
544 Cmd
+= ("-i", Input
[I
])
545 if SectionAlign
and SectionAlign
[I
]:
546 Cmd
+= ("-n", SectionAlign
[I
])
548 CommandFile
= Output
+ '.txt'
549 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
551 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
553 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
554 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
555 GenFdsGlobalVariable
.SecCmdList
= []
556 GenFdsGlobalVariable
.CopyList
= []
558 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
560 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
563 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
564 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
565 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
567 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
571 Cmd
+= ("-r", BaseAddress
)
573 if ForceRebase
== False:
574 Cmd
+= ("-F", "FALSE")
575 elif ForceRebase
== True:
576 Cmd
+= ("-F", "TRUE")
583 Cmd
+= ("-a", AddressFile
)
585 Cmd
+= ("-m", MapFile
)
587 Cmd
+= ("-g", FileSystemGuid
)
588 Cmd
+= ("-o", Output
)
592 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
595 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
596 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
597 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
598 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
600 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
603 if Type
.lower() == "te":
606 Cmd
+= ("-e", SubType
)
608 Cmd
+= ("-s", TimeStamp
)
612 Cmd
+= ("-p", Padding
)
623 Cmd
+= ("-o", Output
)
626 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
627 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
629 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
632 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
633 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
636 if len(EfiInput
) > 0:
643 for EfiFile
in EfiInput
:
645 InputList
.append (EfiFile
)
647 if len(BinaryInput
) > 0:
649 for BinFile
in BinaryInput
:
651 InputList
.append (BinFile
)
654 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
656 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
658 if ClassCode
is not None:
659 Cmd
+= ("-l", ClassCode
)
660 if Revision
is not None:
661 Cmd
+= ("-r", Revision
)
662 if DeviceId
is not None:
663 Cmd
+= ("-i", DeviceId
)
664 if VendorId
is not None:
665 Cmd
+= ("-f", VendorId
)
667 Cmd
+= ("-o", Output
)
669 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
670 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
672 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
675 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
676 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
678 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
681 Cmd
+= Options
.split(' ')
682 Cmd
+= ("-o", Output
)
685 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
686 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
688 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
690 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
692 if type(cmd
) not in (tuple, list):
693 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
695 if GenFdsGlobalVariable
.DebugLevel
!= -1:
696 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
697 GenFdsGlobalVariable
.InfLogger (cmd
)
699 if GenFdsGlobalVariable
.VerboseMode
:
701 GenFdsGlobalVariable
.InfLogger (cmd
)
703 sys
.stdout
.write ('#')
705 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
706 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
707 sys
.stdout
.write('\n')
710 PopenObject
= subprocess
.Popen(' '.join(cmd
), stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, shell
=True)
711 except Exception as X
:
712 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
713 (out
, error
) = PopenObject
.communicate()
715 while PopenObject
.returncode
is None :
717 if returnValue
!= [] and returnValue
[0] != 0:
718 #get command return value
719 returnValue
[0] = PopenObject
.returncode
721 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
722 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
723 GenFdsGlobalVariable
.InfLogger (out
.decode(encoding
='utf-8',errors
='ignore'))
724 GenFdsGlobalVariable
.InfLogger (error
.decode(encoding
='utf-8', errors
='ignore'))
725 if PopenObject
.returncode
!= 0:
727 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
729 def VerboseLogger (msg
):
730 EdkLogger
.verbose(msg
)
735 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
736 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
738 def DebugLogger (Level
, msg
):
739 EdkLogger
.debug(Level
, msg
)
741 ## ReplaceWorkspaceMacro()
743 # @param Str String that may contain macro
744 # @param MacroDict Dictionary that contains macro value pair
746 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
750 Dict
= {'$(WORKSPACE)' : GenFdsGlobalVariable
.WorkSpaceDir
,
751 '$(EDK_SOURCE)' : GenFdsGlobalVariable
.EdkSourceDir
,
752 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
753 '$(TARGET)' : GenFdsGlobalVariable
.TargetName
,
754 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable
.ToolChainTag
,
757 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
758 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
759 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
761 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
763 if MacroDict
is not None and len (MacroDict
) != 0:
764 Dict
.update(MacroDict
)
767 if Str
.find(key
) >= 0 :
768 Str
= Str
.replace (key
, Dict
[key
])
770 if Str
.find('$(ARCH)') >= 0:
771 if len(GenFdsGlobalVariable
.ArchList
) == 1:
772 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
774 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
780 # @param PcdPattern pattern that labels a PCD.
782 def GetPcdValue (PcdPattern
):
783 if PcdPattern
is None :
785 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
786 TokenSpace
= PcdPair
[0]
787 TokenCName
= PcdPair
[1]
790 for Arch
in GenFdsGlobalVariable
.ArchList
:
791 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
792 PcdDict
= Platform
.Pcds
794 PcdObj
= PcdDict
[Key
]
795 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
796 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
797 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
798 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
799 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
801 PcdValue
= PcdObj
.DefaultValue
804 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
806 GenFdsGlobalVariable
.TargetName
,
807 GenFdsGlobalVariable
.ToolChainTag
):
808 PcdDict
= Package
.Pcds
810 PcdObj
= PcdDict
[Key
]
811 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
812 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
813 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
814 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
815 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
817 PcdValue
= PcdObj
.DefaultValue
822 SetDir
= staticmethod(SetDir
)
823 SetEnv
= staticmethod(SetEnv
)
824 ReplaceWorkspaceMacro
= staticmethod(ReplaceWorkspaceMacro
)
825 CallExternalTool
= staticmethod(CallExternalTool
)
826 VerboseLogger
= staticmethod(VerboseLogger
)
827 InfLogger
= staticmethod(InfLogger
)
828 ErrorLogger
= staticmethod(ErrorLogger
)
829 DebugLogger
= staticmethod(DebugLogger
)
830 MacroExtend
= staticmethod (MacroExtend
)
831 GetPcdValue
= staticmethod(GetPcdValue
)
835 # Find location of tools to process data
837 # @param KeyStringList Filter for inputs of section generation
838 # @param CurrentArchList Arch list
839 # @param NameGuid The Guid name
841 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
842 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
843 # if user not specify filter, try to deduce it from global data.
844 if KeyStringList
is None or KeyStringList
== []:
845 Target
= GenFdsGlobalVariable
.TargetName
846 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
847 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
848 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
849 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
850 for Arch
in CurrentArchList
:
851 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
852 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
854 if GenFdsGlobalVariable
.GuidToolDefinition
:
855 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
856 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
858 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
864 for ToolDef
in ToolDefinition
.items():
865 if NameGuid
.lower() == ToolDef
[1].lower() :
866 KeyList
= ToolDef
[0].split('_')
872 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
873 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
874 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
875 ToolPath
= ToolDefinition
.get(ToolPathKey
)
876 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
877 if ToolPathTmp
is None:
878 ToolPathTmp
= ToolPath
880 if ToolPathTmp
!= ToolPath
:
881 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
884 for Arch
in CurrentArchList
:
885 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
886 # key is (ToolChainFamily, ToolChain, CodeBase)
887 for item
in Platform
.BuildOptions
:
888 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
889 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
890 if item
[1] not in BuildOption
:
891 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
893 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
894 for Index
in range(2, -1, -1):
895 for Key
in list(BuildOption
.keys()):
896 List
= Key
.split('_')
897 if List
[Index
] == '*':
898 for String
in ToolDb
[ToolList
[Index
]]:
899 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
901 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
902 if NewKey
not in BuildOption
:
903 BuildOption
[NewKey
] = BuildOption
[Key
]
906 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
910 for Op
in BuildOption
:
911 if NameGuid
== BuildOption
[Op
]:
912 KeyList
= Op
.split('_')
913 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
914 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
915 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
916 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
917 if ToolPathKey
in BuildOption
:
918 ToolPathTmp
= BuildOption
[ToolPathKey
]
919 if ToolOptionKey
in BuildOption
:
920 ToolOption
= BuildOption
[ToolOptionKey
]
922 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
923 return ToolPathTmp
, ToolOption