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
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
28 from AutoGen
.BuildEngine
import ToolBuildRule
29 import Common
.DataType
as DataType
30 from Common
.Misc
import PathClass
31 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
32 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
33 import Common
.GlobalData
as GlobalData
38 class GenFdsGlobalVariable
:
42 # will be FvDir + os.sep + 'Ffs'
49 OutputDirFromDscDict
= {}
55 FvAddressFileName
= ''
59 SharpNumberPerLine
= 40
62 FixedLoadAddress
= False
65 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
66 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
67 __BuildRuleDatabase
= None
68 GuidToolDefinition
= {}
73 EnableGenfdsMultiThread
= True
76 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
77 # At the beginning of each generation of FV, false flag is appended to the list,
78 # after the call to GenerateSection returns, check the size of the output file,
79 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
80 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
81 # At the end of generation of FV, pop the flag.
82 # List is used as a stack to handle nested FV generation.
84 LargeFileInFvFlags
= []
85 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
86 LARGE_FILE_SIZE
= 0x1000000
88 SectionHeader
= Struct("3B 1B")
90 # FvName, FdName, CapName in FDF, Image file name
97 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
98 return GenFdsGlobalVariable
.__BuildRuleDatabase
99 BuildRule
= ToolBuildRule()
100 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule
.ToolBuildRule
101 TargetObj
= TargetTxtDict()
102 ToolDefinitionFile
= TargetObj
.Target
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
103 if ToolDefinitionFile
== '':
104 ToolDefinitionFile
= "Conf/tools_def.txt"
105 if os
.path
.isfile(ToolDefinitionFile
):
106 ToolDefObj
= ToolDefDict((os
.path
.join(os
.getenv("WORKSPACE"), "Conf")))
107 ToolDefinition
= ToolDefObj
.ToolDef
.ToolsDefTxtDatabase
108 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
109 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
110 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
111 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
113 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
114 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
115 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
116 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
117 return GenFdsGlobalVariable
.__BuildRuleDatabase
120 # @param Inf: object of InfBuildData
121 # @param Arch: current arch
124 def GetBuildRules(Inf
, Arch
):
126 Arch
= DataType
.TAB_COMMON
128 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
131 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
132 if not BuildRuleDatabase
:
135 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
136 GenFdsGlobalVariable
.WorkSpaceDir
)
137 BuildDir
= os
.path
.join(
138 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
141 PathClassObj
.BaseName
143 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
145 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
146 "MODULE_NAME":Inf
.BaseName
,
147 "MODULE_GUID":Inf
.Guid
,
148 "MODULE_VERSION":Inf
.Version
,
149 "MODULE_TYPE":Inf
.ModuleType
,
150 "MODULE_FILE":str(PathClassObj
),
151 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
152 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
153 "MODULE_DIR":PathClassObj
.SubDir
,
154 "BASE_NAME":Inf
.BaseName
,
156 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
157 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
158 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
159 "TARGET":GenFdsGlobalVariable
.TargetName
,
160 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
163 "MODULE_BUILD_DIR":BuildDir
,
164 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
165 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
169 for Type
in BuildRuleDatabase
.FileTypeList
:
170 #first try getting build rule by BuildRuleFamily
171 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
173 # build type is always module type, but ...
174 if Inf
.ModuleType
!= Inf
.BuildType
:
175 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
176 #second try getting build rule by ToolChainFamily
178 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
180 # build type is always module type, but ...
181 if Inf
.ModuleType
!= Inf
.BuildType
:
182 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
185 RuleObject
= RuleObject
.Instantiate(Macro
)
186 BuildRules
[Type
] = RuleObject
187 for Ext
in RuleObject
.SourceFileExtList
:
188 BuildRules
[Ext
] = RuleObject
191 ## GetModuleCodaTargetList
193 # @param Inf: object of InfBuildData
194 # @param Arch: current arch
197 def GetModuleCodaTargetList(Inf
, Arch
):
198 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
205 if not Inf
.IsBinaryModule
:
206 for File
in Inf
.Sources
:
207 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
208 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
209 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
211 for File
in Inf
.Binaries
:
212 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
213 FileList
.append((File
, File
.Type
))
215 for File
, FileType
in FileList
:
220 while Index
< len(SourceList
):
221 Source
= SourceList
[Index
]
224 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
225 # Skip all files that are not binary libraries
226 if not Inf
.LibraryClass
:
228 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
229 elif FileType
in BuildRules
:
230 RuleObject
= BuildRules
[FileType
]
231 elif Source
.Ext
in BuildRules
:
232 RuleObject
= BuildRules
[Source
.Ext
]
234 # stop at no more rules
236 TargetList
.add(str(LastTarget
))
239 FileType
= RuleObject
.SourceFileType
241 # stop at STATIC_LIBRARY for library
242 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
244 TargetList
.add(str(LastTarget
))
247 Target
= RuleObject
.Apply(Source
)
250 TargetList
.add(str(LastTarget
))
252 elif not Target
.Outputs
:
253 # Only do build for target with outputs
254 TargetList
.add(str(Target
))
256 # to avoid cyclic rule
257 if FileType
in RuleChain
:
260 RuleChain
.append(FileType
)
261 SourceList
.extend(Target
.Outputs
)
263 FileType
= DataType
.TAB_UNKNOWN_FILE
264 for Cmd
in Target
.Commands
:
265 if "$(CP)" == Cmd
.split()[0]:
266 CpTarget
= Cmd
.split()[2]
267 TargetList
.add(CpTarget
)
269 return list(TargetList
)
273 # @param OutputDir Output directory
274 # @param FdfParser FDF contents parser
275 # @param Workspace The directory of workspace
276 # @param ArchList The Arch list of platform
279 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
280 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
281 GenFdsGlobalVariable
.FdfParser
= FdfParser
282 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
283 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
284 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
285 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
286 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
287 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
288 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
291 # Create FV Address inf file
293 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
294 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
298 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
300 for Arch
in ArchList
:
301 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
302 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
305 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
307 DataType
.TAB_LINE_BREAK
)
310 for Arch
in reversed(ArchList
):
311 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
316 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
318 DataType
.TAB_LINE_BREAK
)
320 FvAddressFile
.close()
323 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
324 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
325 GenFdsGlobalVariable
.FdfParser
= FdfParser
326 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
327 GenFdsGlobalVariable
.ArchList
= ArchList
328 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
329 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
330 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
331 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
332 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
333 for Arch
in ArchList
:
334 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
335 os
.path
.join(GlobalData
.gWorkspace
,
336 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
337 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
338 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
339 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
340 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
341 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
342 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
343 GlobalData
.gGlobalDefines
['TARGET'],
344 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
345 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
346 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
347 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
348 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
349 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
350 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
353 # Create FV Address inf file
355 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
356 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
360 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
362 for Arch
in ArchList
:
363 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
364 GlobalData
.gGlobalDefines
['TARGET'],
365 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
369 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
371 DataType
.TAB_LINE_BREAK
)
374 for Arch
in reversed(ArchList
):
375 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
376 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
377 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
382 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
384 DataType
.TAB_LINE_BREAK
)
386 FvAddressFile
.close()
388 ## ReplaceWorkspaceMacro()
390 # @param String String that may contain macro
393 def ReplaceWorkspaceMacro(String
):
394 String
= mws
.handleWsMacro(String
)
395 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
396 if os
.path
.exists(Str
):
397 if not os
.path
.isabs(Str
):
398 Str
= os
.path
.abspath(Str
)
400 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
401 return os
.path
.normpath(Str
)
403 ## Check if the input files are newer than output files
405 # @param Output Path of output file
406 # @param Input Path list of input files
408 # @retval True if Output doesn't exist, or any Input is newer
409 # @retval False if all Input is older than Output
412 def NeedsUpdate(Output
, Input
):
413 if not os
.path
.exists(Output
):
415 # always update "Output" if no "Input" given
419 # if fdf file is changed after the 'Output" is generated, update the 'Output'
420 OutputTime
= os
.path
.getmtime(Output
)
421 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
425 # always update "Output" if any "Input" doesn't exist
426 if not os
.path
.exists(F
):
428 # always update "Output" if any "Input" is newer than "Output"
429 if os
.path
.getmtime(F
) > OutputTime
:
434 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
435 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
440 Cmd
+= ("-c", CompressionType
)
444 Cmd
+= ("--dummy", DummyFile
)
446 Cmd
+= ("-l", GuidHdrLen
)
447 #Add each guided attribute
448 for Attr
in GuidAttr
:
450 #Section Align is only for dummy section without section type
451 for SecAlign
in InputAlign
:
452 Cmd
+= ("--sectionalign", SecAlign
)
454 CommandFile
= Output
+ '.txt'
457 if Ui
== "$(MODULE_NAME)":
460 Cmd
+= ("-n", '"' + Ui
+ '"')
461 Cmd
+= ("-o", Output
)
462 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
463 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
465 SectionData
= array('B', [0, 0, 0, 0])
466 SectionData
.fromstring(Ui
.encode("utf_16_le"))
467 SectionData
.append(0)
468 SectionData
.append(0)
469 Len
= len(SectionData
)
470 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
471 SaveFileOnChange(Output
, SectionData
.tostring())
476 Cmd
+= ("-j", BuildNumber
)
477 Cmd
+= ("-o", Output
)
479 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
481 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
482 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
484 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
486 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
488 Cmd
+= ("-o", Output
)
491 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
493 if sys
.platform
== "win32":
494 Cmd
= ['if', 'exist', Input
[0]] + Cmd
496 Cmd
= ['-test', '-e', Input
[0], "&&"] + Cmd
497 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
498 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
499 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
500 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
501 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
502 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
503 GenFdsGlobalVariable
.LargeFileInFvFlags
):
504 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
507 def GetAlignment (AlignString
):
510 if AlignString
.endswith('K'):
511 return int (AlignString
.rstrip('K')) * 1024
512 if AlignString
.endswith('M'):
513 return int (AlignString
.rstrip('M')) * 1024 * 1024
514 if AlignString
.endswith('G'):
515 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
516 return int (AlignString
)
519 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
520 SectionAlign
=None, MakefilePath
=None):
521 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
522 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
528 if Align
not in mFfsValidAlign
:
529 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
530 for index
in range(0, len(mFfsValidAlign
) - 1):
531 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
533 Align
= mFfsValidAlign
[index
+ 1]
536 Cmd
+= ("-o", Output
)
537 for I
in range(0, len(Input
)):
539 Cmd
+= ("-oi", Input
[I
])
541 Cmd
+= ("-i", Input
[I
])
542 if SectionAlign
and SectionAlign
[I
]:
543 Cmd
+= ("-n", SectionAlign
[I
])
545 CommandFile
= Output
+ '.txt'
546 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
548 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
550 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
551 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
552 GenFdsGlobalVariable
.SecCmdList
= []
553 GenFdsGlobalVariable
.CopyList
= []
555 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
557 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
560 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
561 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
562 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
564 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
568 Cmd
+= ("-r", BaseAddress
)
570 if ForceRebase
== False:
571 Cmd
+= ("-F", "FALSE")
572 elif ForceRebase
== True:
573 Cmd
+= ("-F", "TRUE")
580 Cmd
+= ("-a", AddressFile
)
582 Cmd
+= ("-m", MapFile
)
584 Cmd
+= ("-g", FileSystemGuid
)
585 Cmd
+= ("-o", Output
)
589 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
592 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
593 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
594 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
595 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
597 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
600 if Type
.lower() == "te":
603 Cmd
+= ("-e", SubType
)
605 Cmd
+= ("-s", TimeStamp
)
609 Cmd
+= ("-p", Padding
)
620 Cmd
+= ("-o", Output
)
623 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
624 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
626 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
629 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
630 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
640 for EfiFile
in EfiInput
:
642 InputList
.append (EfiFile
)
646 for BinFile
in BinaryInput
:
648 InputList
.append (BinFile
)
651 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
653 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
656 Cmd
+= ("-l", ClassCode
)
658 Cmd
+= ("-r", Revision
)
660 Cmd
+= ("-i", DeviceId
)
662 Cmd
+= ("-f", VendorId
)
664 Cmd
+= ("-o", Output
)
666 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
667 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
669 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
672 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
673 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
675 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
678 Cmd
+= Options
.split(' ')
679 Cmd
+= ("-o", Output
)
682 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
683 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
685 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
688 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
690 if type(cmd
) not in (tuple, list):
691 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
693 if GenFdsGlobalVariable
.DebugLevel
!= -1:
694 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
695 GenFdsGlobalVariable
.InfLogger (cmd
)
697 if GenFdsGlobalVariable
.VerboseMode
:
699 GenFdsGlobalVariable
.InfLogger (cmd
)
703 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
704 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
708 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
709 except Exception as X
:
710 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
711 (out
, error
) = PopenObject
.communicate()
713 while PopenObject
.returncode
is None:
715 if returnValue
!= [] and returnValue
[0] != 0:
716 #get command return value
717 returnValue
[0] = PopenObject
.returncode
719 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
720 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
721 GenFdsGlobalVariable
.InfLogger(out
.decode(encoding
='utf-8', errors
='ignore'))
722 GenFdsGlobalVariable
.InfLogger(error
.decode(encoding
='utf-8', errors
='ignore'))
723 if PopenObject
.returncode
!= 0:
725 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
728 def VerboseLogger (msg
):
729 EdkLogger
.verbose(msg
)
736 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
737 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
740 def DebugLogger (Level
, msg
):
741 EdkLogger
.debug(Level
, msg
)
745 # @param Str String that may contain macro
746 # @param MacroDict Dictionary that contains macro value pair
749 def MacroExtend (Str
, MacroDict
=None, Arch
=DataType
.TAB_COMMON
):
753 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
754 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
755 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
756 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
760 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
761 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
763 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
765 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
768 Dict
.update(MacroDict
)
771 if Str
.find(key
) >= 0:
772 Str
= Str
.replace (key
, Dict
[key
])
774 if Str
.find('$(ARCH)') >= 0:
775 if len(GenFdsGlobalVariable
.ArchList
) == 1:
776 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
778 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
784 # @param PcdPattern pattern that labels a PCD.
787 def GetPcdValue (PcdPattern
):
788 if PcdPattern
is None:
790 if PcdPattern
.startswith('PCD('):
791 PcdPair
= PcdPattern
[4:].rstrip(')').strip().split('.')
793 PcdPair
= PcdPattern
.strip().split('.')
794 TokenSpace
= PcdPair
[0]
795 TokenCName
= PcdPair
[1]
797 for Arch
in GenFdsGlobalVariable
.ArchList
:
798 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
799 PcdDict
= Platform
.Pcds
801 PcdObj
= PcdDict
[Key
]
802 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
803 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
804 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
805 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
806 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
808 return PcdObj
.DefaultValue
810 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
812 GenFdsGlobalVariable
.TargetName
,
813 GenFdsGlobalVariable
.ToolChainTag
):
814 PcdDict
= Package
.Pcds
816 PcdObj
= PcdDict
[Key
]
817 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
818 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
819 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
820 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
821 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
823 return PcdObj
.DefaultValue
829 # Find location of tools to process data
831 # @param KeyStringList Filter for inputs of section generation
832 # @param CurrentArchList Arch list
833 # @param NameGuid The Guid name
835 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
836 ToolDefObj
= ToolDefDict((os
.path
.join(os
.getenv("WORKSPACE"), "Conf")))
837 ToolDef
= ToolDefObj
.ToolDef
838 ToolDb
= ToolDef
.ToolsDefTxtDatabase
839 # if user not specify filter, try to deduce it from global data.
840 if KeyStringList
is None or KeyStringList
== []:
841 Target
= GenFdsGlobalVariable
.TargetName
842 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
843 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
844 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
845 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
846 for Arch
in CurrentArchList
:
847 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
848 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
850 if GenFdsGlobalVariable
.GuidToolDefinition
:
851 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
852 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
854 ToolDefinition
= ToolDef
.ToolsDefTxtDictionary
860 for tool_def
in ToolDefinition
.items():
861 if NameGuid
.lower() == tool_def
[1].lower():
862 KeyList
= tool_def
[0].split('_')
868 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
869 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
870 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
871 ToolPath
= ToolDefinition
.get(ToolPathKey
)
872 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
873 if ToolPathTmp
is None:
874 ToolPathTmp
= ToolPath
876 if ToolPathTmp
!= ToolPath
:
877 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
880 for Arch
in CurrentArchList
:
881 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
882 # key is (ToolChainFamily, ToolChain, CodeBase)
883 for item
in Platform
.BuildOptions
:
884 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
885 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
886 if item
[1] not in BuildOption
:
887 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
889 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
890 for Index
in range(2, -1, -1):
891 for Key
in list(BuildOption
.keys()):
892 List
= Key
.split('_')
893 if List
[Index
] == DataType
.TAB_STAR
:
894 for String
in ToolDb
[ToolList
[Index
]]:
895 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
897 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
898 if NewKey
not in BuildOption
:
899 BuildOption
[NewKey
] = BuildOption
[Key
]
902 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
906 for Op
in BuildOption
:
907 if NameGuid
== BuildOption
[Op
]:
908 KeyList
= Op
.split('_')
909 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
910 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
911 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
912 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
913 if ToolPathKey
in BuildOption
:
914 ToolPathTmp
= BuildOption
[ToolPathKey
]
915 if ToolOptionKey
in BuildOption
:
916 ToolOption
= BuildOption
[ToolOptionKey
]
918 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
919 return ToolPathTmp
, ToolOption