2 # Global variables for GenFds
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
12 from __future__
import print_function
13 from __future__
import absolute_import
15 import Common
.LongFilePathOs
as os
16 from sys
import stdout
17 from subprocess
import PIPE
,Popen
18 from struct
import Struct
19 from array
import array
21 from Common
.BuildToolError
import COMMAND_FAILURE
,GENFDS_ERROR
22 from Common
import EdkLogger
23 from Common
.Misc
import SaveFileOnChange
25 from Common
.TargetTxtClassObject
import TargetTxtClassObject
26 from Common
.ToolDefClassObject
import ToolDefClassObject
, ToolDefDict
27 from AutoGen
.BuildEngine
import BuildRule
28 import Common
.DataType
as DataType
29 from Common
.Misc
import PathClass
30 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
31 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
32 import Common
.GlobalData
as GlobalData
37 class GenFdsGlobalVariable
:
41 # will be FvDir + os.sep + 'Ffs'
48 OutputDirFromDscDict
= {}
54 FvAddressFileName
= ''
58 SharpNumberPerLine
= 40
61 FixedLoadAddress
= False
64 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
65 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
66 __BuildRuleDatabase
= None
67 GuidToolDefinition
= {}
72 EnableGenfdsMultiThread
= False
75 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
76 # At the beginning of each generation of FV, false flag is appended to the list,
77 # after the call to GenerateSection returns, check the size of the output file,
78 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
79 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
80 # At the end of generation of FV, pop the flag.
81 # List is used as a stack to handle nested FV generation.
83 LargeFileInFvFlags
= []
84 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
85 LARGE_FILE_SIZE
= 0x1000000
87 SectionHeader
= Struct("3B 1B")
89 # FvName, FdName, CapName in FDF, Image file name
96 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
97 return GenFdsGlobalVariable
.__BuildRuleDatabase
98 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
99 TargetTxt
= TargetTxtClassObject()
100 if os
.path
.isfile(BuildConfigurationFile
) == True:
101 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
102 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
103 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
104 if not BuildRuleFile
:
105 BuildRuleFile
= 'Conf/build_rule.txt'
106 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
107 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
108 if ToolDefinitionFile
== '':
109 ToolDefinitionFile
= "Conf/tools_def.txt"
110 if os
.path
.isfile(ToolDefinitionFile
):
111 ToolDef
= ToolDefClassObject()
112 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
113 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
114 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
115 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
116 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
117 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
119 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
120 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
121 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
122 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
123 return GenFdsGlobalVariable
.__BuildRuleDatabase
126 # @param Inf: object of InfBuildData
127 # @param Arch: current arch
130 def GetBuildRules(Inf
, Arch
):
132 Arch
= DataType
.TAB_COMMON
134 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
137 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
138 if not BuildRuleDatabase
:
141 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
142 GenFdsGlobalVariable
.WorkSpaceDir
)
143 BuildDir
= os
.path
.join(
144 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
147 PathClassObj
.BaseName
149 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
151 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
152 "MODULE_NAME":Inf
.BaseName
,
153 "MODULE_GUID":Inf
.Guid
,
154 "MODULE_VERSION":Inf
.Version
,
155 "MODULE_TYPE":Inf
.ModuleType
,
156 "MODULE_FILE":str(PathClassObj
),
157 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
158 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
159 "MODULE_DIR":PathClassObj
.SubDir
,
160 "BASE_NAME":Inf
.BaseName
,
162 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
163 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
164 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
165 "TARGET":GenFdsGlobalVariable
.TargetName
,
166 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
169 "MODULE_BUILD_DIR":BuildDir
,
170 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
171 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
175 for Type
in BuildRuleDatabase
.FileTypeList
:
176 #first try getting build rule by BuildRuleFamily
177 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
179 # build type is always module type, but ...
180 if Inf
.ModuleType
!= Inf
.BuildType
:
181 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
182 #second try getting build rule by ToolChainFamily
184 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
186 # build type is always module type, but ...
187 if Inf
.ModuleType
!= Inf
.BuildType
:
188 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
191 RuleObject
= RuleObject
.Instantiate(Macro
)
192 BuildRules
[Type
] = RuleObject
193 for Ext
in RuleObject
.SourceFileExtList
:
194 BuildRules
[Ext
] = RuleObject
197 ## GetModuleCodaTargetList
199 # @param Inf: object of InfBuildData
200 # @param Arch: current arch
203 def GetModuleCodaTargetList(Inf
, Arch
):
204 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
211 if not Inf
.IsBinaryModule
:
212 for File
in Inf
.Sources
:
213 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
214 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
215 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
217 for File
in Inf
.Binaries
:
218 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
219 FileList
.append((File
, File
.Type
))
221 for File
, FileType
in FileList
:
226 while Index
< len(SourceList
):
227 Source
= SourceList
[Index
]
230 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
231 # Skip all files that are not binary libraries
232 if not Inf
.LibraryClass
:
234 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
235 elif FileType
in BuildRules
:
236 RuleObject
= BuildRules
[FileType
]
237 elif Source
.Ext
in BuildRules
:
238 RuleObject
= BuildRules
[Source
.Ext
]
240 # stop at no more rules
242 TargetList
.add(str(LastTarget
))
245 FileType
= RuleObject
.SourceFileType
247 # stop at STATIC_LIBRARY for library
248 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
250 TargetList
.add(str(LastTarget
))
253 Target
= RuleObject
.Apply(Source
)
256 TargetList
.add(str(LastTarget
))
258 elif not Target
.Outputs
:
259 # Only do build for target with outputs
260 TargetList
.add(str(Target
))
262 # to avoid cyclic rule
263 if FileType
in RuleChain
:
266 RuleChain
.append(FileType
)
267 SourceList
.extend(Target
.Outputs
)
269 FileType
= DataType
.TAB_UNKNOWN_FILE
270 for Cmd
in Target
.Commands
:
271 if "$(CP)" == Cmd
.split()[0]:
272 CpTarget
= Cmd
.split()[2]
273 TargetList
.add(CpTarget
)
275 return list(TargetList
)
279 # @param OutputDir Output directory
280 # @param FdfParser FDF contents parser
281 # @param Workspace The directory of workspace
282 # @param ArchList The Arch list of platform
285 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
286 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
287 GenFdsGlobalVariable
.FdfParser
= FdfParser
288 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
289 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
290 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
291 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
292 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
293 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
294 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
297 # Create FV Address inf file
299 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
300 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
304 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
306 for Arch
in ArchList
:
307 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
308 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
311 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
313 DataType
.TAB_LINE_BREAK
)
316 for Arch
in reversed(ArchList
):
317 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
322 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
324 DataType
.TAB_LINE_BREAK
)
326 FvAddressFile
.close()
329 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
330 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
331 GenFdsGlobalVariable
.FdfParser
= FdfParser
332 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
333 GenFdsGlobalVariable
.ArchList
= ArchList
334 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
335 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
336 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
337 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
338 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
339 for Arch
in ArchList
:
340 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
341 os
.path
.join(GlobalData
.gWorkspace
,
342 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
343 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
344 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
345 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
346 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
347 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
348 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
349 GlobalData
.gGlobalDefines
['TARGET'],
350 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
351 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
352 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
353 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
354 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
355 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
356 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
359 # Create FV Address inf file
361 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
362 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
366 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
368 for Arch
in ArchList
:
369 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
370 GlobalData
.gGlobalDefines
['TARGET'],
371 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
375 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
377 DataType
.TAB_LINE_BREAK
)
380 for Arch
in reversed(ArchList
):
381 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
382 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
383 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
388 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
390 DataType
.TAB_LINE_BREAK
)
392 FvAddressFile
.close()
394 ## ReplaceWorkspaceMacro()
396 # @param String String that may contain macro
399 def ReplaceWorkspaceMacro(String
):
400 String
= mws
.handleWsMacro(String
)
401 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
402 if os
.path
.exists(Str
):
403 if not os
.path
.isabs(Str
):
404 Str
= os
.path
.abspath(Str
)
406 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
407 return os
.path
.normpath(Str
)
409 ## Check if the input files are newer than output files
411 # @param Output Path of output file
412 # @param Input Path list of input files
414 # @retval True if Output doesn't exist, or any Input is newer
415 # @retval False if all Input is older than Output
418 def NeedsUpdate(Output
, Input
):
419 if not os
.path
.exists(Output
):
421 # always update "Output" if no "Input" given
425 # if fdf file is changed after the 'Output" is generated, update the 'Output'
426 OutputTime
= os
.path
.getmtime(Output
)
427 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
431 # always update "Output" if any "Input" doesn't exist
432 if not os
.path
.exists(F
):
434 # always update "Output" if any "Input" is newer than "Output"
435 if os
.path
.getmtime(F
) > OutputTime
:
440 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
441 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
446 Cmd
+= ("-c", CompressionType
)
450 Cmd
+= ("--dummy", DummyFile
)
452 Cmd
+= ("-l", GuidHdrLen
)
453 #Add each guided attribute
454 for Attr
in GuidAttr
:
456 #Section Align is only for dummy section without section type
457 for SecAlign
in InputAlign
:
458 Cmd
+= ("--sectionalign", SecAlign
)
460 CommandFile
= Output
+ '.txt'
463 if Ui
== "$(MODULE_NAME)":
466 Cmd
+= ("-n", '"' + Ui
+ '"')
467 Cmd
+= ("-o", Output
)
468 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
469 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
471 SectionData
= array('B', [0, 0, 0, 0])
472 SectionData
.fromstring(Ui
.encode("utf_16_le"))
473 SectionData
.append(0)
474 SectionData
.append(0)
475 Len
= len(SectionData
)
476 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
477 SaveFileOnChange(Output
, SectionData
.tostring())
482 Cmd
+= ("-j", BuildNumber
)
483 Cmd
+= ("-o", Output
)
485 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
487 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
488 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
490 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
492 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
494 Cmd
+= ("-o", Output
)
497 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
499 if GlobalData
.gGlobalDefines
.get("FAMILY") == "MSFT":
500 Cmd
= ['if', 'exist', Input
[0]] + Cmd
502 Cmd
= ['test', '-e', Input
[0], "&&"] + Cmd
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
)):
545 Cmd
+= ("-oi", Input
[I
])
547 Cmd
+= ("-i", Input
[I
])
548 if SectionAlign
and SectionAlign
[I
]:
549 Cmd
+= ("-n", SectionAlign
[I
])
551 CommandFile
= Output
+ '.txt'
552 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
554 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
556 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
557 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
558 GenFdsGlobalVariable
.SecCmdList
= []
559 GenFdsGlobalVariable
.CopyList
= []
561 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
563 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
566 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
567 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
568 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
570 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
574 Cmd
+= ("-r", BaseAddress
)
576 if ForceRebase
== False:
577 Cmd
+= ("-F", "FALSE")
578 elif ForceRebase
== True:
579 Cmd
+= ("-F", "TRUE")
586 Cmd
+= ("-a", AddressFile
)
588 Cmd
+= ("-m", MapFile
)
590 Cmd
+= ("-g", FileSystemGuid
)
591 Cmd
+= ("-o", Output
)
595 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
598 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
599 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
600 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
601 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
603 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
606 if Type
.lower() == "te":
609 Cmd
+= ("-e", SubType
)
611 Cmd
+= ("-s", TimeStamp
)
615 Cmd
+= ("-p", Padding
)
626 Cmd
+= ("-o", Output
)
629 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
630 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
632 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
635 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
636 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
646 for EfiFile
in EfiInput
:
648 InputList
.append (EfiFile
)
652 for BinFile
in BinaryInput
:
654 InputList
.append (BinFile
)
657 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
659 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
662 Cmd
+= ("-l", ClassCode
)
664 Cmd
+= ("-r", Revision
)
666 Cmd
+= ("-i", DeviceId
)
668 Cmd
+= ("-f", VendorId
)
670 Cmd
+= ("-o", Output
)
672 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
673 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
675 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
678 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
679 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
681 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
684 Cmd
+= Options
.split(' ')
685 Cmd
+= ("-o", Output
)
688 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
689 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
691 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
694 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
696 if type(cmd
) not in (tuple, list):
697 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
699 if GenFdsGlobalVariable
.DebugLevel
!= -1:
700 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
701 GenFdsGlobalVariable
.InfLogger (cmd
)
703 if GenFdsGlobalVariable
.VerboseMode
:
705 GenFdsGlobalVariable
.InfLogger (cmd
)
709 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
710 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
714 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
715 except Exception as X
:
716 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
717 (out
, error
) = PopenObject
.communicate()
719 while PopenObject
.returncode
is None:
721 if returnValue
!= [] and returnValue
[0] != 0:
722 #get command return value
723 returnValue
[0] = PopenObject
.returncode
725 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
726 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
727 GenFdsGlobalVariable
.InfLogger(out
.decode(encoding
='utf-8', errors
='ignore'))
728 GenFdsGlobalVariable
.InfLogger(error
.decode(encoding
='utf-8', errors
='ignore'))
729 if PopenObject
.returncode
!= 0:
731 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
734 def VerboseLogger (msg
):
735 EdkLogger
.verbose(msg
)
742 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
743 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
746 def DebugLogger (Level
, msg
):
747 EdkLogger
.debug(Level
, msg
)
751 # @param Str String that may contain macro
752 # @param MacroDict Dictionary that contains macro value pair
755 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
759 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
760 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
761 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
762 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
766 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
767 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
769 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
771 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
774 Dict
.update(MacroDict
)
777 if Str
.find(key
) >= 0:
778 Str
= Str
.replace (key
, Dict
[key
])
780 if Str
.find('$(ARCH)') >= 0:
781 if len(GenFdsGlobalVariable
.ArchList
) == 1:
782 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
784 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
790 # @param PcdPattern pattern that labels a PCD.
793 def GetPcdValue (PcdPattern
):
794 if PcdPattern
is None:
796 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
797 TokenSpace
= PcdPair
[0]
798 TokenCName
= PcdPair
[1]
800 for Arch
in GenFdsGlobalVariable
.ArchList
:
801 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
802 PcdDict
= Platform
.Pcds
804 PcdObj
= PcdDict
[Key
]
805 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
806 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
807 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
808 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
809 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
811 return PcdObj
.DefaultValue
813 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
815 GenFdsGlobalVariable
.TargetName
,
816 GenFdsGlobalVariable
.ToolChainTag
):
817 PcdDict
= Package
.Pcds
819 PcdObj
= PcdDict
[Key
]
820 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
821 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
822 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
823 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
824 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
826 return PcdObj
.DefaultValue
832 # Find location of tools to process data
834 # @param KeyStringList Filter for inputs of section generation
835 # @param CurrentArchList Arch list
836 # @param NameGuid The Guid name
838 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
839 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
840 # if user not specify filter, try to deduce it from global data.
841 if KeyStringList
is None or KeyStringList
== []:
842 Target
= GenFdsGlobalVariable
.TargetName
843 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
844 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
845 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
846 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
847 for Arch
in CurrentArchList
:
848 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
849 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
851 if GenFdsGlobalVariable
.GuidToolDefinition
:
852 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
853 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
855 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
861 for ToolDef
in ToolDefinition
.items():
862 if NameGuid
.lower() == ToolDef
[1].lower():
863 KeyList
= ToolDef
[0].split('_')
869 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
870 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
871 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
872 ToolPath
= ToolDefinition
.get(ToolPathKey
)
873 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
874 if ToolPathTmp
is None:
875 ToolPathTmp
= ToolPath
877 if ToolPathTmp
!= ToolPath
:
878 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
881 for Arch
in CurrentArchList
:
882 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
883 # key is (ToolChainFamily, ToolChain, CodeBase)
884 for item
in Platform
.BuildOptions
:
885 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
886 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
887 if item
[1] not in BuildOption
:
888 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
890 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
891 for Index
in range(2, -1, -1):
892 for Key
in list(BuildOption
.keys()):
893 List
= Key
.split('_')
894 if List
[Index
] == DataType
.TAB_STAR
:
895 for String
in ToolDb
[ToolList
[Index
]]:
896 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
898 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
899 if NewKey
not in BuildOption
:
900 BuildOption
[NewKey
] = BuildOption
[Key
]
903 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
907 for Op
in BuildOption
:
908 if NameGuid
== BuildOption
[Op
]:
909 KeyList
= Op
.split('_')
910 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
911 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
912 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
913 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
914 if ToolPathKey
in BuildOption
:
915 ToolPathTmp
= BuildOption
[ToolPathKey
]
916 if ToolOptionKey
in BuildOption
:
917 ToolOption
= BuildOption
[ToolOptionKey
]
919 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
920 return ToolPathTmp
, ToolOption