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