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