2 # Global variables for GenFds
4 # Copyright (c) 2007 - 2021, 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
17 from sys
import stdout
18 from subprocess
import PIPE
,Popen
19 from struct
import Struct
20 from array
import array
22 from Common
.BuildToolError
import COMMAND_FAILURE
,GENFDS_ERROR
23 from Common
import EdkLogger
24 from Common
.Misc
import SaveFileOnChange
26 from Common
.TargetTxtClassObject
import TargetTxtDict
27 from Common
.ToolDefClassObject
import ToolDefDict
,gDefaultToolsDefFile
28 from AutoGen
.BuildEngine
import ToolBuildRule
29 import Common
.DataType
as DataType
30 from Common
.Misc
import PathClass
,CreateDirectory
31 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
32 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
33 import Common
.GlobalData
as GlobalData
34 from Common
.BuildToolError
import *
35 from AutoGen
.AutoGen
import CalculatePriorityValue
40 class GenFdsGlobalVariable
:
44 # will be FvDir + os.sep + 'Ffs'
51 OutputDirFromDscDict
= {}
57 FvAddressFileName
= ''
61 SharpNumberPerLine
= 40
64 FixedLoadAddress
= False
67 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
68 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
69 __BuildRuleDatabase
= None
70 GuidToolDefinition
= {}
75 EnableGenfdsMultiThread
= True
78 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
79 # At the beginning of each generation of FV, false flag is appended to the list,
80 # after the call to GenerateSection returns, check the size of the output file,
81 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
82 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
83 # At the end of generation of FV, pop the flag.
84 # List is used as a stack to handle nested FV generation.
86 LargeFileInFvFlags
= []
87 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
88 LARGE_FILE_SIZE
= 0x1000000
90 SectionHeader
= Struct("3B 1B")
92 # FvName, FdName, CapName in FDF, Image file name
99 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
100 return GenFdsGlobalVariable
.__BuildRuleDatabase
101 BuildRule
= ToolBuildRule()
102 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule
.ToolBuildRule
103 TargetObj
= TargetTxtDict()
104 ToolDefinitionFile
= TargetObj
.Target
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
105 if ToolDefinitionFile
== '':
106 ToolDefinitionFile
= os
.path
.join('Conf', gDefaultToolsDefFile
)
107 if os
.path
.isfile(ToolDefinitionFile
):
108 ToolDefObj
= ToolDefDict((os
.path
.join(os
.getenv("WORKSPACE"), "Conf")))
109 ToolDefinition
= ToolDefObj
.ToolDef
.ToolsDefTxtDatabase
110 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
111 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
112 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
113 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
115 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
116 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
117 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
118 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
119 return GenFdsGlobalVariable
.__BuildRuleDatabase
122 # @param Inf: object of InfBuildData
123 # @param Arch: current arch
126 def GetBuildRules(Inf
, Arch
):
128 Arch
= DataType
.TAB_COMMON
130 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
133 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
134 if not BuildRuleDatabase
:
137 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
138 GenFdsGlobalVariable
.WorkSpaceDir
)
139 BuildDir
= os
.path
.join(
140 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
143 PathClassObj
.BaseName
145 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
147 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
148 "MODULE_NAME":Inf
.BaseName
,
149 "MODULE_GUID":Inf
.Guid
,
150 "MODULE_VERSION":Inf
.Version
,
151 "MODULE_TYPE":Inf
.ModuleType
,
152 "MODULE_FILE":str(PathClassObj
),
153 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
154 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
155 "MODULE_DIR":PathClassObj
.SubDir
,
156 "BASE_NAME":Inf
.BaseName
,
158 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
159 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
160 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
161 "TARGET":GenFdsGlobalVariable
.TargetName
,
162 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
165 "MODULE_BUILD_DIR":BuildDir
,
166 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
167 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
171 for Type
in BuildRuleDatabase
.FileTypeList
:
172 #first try getting build rule by BuildRuleFamily
173 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
175 # build type is always module type, but ...
176 if Inf
.ModuleType
!= Inf
.BuildType
:
177 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
178 #second try getting build rule by ToolChainFamily
180 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
182 # build type is always module type, but ...
183 if Inf
.ModuleType
!= Inf
.BuildType
:
184 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
187 RuleObject
= RuleObject
.Instantiate(Macro
)
188 BuildRules
[Type
] = RuleObject
189 for Ext
in RuleObject
.SourceFileExtList
:
190 BuildRules
[Ext
] = RuleObject
193 ## GetModuleCodaTargetList
195 # @param Inf: object of InfBuildData
196 # @param Arch: current arch
199 def GetModuleCodaTargetList(Inf
, Arch
):
200 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
207 if not Inf
.IsBinaryModule
:
208 for File
in Inf
.Sources
:
209 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
210 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
211 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
213 for File
in Inf
.Binaries
:
214 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
215 FileList
.append((File
, File
.Type
))
217 for File
, FileType
in FileList
:
222 while Index
< len(SourceList
):
223 Source
= SourceList
[Index
]
226 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
227 # Skip all files that are not binary libraries
228 if not Inf
.LibraryClass
:
230 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
231 elif FileType
in BuildRules
:
232 RuleObject
= BuildRules
[FileType
]
233 elif Source
.Ext
in BuildRules
:
234 RuleObject
= BuildRules
[Source
.Ext
]
236 # stop at no more rules
238 TargetList
.add(str(LastTarget
))
241 FileType
= RuleObject
.SourceFileType
243 # stop at STATIC_LIBRARY for library
244 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
246 TargetList
.add(str(LastTarget
))
249 Target
= RuleObject
.Apply(Source
)
252 TargetList
.add(str(LastTarget
))
254 elif not Target
.Outputs
:
255 # Only do build for target with outputs
256 TargetList
.add(str(Target
))
258 # to avoid cyclic rule
259 if FileType
in RuleChain
:
262 RuleChain
.append(FileType
)
263 SourceList
.extend(Target
.Outputs
)
265 FileType
= DataType
.TAB_UNKNOWN_FILE
266 for Cmd
in Target
.Commands
:
267 if "$(CP)" == Cmd
.split()[0]:
268 CpTarget
= Cmd
.split()[2]
269 TargetList
.add(CpTarget
)
271 return list(TargetList
)
275 # @param OutputDir Output directory
276 # @param FdfParser FDF contents parser
277 # @param Workspace The directory of workspace
278 # @param ArchList The Arch list of platform
281 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
282 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
283 GenFdsGlobalVariable
.FdfParser
= FdfParser
284 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
285 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
286 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
287 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
288 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
289 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
290 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
293 # Create FV Address inf file
295 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
296 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
300 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
302 for Arch
in ArchList
:
303 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
304 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
307 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
309 DataType
.TAB_LINE_BREAK
)
312 for Arch
in reversed(ArchList
):
313 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
318 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
320 DataType
.TAB_LINE_BREAK
)
322 FvAddressFile
.close()
325 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
326 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
327 GenFdsGlobalVariable
.FdfParser
= FdfParser
328 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
329 GenFdsGlobalVariable
.ArchList
= ArchList
330 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
331 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
332 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
333 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
334 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
335 for Arch
in ArchList
:
336 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
337 os
.path
.join(GlobalData
.gWorkspace
,
338 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
339 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
340 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
341 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
342 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
343 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
344 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
345 GlobalData
.gGlobalDefines
['TARGET'],
346 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
347 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
348 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
349 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
350 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
351 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
352 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
355 # Create FV Address inf file
357 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
358 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
362 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
364 for Arch
in ArchList
:
365 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
366 GlobalData
.gGlobalDefines
['TARGET'],
367 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
371 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
373 DataType
.TAB_LINE_BREAK
)
376 for Arch
in reversed(ArchList
):
377 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
378 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
379 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
384 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
386 DataType
.TAB_LINE_BREAK
)
388 FvAddressFile
.close()
390 ## ReplaceWorkspaceMacro()
392 # @param String String that may contain macro
395 def ReplaceWorkspaceMacro(String
):
396 String
= mws
.handleWsMacro(String
)
397 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
398 if os
.path
.exists(Str
):
399 if not os
.path
.isabs(Str
):
400 Str
= os
.path
.abspath(Str
)
402 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
403 return os
.path
.normpath(Str
)
405 ## Check if the input files are newer than output files
407 # @param Output Path of output file
408 # @param Input Path list of input files
410 # @retval True if Output doesn't exist, or any Input is newer
411 # @retval False if all Input is older than Output
414 def NeedsUpdate(Output
, Input
):
415 if not os
.path
.exists(Output
):
417 # always update "Output" if no "Input" given
421 # if fdf file is changed after the 'Output" is generated, update the 'Output'
422 OutputTime
= os
.path
.getmtime(Output
)
423 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
427 # always update "Output" if any "Input" doesn't exist
428 if not os
.path
.exists(F
):
430 # always update "Output" if any "Input" is newer than "Output"
431 if os
.path
.getmtime(F
) > OutputTime
:
436 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
437 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
442 Cmd
+= ("-c", CompressionType
)
446 Cmd
+= ("--dummy", DummyFile
)
448 Cmd
+= ("-l", GuidHdrLen
)
449 #Add each guided attribute
450 for Attr
in GuidAttr
:
452 #Section Align is only for dummy section without section type
453 for SecAlign
in InputAlign
:
454 Cmd
+= ("--sectionalign", SecAlign
)
456 CommandFile
= Output
+ '.txt'
459 if Ui
== "$(MODULE_NAME)":
462 Cmd
+= ("-n", '"' + Ui
+ '"')
463 Cmd
+= ("-o", Output
)
464 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
465 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
467 SectionData
= array('B', [0, 0, 0, 0])
468 SectionData
.fromlist(array('B',Ui
.encode('utf-16-le')).tolist())
469 SectionData
.append(0)
470 SectionData
.append(0)
471 Len
= len(SectionData
)
472 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
475 DirName
= os
.path
.dirname(Output
)
476 if not CreateDirectory(DirName
):
477 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % DirName
)
480 DirName
= os
.getcwd()
481 if not os
.access(DirName
, os
.W_OK
):
482 EdkLogger
.error(None, PERMISSION_FAILURE
, "Do not have write permission on directory %s" % DirName
)
485 with
open(Output
, "wb") as Fd
:
486 SectionData
.tofile(Fd
)
489 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s' % X
)
494 Cmd
+= ("-j", BuildNumber
)
495 Cmd
+= ("-o", Output
)
497 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
499 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
500 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
502 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
504 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
506 Cmd
+= ("-o", Output
)
509 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
511 if sys
.platform
== "win32":
512 Cmd
= ['if', 'exist', Input
[0]] + Cmd
514 Cmd
= ['-test', '-e', Input
[0], "&&"] + Cmd
515 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
516 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
517 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
518 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
519 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
520 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
521 GenFdsGlobalVariable
.LargeFileInFvFlags
):
522 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
525 def GetAlignment (AlignString
):
528 if AlignString
.endswith('K'):
529 return int (AlignString
.rstrip('K')) * 1024
530 if AlignString
.endswith('M'):
531 return int (AlignString
.rstrip('M')) * 1024 * 1024
532 if AlignString
.endswith('G'):
533 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
534 return int (AlignString
)
537 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
538 SectionAlign
=None, MakefilePath
=None):
539 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
540 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
546 if Align
not in mFfsValidAlign
:
547 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
548 for index
in range(0, len(mFfsValidAlign
) - 1):
549 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
551 Align
= mFfsValidAlign
[index
+ 1]
554 Cmd
+= ("-o", Output
)
555 for I
in range(0, len(Input
)):
557 Cmd
+= ("-oi", Input
[I
])
559 Cmd
+= ("-i", Input
[I
])
560 if SectionAlign
and SectionAlign
[I
]:
561 Cmd
+= ("-n", SectionAlign
[I
])
563 CommandFile
= Output
+ '.txt'
564 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
566 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
568 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
569 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
570 GenFdsGlobalVariable
.SecCmdList
= []
571 GenFdsGlobalVariable
.CopyList
= []
573 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
575 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
578 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
579 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
580 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
582 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
586 Cmd
+= ("-r", BaseAddress
)
588 if ForceRebase
== False:
589 Cmd
+= ("-F", "FALSE")
590 elif ForceRebase
== True:
591 Cmd
+= ("-F", "TRUE")
598 Cmd
+= ("-a", AddressFile
)
600 Cmd
+= ("-m", MapFile
)
602 Cmd
+= ("-g", FileSystemGuid
)
603 Cmd
+= ("-o", Output
)
607 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
610 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
611 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
612 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
613 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
615 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
618 if Type
.lower() == "te":
621 Cmd
+= ("-e", SubType
)
623 Cmd
+= ("-s", TimeStamp
)
627 Cmd
+= ("-p", Padding
)
638 Cmd
+= ("-o", Output
)
641 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
642 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
644 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
647 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
648 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
658 for EfiFile
in EfiInput
:
660 InputList
.append (EfiFile
)
664 for BinFile
in BinaryInput
:
666 InputList
.append (BinFile
)
669 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
671 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
674 Cmd
+= ("-l", ClassCode
)
676 Cmd
+= ("-r", Revision
)
678 Cmd
+= ("-i", DeviceId
)
680 Cmd
+= ("-f", VendorId
)
682 Cmd
+= ("-o", Output
)
684 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
685 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
687 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
690 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
691 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
693 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
696 Cmd
+= Options
.split(' ')
697 Cmd
+= ("-o", Output
)
700 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
701 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
703 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
706 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
708 if type(cmd
) not in (tuple, list):
709 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
711 if GenFdsGlobalVariable
.DebugLevel
!= -1:
712 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
713 GenFdsGlobalVariable
.InfLogger (cmd
)
715 if GenFdsGlobalVariable
.VerboseMode
:
717 GenFdsGlobalVariable
.InfLogger (cmd
)
721 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
722 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
726 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
727 except Exception as X
:
728 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
729 (out
, error
) = PopenObject
.communicate()
731 while PopenObject
.returncode
is None:
733 if returnValue
!= [] and returnValue
[0] != 0:
734 #get command return value
735 returnValue
[0] = PopenObject
.returncode
737 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
738 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
739 GenFdsGlobalVariable
.InfLogger(out
.decode(encoding
='utf-8', errors
='ignore'))
740 GenFdsGlobalVariable
.InfLogger(error
.decode(encoding
='utf-8', errors
='ignore'))
741 if PopenObject
.returncode
!= 0:
743 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
746 def VerboseLogger (msg
):
747 EdkLogger
.verbose(msg
)
754 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
755 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
758 def DebugLogger (Level
, msg
):
759 EdkLogger
.debug(Level
, msg
)
763 # @param Str String that may contain macro
764 # @param MacroDict Dictionary that contains macro value pair
767 def MacroExtend (Str
, MacroDict
=None, Arch
=DataType
.TAB_COMMON
):
771 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
772 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
773 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
774 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
778 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
779 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
781 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
783 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
786 Dict
.update(MacroDict
)
789 if Str
.find(key
) >= 0:
790 Str
= Str
.replace (key
, Dict
[key
])
792 if Str
.find('$(ARCH)') >= 0:
793 if len(GenFdsGlobalVariable
.ArchList
) == 1:
794 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
796 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
802 # @param PcdPattern pattern that labels a PCD.
805 def GetPcdValue (PcdPattern
):
806 if PcdPattern
is None:
808 if PcdPattern
.startswith('PCD('):
809 PcdPair
= PcdPattern
[4:].rstrip(')').strip().split('.')
811 PcdPair
= PcdPattern
.strip().split('.')
812 TokenSpace
= PcdPair
[0]
813 TokenCName
= PcdPair
[1]
815 for Arch
in GenFdsGlobalVariable
.ArchList
:
816 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
817 PcdDict
= Platform
.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
828 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
830 GenFdsGlobalVariable
.TargetName
,
831 GenFdsGlobalVariable
.ToolChainTag
):
832 PcdDict
= Package
.Pcds
834 PcdObj
= PcdDict
[Key
]
835 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
836 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
837 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
838 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
839 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
841 return PcdObj
.DefaultValue
847 # Find location of tools to process data
849 # @param KeyStringList Filter for inputs of section generation
850 # @param CurrentArchList Arch list
851 # @param NameGuid The Guid name
853 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
854 if GenFdsGlobalVariable
.GuidToolDefinition
:
855 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
856 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
858 ToolDefObj
= ToolDefDict((os
.path
.join(os
.getenv("WORKSPACE"), "Conf")))
859 ToolDef
= ToolDefObj
.ToolDef
860 ToolDb
= ToolDef
.ToolsDefTxtDatabase
861 # if user not specify filter, try to deduce it from global data.
862 if KeyStringList
is None or KeyStringList
== []:
863 Target
= GenFdsGlobalVariable
.TargetName
864 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
865 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
866 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
867 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
868 for Arch
in CurrentArchList
:
869 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
870 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
874 for Arch
in CurrentArchList
:
877 MatchOptionsItem
= None
878 for KeyString
in KeyStringList
:
879 KeyStringBuildTarget
, KeyStringToolChain
, KeyStringArch
= KeyString
.split('_')
880 if KeyStringArch
!= Arch
:
882 for Item
in ToolDef
.ToolsDefTxtDictionary
:
883 if len(Item
.split('_')) < 5:
885 ItemTarget
, ItemToolChain
, ItemArch
, ItemTool
, ItemAttr
= Item
.split('_')
886 if ItemTarget
== DataType
.TAB_STAR
:
887 ItemTarget
= KeyStringBuildTarget
888 if ItemToolChain
== DataType
.TAB_STAR
:
889 ItemToolChain
= KeyStringToolChain
890 if ItemArch
== DataType
.TAB_STAR
:
891 ItemArch
= KeyStringArch
892 if ItemTarget
!= KeyStringBuildTarget
:
894 if ItemToolChain
!= KeyStringToolChain
:
896 if ItemArch
!= KeyStringArch
:
898 if ItemAttr
!= DataType
.TAB_GUID
:
901 if ToolDef
.ToolsDefTxtDictionary
[Item
].lower() != NameGuid
.lower():
902 # No GUID value match
905 if MatchItem
.split('_')[3] == ItemTool
:
906 # Tool name is the same
908 if CalculatePriorityValue(MatchItem
) > CalculatePriorityValue(Item
):
909 # Current MatchItem is higher priority than new match item
914 ToolName
= MatchItem
.split('_')[3]
915 for Item
in ToolDef
.ToolsDefTxtDictionary
:
916 if len(Item
.split('_')) < 5:
918 ItemTarget
, ItemToolChain
, ItemArch
, ItemTool
, ItemAttr
= Item
.split('_')
919 if ItemTarget
== DataType
.TAB_STAR
:
920 ItemTarget
= KeyStringBuildTarget
921 if ItemToolChain
== DataType
.TAB_STAR
:
922 ItemToolChain
= KeyStringToolChain
923 if ItemArch
== DataType
.TAB_STAR
:
924 ItemArch
= KeyStringArch
925 if ItemTarget
!= KeyStringBuildTarget
:
927 if ItemToolChain
!= KeyStringToolChain
:
929 if ItemArch
!= KeyStringArch
:
931 if ItemTool
!= ToolName
:
933 if ItemAttr
== 'PATH':
935 if CalculatePriorityValue(MatchPathItem
) <= CalculatePriorityValue(Item
):
939 if ItemAttr
== 'FLAGS':
941 if CalculatePriorityValue(MatchOptionsItem
) <= CalculatePriorityValue(Item
):
942 MatchOptionsItem
= Item
944 MatchOptionsItem
= Item
946 ToolPathTmp
= ToolDef
.ToolsDefTxtDictionary
[MatchPathItem
]
948 ToolOption
= ToolDef
.ToolsDefTxtDictionary
[MatchOptionsItem
]
950 for Arch
in CurrentArchList
:
953 MatchOptionsItem
= None
954 for KeyString
in KeyStringList
:
955 KeyStringBuildTarget
, KeyStringToolChain
, KeyStringArch
= KeyString
.split('_')
956 if KeyStringArch
!= Arch
:
958 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, KeyStringBuildTarget
, KeyStringToolChain
]
959 for Item
in Platform
.BuildOptions
:
960 if len(Item
[1].split('_')) < 5:
962 ItemTarget
, ItemToolChain
, ItemArch
, ItemTool
, ItemAttr
= Item
[1].split('_')
963 if ItemTarget
== DataType
.TAB_STAR
:
964 ItemTarget
= KeyStringBuildTarget
965 if ItemToolChain
== DataType
.TAB_STAR
:
966 ItemToolChain
= KeyStringToolChain
967 if ItemArch
== DataType
.TAB_STAR
:
968 ItemArch
= KeyStringArch
969 if ItemTarget
!= KeyStringBuildTarget
:
971 if ItemToolChain
!= KeyStringToolChain
:
973 if ItemArch
!= KeyStringArch
:
975 if ItemAttr
!= DataType
.TAB_GUID
:
976 # Not GUID attribute match
978 if Platform
.BuildOptions
[Item
].lower() != NameGuid
.lower():
979 # No GUID value match
982 if MatchItem
[1].split('_')[3] == ItemTool
:
983 # Tool name is the same
985 if CalculatePriorityValue(MatchItem
[1]) > CalculatePriorityValue(Item
[1]):
986 # Current MatchItem is higher priority than new match item
991 ToolName
= MatchItem
[1].split('_')[3]
992 for Item
in Platform
.BuildOptions
:
993 if len(Item
[1].split('_')) < 5:
995 ItemTarget
, ItemToolChain
, ItemArch
, ItemTool
, ItemAttr
= Item
[1].split('_')
996 if ItemTarget
== DataType
.TAB_STAR
:
997 ItemTarget
= KeyStringBuildTarget
998 if ItemToolChain
== DataType
.TAB_STAR
:
999 ItemToolChain
= KeyStringToolChain
1000 if ItemArch
== DataType
.TAB_STAR
:
1001 ItemArch
= KeyStringArch
1002 if ItemTarget
!= KeyStringBuildTarget
:
1004 if ItemToolChain
!= KeyStringToolChain
:
1006 if ItemArch
!= KeyStringArch
:
1008 if ItemTool
!= ToolName
:
1010 if ItemAttr
== 'PATH':
1012 if CalculatePriorityValue(MatchPathItem
[1]) <= CalculatePriorityValue(Item
[1]):
1013 MatchPathItem
= Item
1015 MatchPathItem
= Item
1016 if ItemAttr
== 'FLAGS':
1017 if MatchOptionsItem
:
1018 if CalculatePriorityValue(MatchOptionsItem
[1]) <= CalculatePriorityValue(Item
[1]):
1019 MatchOptionsItem
= Item
1021 MatchOptionsItem
= Item
1023 ToolPathTmp
= Platform
.BuildOptions
[MatchPathItem
]
1024 if MatchOptionsItem
:
1025 ToolOption
= Platform
.BuildOptions
[MatchOptionsItem
]
1026 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
1027 return ToolPathTmp
, ToolOption