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