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 TargetTxt
26 from Common
.ToolDefClassObject
import ToolDef
27 from AutoGen
.BuildEngine
import BuildRuleObj
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
= True
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 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRuleObj
99 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
100 if ToolDefinitionFile
== '':
101 ToolDefinitionFile
= "Conf/tools_def.txt"
102 if os
.path
.isfile(ToolDefinitionFile
):
103 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
104 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
105 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
106 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
107 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
109 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
110 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
111 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
112 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
113 return GenFdsGlobalVariable
.__BuildRuleDatabase
116 # @param Inf: object of InfBuildData
117 # @param Arch: current arch
120 def GetBuildRules(Inf
, Arch
):
122 Arch
= DataType
.TAB_COMMON
124 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
127 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
128 if not BuildRuleDatabase
:
131 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
132 GenFdsGlobalVariable
.WorkSpaceDir
)
133 BuildDir
= os
.path
.join(
134 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
137 PathClassObj
.BaseName
139 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
141 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
142 "MODULE_NAME":Inf
.BaseName
,
143 "MODULE_GUID":Inf
.Guid
,
144 "MODULE_VERSION":Inf
.Version
,
145 "MODULE_TYPE":Inf
.ModuleType
,
146 "MODULE_FILE":str(PathClassObj
),
147 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
148 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
149 "MODULE_DIR":PathClassObj
.SubDir
,
150 "BASE_NAME":Inf
.BaseName
,
152 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
153 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
154 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
155 "TARGET":GenFdsGlobalVariable
.TargetName
,
156 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
159 "MODULE_BUILD_DIR":BuildDir
,
160 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
161 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
165 for Type
in BuildRuleDatabase
.FileTypeList
:
166 #first try getting build rule by BuildRuleFamily
167 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
169 # build type is always module type, but ...
170 if Inf
.ModuleType
!= Inf
.BuildType
:
171 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
172 #second try getting build rule by ToolChainFamily
174 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
176 # build type is always module type, but ...
177 if Inf
.ModuleType
!= Inf
.BuildType
:
178 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
181 RuleObject
= RuleObject
.Instantiate(Macro
)
182 BuildRules
[Type
] = RuleObject
183 for Ext
in RuleObject
.SourceFileExtList
:
184 BuildRules
[Ext
] = RuleObject
187 ## GetModuleCodaTargetList
189 # @param Inf: object of InfBuildData
190 # @param Arch: current arch
193 def GetModuleCodaTargetList(Inf
, Arch
):
194 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
201 if not Inf
.IsBinaryModule
:
202 for File
in Inf
.Sources
:
203 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
204 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
205 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
207 for File
in Inf
.Binaries
:
208 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
209 FileList
.append((File
, File
.Type
))
211 for File
, FileType
in FileList
:
216 while Index
< len(SourceList
):
217 Source
= SourceList
[Index
]
220 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
221 # Skip all files that are not binary libraries
222 if not Inf
.LibraryClass
:
224 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
225 elif FileType
in BuildRules
:
226 RuleObject
= BuildRules
[FileType
]
227 elif Source
.Ext
in BuildRules
:
228 RuleObject
= BuildRules
[Source
.Ext
]
230 # stop at no more rules
232 TargetList
.add(str(LastTarget
))
235 FileType
= RuleObject
.SourceFileType
237 # stop at STATIC_LIBRARY for library
238 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
240 TargetList
.add(str(LastTarget
))
243 Target
= RuleObject
.Apply(Source
)
246 TargetList
.add(str(LastTarget
))
248 elif not Target
.Outputs
:
249 # Only do build for target with outputs
250 TargetList
.add(str(Target
))
252 # to avoid cyclic rule
253 if FileType
in RuleChain
:
256 RuleChain
.append(FileType
)
257 SourceList
.extend(Target
.Outputs
)
259 FileType
= DataType
.TAB_UNKNOWN_FILE
260 for Cmd
in Target
.Commands
:
261 if "$(CP)" == Cmd
.split()[0]:
262 CpTarget
= Cmd
.split()[2]
263 TargetList
.add(CpTarget
)
265 return list(TargetList
)
269 # @param OutputDir Output directory
270 # @param FdfParser FDF contents parser
271 # @param Workspace The directory of workspace
272 # @param ArchList The Arch list of platform
275 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
276 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
277 GenFdsGlobalVariable
.FdfParser
= FdfParser
278 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
279 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
280 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
281 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
282 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
283 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
284 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
287 # Create FV Address inf file
289 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
290 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
294 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
296 for Arch
in ArchList
:
297 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
298 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
301 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
303 DataType
.TAB_LINE_BREAK
)
306 for Arch
in reversed(ArchList
):
307 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
312 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
314 DataType
.TAB_LINE_BREAK
)
316 FvAddressFile
.close()
319 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
320 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
321 GenFdsGlobalVariable
.FdfParser
= FdfParser
322 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
323 GenFdsGlobalVariable
.ArchList
= ArchList
324 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
325 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
326 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
327 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
328 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
329 for Arch
in ArchList
:
330 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
331 os
.path
.join(GlobalData
.gWorkspace
,
332 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
333 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
334 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
335 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
336 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
337 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
338 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
339 GlobalData
.gGlobalDefines
['TARGET'],
340 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
341 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
342 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
343 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
344 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
345 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
346 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
349 # Create FV Address inf file
351 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
352 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
356 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
358 for Arch
in ArchList
:
359 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
360 GlobalData
.gGlobalDefines
['TARGET'],
361 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
365 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
367 DataType
.TAB_LINE_BREAK
)
370 for Arch
in reversed(ArchList
):
371 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
372 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
373 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
378 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
380 DataType
.TAB_LINE_BREAK
)
382 FvAddressFile
.close()
384 ## ReplaceWorkspaceMacro()
386 # @param String String that may contain macro
389 def ReplaceWorkspaceMacro(String
):
390 String
= mws
.handleWsMacro(String
)
391 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
392 if os
.path
.exists(Str
):
393 if not os
.path
.isabs(Str
):
394 Str
= os
.path
.abspath(Str
)
396 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
397 return os
.path
.normpath(Str
)
399 ## Check if the input files are newer than output files
401 # @param Output Path of output file
402 # @param Input Path list of input files
404 # @retval True if Output doesn't exist, or any Input is newer
405 # @retval False if all Input is older than Output
408 def NeedsUpdate(Output
, Input
):
409 if not os
.path
.exists(Output
):
411 # always update "Output" if no "Input" given
415 # if fdf file is changed after the 'Output" is generated, update the 'Output'
416 OutputTime
= os
.path
.getmtime(Output
)
417 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
421 # always update "Output" if any "Input" doesn't exist
422 if not os
.path
.exists(F
):
424 # always update "Output" if any "Input" is newer than "Output"
425 if os
.path
.getmtime(F
) > OutputTime
:
430 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
431 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
436 Cmd
+= ("-c", CompressionType
)
440 Cmd
+= ("--dummy", DummyFile
)
442 Cmd
+= ("-l", GuidHdrLen
)
443 #Add each guided attribute
444 for Attr
in GuidAttr
:
446 #Section Align is only for dummy section without section type
447 for SecAlign
in InputAlign
:
448 Cmd
+= ("--sectionalign", SecAlign
)
450 CommandFile
= Output
+ '.txt'
453 if Ui
== "$(MODULE_NAME)":
456 Cmd
+= ("-n", '"' + Ui
+ '"')
457 Cmd
+= ("-o", Output
)
458 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
459 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
461 SectionData
= array('B', [0, 0, 0, 0])
462 SectionData
.fromstring(Ui
.encode("utf_16_le"))
463 SectionData
.append(0)
464 SectionData
.append(0)
465 Len
= len(SectionData
)
466 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
467 SaveFileOnChange(Output
, SectionData
.tostring())
472 Cmd
+= ("-j", BuildNumber
)
473 Cmd
+= ("-o", Output
)
475 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
477 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
478 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
480 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
482 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
484 Cmd
+= ("-o", Output
)
487 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
489 if GlobalData
.gGlobalDefines
.get("FAMILY") == "MSFT":
490 Cmd
= ['if', 'exist', Input
[0]] + Cmd
492 Cmd
= ['-test', '-e', Input
[0], "&&"] + Cmd
493 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
494 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
495 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
496 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
497 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
498 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
499 GenFdsGlobalVariable
.LargeFileInFvFlags
):
500 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
503 def GetAlignment (AlignString
):
506 if AlignString
.endswith('K'):
507 return int (AlignString
.rstrip('K')) * 1024
508 if AlignString
.endswith('M'):
509 return int (AlignString
.rstrip('M')) * 1024 * 1024
510 if AlignString
.endswith('G'):
511 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
512 return int (AlignString
)
515 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
516 SectionAlign
=None, MakefilePath
=None):
517 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
518 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
524 if Align
not in mFfsValidAlign
:
525 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
526 for index
in range(0, len(mFfsValidAlign
) - 1):
527 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
529 Align
= mFfsValidAlign
[index
+ 1]
532 Cmd
+= ("-o", Output
)
533 for I
in range(0, len(Input
)):
535 Cmd
+= ("-oi", Input
[I
])
537 Cmd
+= ("-i", Input
[I
])
538 if SectionAlign
and SectionAlign
[I
]:
539 Cmd
+= ("-n", SectionAlign
[I
])
541 CommandFile
= Output
+ '.txt'
542 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
544 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
546 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
547 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
548 GenFdsGlobalVariable
.SecCmdList
= []
549 GenFdsGlobalVariable
.CopyList
= []
551 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
553 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
556 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
557 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
558 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
560 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
564 Cmd
+= ("-r", BaseAddress
)
566 if ForceRebase
== False:
567 Cmd
+= ("-F", "FALSE")
568 elif ForceRebase
== True:
569 Cmd
+= ("-F", "TRUE")
576 Cmd
+= ("-a", AddressFile
)
578 Cmd
+= ("-m", MapFile
)
580 Cmd
+= ("-g", FileSystemGuid
)
581 Cmd
+= ("-o", Output
)
585 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
588 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
589 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
590 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
591 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
593 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
596 if Type
.lower() == "te":
599 Cmd
+= ("-e", SubType
)
601 Cmd
+= ("-s", TimeStamp
)
605 Cmd
+= ("-p", Padding
)
616 Cmd
+= ("-o", Output
)
619 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
620 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
622 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
625 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
626 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
636 for EfiFile
in EfiInput
:
638 InputList
.append (EfiFile
)
642 for BinFile
in BinaryInput
:
644 InputList
.append (BinFile
)
647 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
649 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
652 Cmd
+= ("-l", ClassCode
)
654 Cmd
+= ("-r", Revision
)
656 Cmd
+= ("-i", DeviceId
)
658 Cmd
+= ("-f", VendorId
)
660 Cmd
+= ("-o", Output
)
662 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
663 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
665 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
668 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
669 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
671 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
674 Cmd
+= Options
.split(' ')
675 Cmd
+= ("-o", Output
)
678 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
679 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
681 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
684 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
686 if type(cmd
) not in (tuple, list):
687 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
689 if GenFdsGlobalVariable
.DebugLevel
!= -1:
690 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
691 GenFdsGlobalVariable
.InfLogger (cmd
)
693 if GenFdsGlobalVariable
.VerboseMode
:
695 GenFdsGlobalVariable
.InfLogger (cmd
)
699 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
700 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
704 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
705 except Exception as X
:
706 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
707 (out
, error
) = PopenObject
.communicate()
709 while PopenObject
.returncode
is None:
711 if returnValue
!= [] and returnValue
[0] != 0:
712 #get command return value
713 returnValue
[0] = PopenObject
.returncode
715 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
716 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
717 GenFdsGlobalVariable
.InfLogger(out
.decode(encoding
='utf-8', errors
='ignore'))
718 GenFdsGlobalVariable
.InfLogger(error
.decode(encoding
='utf-8', errors
='ignore'))
719 if PopenObject
.returncode
!= 0:
721 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
724 def VerboseLogger (msg
):
725 EdkLogger
.verbose(msg
)
732 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
733 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
736 def DebugLogger (Level
, msg
):
737 EdkLogger
.debug(Level
, msg
)
741 # @param Str String that may contain macro
742 # @param MacroDict Dictionary that contains macro value pair
745 def MacroExtend (Str
, MacroDict
=None, Arch
=DataType
.TAB_COMMON
):
749 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
750 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
751 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
752 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
756 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
757 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
759 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
761 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
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.
783 def GetPcdValue (PcdPattern
):
784 if PcdPattern
is None:
786 if PcdPattern
.startswith('PCD('):
787 PcdPair
= PcdPattern
[4:].rstrip(')').strip().split('.')
789 PcdPair
= PcdPattern
.strip().split('.')
790 TokenSpace
= PcdPair
[0]
791 TokenCName
= PcdPair
[1]
793 for Arch
in GenFdsGlobalVariable
.ArchList
:
794 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
795 PcdDict
= Platform
.Pcds
797 PcdObj
= PcdDict
[Key
]
798 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
799 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
800 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
801 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
802 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
804 return PcdObj
.DefaultValue
806 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
808 GenFdsGlobalVariable
.TargetName
,
809 GenFdsGlobalVariable
.ToolChainTag
):
810 PcdDict
= Package
.Pcds
812 PcdObj
= PcdDict
[Key
]
813 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
814 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
815 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
816 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
817 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
819 return PcdObj
.DefaultValue
825 # Find location of tools to process data
827 # @param KeyStringList Filter for inputs of section generation
828 # @param CurrentArchList Arch list
829 # @param NameGuid The Guid name
831 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
832 ToolDb
= ToolDef
.ToolsDefTxtDatabase
833 # if user not specify filter, try to deduce it from global data.
834 if KeyStringList
is None or KeyStringList
== []:
835 Target
= GenFdsGlobalVariable
.TargetName
836 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
837 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
838 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
839 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
840 for Arch
in CurrentArchList
:
841 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
842 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
844 if GenFdsGlobalVariable
.GuidToolDefinition
:
845 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
846 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
848 ToolDefinition
= ToolDef
.ToolsDefTxtDictionary
854 for tool_def
in ToolDefinition
.items():
855 if NameGuid
.lower() == tool_def
[1].lower():
856 KeyList
= tool_def
[0].split('_')
862 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
863 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
864 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
865 ToolPath
= ToolDefinition
.get(ToolPathKey
)
866 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
867 if ToolPathTmp
is None:
868 ToolPathTmp
= ToolPath
870 if ToolPathTmp
!= ToolPath
:
871 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
874 for Arch
in CurrentArchList
:
875 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
876 # key is (ToolChainFamily, ToolChain, CodeBase)
877 for item
in Platform
.BuildOptions
:
878 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
879 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
880 if item
[1] not in BuildOption
:
881 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
883 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
884 for Index
in range(2, -1, -1):
885 for Key
in list(BuildOption
.keys()):
886 List
= Key
.split('_')
887 if List
[Index
] == DataType
.TAB_STAR
:
888 for String
in ToolDb
[ToolList
[Index
]]:
889 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
891 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
892 if NewKey
not in BuildOption
:
893 BuildOption
[NewKey
] = BuildOption
[Key
]
896 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
900 for Op
in BuildOption
:
901 if NameGuid
== BuildOption
[Op
]:
902 KeyList
= Op
.split('_')
903 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
904 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
905 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
906 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
907 if ToolPathKey
in BuildOption
:
908 ToolPathTmp
= BuildOption
[ToolPathKey
]
909 if ToolOptionKey
in BuildOption
:
910 ToolOption
= BuildOption
[ToolOptionKey
]
912 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
913 return ToolPathTmp
, ToolOption