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