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 from __future__
import print_function
19 import Common
.LongFilePathOs
as os
25 from Common
.BuildToolError
import *
26 from Common
import EdkLogger
27 from Common
.Misc
import SaveFileOnChange
29 from Common
.TargetTxtClassObject
import TargetTxtClassObject
30 from Common
.ToolDefClassObject
import ToolDefClassObject
, ToolDefDict
31 from AutoGen
.BuildEngine
import BuildRule
32 import Common
.DataType
as DataType
33 from Common
.Misc
import PathClass
34 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
35 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
40 class GenFdsGlobalVariable
:
44 # will be FvDir + os.sep + 'Ffs'
52 OutputDirFromDscDict
= {}
59 FvAddressFileName
= ''
63 SharpNumberPerLine
= 40
66 FixedLoadAddress
= False
69 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
70 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
71 __BuildRuleDatabase
= None
72 GuidToolDefinition
= {}
77 EnableGenfdsMultiThread
= False
80 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
81 # At the beginning of each generation of FV, false flag is appended to the list,
82 # after the call to GenerateSection returns, check the size of the output file,
83 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
84 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
85 # At the end of generation of FV, pop the flag.
86 # List is used as a stack to handle nested FV generation.
88 LargeFileInFvFlags
= []
89 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
90 LARGE_FILE_SIZE
= 0x1000000
92 SectionHeader
= struct
.Struct("3B 1B")
94 # FvName, FdName, CapName in FDF, Image file name
100 def __LoadBuildRule():
101 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
102 return GenFdsGlobalVariable
.__BuildRuleDatabase
103 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
104 TargetTxt
= TargetTxtClassObject()
105 if os
.path
.isfile(BuildConfigurationFile
) == True:
106 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
107 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
108 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
109 if not BuildRuleFile
:
110 BuildRuleFile
= 'Conf/build_rule.txt'
111 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
112 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
113 if ToolDefinitionFile
== '':
114 ToolDefinitionFile
= "Conf/tools_def.txt"
115 if os
.path
.isfile(ToolDefinitionFile
):
116 ToolDef
= ToolDefClassObject()
117 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
118 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
119 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
120 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
121 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
122 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
124 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
125 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
126 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
127 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
128 return GenFdsGlobalVariable
.__BuildRuleDatabase
131 # @param Inf: object of InfBuildData
132 # @param Arch: current arch
135 def GetBuildRules(Inf
, Arch
):
137 Arch
= DataType
.TAB_COMMON
139 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
142 BuildRuleDatabase
= GenFdsGlobalVariable
.__LoadBuildRule
()
143 if not BuildRuleDatabase
:
146 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
147 GenFdsGlobalVariable
.WorkSpaceDir
)
149 Macro
["WORKSPACE" ] = GenFdsGlobalVariable
.WorkSpaceDir
150 Macro
["MODULE_NAME" ] = Inf
.BaseName
151 Macro
["MODULE_GUID" ] = Inf
.Guid
152 Macro
["MODULE_VERSION" ] = Inf
.Version
153 Macro
["MODULE_TYPE" ] = Inf
.ModuleType
154 Macro
["MODULE_FILE" ] = str(PathClassObj
)
155 Macro
["MODULE_FILE_BASE_NAME" ] = PathClassObj
.BaseName
156 Macro
["MODULE_RELATIVE_DIR" ] = PathClassObj
.SubDir
157 Macro
["MODULE_DIR" ] = PathClassObj
.SubDir
159 Macro
["BASE_NAME" ] = Inf
.BaseName
161 Macro
["ARCH" ] = Arch
162 Macro
["TOOLCHAIN" ] = GenFdsGlobalVariable
.ToolChainTag
163 Macro
["TOOLCHAIN_TAG" ] = GenFdsGlobalVariable
.ToolChainTag
164 Macro
["TOOL_CHAIN_TAG" ] = GenFdsGlobalVariable
.ToolChainTag
165 Macro
["TARGET" ] = GenFdsGlobalVariable
.TargetName
167 Macro
["BUILD_DIR" ] = GenFdsGlobalVariable
.OutputDirDict
[Arch
]
168 Macro
["BIN_DIR" ] = os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
169 Macro
["LIB_DIR" ] = os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
170 BuildDir
= os
.path
.join(
171 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
174 PathClassObj
.BaseName
176 Macro
["MODULE_BUILD_DIR" ] = BuildDir
177 Macro
["OUTPUT_DIR" ] = os
.path
.join(BuildDir
, "OUTPUT")
178 Macro
["DEBUG_DIR" ] = os
.path
.join(BuildDir
, "DEBUG")
181 for Type
in BuildRuleDatabase
.FileTypeList
:
182 #first try getting build rule by BuildRuleFamily
183 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
185 # build type is always module type, but ...
186 if Inf
.ModuleType
!= Inf
.BuildType
:
187 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
188 #second try getting build rule by ToolChainFamily
190 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
192 # build type is always module type, but ...
193 if Inf
.ModuleType
!= Inf
.BuildType
:
194 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
197 RuleObject
= RuleObject
.Instantiate(Macro
)
198 BuildRules
[Type
] = RuleObject
199 for Ext
in RuleObject
.SourceFileExtList
:
200 BuildRules
[Ext
] = RuleObject
203 ## GetModuleCodaTargetList
205 # @param Inf: object of InfBuildData
206 # @param Arch: current arch
209 def GetModuleCodaTargetList(Inf
, Arch
):
210 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
217 if not Inf
.IsBinaryModule
:
218 for File
in Inf
.Sources
:
219 if File
.TagName
in ("", "*", GenFdsGlobalVariable
.ToolChainTag
) and \
220 File
.ToolChainFamily
in ("", "*", GenFdsGlobalVariable
.ToolChainFamily
):
221 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
223 for File
in Inf
.Binaries
:
224 if File
.Target
in [DataType
.TAB_COMMON
, '*', GenFdsGlobalVariable
.TargetName
]:
225 FileList
.append((File
, File
.Type
))
227 for File
, FileType
in FileList
:
232 while Index
< len(SourceList
):
233 Source
= SourceList
[Index
]
236 if File
.IsBinary
and File
== Source
and Inf
.Binaries
is not None and File
in Inf
.Binaries
:
237 # Skip all files that are not binary libraries
238 if not Inf
.LibraryClass
:
240 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
241 elif FileType
in BuildRules
:
242 RuleObject
= BuildRules
[FileType
]
243 elif Source
.Ext
in BuildRules
:
244 RuleObject
= BuildRules
[Source
.Ext
]
246 # stop at no more rules
248 TargetList
.add(str(LastTarget
))
251 FileType
= RuleObject
.SourceFileType
253 # stop at STATIC_LIBRARY for library
254 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
256 TargetList
.add(str(LastTarget
))
259 Target
= RuleObject
.Apply(Source
)
262 TargetList
.add(str(LastTarget
))
264 elif not Target
.Outputs
:
265 # Only do build for target with outputs
266 TargetList
.add(str(Target
))
268 # to avoid cyclic rule
269 if FileType
in RuleChain
:
272 RuleChain
.append(FileType
)
273 SourceList
.extend(Target
.Outputs
)
275 FileType
= DataType
.TAB_UNKNOWN_FILE
276 for Cmd
in Target
.Commands
:
277 if "$(CP)" == Cmd
.split()[0]:
278 CpTarget
= Cmd
.split()[2]
279 TargetList
.add(CpTarget
)
281 return list(TargetList
)
285 # @param OutputDir Output directory
286 # @param FdfParser FDF contents parser
287 # @param Workspace The directory of workspace
288 # @param ArchList The Arch list of platform
290 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
291 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir
)
292 # GenFdsGlobalVariable.OutputDirDict = OutputDir
293 GenFdsGlobalVariable
.FdfParser
= FdfParser
294 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
295 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
296 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
) :
297 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
298 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
299 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
) :
300 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
304 # Create FV Address inf file
306 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
307 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
311 FvAddressFile
.writelines("[options]" + T_CHAR_LF
)
313 for Arch
in ArchList
:
314 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
315 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
318 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
323 for Arch
in ArchList
:
324 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
:
325 RtAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
327 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
331 FvAddressFile
.close()
333 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
334 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
335 GenFdsGlobalVariable
.FdfParser
= FdfParser
336 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
337 GenFdsGlobalVariable
.ArchList
= ArchList
338 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
339 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
340 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
341 GenFdsGlobalVariable
.EdkSourceDir
= GlobalData
.gGlobalDefines
["EDK_SOURCE"]
342 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
343 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
344 for Arch
in ArchList
:
345 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
346 os
.path
.join(GlobalData
.gWorkspace
,
347 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
348 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
349 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
350 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
351 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
352 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
353 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
354 GlobalData
.gGlobalDefines
['TARGET'],
355 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
356 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
357 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
358 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
359 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
360 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
361 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
365 # Create FV Address inf file
367 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
368 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
372 FvAddressFile
.writelines("[options]" + T_CHAR_LF
)
374 for Arch
in ArchList
:
375 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
376 GlobalData
.gGlobalDefines
['TARGET'],
377 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
381 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
386 for Arch
in ArchList
:
387 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
388 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
389 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
:
390 RtAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
391 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
392 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
394 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
398 FvAddressFile
.close()
400 ## ReplaceWorkspaceMacro()
402 # @param String String that may contain macro
404 def ReplaceWorkspaceMacro(String
):
405 String
= mws
.handleWsMacro(String
)
406 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
407 if os
.path
.exists(Str
):
408 if not os
.path
.isabs(Str
):
409 Str
= os
.path
.abspath(Str
)
411 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
412 return os
.path
.normpath(Str
)
414 ## Check if the input files are newer than output files
416 # @param Output Path of output file
417 # @param Input Path list of input files
419 # @retval True if Output doesn't exist, or any Input is newer
420 # @retval False if all Input is older than Output
423 def NeedsUpdate(Output
, Input
):
424 if not os
.path
.exists(Output
):
426 # always update "Output" if no "Input" given
427 if Input
is None or len(Input
) == 0:
430 # if fdf file is changed after the 'Output" is generated, update the 'Output'
431 OutputTime
= os
.path
.getmtime(Output
)
432 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
436 # always update "Output" if any "Input" doesn't exist
437 if not os
.path
.exists(F
):
439 # always update "Output" if any "Input" is newer than "Output"
440 if os
.path
.getmtime(F
) > OutputTime
:
445 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
446 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
451 Cmd
+= ("-c", CompressionType
)
454 if DummyFile
is not None:
455 Cmd
+= ("--dummy", DummyFile
)
457 Cmd
+= ("-l", GuidHdrLen
)
458 #Add each guided attribute
459 for Attr
in GuidAttr
:
461 #Section Align is only for dummy section without section type
462 for SecAlign
in InputAlign
:
463 Cmd
+= ("--sectionalign", SecAlign
)
465 CommandFile
= Output
+ '.txt'
468 if Ui
== "$(MODULE_NAME)":
471 Cmd
+= ("-n", '"' + Ui
+ '"')
472 Cmd
+= ("-o", Output
)
473 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
474 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
476 SectionData
= array
.array('B', [0, 0, 0, 0])
477 SectionData
.fromstring(Ui
.encode("utf_16_le"))
478 SectionData
.append(0)
479 SectionData
.append(0)
480 Len
= len(SectionData
)
481 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
482 SaveFileOnChange(Output
, SectionData
.tostring())
487 Cmd
+= ("-j", BuildNumber
)
488 Cmd
+= ("-o", Output
)
490 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
492 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
493 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
495 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
497 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
499 Cmd
+= ("-o", Output
)
502 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
504 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
505 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
506 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
507 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
508 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
509 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
510 GenFdsGlobalVariable
.LargeFileInFvFlags
):
511 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
514 def GetAlignment (AlignString
):
515 if AlignString
is None:
517 if AlignString
in ("1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K"):
518 return int (AlignString
.rstrip('K')) * 1024
519 elif AlignString
in ("1M", "2M", "4M", "8M", "16M"):
520 return int (AlignString
.rstrip('M')) * 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 GenerateVtf(Output
, Input
, BaseAddress
=None, FvSize
=None):
596 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
):
598 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
601 if BaseAddress
and FvSize \
602 and len(BaseAddress
) == len(FvSize
):
603 for I
in range(0, len(BaseAddress
)):
604 Cmd
+= ("-r", BaseAddress
[I
], "-s", FvSize
[I
])
605 Cmd
+= ("-o", Output
)
609 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate VTF")
612 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
613 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
614 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
615 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
617 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
620 if Type
.lower() == "te":
623 Cmd
+= ("-e", SubType
)
625 Cmd
+= ("-s", TimeStamp
)
629 Cmd
+= ("-p", Padding
)
640 Cmd
+= ("-o", Output
)
643 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
644 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
646 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
649 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
650 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
653 if len(EfiInput
) > 0:
660 for EfiFile
in EfiInput
:
662 InputList
.append (EfiFile
)
664 if len(BinaryInput
) > 0:
666 for BinFile
in BinaryInput
:
668 InputList
.append (BinFile
)
671 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
673 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
675 if ClassCode
is not None:
676 Cmd
+= ("-l", ClassCode
)
677 if Revision
is not None:
678 Cmd
+= ("-r", Revision
)
679 if DeviceId
is not None:
680 Cmd
+= ("-i", DeviceId
)
681 if VendorId
is not None:
682 Cmd
+= ("-f", VendorId
)
684 Cmd
+= ("-o", Output
)
686 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
687 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
689 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
692 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
693 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
695 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
698 Cmd
+= Options
.split(' ')
699 Cmd
+= ("-o", Output
)
702 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
703 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
705 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
707 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
709 if type(cmd
) not in (tuple, list):
710 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
712 if GenFdsGlobalVariable
.DebugLevel
!= -1:
713 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
714 GenFdsGlobalVariable
.InfLogger (cmd
)
716 if GenFdsGlobalVariable
.VerboseMode
:
718 GenFdsGlobalVariable
.InfLogger (cmd
)
720 sys
.stdout
.write ('#')
722 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
723 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
724 sys
.stdout
.write('\n')
727 PopenObject
= subprocess
.Popen(' '.join(cmd
), stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, shell
=True)
728 except Exception as X
:
729 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
730 (out
, error
) = PopenObject
.communicate()
732 while PopenObject
.returncode
is None :
734 if returnValue
!= [] and returnValue
[0] != 0:
735 #get command return value
736 returnValue
[0] = PopenObject
.returncode
738 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
739 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
740 GenFdsGlobalVariable
.InfLogger (out
)
741 GenFdsGlobalVariable
.InfLogger (error
)
742 if PopenObject
.returncode
!= 0:
744 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
746 def VerboseLogger (msg
):
747 EdkLogger
.verbose(msg
)
752 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
753 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
755 def DebugLogger (Level
, msg
):
756 EdkLogger
.debug(Level
, msg
)
758 ## ReplaceWorkspaceMacro()
760 # @param Str String that may contain macro
761 # @param MacroDict Dictionary that contains macro value pair
763 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
767 Dict
= {'$(WORKSPACE)' : GenFdsGlobalVariable
.WorkSpaceDir
,
768 '$(EDK_SOURCE)' : GenFdsGlobalVariable
.EdkSourceDir
,
769 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
770 '$(TARGET)' : GenFdsGlobalVariable
.TargetName
,
771 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable
.ToolChainTag
,
774 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
775 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
776 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
778 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
780 if MacroDict
is not None and len (MacroDict
) != 0:
781 Dict
.update(MacroDict
)
784 if Str
.find(key
) >= 0 :
785 Str
= Str
.replace (key
, Dict
[key
])
787 if Str
.find('$(ARCH)') >= 0:
788 if len(GenFdsGlobalVariable
.ArchList
) == 1:
789 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
791 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
797 # @param PcdPattern pattern that labels a PCD.
799 def GetPcdValue (PcdPattern
):
800 if PcdPattern
is None :
802 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
803 TokenSpace
= PcdPair
[0]
804 TokenCName
= PcdPair
[1]
807 for Arch
in GenFdsGlobalVariable
.ArchList
:
808 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
809 PcdDict
= Platform
.Pcds
811 PcdObj
= PcdDict
[Key
]
812 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
813 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
814 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
815 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
816 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
818 PcdValue
= PcdObj
.DefaultValue
821 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
823 GenFdsGlobalVariable
.TargetName
,
824 GenFdsGlobalVariable
.ToolChainTag
):
825 PcdDict
= Package
.Pcds
827 PcdObj
= PcdDict
[Key
]
828 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
829 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
830 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
831 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
832 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
834 PcdValue
= PcdObj
.DefaultValue
839 SetDir
= staticmethod(SetDir
)
840 SetEnv
= staticmethod(SetEnv
)
841 ReplaceWorkspaceMacro
= staticmethod(ReplaceWorkspaceMacro
)
842 CallExternalTool
= staticmethod(CallExternalTool
)
843 VerboseLogger
= staticmethod(VerboseLogger
)
844 InfLogger
= staticmethod(InfLogger
)
845 ErrorLogger
= staticmethod(ErrorLogger
)
846 DebugLogger
= staticmethod(DebugLogger
)
847 MacroExtend
= staticmethod (MacroExtend
)
848 GetPcdValue
= staticmethod(GetPcdValue
)
852 # Find location of tools to process data
854 # @param KeyStringList Filter for inputs of section generation
855 # @param CurrentArchList Arch list
856 # @param NameGuid The Guid name
858 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
859 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
860 # if user not specify filter, try to deduce it from global data.
861 if KeyStringList
is None or KeyStringList
== []:
862 Target
= GenFdsGlobalVariable
.TargetName
863 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
864 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
865 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
866 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
867 for Arch
in CurrentArchList
:
868 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
869 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
871 if GenFdsGlobalVariable
.GuidToolDefinition
:
872 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
873 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
875 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
881 for ToolDef
in ToolDefinition
.items():
882 if NameGuid
.lower() == ToolDef
[1].lower() :
883 KeyList
= ToolDef
[0].split('_')
889 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
890 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
891 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
892 ToolPath
= ToolDefinition
.get(ToolPathKey
)
893 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
894 if ToolPathTmp
is None:
895 ToolPathTmp
= ToolPath
897 if ToolPathTmp
!= ToolPath
:
898 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
901 for Arch
in CurrentArchList
:
902 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
903 # key is (ToolChainFamily, ToolChain, CodeBase)
904 for item
in Platform
.BuildOptions
:
905 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
906 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
907 if item
[1] not in BuildOption
:
908 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
910 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
911 for Index
in range(2, -1, -1):
912 for Key
in list(BuildOption
.keys()):
913 List
= Key
.split('_')
914 if List
[Index
] == '*':
915 for String
in ToolDb
[ToolList
[Index
]]:
916 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
918 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
919 if NewKey
not in BuildOption
:
920 BuildOption
[NewKey
] = BuildOption
[Key
]
923 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
927 for Op
in BuildOption
:
928 if NameGuid
== BuildOption
[Op
]:
929 KeyList
= Op
.split('_')
930 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
931 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
932 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
933 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
934 if ToolPathKey
in BuildOption
:
935 ToolPathTmp
= BuildOption
[ToolPathKey
]
936 if ToolOptionKey
in BuildOption
:
937 ToolOption
= BuildOption
[ToolOptionKey
]
939 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
940 return ToolPathTmp
, ToolOption