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