2 # Global variables for GenFds
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 from __future__
import print_function
19 from __future__
import absolute_import
21 import Common
.LongFilePathOs
as os
22 from sys
import stdout
23 from subprocess
import PIPE
,Popen
24 from struct
import Struct
25 from array
import array
27 from Common
.BuildToolError
import COMMAND_FAILURE
,GENFDS_ERROR
28 from Common
import EdkLogger
29 from Common
.Misc
import SaveFileOnChange
31 from Common
.TargetTxtClassObject
import TargetTxtClassObject
32 from Common
.ToolDefClassObject
import ToolDefClassObject
, ToolDefDict
33 from AutoGen
.BuildEngine
import BuildRule
34 import Common
.DataType
as DataType
35 from Common
.Misc
import PathClass
36 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
37 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
42 class GenFdsGlobalVariable
:
46 # will be FvDir + os.sep + 'Ffs'
53 OutputDirFromDscDict
= {}
59 FvAddressFileName
= ''
63 SharpNumberPerLine
= 40
66 FixedLoadAddress
= False
69 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
70 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
71 __BuildRuleDatabase
= None
72 GuidToolDefinition
= {}
77 EnableGenfdsMultiThread
= False
80 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
81 # At the beginning of each generation of FV, false flag is appended to the list,
82 # after the call to GenerateSection returns, check the size of the output file,
83 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
84 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
85 # At the end of generation of FV, pop the flag.
86 # List is used as a stack to handle nested FV generation.
88 LargeFileInFvFlags
= []
89 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
90 LARGE_FILE_SIZE
= 0x1000000
92 SectionHeader
= Struct("3B 1B")
94 # FvName, FdName, CapName in FDF, Image file name
100 def _LoadBuildRule():
101 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
102 return GenFdsGlobalVariable
.__BuildRuleDatabase
103 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
104 TargetTxt
= TargetTxtClassObject()
105 if os
.path
.isfile(BuildConfigurationFile
) == True:
106 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
107 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
108 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
109 if not BuildRuleFile
:
110 BuildRuleFile
= 'Conf/build_rule.txt'
111 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
112 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
113 if ToolDefinitionFile
== '':
114 ToolDefinitionFile
= "Conf/tools_def.txt"
115 if os
.path
.isfile(ToolDefinitionFile
):
116 ToolDef
= ToolDefClassObject()
117 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
118 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
119 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
120 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
121 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
122 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
124 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
125 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
126 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
127 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
128 return GenFdsGlobalVariable
.__BuildRuleDatabase
131 # @param Inf: object of InfBuildData
132 # @param Arch: current arch
135 def GetBuildRules(Inf
, Arch
):
137 Arch
= DataType
.TAB_COMMON
139 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
142 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
143 if not BuildRuleDatabase
:
146 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
147 GenFdsGlobalVariable
.WorkSpaceDir
)
148 BuildDir
= os
.path
.join(
149 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
152 PathClassObj
.BaseName
154 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
156 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
157 "MODULE_NAME":Inf
.BaseName
,
158 "MODULE_GUID":Inf
.Guid
,
159 "MODULE_VERSION":Inf
.Version
,
160 "MODULE_TYPE":Inf
.ModuleType
,
161 "MODULE_FILE":str(PathClassObj
),
162 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
163 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
164 "MODULE_DIR":PathClassObj
.SubDir
,
165 "BASE_NAME":Inf
.BaseName
,
167 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
168 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
169 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
170 "TARGET":GenFdsGlobalVariable
.TargetName
,
171 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
174 "MODULE_BUILD_DIR":BuildDir
,
175 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
176 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
180 for Type
in BuildRuleDatabase
.FileTypeList
:
181 #first try getting build rule by BuildRuleFamily
182 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
184 # build type is always module type, but ...
185 if Inf
.ModuleType
!= Inf
.BuildType
:
186 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
187 #second try getting build rule by ToolChainFamily
189 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
191 # build type is always module type, but ...
192 if Inf
.ModuleType
!= Inf
.BuildType
:
193 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
196 RuleObject
= RuleObject
.Instantiate(Macro
)
197 BuildRules
[Type
] = RuleObject
198 for Ext
in RuleObject
.SourceFileExtList
:
199 BuildRules
[Ext
] = RuleObject
202 ## GetModuleCodaTargetList
204 # @param Inf: object of InfBuildData
205 # @param Arch: current arch
208 def GetModuleCodaTargetList(Inf
, Arch
):
209 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
216 if not Inf
.IsBinaryModule
:
217 for File
in Inf
.Sources
:
218 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
219 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
220 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
222 for File
in Inf
.Binaries
:
223 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
224 FileList
.append((File
, File
.Type
))
226 for File
, FileType
in FileList
:
231 while Index
< len(SourceList
):
232 Source
= SourceList
[Index
]
235 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
236 # Skip all files that are not binary libraries
237 if not Inf
.LibraryClass
:
239 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
240 elif FileType
in BuildRules
:
241 RuleObject
= BuildRules
[FileType
]
242 elif Source
.Ext
in BuildRules
:
243 RuleObject
= BuildRules
[Source
.Ext
]
245 # stop at no more rules
247 TargetList
.add(str(LastTarget
))
250 FileType
= RuleObject
.SourceFileType
252 # stop at STATIC_LIBRARY for library
253 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
255 TargetList
.add(str(LastTarget
))
258 Target
= RuleObject
.Apply(Source
)
261 TargetList
.add(str(LastTarget
))
263 elif not Target
.Outputs
:
264 # Only do build for target with outputs
265 TargetList
.add(str(Target
))
267 # to avoid cyclic rule
268 if FileType
in RuleChain
:
271 RuleChain
.append(FileType
)
272 SourceList
.extend(Target
.Outputs
)
274 FileType
= DataType
.TAB_UNKNOWN_FILE
275 for Cmd
in Target
.Commands
:
276 if "$(CP)" == Cmd
.split()[0]:
277 CpTarget
= Cmd
.split()[2]
278 TargetList
.add(CpTarget
)
280 return list(TargetList
)
284 # @param OutputDir Output directory
285 # @param FdfParser FDF contents parser
286 # @param Workspace The directory of workspace
287 # @param ArchList The Arch list of platform
290 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
291 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
292 GenFdsGlobalVariable
.FdfParser
= FdfParser
293 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
294 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
295 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
296 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
297 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
298 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
299 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
302 # Create FV Address inf file
304 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
305 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
309 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
311 for Arch
in ArchList
:
312 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
313 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
316 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
318 DataType
.TAB_LINE_BREAK
)
321 for Arch
in reversed(ArchList
):
322 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
327 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
329 DataType
.TAB_LINE_BREAK
)
331 FvAddressFile
.close()
334 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
335 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
336 GenFdsGlobalVariable
.FdfParser
= FdfParser
337 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
338 GenFdsGlobalVariable
.ArchList
= ArchList
339 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
340 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
341 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
342 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
343 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
344 for Arch
in ArchList
:
345 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
346 os
.path
.join(GlobalData
.gWorkspace
,
347 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
348 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
349 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
350 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
351 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
352 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
353 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
354 GlobalData
.gGlobalDefines
['TARGET'],
355 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
356 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
357 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
358 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
359 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
360 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
361 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
364 # Create FV Address inf file
366 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
367 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
371 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
373 for Arch
in ArchList
:
374 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
375 GlobalData
.gGlobalDefines
['TARGET'],
376 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
380 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
382 DataType
.TAB_LINE_BREAK
)
385 for Arch
in reversed(ArchList
):
386 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
387 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
388 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
393 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
395 DataType
.TAB_LINE_BREAK
)
397 FvAddressFile
.close()
399 ## ReplaceWorkspaceMacro()
401 # @param String String that may contain macro
404 def ReplaceWorkspaceMacro(String
):
405 String
= mws
.handleWsMacro(String
)
406 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
407 if os
.path
.exists(Str
):
408 if not os
.path
.isabs(Str
):
409 Str
= os
.path
.abspath(Str
)
411 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
412 return os
.path
.normpath(Str
)
414 ## Check if the input files are newer than output files
416 # @param Output Path of output file
417 # @param Input Path list of input files
419 # @retval True if Output doesn't exist, or any Input is newer
420 # @retval False if all Input is older than Output
423 def NeedsUpdate(Output
, Input
):
424 if not os
.path
.exists(Output
):
426 # always update "Output" if no "Input" given
430 # if fdf file is changed after the 'Output" is generated, update the 'Output'
431 OutputTime
= os
.path
.getmtime(Output
)
432 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
436 # always update "Output" if any "Input" doesn't exist
437 if not os
.path
.exists(F
):
439 # always update "Output" if any "Input" is newer than "Output"
440 if os
.path
.getmtime(F
) > OutputTime
:
445 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
446 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
451 Cmd
+= ("-c", CompressionType
)
455 Cmd
+= ("--dummy", DummyFile
)
457 Cmd
+= ("-l", GuidHdrLen
)
458 #Add each guided attribute
459 for Attr
in GuidAttr
:
461 #Section Align is only for dummy section without section type
462 for SecAlign
in InputAlign
:
463 Cmd
+= ("--sectionalign", SecAlign
)
465 CommandFile
= Output
+ '.txt'
468 if Ui
== "$(MODULE_NAME)":
471 Cmd
+= ("-n", '"' + Ui
+ '"')
472 Cmd
+= ("-o", Output
)
473 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
474 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
476 SectionData
= array('B', [0, 0, 0, 0])
477 SectionData
.fromstring(Ui
.encode("utf_16_le"))
478 SectionData
.append(0)
479 SectionData
.append(0)
480 Len
= len(SectionData
)
481 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
482 SaveFileOnChange(Output
, SectionData
.tostring())
487 Cmd
+= ("-j", BuildNumber
)
488 Cmd
+= ("-o", Output
)
490 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
492 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
493 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
495 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
497 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
499 Cmd
+= ("-o", Output
)
502 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
504 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
505 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
506 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
507 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
508 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
509 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
510 GenFdsGlobalVariable
.LargeFileInFvFlags
):
511 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
514 def GetAlignment (AlignString
):
517 if AlignString
.endswith('K'):
518 return int (AlignString
.rstrip('K')) * 1024
519 if AlignString
.endswith('M'):
520 return int (AlignString
.rstrip('M')) * 1024 * 1024
521 if AlignString
.endswith('G'):
522 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
523 return int (AlignString
)
526 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
527 SectionAlign
=None, MakefilePath
=None):
528 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
529 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
535 if Align
not in mFfsValidAlign
:
536 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
537 for index
in range(0, len(mFfsValidAlign
) - 1):
538 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
540 Align
= mFfsValidAlign
[index
+ 1]
543 Cmd
+= ("-o", Output
)
544 for I
in range(0, len(Input
)):
545 Cmd
+= ("-i", Input
[I
])
546 if SectionAlign
and SectionAlign
[I
]:
547 Cmd
+= ("-n", SectionAlign
[I
])
549 CommandFile
= Output
+ '.txt'
550 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
552 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
554 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
555 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
556 GenFdsGlobalVariable
.SecCmdList
= []
557 GenFdsGlobalVariable
.CopyList
= []
559 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
561 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
564 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
565 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
566 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
568 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
572 Cmd
+= ("-r", BaseAddress
)
574 if ForceRebase
== False:
575 Cmd
+= ("-F", "FALSE")
576 elif ForceRebase
== True:
577 Cmd
+= ("-F", "TRUE")
584 Cmd
+= ("-a", AddressFile
)
586 Cmd
+= ("-m", MapFile
)
588 Cmd
+= ("-g", FileSystemGuid
)
589 Cmd
+= ("-o", Output
)
593 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
596 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
597 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
598 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
599 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
601 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
604 if Type
.lower() == "te":
607 Cmd
+= ("-e", SubType
)
609 Cmd
+= ("-s", TimeStamp
)
613 Cmd
+= ("-p", Padding
)
624 Cmd
+= ("-o", Output
)
627 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
628 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
630 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
633 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
634 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
644 for EfiFile
in EfiInput
:
646 InputList
.append (EfiFile
)
650 for BinFile
in BinaryInput
:
652 InputList
.append (BinFile
)
655 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
657 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
660 Cmd
+= ("-l", ClassCode
)
662 Cmd
+= ("-r", Revision
)
664 Cmd
+= ("-i", DeviceId
)
666 Cmd
+= ("-f", VendorId
)
668 Cmd
+= ("-o", Output
)
670 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
671 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
673 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
676 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
677 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
679 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
682 Cmd
+= Options
.split(' ')
683 Cmd
+= ("-o", Output
)
686 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
687 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
689 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
692 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
694 if type(cmd
) not in (tuple, list):
695 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
697 if GenFdsGlobalVariable
.DebugLevel
!= -1:
698 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
699 GenFdsGlobalVariable
.InfLogger (cmd
)
701 if GenFdsGlobalVariable
.VerboseMode
:
703 GenFdsGlobalVariable
.InfLogger (cmd
)
707 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
708 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
712 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
713 except Exception as X
:
714 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
715 (out
, error
) = PopenObject
.communicate()
717 while PopenObject
.returncode
is None:
719 if returnValue
!= [] and returnValue
[0] != 0:
720 #get command return value
721 returnValue
[0] = PopenObject
.returncode
723 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
724 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
725 GenFdsGlobalVariable
.InfLogger (out
)
726 GenFdsGlobalVariable
.InfLogger (error
)
727 if PopenObject
.returncode
!= 0:
729 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
732 def VerboseLogger (msg
):
733 EdkLogger
.verbose(msg
)
740 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
741 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
744 def DebugLogger (Level
, msg
):
745 EdkLogger
.debug(Level
, msg
)
749 # @param Str String that may contain macro
750 # @param MacroDict Dictionary that contains macro value pair
753 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
757 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
758 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
759 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
760 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
764 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
765 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
767 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
769 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
772 Dict
.update(MacroDict
)
775 if Str
.find(key
) >= 0:
776 Str
= Str
.replace (key
, Dict
[key
])
778 if Str
.find('$(ARCH)') >= 0:
779 if len(GenFdsGlobalVariable
.ArchList
) == 1:
780 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
782 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
788 # @param PcdPattern pattern that labels a PCD.
791 def GetPcdValue (PcdPattern
):
792 if PcdPattern
is None:
794 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
795 TokenSpace
= PcdPair
[0]
796 TokenCName
= PcdPair
[1]
798 for Arch
in GenFdsGlobalVariable
.ArchList
:
799 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
800 PcdDict
= Platform
.Pcds
802 PcdObj
= PcdDict
[Key
]
803 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
804 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
805 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
806 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
807 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
809 return PcdObj
.DefaultValue
811 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
813 GenFdsGlobalVariable
.TargetName
,
814 GenFdsGlobalVariable
.ToolChainTag
):
815 PcdDict
= Package
.Pcds
817 PcdObj
= PcdDict
[Key
]
818 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
819 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
820 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
821 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
822 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
824 return PcdObj
.DefaultValue
830 # Find location of tools to process data
832 # @param KeyStringList Filter for inputs of section generation
833 # @param CurrentArchList Arch list
834 # @param NameGuid The Guid name
836 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
837 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
838 # if user not specify filter, try to deduce it from global data.
839 if KeyStringList
is None or KeyStringList
== []:
840 Target
= GenFdsGlobalVariable
.TargetName
841 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
842 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
843 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
844 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
845 for Arch
in CurrentArchList
:
846 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
847 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
849 if GenFdsGlobalVariable
.GuidToolDefinition
:
850 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
851 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
853 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
859 for ToolDef
in ToolDefinition
.items():
860 if NameGuid
.lower() == ToolDef
[1].lower():
861 KeyList
= ToolDef
[0].split('_')
867 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
868 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
869 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
870 ToolPath
= ToolDefinition
.get(ToolPathKey
)
871 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
872 if ToolPathTmp
is None:
873 ToolPathTmp
= ToolPath
875 if ToolPathTmp
!= ToolPath
:
876 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
879 for Arch
in CurrentArchList
:
880 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
881 # key is (ToolChainFamily, ToolChain, CodeBase)
882 for item
in Platform
.BuildOptions
:
883 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
884 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
885 if item
[1] not in BuildOption
:
886 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
888 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
889 for Index
in range(2, -1, -1):
890 for Key
in list(BuildOption
.keys()):
891 List
= Key
.split('_')
892 if List
[Index
] == DataType
.TAB_STAR
:
893 for String
in ToolDb
[ToolList
[Index
]]:
894 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
896 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
897 if NewKey
not in BuildOption
:
898 BuildOption
[NewKey
] = BuildOption
[Key
]
901 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
905 for Op
in BuildOption
:
906 if NameGuid
== BuildOption
[Op
]:
907 KeyList
= Op
.split('_')
908 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
909 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
910 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
911 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
912 if ToolPathKey
in BuildOption
:
913 ToolPathTmp
= BuildOption
[ToolPathKey
]
914 if ToolOptionKey
in BuildOption
:
915 ToolOption
= BuildOption
[ToolOptionKey
]
917 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
918 return ToolPathTmp
, ToolOption