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