]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / GenFdsGlobalVariable.py
1 ## @file
2 # Global variables for GenFds
3 #
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ##
10 # Import Modules
11 #
12 from __future__ import print_function
13 from __future__ import absolute_import
14
15 import Common.LongFilePathOs as os
16 from sys import stdout
17 from subprocess import PIPE,Popen
18 from struct import Struct
19 from array import array
20
21 from Common.BuildToolError import COMMAND_FAILURE,GENFDS_ERROR
22 from Common import EdkLogger
23 from Common.Misc import SaveFileOnChange
24
25 from Common.TargetTxtClassObject import TargetTxtClassObject
26 from Common.ToolDefClassObject import ToolDefClassObject, ToolDefDict
27 from AutoGen.BuildEngine import BuildRule
28 import Common.DataType as DataType
29 from Common.Misc import PathClass
30 from Common.LongFilePathSupport import OpenLongFilePath as open
31 from Common.MultipleWorkspace import MultipleWorkspace as mws
32
33 ## Global variables
34 #
35 #
36 class GenFdsGlobalVariable:
37 FvDir = ''
38 OutputDirDict = {}
39 BinDir = ''
40 # will be FvDir + os.sep + 'Ffs'
41 FfsDir = ''
42 FdfParser = None
43 LibDir = ''
44 WorkSpace = None
45 WorkSpaceDir = ''
46 ConfDir = ''
47 OutputDirFromDscDict = {}
48 TargetName = ''
49 ToolChainTag = ''
50 RuleDict = {}
51 ArchList = None
52 ActivePlatform = None
53 FvAddressFileName = ''
54 VerboseMode = False
55 DebugLevel = -1
56 SharpCounter = 0
57 SharpNumberPerLine = 40
58 FdfFile = ''
59 FdfFileTimeStamp = 0
60 FixedLoadAddress = False
61 PlatformName = ''
62
63 BuildRuleFamily = DataType.TAB_COMPILER_MSFT
64 ToolChainFamily = DataType.TAB_COMPILER_MSFT
65 __BuildRuleDatabase = None
66 GuidToolDefinition = {}
67 FfsCmdDict = {}
68 SecCmdList = []
69 CopyList = []
70 ModuleFile = ''
71 EnableGenfdsMultiThread = False
72
73 #
74 # The list whose element are flags to indicate if large FFS or SECTION files exist in FV.
75 # At the beginning of each generation of FV, false flag is appended to the list,
76 # after the call to GenerateSection returns, check the size of the output file,
77 # if it is greater than 0xFFFFFF, the tail flag in list is set to true,
78 # and EFI_FIRMWARE_FILE_SYSTEM3_GUID is passed to C GenFv.
79 # At the end of generation of FV, pop the flag.
80 # List is used as a stack to handle nested FV generation.
81 #
82 LargeFileInFvFlags = []
83 EFI_FIRMWARE_FILE_SYSTEM3_GUID = '5473C07A-3DCB-4dca-BD6F-1E9689E7349A'
84 LARGE_FILE_SIZE = 0x1000000
85
86 SectionHeader = Struct("3B 1B")
87
88 # FvName, FdName, CapName in FDF, Image file name
89 ImageBinDict = {}
90
91 ## LoadBuildRule
92 #
93 @staticmethod
94 def _LoadBuildRule():
95 if GenFdsGlobalVariable.__BuildRuleDatabase:
96 return GenFdsGlobalVariable.__BuildRuleDatabase
97 BuildConfigurationFile = os.path.normpath(os.path.join(GenFdsGlobalVariable.ConfDir, "target.txt"))
98 TargetTxt = TargetTxtClassObject()
99 if os.path.isfile(BuildConfigurationFile) == True:
100 TargetTxt.LoadTargetTxtFile(BuildConfigurationFile)
101 if DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF in TargetTxt.TargetTxtDictionary:
102 BuildRuleFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_BUILD_RULE_CONF]
103 if not BuildRuleFile:
104 BuildRuleFile = 'Conf/build_rule.txt'
105 GenFdsGlobalVariable.__BuildRuleDatabase = BuildRule(BuildRuleFile)
106 ToolDefinitionFile = TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
107 if ToolDefinitionFile == '':
108 ToolDefinitionFile = "Conf/tools_def.txt"
109 if os.path.isfile(ToolDefinitionFile):
110 ToolDef = ToolDefClassObject()
111 ToolDef.LoadToolDefFile(ToolDefinitionFile)
112 ToolDefinition = ToolDef.ToolsDefTxtDatabase
113 if DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDefinition \
114 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY] \
115 and ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]:
116 GenFdsGlobalVariable.BuildRuleFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_BUILDRULEFAMILY][GenFdsGlobalVariable.ToolChainTag]
117
118 if DataType.TAB_TOD_DEFINES_FAMILY in ToolDefinition \
119 and GenFdsGlobalVariable.ToolChainTag in ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY] \
120 and ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]:
121 GenFdsGlobalVariable.ToolChainFamily = ToolDefinition[DataType.TAB_TOD_DEFINES_FAMILY][GenFdsGlobalVariable.ToolChainTag]
122 return GenFdsGlobalVariable.__BuildRuleDatabase
123
124 ## GetBuildRules
125 # @param Inf: object of InfBuildData
126 # @param Arch: current arch
127 #
128 @staticmethod
129 def GetBuildRules(Inf, Arch):
130 if not Arch:
131 Arch = DataType.TAB_COMMON
132
133 if not Arch in GenFdsGlobalVariable.OutputDirDict:
134 return {}
135
136 BuildRuleDatabase = GenFdsGlobalVariable._LoadBuildRule()
137 if not BuildRuleDatabase:
138 return {}
139
140 PathClassObj = PathClass(Inf.MetaFile.File,
141 GenFdsGlobalVariable.WorkSpaceDir)
142 BuildDir = os.path.join(
143 GenFdsGlobalVariable.OutputDirDict[Arch],
144 Arch,
145 PathClassObj.SubDir,
146 PathClassObj.BaseName
147 )
148 BinDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
149 Macro = {
150 "WORKSPACE":GenFdsGlobalVariable.WorkSpaceDir,
151 "MODULE_NAME":Inf.BaseName,
152 "MODULE_GUID":Inf.Guid,
153 "MODULE_VERSION":Inf.Version,
154 "MODULE_TYPE":Inf.ModuleType,
155 "MODULE_FILE":str(PathClassObj),
156 "MODULE_FILE_BASE_NAME":PathClassObj.BaseName,
157 "MODULE_RELATIVE_DIR":PathClassObj.SubDir,
158 "MODULE_DIR":PathClassObj.SubDir,
159 "BASE_NAME":Inf.BaseName,
160 "ARCH":Arch,
161 "TOOLCHAIN":GenFdsGlobalVariable.ToolChainTag,
162 "TOOLCHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
163 "TOOL_CHAIN_TAG":GenFdsGlobalVariable.ToolChainTag,
164 "TARGET":GenFdsGlobalVariable.TargetName,
165 "BUILD_DIR":GenFdsGlobalVariable.OutputDirDict[Arch],
166 "BIN_DIR":BinDir,
167 "LIB_DIR":BinDir,
168 "MODULE_BUILD_DIR":BuildDir,
169 "OUTPUT_DIR":os.path.join(BuildDir, "OUTPUT"),
170 "DEBUG_DIR":os.path.join(BuildDir, "DEBUG")
171 }
172
173 BuildRules = {}
174 for Type in BuildRuleDatabase.FileTypeList:
175 #first try getting build rule by BuildRuleFamily
176 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
177 if not RuleObject:
178 # build type is always module type, but ...
179 if Inf.ModuleType != Inf.BuildType:
180 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.BuildRuleFamily]
181 #second try getting build rule by ToolChainFamily
182 if not RuleObject:
183 RuleObject = BuildRuleDatabase[Type, Inf.BuildType, Arch, GenFdsGlobalVariable.ToolChainFamily]
184 if not RuleObject:
185 # build type is always module type, but ...
186 if Inf.ModuleType != Inf.BuildType:
187 RuleObject = BuildRuleDatabase[Type, Inf.ModuleType, Arch, GenFdsGlobalVariable.ToolChainFamily]
188 if not RuleObject:
189 continue
190 RuleObject = RuleObject.Instantiate(Macro)
191 BuildRules[Type] = RuleObject
192 for Ext in RuleObject.SourceFileExtList:
193 BuildRules[Ext] = RuleObject
194 return BuildRules
195
196 ## GetModuleCodaTargetList
197 #
198 # @param Inf: object of InfBuildData
199 # @param Arch: current arch
200 #
201 @staticmethod
202 def GetModuleCodaTargetList(Inf, Arch):
203 BuildRules = GenFdsGlobalVariable.GetBuildRules(Inf, Arch)
204 if not BuildRules:
205 return []
206
207 TargetList = set()
208 FileList = []
209
210 if not Inf.IsBinaryModule:
211 for File in Inf.Sources:
212 if File.TagName in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainTag} and \
213 File.ToolChainFamily in {"", DataType.TAB_STAR, GenFdsGlobalVariable.ToolChainFamily}:
214 FileList.append((File, DataType.TAB_UNKNOWN_FILE))
215
216 for File in Inf.Binaries:
217 if File.Target in {DataType.TAB_COMMON, DataType.TAB_STAR, GenFdsGlobalVariable.TargetName}:
218 FileList.append((File, File.Type))
219
220 for File, FileType in FileList:
221 LastTarget = None
222 RuleChain = []
223 SourceList = [File]
224 Index = 0
225 while Index < len(SourceList):
226 Source = SourceList[Index]
227 Index = Index + 1
228
229 if File.IsBinary and File == Source and Inf.Binaries and File in Inf.Binaries:
230 # Skip all files that are not binary libraries
231 if not Inf.LibraryClass:
232 continue
233 RuleObject = BuildRules[DataType.TAB_DEFAULT_BINARY_FILE]
234 elif FileType in BuildRules:
235 RuleObject = BuildRules[FileType]
236 elif Source.Ext in BuildRules:
237 RuleObject = BuildRules[Source.Ext]
238 else:
239 # stop at no more rules
240 if LastTarget:
241 TargetList.add(str(LastTarget))
242 break
243
244 FileType = RuleObject.SourceFileType
245
246 # stop at STATIC_LIBRARY for library
247 if Inf.LibraryClass and FileType == DataType.TAB_STATIC_LIBRARY:
248 if LastTarget:
249 TargetList.add(str(LastTarget))
250 break
251
252 Target = RuleObject.Apply(Source)
253 if not Target:
254 if LastTarget:
255 TargetList.add(str(LastTarget))
256 break
257 elif not Target.Outputs:
258 # Only do build for target with outputs
259 TargetList.add(str(Target))
260
261 # to avoid cyclic rule
262 if FileType in RuleChain:
263 break
264
265 RuleChain.append(FileType)
266 SourceList.extend(Target.Outputs)
267 LastTarget = Target
268 FileType = DataType.TAB_UNKNOWN_FILE
269 for Cmd in Target.Commands:
270 if "$(CP)" == Cmd.split()[0]:
271 CpTarget = Cmd.split()[2]
272 TargetList.add(CpTarget)
273
274 return list(TargetList)
275
276 ## SetDir()
277 #
278 # @param OutputDir Output directory
279 # @param FdfParser FDF contents parser
280 # @param Workspace The directory of workspace
281 # @param ArchList The Arch list of platform
282 #
283 @staticmethod
284 def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
285 GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir:%s" % OutputDir)
286 GenFdsGlobalVariable.FdfParser = FdfParser
287 GenFdsGlobalVariable.WorkSpace = WorkSpace
288 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
289 if not os.path.exists(GenFdsGlobalVariable.FvDir):
290 os.makedirs(GenFdsGlobalVariable.FvDir)
291 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
292 if not os.path.exists(GenFdsGlobalVariable.FfsDir):
293 os.makedirs(GenFdsGlobalVariable.FfsDir)
294
295 #
296 # Create FV Address inf file
297 #
298 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
299 FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
300 #
301 # Add [Options]
302 #
303 FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
304 BsAddress = '0'
305 for Arch in ArchList:
306 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress:
307 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].BsBaseAddress
308 break
309
310 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
311 BsAddress + \
312 DataType.TAB_LINE_BREAK)
313
314 RtAddress = '0'
315 for Arch in reversed(ArchList):
316 temp = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
317 if temp:
318 RtAddress = temp
319 break
320
321 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
322 RtAddress + \
323 DataType.TAB_LINE_BREAK)
324
325 FvAddressFile.close()
326
327 @staticmethod
328 def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData):
329 GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile
330 GenFdsGlobalVariable.FdfParser = FdfParser
331 GenFdsGlobalVariable.WorkSpace = WorkSpace.Db
332 GenFdsGlobalVariable.ArchList = ArchList
333 GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]
334 GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"]
335 GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform
336 GenFdsGlobalVariable.ConfDir = GlobalData.gConfDirectory
337 GenFdsGlobalVariable.EnableGenfdsMultiThread = GlobalData.gEnableGenfdsMultiThread
338 for Arch in ArchList:
339 GenFdsGlobalVariable.OutputDirDict[Arch] = os.path.normpath(
340 os.path.join(GlobalData.gWorkspace,
341 WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
342 GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory,
343 GlobalData.gGlobalDefines['TARGET'] +'_' + GlobalData.gGlobalDefines['TOOLCHAIN']))
344 GenFdsGlobalVariable.OutputDirFromDscDict[Arch] = os.path.normpath(
345 WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
346 GlobalData.gGlobalDefines['TARGET'], GlobalData.gGlobalDefines['TOOLCHAIN']].OutputDirectory)
347 GenFdsGlobalVariable.PlatformName = WorkSpace.Db.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
348 GlobalData.gGlobalDefines['TARGET'],
349 GlobalData.gGlobalDefines['TOOLCHAIN']].PlatformName
350 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], DataType.TAB_FV_DIRECTORY)
351 if not os.path.exists(GenFdsGlobalVariable.FvDir):
352 os.makedirs(GenFdsGlobalVariable.FvDir)
353 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
354 if not os.path.exists(GenFdsGlobalVariable.FfsDir):
355 os.makedirs(GenFdsGlobalVariable.FfsDir)
356
357 #
358 # Create FV Address inf file
359 #
360 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
361 FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
362 #
363 # Add [Options]
364 #
365 FvAddressFile.writelines("[options]" + DataType.TAB_LINE_BREAK)
366 BsAddress = '0'
367 for Arch in ArchList:
368 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
369 GlobalData.gGlobalDefines['TARGET'],
370 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress
371 if BsAddress:
372 break
373
374 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
375 BsAddress + \
376 DataType.TAB_LINE_BREAK)
377
378 RtAddress = '0'
379 for Arch in reversed(ArchList):
380 temp = GenFdsGlobalVariable.WorkSpace.BuildObject[
381 GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
382 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress
383 if temp:
384 RtAddress = temp
385 break
386
387 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
388 RtAddress + \
389 DataType.TAB_LINE_BREAK)
390
391 FvAddressFile.close()
392
393 ## ReplaceWorkspaceMacro()
394 #
395 # @param String String that may contain macro
396 #
397 @staticmethod
398 def ReplaceWorkspaceMacro(String):
399 String = mws.handleWsMacro(String)
400 Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
401 if os.path.exists(Str):
402 if not os.path.isabs(Str):
403 Str = os.path.abspath(Str)
404 else:
405 Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String)
406 return os.path.normpath(Str)
407
408 ## Check if the input files are newer than output files
409 #
410 # @param Output Path of output file
411 # @param Input Path list of input files
412 #
413 # @retval True if Output doesn't exist, or any Input is newer
414 # @retval False if all Input is older than Output
415 #
416 @staticmethod
417 def NeedsUpdate(Output, Input):
418 if not os.path.exists(Output):
419 return True
420 # always update "Output" if no "Input" given
421 if not Input:
422 return True
423
424 # if fdf file is changed after the 'Output" is generated, update the 'Output'
425 OutputTime = os.path.getmtime(Output)
426 if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime:
427 return True
428
429 for F in Input:
430 # always update "Output" if any "Input" doesn't exist
431 if not os.path.exists(F):
432 return True
433 # always update "Output" if any "Input" is newer than "Output"
434 if os.path.getmtime(F) > OutputTime:
435 return True
436 return False
437
438 @staticmethod
439 def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
440 GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=[], BuildNumber=None, DummyFile=None, IsMakefile=False):
441 Cmd = ["GenSec"]
442 if Type:
443 Cmd += ("-s", Type)
444 if CompressionType:
445 Cmd += ("-c", CompressionType)
446 if Guid:
447 Cmd += ("-g", Guid)
448 if DummyFile:
449 Cmd += ("--dummy", DummyFile)
450 if GuidHdrLen:
451 Cmd += ("-l", GuidHdrLen)
452 #Add each guided attribute
453 for Attr in GuidAttr:
454 Cmd += ("-r", Attr)
455 #Section Align is only for dummy section without section type
456 for SecAlign in InputAlign:
457 Cmd += ("--sectionalign", SecAlign)
458
459 CommandFile = Output + '.txt'
460 if Ui:
461 if IsMakefile:
462 if Ui == "$(MODULE_NAME)":
463 Cmd += ('-n', Ui)
464 else:
465 Cmd += ("-n", '"' + Ui + '"')
466 Cmd += ("-o", Output)
467 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
468 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
469 else:
470 SectionData = array('B', [0, 0, 0, 0])
471 SectionData.fromstring(Ui.encode("utf_16_le"))
472 SectionData.append(0)
473 SectionData.append(0)
474 Len = len(SectionData)
475 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
476 SaveFileOnChange(Output, SectionData.tostring())
477
478 elif Ver:
479 Cmd += ("-n", Ver)
480 if BuildNumber:
481 Cmd += ("-j", BuildNumber)
482 Cmd += ("-o", Output)
483
484 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
485 if IsMakefile:
486 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
487 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
488 else:
489 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
490 return
491 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
492 else:
493 Cmd += ("-o", Output)
494 Cmd += Input
495
496 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
497 if IsMakefile:
498 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
499 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
500 elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
501 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
502 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
503 if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and
504 GenFdsGlobalVariable.LargeFileInFvFlags):
505 GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True
506
507 @staticmethod
508 def GetAlignment (AlignString):
509 if not AlignString:
510 return 0
511 if AlignString.endswith('K'):
512 return int (AlignString.rstrip('K')) * 1024
513 if AlignString.endswith('M'):
514 return int (AlignString.rstrip('M')) * 1024 * 1024
515 if AlignString.endswith('G'):
516 return int (AlignString.rstrip('G')) * 1024 * 1024 * 1024
517 return int (AlignString)
518
519 @staticmethod
520 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
521 SectionAlign=None, MakefilePath=None):
522 Cmd = ["GenFfs", "-t", Type, "-g", Guid]
523 mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
524 if Fixed == True:
525 Cmd.append("-x")
526 if CheckSum:
527 Cmd.append("-s")
528 if Align:
529 if Align not in mFfsValidAlign:
530 Align = GenFdsGlobalVariable.GetAlignment (Align)
531 for index in range(0, len(mFfsValidAlign) - 1):
532 if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))):
533 break
534 Align = mFfsValidAlign[index + 1]
535 Cmd += ("-a", Align)
536
537 Cmd += ("-o", Output)
538 for I in range(0, len(Input)):
539 Cmd += ("-i", Input[I])
540 if SectionAlign and SectionAlign[I]:
541 Cmd += ("-n", SectionAlign[I])
542
543 CommandFile = Output + '.txt'
544 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
545
546 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
547 if MakefilePath:
548 if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict:
549 GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath
550 GenFdsGlobalVariable.SecCmdList = []
551 GenFdsGlobalVariable.CopyList = []
552 else:
553 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
554 return
555 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
556
557 @staticmethod
558 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
559 AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
560 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
561 return
562 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
563
564 Cmd = ["GenFv"]
565 if BaseAddress:
566 Cmd += ("-r", BaseAddress)
567
568 if ForceRebase == False:
569 Cmd += ("-F", "FALSE")
570 elif ForceRebase == True:
571 Cmd += ("-F", "TRUE")
572
573 if Capsule:
574 Cmd.append("-c")
575 if Dump:
576 Cmd.append("-p")
577 if AddressFile:
578 Cmd += ("-a", AddressFile)
579 if MapFile:
580 Cmd += ("-m", MapFile)
581 if FileSystemGuid:
582 Cmd += ("-g", FileSystemGuid)
583 Cmd += ("-o", Output)
584 for I in Input:
585 Cmd += ("-i", I)
586
587 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
588
589 @staticmethod
590 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
591 Strip=False, Replace=False, TimeStamp=None, Join=False,
592 Align=None, Padding=None, Convert=False, IsMakefile=False):
593 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
594 return
595 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
596
597 Cmd = ["GenFw"]
598 if Type.lower() == "te":
599 Cmd.append("-t")
600 if SubType:
601 Cmd += ("-e", SubType)
602 if TimeStamp:
603 Cmd += ("-s", TimeStamp)
604 if Align:
605 Cmd += ("-a", Align)
606 if Padding:
607 Cmd += ("-p", Padding)
608 if Zero:
609 Cmd.append("-z")
610 if Strip:
611 Cmd.append("-l")
612 if Replace:
613 Cmd.append("-r")
614 if Join:
615 Cmd.append("-j")
616 if Convert:
617 Cmd.append("-m")
618 Cmd += ("-o", Output)
619 Cmd += Input
620 if IsMakefile:
621 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
622 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
623 else:
624 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
625
626 @staticmethod
627 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
628 Revision=None, DeviceId=None, VendorId=None, IsMakefile=False):
629 InputList = []
630 Cmd = ["EfiRom"]
631 if EfiInput:
632
633 if Compress:
634 Cmd.append("-ec")
635 else:
636 Cmd.append("-e")
637
638 for EfiFile in EfiInput:
639 Cmd.append(EfiFile)
640 InputList.append (EfiFile)
641
642 if BinaryInput:
643 Cmd.append("-b")
644 for BinFile in BinaryInput:
645 Cmd.append(BinFile)
646 InputList.append (BinFile)
647
648 # Check List
649 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile:
650 return
651 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
652
653 if ClassCode:
654 Cmd += ("-l", ClassCode)
655 if Revision:
656 Cmd += ("-r", Revision)
657 if DeviceId:
658 Cmd += ("-i", DeviceId)
659 if VendorId:
660 Cmd += ("-f", VendorId)
661
662 Cmd += ("-o", Output)
663 if IsMakefile:
664 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
665 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
666 else:
667 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
668
669 @staticmethod
670 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False):
671 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
672 return
673 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
674
675 Cmd = [ToolPath, ]
676 Cmd += Options.split(' ')
677 Cmd += ("-o", Output)
678 Cmd += Input
679 if IsMakefile:
680 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
681 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
682 else:
683 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
684
685 @staticmethod
686 def CallExternalTool (cmd, errorMess, returnValue=[]):
687
688 if type(cmd) not in (tuple, list):
689 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
690
691 if GenFdsGlobalVariable.DebugLevel != -1:
692 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
693 GenFdsGlobalVariable.InfLogger (cmd)
694
695 if GenFdsGlobalVariable.VerboseMode:
696 cmd += ('-v',)
697 GenFdsGlobalVariable.InfLogger (cmd)
698 else:
699 stdout.write ('#')
700 stdout.flush()
701 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
702 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
703 stdout.write('\n')
704
705 try:
706 PopenObject = Popen(' '.join(cmd), stdout=PIPE, stderr=PIPE, shell=True)
707 except Exception as X:
708 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
709 (out, error) = PopenObject.communicate()
710
711 while PopenObject.returncode is None:
712 PopenObject.wait()
713 if returnValue != [] and returnValue[0] != 0:
714 #get command return value
715 returnValue[0] = PopenObject.returncode
716 return
717 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
718 GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
719 GenFdsGlobalVariable.InfLogger(out.decode(encoding='utf-8', errors='ignore'))
720 GenFdsGlobalVariable.InfLogger(error.decode(encoding='utf-8', errors='ignore'))
721 if PopenObject.returncode != 0:
722 print("###", cmd)
723 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
724
725 @staticmethod
726 def VerboseLogger (msg):
727 EdkLogger.verbose(msg)
728
729 @staticmethod
730 def InfLogger (msg):
731 EdkLogger.info(msg)
732
733 @staticmethod
734 def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
735 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
736
737 @staticmethod
738 def DebugLogger (Level, msg):
739 EdkLogger.debug(Level, msg)
740
741 ## MacroExtend()
742 #
743 # @param Str String that may contain macro
744 # @param MacroDict Dictionary that contains macro value pair
745 #
746 @staticmethod
747 def MacroExtend (Str, MacroDict={}, Arch=DataType.TAB_COMMON):
748 if Str is None:
749 return None
750
751 Dict = {'$(WORKSPACE)': GenFdsGlobalVariable.WorkSpaceDir,
752 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
753 '$(TARGET)': GenFdsGlobalVariable.TargetName,
754 '$(TOOL_CHAIN_TAG)': GenFdsGlobalVariable.ToolChainTag,
755 '$(SPACE)': ' '
756 }
757
758 if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList:
759 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
760 else:
761 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
762
763 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
764
765 if MacroDict:
766 Dict.update(MacroDict)
767
768 for key in Dict:
769 if Str.find(key) >= 0:
770 Str = Str.replace (key, Dict[key])
771
772 if Str.find('$(ARCH)') >= 0:
773 if len(GenFdsGlobalVariable.ArchList) == 1:
774 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
775 else:
776 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
777
778 return Str
779
780 ## GetPcdValue()
781 #
782 # @param PcdPattern pattern that labels a PCD.
783 #
784 @staticmethod
785 def GetPcdValue (PcdPattern):
786 if PcdPattern is None:
787 return None
788 PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.')
789 TokenSpace = PcdPair[0]
790 TokenCName = PcdPair[1]
791
792 for Arch in GenFdsGlobalVariable.ArchList:
793 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
794 PcdDict = Platform.Pcds
795 for Key in PcdDict:
796 PcdObj = PcdDict[Key]
797 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
798 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
799 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
800 if PcdObj.DatumType != DataType.TAB_VOID:
801 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
802
803 return PcdObj.DefaultValue
804
805 for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
806 Arch,
807 GenFdsGlobalVariable.TargetName,
808 GenFdsGlobalVariable.ToolChainTag):
809 PcdDict = Package.Pcds
810 for Key in PcdDict:
811 PcdObj = PcdDict[Key]
812 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
813 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
814 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
815 if PcdObj.DatumType != DataType.TAB_VOID:
816 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
817
818 return PcdObj.DefaultValue
819
820 return ''
821
822 ## FindExtendTool()
823 #
824 # Find location of tools to process data
825 #
826 # @param KeyStringList Filter for inputs of section generation
827 # @param CurrentArchList Arch list
828 # @param NameGuid The Guid name
829 #
830 def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
831 ToolDb = ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
832 # if user not specify filter, try to deduce it from global data.
833 if KeyStringList is None or KeyStringList == []:
834 Target = GenFdsGlobalVariable.TargetName
835 ToolChain = GenFdsGlobalVariable.ToolChainTag
836 if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
837 EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
838 KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
839 for Arch in CurrentArchList:
840 if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
841 KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
842
843 if GenFdsGlobalVariable.GuidToolDefinition:
844 if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
845 return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
846
847 ToolDefinition = ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
848 ToolPathTmp = None
849 ToolOption = None
850 ToolPathKey = None
851 ToolOptionKey = None
852 KeyList = None
853 for ToolDef in ToolDefinition.items():
854 if NameGuid.lower() == ToolDef[1].lower():
855 KeyList = ToolDef[0].split('_')
856 Key = KeyList[0] + \
857 '_' + \
858 KeyList[1] + \
859 '_' + \
860 KeyList[2]
861 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
862 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
863 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
864 ToolPath = ToolDefinition.get(ToolPathKey)
865 ToolOption = ToolDefinition.get(ToolOptionKey)
866 if ToolPathTmp is None:
867 ToolPathTmp = ToolPath
868 else:
869 if ToolPathTmp != ToolPath:
870 EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
871
872 BuildOption = {}
873 for Arch in CurrentArchList:
874 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
875 # key is (ToolChainFamily, ToolChain, CodeBase)
876 for item in Platform.BuildOptions:
877 if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]:
878 if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]):
879 if item[1] not in BuildOption:
880 BuildOption[item[1]] = Platform.BuildOptions[item]
881 if BuildOption:
882 ToolList = [DataType.TAB_TOD_DEFINES_TARGET, DataType.TAB_TOD_DEFINES_TOOL_CHAIN_TAG, DataType.TAB_TOD_DEFINES_TARGET_ARCH]
883 for Index in range(2, -1, -1):
884 for Key in list(BuildOption.keys()):
885 List = Key.split('_')
886 if List[Index] == DataType.TAB_STAR:
887 for String in ToolDb[ToolList[Index]]:
888 if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]:
889 List[Index] = String
890 NewKey = '%s_%s_%s_%s_%s' % tuple(List)
891 if NewKey not in BuildOption:
892 BuildOption[NewKey] = BuildOption[Key]
893 continue
894 del BuildOption[Key]
895 elif List[Index] not in ToolDb[ToolList[Index]]:
896 del BuildOption[Key]
897 if BuildOption:
898 if not KeyList:
899 for Op in BuildOption:
900 if NameGuid == BuildOption[Op]:
901 KeyList = Op.split('_')
902 Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2]
903 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
904 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
905 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
906 if ToolPathKey in BuildOption:
907 ToolPathTmp = BuildOption[ToolPathKey]
908 if ToolOptionKey in BuildOption:
909 ToolOption = BuildOption[ToolOptionKey]
910
911 GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
912 return ToolPathTmp, ToolOption