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