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
= {}
61 FvAddressFileName
= ''
65 SharpNumberPerLine
= 40
68 FixedLoadAddress
= False
71 BuildRuleFamily
= DataType
.TAB_COMPILER_MSFT
72 ToolChainFamily
= DataType
.TAB_COMPILER_MSFT
73 __BuildRuleDatabase
= None
74 GuidToolDefinition
= {}
79 EnableGenfdsMultiThread
= False
82 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
83 # At the beginning of each generation of FV, false flag is appended to the list,
84 # after the call to GenerateSection returns, check the size of the output file,
85 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
86 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
87 # At the end of generation of FV, pop the flag.
88 # List is used as a stack to handle nested FV generation.
90 LargeFileInFvFlags
= []
91 EFI_FIRMWARE_FILE_SYSTEM3_GUID
= '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
92 LARGE_FILE_SIZE
= 0x1000000
94 SectionHeader
= Struct("3B 1B")
96 # FvName, FdName, CapName in FDF, Image file name
102 def _LoadBuildRule():
103 if GenFdsGlobalVariable
.__BuildRuleDatabase
:
104 return GenFdsGlobalVariable
.__BuildRuleDatabase
105 BuildConfigurationFile
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.ConfDir
, "target.txt"))
106 TargetTxt
= TargetTxtClassObject()
107 if os
.path
.isfile(BuildConfigurationFile
) == True:
108 TargetTxt
.LoadTargetTxtFile(BuildConfigurationFile
)
109 if DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
in TargetTxt
.TargetTxtDictionary
:
110 BuildRuleFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_BUILD_RULE_CONF
]
111 if not BuildRuleFile
:
112 BuildRuleFile
= 'Conf/build_rule.txt'
113 GenFdsGlobalVariable
.__BuildRuleDatabase
= BuildRule(BuildRuleFile
)
114 ToolDefinitionFile
= TargetTxt
.TargetTxtDictionary
[DataType
.TAB_TAT_DEFINES_TOOL_CHAIN_CONF
]
115 if ToolDefinitionFile
== '':
116 ToolDefinitionFile
= "Conf/tools_def.txt"
117 if os
.path
.isfile(ToolDefinitionFile
):
118 ToolDef
= ToolDefClassObject()
119 ToolDef
.LoadToolDefFile(ToolDefinitionFile
)
120 ToolDefinition
= ToolDef
.ToolsDefTxtDatabase
121 if DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
in ToolDefinition \
122 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
] \
123 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
124 GenFdsGlobalVariable
.BuildRuleFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_BUILDRULEFAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
126 if DataType
.TAB_TOD_DEFINES_FAMILY
in ToolDefinition \
127 and GenFdsGlobalVariable
.ToolChainTag
in ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
] \
128 and ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]:
129 GenFdsGlobalVariable
.ToolChainFamily
= ToolDefinition
[DataType
.TAB_TOD_DEFINES_FAMILY
][GenFdsGlobalVariable
.ToolChainTag
]
130 return GenFdsGlobalVariable
.__BuildRuleDatabase
133 # @param Inf: object of InfBuildData
134 # @param Arch: current arch
137 def GetBuildRules(Inf
, Arch
):
139 Arch
= DataType
.TAB_COMMON
141 if not Arch
in GenFdsGlobalVariable
.OutputDirDict
:
144 BuildRuleDatabase
= GenFdsGlobalVariable
._LoadBuildRule
()
145 if not BuildRuleDatabase
:
148 PathClassObj
= PathClass(Inf
.MetaFile
.File
,
149 GenFdsGlobalVariable
.WorkSpaceDir
)
150 BuildDir
= os
.path
.join(
151 GenFdsGlobalVariable
.OutputDirDict
[Arch
],
154 PathClassObj
.BaseName
156 BinDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[Arch
], Arch
)
158 "WORKSPACE":GenFdsGlobalVariable
.WorkSpaceDir
,
159 "MODULE_NAME":Inf
.BaseName
,
160 "MODULE_GUID":Inf
.Guid
,
161 "MODULE_VERSION":Inf
.Version
,
162 "MODULE_TYPE":Inf
.ModuleType
,
163 "MODULE_FILE":str(PathClassObj
),
164 "MODULE_FILE_BASE_NAME":PathClassObj
.BaseName
,
165 "MODULE_RELATIVE_DIR":PathClassObj
.SubDir
,
166 "MODULE_DIR":PathClassObj
.SubDir
,
167 "BASE_NAME":Inf
.BaseName
,
169 "TOOLCHAIN":GenFdsGlobalVariable
.ToolChainTag
,
170 "TOOLCHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
171 "TOOL_CHAIN_TAG":GenFdsGlobalVariable
.ToolChainTag
,
172 "TARGET":GenFdsGlobalVariable
.TargetName
,
173 "BUILD_DIR":GenFdsGlobalVariable
.OutputDirDict
[Arch
],
176 "MODULE_BUILD_DIR":BuildDir
,
177 "OUTPUT_DIR":os
.path
.join(BuildDir
, "OUTPUT"),
178 "DEBUG_DIR":os
.path
.join(BuildDir
, "DEBUG")
182 for Type
in BuildRuleDatabase
.FileTypeList
:
183 #first try getting build rule by BuildRuleFamily
184 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
186 # build type is always module type, but ...
187 if Inf
.ModuleType
!= Inf
.BuildType
:
188 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.BuildRuleFamily
]
189 #second try getting build rule by ToolChainFamily
191 RuleObject
= BuildRuleDatabase
[Type
, Inf
.BuildType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
193 # build type is always module type, but ...
194 if Inf
.ModuleType
!= Inf
.BuildType
:
195 RuleObject
= BuildRuleDatabase
[Type
, Inf
.ModuleType
, Arch
, GenFdsGlobalVariable
.ToolChainFamily
]
198 RuleObject
= RuleObject
.Instantiate(Macro
)
199 BuildRules
[Type
] = RuleObject
200 for Ext
in RuleObject
.SourceFileExtList
:
201 BuildRules
[Ext
] = RuleObject
204 ## GetModuleCodaTargetList
206 # @param Inf: object of InfBuildData
207 # @param Arch: current arch
210 def GetModuleCodaTargetList(Inf
, Arch
):
211 BuildRules
= GenFdsGlobalVariable
.GetBuildRules(Inf
, Arch
)
218 if not Inf
.IsBinaryModule
:
219 for File
in Inf
.Sources
:
220 if File
.TagName
in {"", "*", GenFdsGlobalVariable
.ToolChainTag
} and \
221 File
.ToolChainFamily
in {"", "*", GenFdsGlobalVariable
.ToolChainFamily
}:
222 FileList
.append((File
, DataType
.TAB_UNKNOWN_FILE
))
224 for File
in Inf
.Binaries
:
225 if File
.Target
in {DataType
.TAB_COMMON
, '*', GenFdsGlobalVariable
.TargetName
}:
226 FileList
.append((File
, File
.Type
))
228 for File
, FileType
in FileList
:
233 while Index
< len(SourceList
):
234 Source
= SourceList
[Index
]
237 if File
.IsBinary
and File
== Source
and Inf
.Binaries
and File
in Inf
.Binaries
:
238 # Skip all files that are not binary libraries
239 if not Inf
.LibraryClass
:
241 RuleObject
= BuildRules
[DataType
.TAB_DEFAULT_BINARY_FILE
]
242 elif FileType
in BuildRules
:
243 RuleObject
= BuildRules
[FileType
]
244 elif Source
.Ext
in BuildRules
:
245 RuleObject
= BuildRules
[Source
.Ext
]
247 # stop at no more rules
249 TargetList
.add(str(LastTarget
))
252 FileType
= RuleObject
.SourceFileType
254 # stop at STATIC_LIBRARY for library
255 if Inf
.LibraryClass
and FileType
== DataType
.TAB_STATIC_LIBRARY
:
257 TargetList
.add(str(LastTarget
))
260 Target
= RuleObject
.Apply(Source
)
263 TargetList
.add(str(LastTarget
))
265 elif not Target
.Outputs
:
266 # Only do build for target with outputs
267 TargetList
.add(str(Target
))
269 # to avoid cyclic rule
270 if FileType
in RuleChain
:
273 RuleChain
.append(FileType
)
274 SourceList
.extend(Target
.Outputs
)
276 FileType
= DataType
.TAB_UNKNOWN_FILE
277 for Cmd
in Target
.Commands
:
278 if "$(CP)" == Cmd
.split()[0]:
279 CpTarget
= Cmd
.split()[2]
280 TargetList
.add(CpTarget
)
282 return list(TargetList
)
286 # @param OutputDir Output directory
287 # @param FdfParser FDF contents parser
288 # @param Workspace The directory of workspace
289 # @param ArchList The Arch list of platform
292 def SetDir (OutputDir
, FdfParser
, WorkSpace
, ArchList
):
293 GenFdsGlobalVariable
.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir
)
294 GenFdsGlobalVariable
.FdfParser
= FdfParser
295 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
296 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
297 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
298 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
299 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
300 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
301 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
304 # Create FV Address inf file
306 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
307 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
311 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
313 for Arch
in ArchList
:
314 if GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
:
315 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].BsBaseAddress
318 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
320 DataType
.TAB_LINE_BREAK
)
323 for Arch
in reversed(ArchList
):
324 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
].RtBaseAddress
329 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
331 DataType
.TAB_LINE_BREAK
)
333 FvAddressFile
.close()
336 def SetEnv(FdfParser
, WorkSpace
, ArchList
, GlobalData
):
337 GenFdsGlobalVariable
.ModuleFile
= WorkSpace
.ModuleFile
338 GenFdsGlobalVariable
.FdfParser
= FdfParser
339 GenFdsGlobalVariable
.WorkSpace
= WorkSpace
.Db
340 GenFdsGlobalVariable
.ArchList
= ArchList
341 GenFdsGlobalVariable
.ToolChainTag
= GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]
342 GenFdsGlobalVariable
.TargetName
= GlobalData
.gGlobalDefines
["TARGET"]
343 GenFdsGlobalVariable
.ActivePlatform
= GlobalData
.gActivePlatform
344 GenFdsGlobalVariable
.EdkSourceDir
= GlobalData
.gGlobalDefines
["EDK_SOURCE"]
345 GenFdsGlobalVariable
.ConfDir
= GlobalData
.gConfDirectory
346 GenFdsGlobalVariable
.EnableGenfdsMultiThread
= GlobalData
.gEnableGenfdsMultiThread
347 for Arch
in ArchList
:
348 GenFdsGlobalVariable
.OutputDirDict
[Arch
] = os
.path
.normpath(
349 os
.path
.join(GlobalData
.gWorkspace
,
350 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
351 GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
,
352 GlobalData
.gGlobalDefines
['TARGET'] +'_' + GlobalData
.gGlobalDefines
['TOOLCHAIN']))
353 GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
] = os
.path
.normpath(
354 WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
355 GlobalData
.gGlobalDefines
['TARGET'], GlobalData
.gGlobalDefines
['TOOLCHAIN']].OutputDirectory
)
356 GenFdsGlobalVariable
.PlatformName
= WorkSpace
.Db
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
357 GlobalData
.gGlobalDefines
['TARGET'],
358 GlobalData
.gGlobalDefines
['TOOLCHAIN']].PlatformName
359 GenFdsGlobalVariable
.FvDir
= os
.path
.join(GenFdsGlobalVariable
.OutputDirDict
[ArchList
[0]], DataType
.TAB_FV_DIRECTORY
)
360 if not os
.path
.exists(GenFdsGlobalVariable
.FvDir
):
361 os
.makedirs(GenFdsGlobalVariable
.FvDir
)
362 GenFdsGlobalVariable
.FfsDir
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, 'Ffs')
363 if not os
.path
.exists(GenFdsGlobalVariable
.FfsDir
):
364 os
.makedirs(GenFdsGlobalVariable
.FfsDir
)
367 # Create FV Address inf file
369 GenFdsGlobalVariable
.FvAddressFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, 'FvAddress.inf')
370 FvAddressFile
= open(GenFdsGlobalVariable
.FvAddressFileName
, 'w')
374 FvAddressFile
.writelines("[options]" + DataType
.TAB_LINE_BREAK
)
376 for Arch
in ArchList
:
377 BsAddress
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
,
378 GlobalData
.gGlobalDefines
['TARGET'],
379 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].BsBaseAddress
383 FvAddressFile
.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
385 DataType
.TAB_LINE_BREAK
)
388 for Arch
in reversed(ArchList
):
389 temp
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[
390 GenFdsGlobalVariable
.ActivePlatform
, Arch
, GlobalData
.gGlobalDefines
['TARGET'],
391 GlobalData
.gGlobalDefines
["TOOL_CHAIN_TAG"]].RtBaseAddress
396 FvAddressFile
.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
398 DataType
.TAB_LINE_BREAK
)
400 FvAddressFile
.close()
402 ## ReplaceWorkspaceMacro()
404 # @param String String that may contain macro
407 def ReplaceWorkspaceMacro(String
):
408 String
= mws
.handleWsMacro(String
)
409 Str
= String
.replace('$(WORKSPACE)', GenFdsGlobalVariable
.WorkSpaceDir
)
410 if os
.path
.exists(Str
):
411 if not os
.path
.isabs(Str
):
412 Str
= os
.path
.abspath(Str
)
414 Str
= mws
.join(GenFdsGlobalVariable
.WorkSpaceDir
, String
)
415 return os
.path
.normpath(Str
)
417 ## Check if the input files are newer than output files
419 # @param Output Path of output file
420 # @param Input Path list of input files
422 # @retval True if Output doesn't exist, or any Input is newer
423 # @retval False if all Input is older than Output
426 def NeedsUpdate(Output
, Input
):
427 if not os
.path
.exists(Output
):
429 # always update "Output" if no "Input" given
433 # if fdf file is changed after the 'Output" is generated, update the 'Output'
434 OutputTime
= os
.path
.getmtime(Output
)
435 if GenFdsGlobalVariable
.FdfFileTimeStamp
> OutputTime
:
439 # always update "Output" if any "Input" doesn't exist
440 if not os
.path
.exists(F
):
442 # always update "Output" if any "Input" is newer than "Output"
443 if os
.path
.getmtime(F
) > OutputTime
:
448 def GenerateSection(Output
, Input
, Type
=None, CompressionType
=None, Guid
=None,
449 GuidHdrLen
=None, GuidAttr
=[], Ui
=None, Ver
=None, InputAlign
=[], BuildNumber
=None, DummyFile
=None, IsMakefile
=False):
454 Cmd
+= ("-c", CompressionType
)
458 Cmd
+= ("--dummy", DummyFile
)
460 Cmd
+= ("-l", GuidHdrLen
)
461 #Add each guided attribute
462 for Attr
in GuidAttr
:
464 #Section Align is only for dummy section without section type
465 for SecAlign
in InputAlign
:
466 Cmd
+= ("--sectionalign", SecAlign
)
468 CommandFile
= Output
+ '.txt'
471 if Ui
== "$(MODULE_NAME)":
474 Cmd
+= ("-n", '"' + Ui
+ '"')
475 Cmd
+= ("-o", Output
)
476 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
477 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
479 SectionData
= array('B', [0, 0, 0, 0])
480 SectionData
.fromstring(Ui
.encode("utf_16_le"))
481 SectionData
.append(0)
482 SectionData
.append(0)
483 Len
= len(SectionData
)
484 GenFdsGlobalVariable
.SectionHeader
.pack_into(SectionData
, 0, Len
& 0xff, (Len
>> 8) & 0xff, (Len
>> 16) & 0xff, 0x15)
485 SaveFileOnChange(Output
, SectionData
.tostring())
490 Cmd
+= ("-j", BuildNumber
)
491 Cmd
+= ("-o", Output
)
493 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
495 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
496 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
498 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
500 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
502 Cmd
+= ("-o", Output
)
505 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
507 if ' '.join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
508 GenFdsGlobalVariable
.SecCmdList
.append(' '.join(Cmd
).strip())
509 elif GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
510 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
511 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate section")
512 if (os
.path
.getsize(Output
) >= GenFdsGlobalVariable
.LARGE_FILE_SIZE
and
513 GenFdsGlobalVariable
.LargeFileInFvFlags
):
514 GenFdsGlobalVariable
.LargeFileInFvFlags
[-1] = True
517 def GetAlignment (AlignString
):
520 if AlignString
.endswith('K'):
521 return int (AlignString
.rstrip('K')) * 1024
522 if AlignString
.endswith('M'):
523 return int (AlignString
.rstrip('M')) * 1024 * 1024
524 if AlignString
.endswith('G'):
525 return int (AlignString
.rstrip('G')) * 1024 * 1024 * 1024
526 return int (AlignString
)
529 def GenerateFfs(Output
, Input
, Type
, Guid
, Fixed
=False, CheckSum
=False, Align
=None,
530 SectionAlign
=None, MakefilePath
=None):
531 Cmd
= ["GenFfs", "-t", Type
, "-g", Guid
]
532 mFfsValidAlign
= ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
538 if Align
not in mFfsValidAlign
:
539 Align
= GenFdsGlobalVariable
.GetAlignment (Align
)
540 for index
in range(0, len(mFfsValidAlign
) - 1):
541 if ((Align
> GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
])) and (Align
<= GenFdsGlobalVariable
.GetAlignment(mFfsValidAlign
[index
+ 1]))):
543 Align
= mFfsValidAlign
[index
+ 1]
546 Cmd
+= ("-o", Output
)
547 for I
in range(0, len(Input
)):
548 Cmd
+= ("-i", Input
[I
])
549 if SectionAlign
and SectionAlign
[I
]:
550 Cmd
+= ("-n", SectionAlign
[I
])
552 CommandFile
= Output
+ '.txt'
553 SaveFileOnChange(CommandFile
, ' '.join(Cmd
), False)
555 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
557 if (tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)) not in GenFdsGlobalVariable
.FfsCmdDict
:
558 GenFdsGlobalVariable
.FfsCmdDict
[tuple(Cmd
), tuple(GenFdsGlobalVariable
.SecCmdList
), tuple(GenFdsGlobalVariable
.CopyList
)] = MakefilePath
559 GenFdsGlobalVariable
.SecCmdList
= []
560 GenFdsGlobalVariable
.CopyList
= []
562 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, list(Input
) + [CommandFile
]):
564 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FFS")
567 def GenerateFirmwareVolume(Output
, Input
, BaseAddress
=None, ForceRebase
=None, Capsule
=False, Dump
=False,
568 AddressFile
=None, MapFile
=None, FfsList
=[], FileSystemGuid
=None):
569 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
+FfsList
):
571 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
575 Cmd
+= ("-r", BaseAddress
)
577 if ForceRebase
== False:
578 Cmd
+= ("-F", "FALSE")
579 elif ForceRebase
== True:
580 Cmd
+= ("-F", "TRUE")
587 Cmd
+= ("-a", AddressFile
)
589 Cmd
+= ("-m", MapFile
)
591 Cmd
+= ("-g", FileSystemGuid
)
592 Cmd
+= ("-o", Output
)
596 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate FV")
599 def GenerateFirmwareImage(Output
, Input
, Type
="efi", SubType
=None, Zero
=False,
600 Strip
=False, Replace
=False, TimeStamp
=None, Join
=False,
601 Align
=None, Padding
=None, Convert
=False, IsMakefile
=False):
602 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
604 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
607 if Type
.lower() == "te":
610 Cmd
+= ("-e", SubType
)
612 Cmd
+= ("-s", TimeStamp
)
616 Cmd
+= ("-p", Padding
)
627 Cmd
+= ("-o", Output
)
630 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
631 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
633 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate firmware image")
636 def GenerateOptionRom(Output
, EfiInput
, BinaryInput
, Compress
=False, ClassCode
=None,
637 Revision
=None, DeviceId
=None, VendorId
=None, IsMakefile
=False):
647 for EfiFile
in EfiInput
:
649 InputList
.append (EfiFile
)
653 for BinFile
in BinaryInput
:
655 InputList
.append (BinFile
)
658 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, InputList
) and not IsMakefile
:
660 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, InputList
))
663 Cmd
+= ("-l", ClassCode
)
665 Cmd
+= ("-r", Revision
)
667 Cmd
+= ("-i", DeviceId
)
669 Cmd
+= ("-f", VendorId
)
671 Cmd
+= ("-o", Output
)
673 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
674 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
676 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to generate option rom")
679 def GuidTool(Output
, Input
, ToolPath
, Options
='', returnValue
=[], IsMakefile
=False):
680 if not GenFdsGlobalVariable
.NeedsUpdate(Output
, Input
) and not IsMakefile
:
682 GenFdsGlobalVariable
.DebugLogger(EdkLogger
.DEBUG_5
, "%s needs update because of newer %s" % (Output
, Input
))
685 Cmd
+= Options
.split(' ')
686 Cmd
+= ("-o", Output
)
689 if " ".join(Cmd
).strip() not in GenFdsGlobalVariable
.SecCmdList
:
690 GenFdsGlobalVariable
.SecCmdList
.append(" ".join(Cmd
).strip())
692 GenFdsGlobalVariable
.CallExternalTool(Cmd
, "Failed to call " + ToolPath
, returnValue
)
695 def CallExternalTool (cmd
, errorMess
, returnValue
=[]):
697 if type(cmd
) not in (tuple, list):
698 GenFdsGlobalVariable
.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
700 if GenFdsGlobalVariable
.DebugLevel
!= -1:
701 cmd
+= ('--debug', str(GenFdsGlobalVariable
.DebugLevel
))
702 GenFdsGlobalVariable
.InfLogger (cmd
)
704 if GenFdsGlobalVariable
.VerboseMode
:
706 GenFdsGlobalVariable
.InfLogger (cmd
)
710 GenFdsGlobalVariable
.SharpCounter
= GenFdsGlobalVariable
.SharpCounter
+ 1
711 if GenFdsGlobalVariable
.SharpCounter
% GenFdsGlobalVariable
.SharpNumberPerLine
== 0:
715 PopenObject
= Popen(' '.join(cmd
), stdout
=PIPE
, stderr
=PIPE
, shell
=True)
716 except Exception as X
:
717 EdkLogger
.error("GenFds", COMMAND_FAILURE
, ExtraData
="%s: %s" % (str(X
), cmd
[0]))
718 (out
, error
) = PopenObject
.communicate()
720 while PopenObject
.returncode
is None:
722 if returnValue
!= [] and returnValue
[0] != 0:
723 #get command return value
724 returnValue
[0] = PopenObject
.returncode
726 if PopenObject
.returncode
!= 0 or GenFdsGlobalVariable
.VerboseMode
or GenFdsGlobalVariable
.DebugLevel
!= -1:
727 GenFdsGlobalVariable
.InfLogger ("Return Value = %d" % PopenObject
.returncode
)
728 GenFdsGlobalVariable
.InfLogger (out
)
729 GenFdsGlobalVariable
.InfLogger (error
)
730 if PopenObject
.returncode
!= 0:
732 EdkLogger
.error("GenFds", COMMAND_FAILURE
, errorMess
)
735 def VerboseLogger (msg
):
736 EdkLogger
.verbose(msg
)
743 def ErrorLogger (msg
, File
=None, Line
=None, ExtraData
=None):
744 EdkLogger
.error('GenFds', GENFDS_ERROR
, msg
, File
, Line
, ExtraData
)
747 def DebugLogger (Level
, msg
):
748 EdkLogger
.debug(Level
, msg
)
752 # @param Str String that may contain macro
753 # @param MacroDict Dictionary that contains macro value pair
756 def MacroExtend (Str
, MacroDict
={}, Arch
=DataType
.TAB_COMMON
):
760 Dict
= {'$(WORKSPACE)': GenFdsGlobalVariable
.WorkSpaceDir
,
761 '$(EDK_SOURCE)': GenFdsGlobalVariable
.EdkSourceDir
,
762 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
763 '$(TARGET)': GenFdsGlobalVariable
.TargetName
,
764 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable
.ToolChainTag
,
768 if Arch
!= DataType
.TAB_COMMON
and Arch
in GenFdsGlobalVariable
.ArchList
:
769 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[Arch
]
771 OutputDir
= GenFdsGlobalVariable
.OutputDirFromDscDict
[GenFdsGlobalVariable
.ArchList
[0]]
773 Dict
['$(OUTPUT_DIRECTORY)'] = OutputDir
776 Dict
.update(MacroDict
)
779 if Str
.find(key
) >= 0:
780 Str
= Str
.replace (key
, Dict
[key
])
782 if Str
.find('$(ARCH)') >= 0:
783 if len(GenFdsGlobalVariable
.ArchList
) == 1:
784 Str
= Str
.replace('$(ARCH)', GenFdsGlobalVariable
.ArchList
[0])
786 EdkLogger
.error("GenFds", GENFDS_ERROR
, "No way to determine $(ARCH) for %s" % Str
)
792 # @param PcdPattern pattern that labels a PCD.
795 def GetPcdValue (PcdPattern
):
796 if PcdPattern
is None:
798 PcdPair
= PcdPattern
.lstrip('PCD(').rstrip(')').strip().split('.')
799 TokenSpace
= PcdPair
[0]
800 TokenCName
= PcdPair
[1]
802 for Arch
in GenFdsGlobalVariable
.ArchList
:
803 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
804 PcdDict
= Platform
.Pcds
806 PcdObj
= PcdDict
[Key
]
807 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
808 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
809 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
810 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
811 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
813 return PcdObj
.DefaultValue
815 for Package
in GenFdsGlobalVariable
.WorkSpace
.GetPackageList(GenFdsGlobalVariable
.ActivePlatform
,
817 GenFdsGlobalVariable
.TargetName
,
818 GenFdsGlobalVariable
.ToolChainTag
):
819 PcdDict
= Package
.Pcds
821 PcdObj
= PcdDict
[Key
]
822 if (PcdObj
.TokenCName
== TokenCName
) and (PcdObj
.TokenSpaceGuidCName
== TokenSpace
):
823 if PcdObj
.Type
!= DataType
.TAB_PCDS_FIXED_AT_BUILD
:
824 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not FixedAtBuild type." % PcdPattern
)
825 if PcdObj
.DatumType
!= DataType
.TAB_VOID
:
826 EdkLogger
.error("GenFds", GENFDS_ERROR
, "%s is not VOID* datum type." % PcdPattern
)
828 return PcdObj
.DefaultValue
834 # Find location of tools to process data
836 # @param KeyStringList Filter for inputs of section generation
837 # @param CurrentArchList Arch list
838 # @param NameGuid The Guid name
840 def FindExtendTool(KeyStringList
, CurrentArchList
, NameGuid
):
841 ToolDb
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDatabase
842 # if user not specify filter, try to deduce it from global data.
843 if KeyStringList
is None or KeyStringList
== []:
844 Target
= GenFdsGlobalVariable
.TargetName
845 ToolChain
= GenFdsGlobalVariable
.ToolChainTag
846 if ToolChain
not in ToolDb
['TOOL_CHAIN_TAG']:
847 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain
)
848 KeyStringList
= [Target
+ '_' + ToolChain
+ '_' + CurrentArchList
[0]]
849 for Arch
in CurrentArchList
:
850 if Target
+ '_' + ToolChain
+ '_' + Arch
not in KeyStringList
:
851 KeyStringList
.append(Target
+ '_' + ToolChain
+ '_' + Arch
)
853 if GenFdsGlobalVariable
.GuidToolDefinition
:
854 if NameGuid
in GenFdsGlobalVariable
.GuidToolDefinition
:
855 return GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
]
857 ToolDefinition
= ToolDefDict(GenFdsGlobalVariable
.ConfDir
).ToolsDefTxtDictionary
863 for ToolDef
in ToolDefinition
.items():
864 if NameGuid
.lower() == ToolDef
[1].lower():
865 KeyList
= ToolDef
[0].split('_')
871 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
872 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
873 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
874 ToolPath
= ToolDefinition
.get(ToolPathKey
)
875 ToolOption
= ToolDefinition
.get(ToolOptionKey
)
876 if ToolPathTmp
is None:
877 ToolPathTmp
= ToolPath
879 if ToolPathTmp
!= ToolPath
:
880 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp
, ToolPath
))
883 for Arch
in CurrentArchList
:
884 Platform
= GenFdsGlobalVariable
.WorkSpace
.BuildObject
[GenFdsGlobalVariable
.ActivePlatform
, Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]
885 # key is (ToolChainFamily, ToolChain, CodeBase)
886 for item
in Platform
.BuildOptions
:
887 if '_PATH' in item
[1] or '_FLAGS' in item
[1] or '_GUID' in item
[1]:
888 if not item
[0] or (item
[0] and GenFdsGlobalVariable
.ToolChainFamily
== item
[0]):
889 if item
[1] not in BuildOption
:
890 BuildOption
[item
[1]] = Platform
.BuildOptions
[item
]
892 ToolList
= [DataType
.TAB_TOD_DEFINES_TARGET
, DataType
.TAB_TOD_DEFINES_TOOL_CHAIN_TAG
, DataType
.TAB_TOD_DEFINES_TARGET_ARCH
]
893 for Index
in range(2, -1, -1):
894 for Key
in list(BuildOption
.keys()):
895 List
= Key
.split('_')
896 if List
[Index
] == '*':
897 for String
in ToolDb
[ToolList
[Index
]]:
898 if String
in [Arch
, GenFdsGlobalVariable
.TargetName
, GenFdsGlobalVariable
.ToolChainTag
]:
900 NewKey
= '%s_%s_%s_%s_%s' % tuple(List
)
901 if NewKey
not in BuildOption
:
902 BuildOption
[NewKey
] = BuildOption
[Key
]
905 elif List
[Index
] not in ToolDb
[ToolList
[Index
]]:
909 for Op
in BuildOption
:
910 if NameGuid
== BuildOption
[Op
]:
911 KeyList
= Op
.split('_')
912 Key
= KeyList
[0] + '_' + KeyList
[1] +'_' + KeyList
[2]
913 if Key
in KeyStringList
and KeyList
[4] == DataType
.TAB_GUID
:
914 ToolPathKey
= Key
+ '_' + KeyList
[3] + '_PATH'
915 ToolOptionKey
= Key
+ '_' + KeyList
[3] + '_FLAGS'
916 if ToolPathKey
in BuildOption
:
917 ToolPathTmp
= BuildOption
[ToolPathKey
]
918 if ToolOptionKey
in BuildOption
:
919 ToolOption
= BuildOption
[ToolOptionKey
]
921 GenFdsGlobalVariable
.GuidToolDefinition
[NameGuid
] = (ToolPathTmp
, ToolOption
)
922 return ToolPathTmp
, ToolOption