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'
54 OutputDirFromDscDict
= {}
60 FvAddressFileName
= ''
64 SharpNumberPerLine
= 40
67 FixedLoadAddress
= False
70 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
71 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
72 __BuildRuleDatabase
= None
73 GuidToolDefinition
= {}
78 EnableGenfdsMultiThread
= False
81 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
82 # At the beginning of each generation of FV, false flag is appended to the list,
83 # after the call to GenerateSection returns, check the size of the output file,
84 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
85 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
86 # At the end of generation of FV, pop the flag.
87 # List is used as a stack to handle nested FV generation.
89 LargeFileInFvFlags
= []
90 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
91 LARGE_FILE_SIZE
= 0x1000000
93 SectionHeader
= Struct("3B 1B")
95 # FvName, FdName, CapName in FDF, Image file name
101 def _LoadBuildRule():
102 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
103 return GenFdsGlobalVariable
.__BuildRuleDatabase
104 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
105 TargetTxt
= TargetTxtClassObject()
106 if os
.path
.isfile(BuildConfigurationFile
) == True:
107 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
108 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
109 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
110 if not BuildRuleFile
:
111 BuildRuleFile
= 'Conf/build_rule.txt'
112 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
113 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
114 if ToolDefinitionFile
== '':
115 ToolDefinitionFile
= "Conf/tools_def.txt"
116 if os
.path
.isfile(ToolDefinitionFile
):
117 ToolDef
= ToolDefClassObject()
118 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
119 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
120 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
121 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
122 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
123 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
125 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
126 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
127 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
128 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
129 return GenFdsGlobalVariable
.__BuildRuleDatabase
132 # @param Inf: object of InfBuildData
133 # @param Arch: current arch
136 def GetBuildRules(Inf
, Arch
):
138 Arch
= DataType
.TAB_COMMON
140 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
143 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
144 if not BuildRuleDatabase
:
147 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
148 GenFdsGlobalVariable
.WorkSpaceDir
)
149 BuildDir
= os
.path
.join(
150 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
153 PathClassObj
.BaseName
155 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
157 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
158 "MODULE_NAME":Inf
.BaseName
,
159 "MODULE_GUID":Inf
.Guid
,
160 "MODULE_VERSION":Inf
.Version
,
161 "MODULE_TYPE":Inf
.ModuleType
,
162 "MODULE_FILE":str(PathClassObj
),
163 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
164 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
165 "MODULE_DIR":PathClassObj
.SubDir
,
166 "BASE_NAME":Inf
.BaseName
,
168 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
169 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
170 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
171 "TARGET":GenFdsGlobalVariable
.TargetName
,
172 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
175 "MODULE_BUILD_DIR":BuildDir
,
176 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
177 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
181 for Type
in BuildRuleDatabase
.FileTypeList
:
182 #first try getting build rule by BuildRuleFamily
183 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
185 # build type is always module type, but ...
186 if Inf
.ModuleType
!= Inf
.BuildType
:
187 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
188 #second try getting build rule by ToolChainFamily
190 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
192 # build type is always module type, but ...
193 if Inf
.ModuleType
!= Inf
.BuildType
:
194 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
197 RuleObject
= RuleObject
.Instantiate(Macro
)
198 BuildRules
[Type
] = RuleObject
199 for Ext
in RuleObject
.SourceFileExtList
:
200 BuildRules
[Ext
] = RuleObject
203 ## GetModuleCodaTargetList
205 # @param Inf: object of InfBuildData
206 # @param Arch: current arch
209 def GetModuleCodaTargetList(Inf
, Arch
):
210 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
217 if not Inf
.IsBinaryModule
:
218 for File
in Inf
.Sources
:
219 if File
.TagName
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainTag
} and \
220 File
.ToolChainFamily
in {"", DataType
.TAB_STAR
, GenFdsGlobalVariable
.ToolChainFamily
}:
221 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
223 for File
in Inf
.Binaries
:
224 if File
.Target
in {DataType
.TAB_COMMON
, DataType
.TAB_STAR
, GenFdsGlobalVariable
.TargetName
}:
225 FileList
.append((File
, File
.Type
))
227 for File
, FileType
in FileList
:
232 while Index
< len(SourceList
):
233 Source
= SourceList
[Index
]
236 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
237 # Skip all files that are not binary libraries
238 if not Inf
.LibraryClass
:
240 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
241 elif FileType
in BuildRules
:
242 RuleObject
= BuildRules
[FileType
]
243 elif Source
.Ext
in BuildRules
:
244 RuleObject
= BuildRules
[Source
.Ext
]
246 # stop at no more rules
248 TargetList
.add(str(LastTarget
))
251 FileType
= RuleObject
.SourceFileType
253 # stop at STATIC_LIBRARY for library
254 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
256 TargetList
.add(str(LastTarget
))
259 Target
= RuleObject
.Apply(Source
)
262 TargetList
.add(str(LastTarget
))
264 elif not Target
.Outputs
:
265 # Only do build for target with outputs
266 TargetList
.add(str(Target
))
268 # to avoid cyclic rule
269 if FileType
in RuleChain
:
272 RuleChain
.append(FileType
)
273 SourceList
.extend(Target
.Outputs
)
275 FileType
= DataType
.TAB_UNKNOWN_FILE
276 for Cmd
in Target
.Commands
:
277 if "$(CP)" == Cmd
.split()[0]:
278 CpTarget
= Cmd
.split()[2]
279 TargetList
.add(CpTarget
)
281 return list(TargetList
)
285 # @param OutputDir Output directory
286 # @param FdfParser FDF contents parser
287 # @param Workspace The directory of workspace
288 # @param ArchList The Arch list of platform
291 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
292 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
293 GenFdsGlobalVariable
.FdfParser
= FdfParser
294 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
295 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
296 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
297 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
298 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
299 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
300 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
303 # Create FV Address inf file
305 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
306 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
310 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
312 for Arch
in ArchList
:
313 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
314 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
317 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
319 DataType
.TAB_LINE_BREAK
)
322 for Arch
in reversed(ArchList
):
323 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
328 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
330 DataType
.TAB_LINE_BREAK
)
332 FvAddressFile
.close()
335 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
336 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
337 GenFdsGlobalVariable
.FdfParser
= FdfParser
338 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
339 GenFdsGlobalVariable
.ArchList
= ArchList
340 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
341 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
342 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
343 GenFdsGlobalVariable
.EdkSourceDir
= GlobalData
.gGlobalDefines
["EDK_SOURCE"]
344 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
345 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
346 for Arch
in ArchList
:
347 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
348 os
.path
.join(GlobalData
.gWorkspace
,
349 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
350 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
351 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
352 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
353 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
354 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
355 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
356 GlobalData
.gGlobalDefines
['TARGET'],
357 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
358 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
359 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
360 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
361 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
362 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
363 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
366 # Create FV Address inf file
368 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
369 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
373 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
375 for Arch
in ArchList
:
376 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
377 GlobalData
.gGlobalDefines
['TARGET'],
378 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
382 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
384 DataType
.TAB_LINE_BREAK
)
387 for Arch
in reversed(ArchList
):
388 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
389 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
390 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
395 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
397 DataType
.TAB_LINE_BREAK
)
399 FvAddressFile
.close()
401 ## ReplaceWorkspaceMacro()
403 # @param String String that may contain macro
406 def ReplaceWorkspaceMacro(String
):
407 String
= mws
.handleWsMacro(String
)
408 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
409 if os
.path
.exists(Str
):
410 if not os
.path
.isabs(Str
):
411 Str
= os
.path
.abspath(Str
)
413 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
414 return os
.path
.normpath(Str
)
416 ## Check if the input files are newer than output files
418 # @param Output Path of output file
419 # @param Input Path list of input files
421 # @retval True if Output doesn't exist, or any Input is newer
422 # @retval False if all Input is older than Output
425 def NeedsUpdate(Output
, Input
):
426 if not os
.path
.exists(Output
):
428 # always update "Output" if no "Input" given
432 # if fdf file is changed after the 'Output" is generated, update the 'Output'
433 OutputTime
= os
.path
.getmtime(Output
)
434 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
438 # always update "Output" if any "Input" doesn't exist
439 if not os
.path
.exists(F
):
441 # always update "Output" if any "Input" is newer than "Output"
442 if os
.path
.getmtime(F
) > OutputTime
:
447 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
448 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
453 Cmd
+= ("-c", CompressionType
)
457 Cmd
+= ("--dummy", DummyFile
)
459 Cmd
+= ("-l", GuidHdrLen
)
460 #Add each guided attribute
461 for Attr
in GuidAttr
:
463 #Section Align is only for dummy section without section type
464 for SecAlign
in InputAlign
:
465 Cmd
+= ("--sectionalign", SecAlign
)
467 CommandFile
= Output
+ '.txt'
470 if Ui
== "$(MODULE_NAME)":
473 Cmd
+= ("-n", '"' + Ui
+ '"')
474 Cmd
+= ("-o", Output
)
475 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
476 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
478 SectionData
= array('B', [0, 0, 0, 0])
479 SectionData
.fromstring(Ui
.encode("utf_16_le"))
480 SectionData
.append(0)
481 SectionData
.append(0)
482 Len
= len(SectionData
)
483 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
484 SaveFileOnChange(Output
, SectionData
.tostring())
489 Cmd
+= ("-j", BuildNumber
)
490 Cmd
+= ("-o", Output
)
492 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
494 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
495 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
497 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
499 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
501 Cmd
+= ("-o", Output
)
504 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
506 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
507 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
508 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
509 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
510 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
511 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
512 GenFdsGlobalVariable
.LargeFileInFvFlags
):
513 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
516 def GetAlignment (AlignString
):
519 if AlignString
.endswith('K'):
520 return int (AlignString
.rstrip('K')) * 1024
521 if AlignString
.endswith('M'):
522 return int (AlignString
.rstrip('M')) * 1024 * 1024
523 if AlignString
.endswith('G'):
524 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
525 return int (AlignString
)
528 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
529 SectionAlign
=None, MakefilePath
=None):
530 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
531 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
537 if Align
not in mFfsValidAlign
:
538 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
539 for index
in range(0, len(mFfsValidAlign
) - 1):
540 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
542 Align
= mFfsValidAlign
[index
+ 1]
545 Cmd
+= ("-o", Output
)
546 for I
in range(0, len(Input
)):
547 Cmd
+= ("-i", Input
[I
])
548 if SectionAlign
and SectionAlign
[I
]:
549 Cmd
+= ("-n", SectionAlign
[I
])
551 CommandFile
= Output
+ '.txt'
552 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
554 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
556 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
557 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
558 GenFdsGlobalVariable
.SecCmdList
= []
559 GenFdsGlobalVariable
.CopyList
= []
561 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
563 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
566 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
567 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
568 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
570 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
574 Cmd
+= ("-r", BaseAddress
)
576 if ForceRebase
== False:
577 Cmd
+= ("-F", "FALSE")
578 elif ForceRebase
== True:
579 Cmd
+= ("-F", "TRUE")
586 Cmd
+= ("-a", AddressFile
)
588 Cmd
+= ("-m", MapFile
)
590 Cmd
+= ("-g", FileSystemGuid
)
591 Cmd
+= ("-o", Output
)
595 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
598 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
599 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
600 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
601 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
603 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
606 if Type
.lower() == "te":
609 Cmd
+= ("-e", SubType
)
611 Cmd
+= ("-s", TimeStamp
)
615 Cmd
+= ("-p", Padding
)
626 Cmd
+= ("-o", Output
)
629 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
630 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
632 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
635 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
636 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
646 for EfiFile
in EfiInput
:
648 InputList
.append (EfiFile
)
652 for BinFile
in BinaryInput
:
654 InputList
.append (BinFile
)
657 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
659 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
662 Cmd
+= ("-l", ClassCode
)
664 Cmd
+= ("-r", Revision
)
666 Cmd
+= ("-i", DeviceId
)
668 Cmd
+= ("-f", VendorId
)
670 Cmd
+= ("-o", Output
)
672 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
673 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
675 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
678 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
679 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
681 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
684 Cmd
+= Options
.split(' ')
685 Cmd
+= ("-o", Output
)
688 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
689 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
691 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
694 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
696 if type(cmd
) not in (tuple, list):
697 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
699 if GenFdsGlobalVariable
.DebugLevel
!= -1:
700 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
701 GenFdsGlobalVariable
.InfLogger (cmd
)
703 if GenFdsGlobalVariable
.VerboseMode
:
705 GenFdsGlobalVariable
.InfLogger (cmd
)
709 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
710 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
714 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
715 except Exception as X
:
716 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
717 (out
, error
) = PopenObject
.communicate()
719 while PopenObject
.returncode
is None:
721 if returnValue
!= [] and returnValue
[0] != 0:
722 #get command return value
723 returnValue
[0] = PopenObject
.returncode
725 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
726 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
727 GenFdsGlobalVariable
.InfLogger (out
)
728 GenFdsGlobalVariable
.InfLogger (error
)
729 if PopenObject
.returncode
!= 0:
731 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
734 def VerboseLogger (msg
):
735 EdkLogger
.verbose(msg
)
742 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
743 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
746 def DebugLogger (Level
, msg
):
747 EdkLogger
.debug(Level
, msg
)
751 # @param Str String that may contain macro
752 # @param MacroDict Dictionary that contains macro value pair
755 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
759 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
760 '$(EDK_SOURCE)': GenFdsGlobalVariable
.EdkSourceDir
,
761 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
762 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
763 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
767 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
768 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
770 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
772 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
775 Dict
.update(MacroDict
)
778 if Str
.find(key
) >= 0:
779 Str
= Str
.replace (key
, Dict
[key
])
781 if Str
.find('$(ARCH)') >= 0:
782 if len(GenFdsGlobalVariable
.ArchList
) == 1:
783 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
785 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
791 # @param PcdPattern pattern that labels a PCD.
794 def GetPcdValue (PcdPattern
):
795 if PcdPattern
is None:
797 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
798 TokenSpace
= PcdPair
[0]
799 TokenCName
= PcdPair
[1]
801 for Arch
in GenFdsGlobalVariable
.ArchList
:
802 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
803 PcdDict
= Platform
.Pcds
805 PcdObj
= PcdDict
[Key
]
806 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
807 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
808 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
809 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
810 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
812 return PcdObj
.DefaultValue
814 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
816 GenFdsGlobalVariable
.TargetName
,
817 GenFdsGlobalVariable
.ToolChainTag
):
818 PcdDict
= Package
.Pcds
820 PcdObj
= PcdDict
[Key
]
821 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
822 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
823 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
824 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
825 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
827 return PcdObj
.DefaultValue
833 # Find location of tools to process data
835 # @param KeyStringList Filter for inputs of section generation
836 # @param CurrentArchList Arch list
837 # @param NameGuid The Guid name
839 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
840 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
841 # if user not specify filter, try to deduce it from global data.
842 if KeyStringList
is None or KeyStringList
== []:
843 Target
= GenFdsGlobalVariable
.TargetName
844 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
845 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
846 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
847 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
848 for Arch
in CurrentArchList
:
849 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
850 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
852 if GenFdsGlobalVariable
.GuidToolDefinition
:
853 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
854 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
856 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
862 for ToolDef
in ToolDefinition
.items():
863 if NameGuid
.lower() == ToolDef
[1].lower():
864 KeyList
= ToolDef
[0].split('_')
870 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
871 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
872 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
873 ToolPath
= ToolDefinition
.get(ToolPathKey
)
874 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
875 if ToolPathTmp
is None:
876 ToolPathTmp
= ToolPath
878 if ToolPathTmp
!= ToolPath
:
879 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
882 for Arch
in CurrentArchList
:
883 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
884 # key is (ToolChainFamily, ToolChain, CodeBase)
885 for item
in Platform
.BuildOptions
:
886 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
887 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
888 if item
[1] not in BuildOption
:
889 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
891 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
892 for Index
in range(2, -1, -1):
893 for Key
in list(BuildOption
.keys()):
894 List
= Key
.split('_')
895 if List
[Index
] == DataType
.TAB_STAR
:
896 for String
in ToolDb
[ToolList
[Index
]]:
897 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
899 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
900 if NewKey
not in BuildOption
:
901 BuildOption
[NewKey
] = BuildOption
[Key
]
904 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
908 for Op
in BuildOption
:
909 if NameGuid
== BuildOption
[Op
]:
910 KeyList
= Op
.split('_')
911 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
912 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
913 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
914 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
915 if ToolPathKey
in BuildOption
:
916 ToolPathTmp
= BuildOption
[ToolPathKey
]
917 if ToolOptionKey
in BuildOption
:
918 ToolOption
= BuildOption
[ToolOptionKey
]
920 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
921 return ToolPathTmp
, ToolOption