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