]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
BaseTools: Move ImageBinDict to GenFdsGlobalVariable.py
[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 import Common.LongFilePathOs as os
20 import sys
21 import subprocess
22 import struct
23 import array
24
25 from Common.BuildToolError import *
26 from Common import EdkLogger
27 from Common.Misc import SaveFileOnChange
28
29 from Common.TargetTxtClassObject import TargetTxtClassObject
30 from Common.ToolDefClassObject import ToolDefClassObject, ToolDefDict
31 from AutoGen.BuildEngine import BuildRule
32 import Common.DataType as DataType
33 from Common.Misc import PathClass
34 from Common.LongFilePathSupport import OpenLongFilePath as open
35 from Common.MultipleWorkspace import MultipleWorkspace as mws
36
37 ## Global variables
38 #
39 #
40 class GenFdsGlobalVariable:
41 FvDir = ''
42 OutputDirDict = {}
43 BinDir = ''
44 # will be FvDir + os.sep + 'Ffs'
45 FfsDir = ''
46 FdfParser = None
47 LibDir = ''
48 WorkSpace = None
49 WorkSpaceDir = ''
50 ConfDir = ''
51 EdkSourceDir = ''
52 OutputDirFromDscDict = {}
53 TargetName = ''
54 ToolChainTag = ''
55 RuleDict = {}
56 ArchList = None
57 VtfDict = {}
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 = "MSFT"
70 ToolChainFamily = "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.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 Macro = {}
149 Macro["WORKSPACE" ] = GenFdsGlobalVariable.WorkSpaceDir
150 Macro["MODULE_NAME" ] = Inf.BaseName
151 Macro["MODULE_GUID" ] = Inf.Guid
152 Macro["MODULE_VERSION" ] = Inf.Version
153 Macro["MODULE_TYPE" ] = Inf.ModuleType
154 Macro["MODULE_FILE" ] = str(PathClassObj)
155 Macro["MODULE_FILE_BASE_NAME" ] = PathClassObj.BaseName
156 Macro["MODULE_RELATIVE_DIR" ] = PathClassObj.SubDir
157 Macro["MODULE_DIR" ] = PathClassObj.SubDir
158
159 Macro["BASE_NAME" ] = Inf.BaseName
160
161 Macro["ARCH" ] = Arch
162 Macro["TOOLCHAIN" ] = GenFdsGlobalVariable.ToolChainTag
163 Macro["TOOLCHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag
164 Macro["TOOL_CHAIN_TAG" ] = GenFdsGlobalVariable.ToolChainTag
165 Macro["TARGET" ] = GenFdsGlobalVariable.TargetName
166
167 Macro["BUILD_DIR" ] = GenFdsGlobalVariable.OutputDirDict[Arch]
168 Macro["BIN_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
169 Macro["LIB_DIR" ] = os.path.join(GenFdsGlobalVariable.OutputDirDict[Arch], Arch)
170 BuildDir = os.path.join(
171 GenFdsGlobalVariable.OutputDirDict[Arch],
172 Arch,
173 PathClassObj.SubDir,
174 PathClassObj.BaseName
175 )
176 Macro["MODULE_BUILD_DIR" ] = BuildDir
177 Macro["OUTPUT_DIR" ] = os.path.join(BuildDir, "OUTPUT")
178 Macro["DEBUG_DIR" ] = os.path.join(BuildDir, "DEBUG")
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 ("", "*", GenFdsGlobalVariable.ToolChainTag) and \
220 File.ToolChainFamily in ("", "*", 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, '*', 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 is not None 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 def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
291 GenFdsGlobalVariable.VerboseLogger("GenFdsGlobalVariable.OutputDir :%s" % OutputDir)
292 # GenFdsGlobalVariable.OutputDirDict = 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 T_CHAR_LF = '\n'
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]" + T_CHAR_LF)
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 T_CHAR_LF)
321
322 RtAddress = '0'
323 for Arch in ArchList:
324 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress:
325 RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag].RtBaseAddress
326
327 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
328 RtAddress + \
329 T_CHAR_LF)
330
331 FvAddressFile.close()
332
333 def SetEnv(FdfParser, WorkSpace, ArchList, GlobalData):
334 GenFdsGlobalVariable.ModuleFile = WorkSpace.ModuleFile
335 GenFdsGlobalVariable.FdfParser = FdfParser
336 GenFdsGlobalVariable.WorkSpace = WorkSpace.Db
337 GenFdsGlobalVariable.ArchList = ArchList
338 GenFdsGlobalVariable.ToolChainTag = GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]
339 GenFdsGlobalVariable.TargetName = GlobalData.gGlobalDefines["TARGET"]
340 GenFdsGlobalVariable.ActivePlatform = GlobalData.gActivePlatform
341 GenFdsGlobalVariable.EdkSourceDir = GlobalData.gGlobalDefines["EDK_SOURCE"]
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 T_CHAR_LF = '\n'
364 #
365 # Create FV Address inf file
366 #
367 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
368 FvAddressFile = open(GenFdsGlobalVariable.FvAddressFileName, 'w')
369 #
370 # Add [Options]
371 #
372 FvAddressFile.writelines("[options]" + T_CHAR_LF)
373 BsAddress = '0'
374 for Arch in ArchList:
375 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch,
376 GlobalData.gGlobalDefines['TARGET'],
377 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].BsBaseAddress
378 if BsAddress:
379 break
380
381 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
382 BsAddress + \
383 T_CHAR_LF)
384
385 RtAddress = '0'
386 for Arch in ArchList:
387 if GenFdsGlobalVariable.WorkSpace.BuildObject[
388 GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
389 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress:
390 RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[
391 GenFdsGlobalVariable.ActivePlatform, Arch, GlobalData.gGlobalDefines['TARGET'],
392 GlobalData.gGlobalDefines["TOOL_CHAIN_TAG"]].RtBaseAddress
393
394 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
395 RtAddress + \
396 T_CHAR_LF)
397
398 FvAddressFile.close()
399
400 ## ReplaceWorkspaceMacro()
401 #
402 # @param String String that may contain macro
403 #
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 Input is None or len(Input) == 0:
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 is not None:
453 Cmd += ("-g", Guid)
454 if DummyFile is not None:
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.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 AlignString is None:
516 return 0
517 if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K"):
518 return int (AlignString.rstrip('K')) * 1024
519 elif AlignString in ("1M", "2M", "4M", "8M", "16M"):
520 return int (AlignString.rstrip('M')) * 1024 * 1024
521 else:
522 return int (AlignString)
523
524 @staticmethod
525 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
526 SectionAlign=None, MakefilePath=None):
527 Cmd = ["GenFfs", "-t", Type, "-g", Guid]
528 mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
529 if Fixed == True:
530 Cmd.append("-x")
531 if CheckSum:
532 Cmd.append("-s")
533 if Align:
534 if Align not in mFfsValidAlign:
535 Align = GenFdsGlobalVariable.GetAlignment (Align)
536 for index in range(0, len(mFfsValidAlign) - 1):
537 if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))):
538 break
539 Align = mFfsValidAlign[index + 1]
540 Cmd += ("-a", Align)
541
542 Cmd += ("-o", Output)
543 for I in range(0, len(Input)):
544 Cmd += ("-i", Input[I])
545 if SectionAlign and SectionAlign[I]:
546 Cmd += ("-n", SectionAlign[I])
547
548 CommandFile = Output + '.txt'
549 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
550
551 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
552 if MakefilePath:
553 if (tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict:
554 GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath
555 GenFdsGlobalVariable.SecCmdList = []
556 GenFdsGlobalVariable.CopyList = []
557 else:
558 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
559 return
560 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
561
562 @staticmethod
563 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
564 AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
565 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
566 return
567 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
568
569 Cmd = ["GenFv"]
570 if BaseAddress:
571 Cmd += ("-r", BaseAddress)
572
573 if ForceRebase == False:
574 Cmd += ("-F", "FALSE")
575 elif ForceRebase == True:
576 Cmd += ("-F", "TRUE")
577
578 if Capsule:
579 Cmd.append("-c")
580 if Dump:
581 Cmd.append("-p")
582 if AddressFile:
583 Cmd += ("-a", AddressFile)
584 if MapFile:
585 Cmd += ("-m", MapFile)
586 if FileSystemGuid:
587 Cmd += ("-g", FileSystemGuid)
588 Cmd += ("-o", Output)
589 for I in Input:
590 Cmd += ("-i", I)
591
592 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
593
594 @staticmethod
595 def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None):
596 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
597 return
598 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
599
600 Cmd = ["GenVtf"]
601 if BaseAddress and FvSize \
602 and len(BaseAddress) == len(FvSize):
603 for I in range(0, len(BaseAddress)):
604 Cmd += ("-r", BaseAddress[I], "-s", FvSize[I])
605 Cmd += ("-o", Output)
606 for F in Input:
607 Cmd += ("-f", F)
608
609 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF")
610
611 @staticmethod
612 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
613 Strip=False, Replace=False, TimeStamp=None, Join=False,
614 Align=None, Padding=None, Convert=False, IsMakefile=False):
615 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
616 return
617 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
618
619 Cmd = ["GenFw"]
620 if Type.lower() == "te":
621 Cmd.append("-t")
622 if SubType:
623 Cmd += ("-e", SubType)
624 if TimeStamp:
625 Cmd += ("-s", TimeStamp)
626 if Align:
627 Cmd += ("-a", Align)
628 if Padding:
629 Cmd += ("-p", Padding)
630 if Zero:
631 Cmd.append("-z")
632 if Strip:
633 Cmd.append("-l")
634 if Replace:
635 Cmd.append("-r")
636 if Join:
637 Cmd.append("-j")
638 if Convert:
639 Cmd.append("-m")
640 Cmd += ("-o", Output)
641 Cmd += Input
642 if IsMakefile:
643 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
644 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
645 else:
646 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
647
648 @staticmethod
649 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
650 Revision=None, DeviceId=None, VendorId=None, IsMakefile=False):
651 InputList = []
652 Cmd = ["EfiRom"]
653 if len(EfiInput) > 0:
654
655 if Compress:
656 Cmd.append("-ec")
657 else:
658 Cmd.append("-e")
659
660 for EfiFile in EfiInput:
661 Cmd.append(EfiFile)
662 InputList.append (EfiFile)
663
664 if len(BinaryInput) > 0:
665 Cmd.append("-b")
666 for BinFile in BinaryInput:
667 Cmd.append(BinFile)
668 InputList.append (BinFile)
669
670 # Check List
671 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile:
672 return
673 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
674
675 if ClassCode is not None:
676 Cmd += ("-l", ClassCode)
677 if Revision is not None:
678 Cmd += ("-r", Revision)
679 if DeviceId is not None:
680 Cmd += ("-i", DeviceId)
681 if VendorId is not None:
682 Cmd += ("-f", VendorId)
683
684 Cmd += ("-o", Output)
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 generate option rom")
690
691 @staticmethod
692 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False):
693 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
694 return
695 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
696
697 Cmd = [ToolPath, ]
698 Cmd += Options.split(' ')
699 Cmd += ("-o", Output)
700 Cmd += Input
701 if IsMakefile:
702 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
703 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
704 else:
705 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
706
707 def CallExternalTool (cmd, errorMess, returnValue=[]):
708
709 if type(cmd) not in (tuple, list):
710 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
711
712 if GenFdsGlobalVariable.DebugLevel != -1:
713 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
714 GenFdsGlobalVariable.InfLogger (cmd)
715
716 if GenFdsGlobalVariable.VerboseMode:
717 cmd += ('-v',)
718 GenFdsGlobalVariable.InfLogger (cmd)
719 else:
720 sys.stdout.write ('#')
721 sys.stdout.flush()
722 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
723 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
724 sys.stdout.write('\n')
725
726 try:
727 PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
728 except Exception as X:
729 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
730 (out, error) = PopenObject.communicate()
731
732 while PopenObject.returncode is None :
733 PopenObject.wait()
734 if returnValue != [] and returnValue[0] != 0:
735 #get command return value
736 returnValue[0] = PopenObject.returncode
737 return
738 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
739 GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
740 GenFdsGlobalVariable.InfLogger (out)
741 GenFdsGlobalVariable.InfLogger (error)
742 if PopenObject.returncode != 0:
743 print("###", cmd)
744 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
745
746 def VerboseLogger (msg):
747 EdkLogger.verbose(msg)
748
749 def InfLogger (msg):
750 EdkLogger.info(msg)
751
752 def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
753 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
754
755 def DebugLogger (Level, msg):
756 EdkLogger.debug(Level, msg)
757
758 ## ReplaceWorkspaceMacro()
759 #
760 # @param Str String that may contain macro
761 # @param MacroDict Dictionary that contains macro value pair
762 #
763 def MacroExtend (Str, MacroDict={}, Arch=DataType.TAB_COMMON):
764 if Str is None :
765 return None
766
767 Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir,
768 '$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir,
769 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
770 '$(TARGET)' : GenFdsGlobalVariable.TargetName,
771 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag,
772 '$(SPACE)' : ' '
773 }
774 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
775 if Arch != DataType.TAB_COMMON and Arch in GenFdsGlobalVariable.ArchList:
776 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
777
778 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
779
780 if MacroDict is not None and len (MacroDict) != 0:
781 Dict.update(MacroDict)
782
783 for key in Dict:
784 if Str.find(key) >= 0 :
785 Str = Str.replace (key, Dict[key])
786
787 if Str.find('$(ARCH)') >= 0:
788 if len(GenFdsGlobalVariable.ArchList) == 1:
789 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
790 else:
791 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
792
793 return Str
794
795 ## GetPcdValue()
796 #
797 # @param PcdPattern pattern that labels a PCD.
798 #
799 def GetPcdValue (PcdPattern):
800 if PcdPattern is None :
801 return None
802 PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.')
803 TokenSpace = PcdPair[0]
804 TokenCName = PcdPair[1]
805
806 PcdValue = ''
807 for Arch in GenFdsGlobalVariable.ArchList:
808 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
809 PcdDict = Platform.Pcds
810 for Key in PcdDict:
811 PcdObj = PcdDict[Key]
812 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
813 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
814 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
815 if PcdObj.DatumType != DataType.TAB_VOID:
816 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
817
818 PcdValue = PcdObj.DefaultValue
819 return PcdValue
820
821 for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
822 Arch,
823 GenFdsGlobalVariable.TargetName,
824 GenFdsGlobalVariable.ToolChainTag):
825 PcdDict = Package.Pcds
826 for Key in PcdDict:
827 PcdObj = PcdDict[Key]
828 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
829 if PcdObj.Type != DataType.TAB_PCDS_FIXED_AT_BUILD:
830 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
831 if PcdObj.DatumType != DataType.TAB_VOID:
832 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
833
834 PcdValue = PcdObj.DefaultValue
835 return PcdValue
836
837 return PcdValue
838
839 SetDir = staticmethod(SetDir)
840 SetEnv = staticmethod(SetEnv)
841 ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro)
842 CallExternalTool = staticmethod(CallExternalTool)
843 VerboseLogger = staticmethod(VerboseLogger)
844 InfLogger = staticmethod(InfLogger)
845 ErrorLogger = staticmethod(ErrorLogger)
846 DebugLogger = staticmethod(DebugLogger)
847 MacroExtend = staticmethod (MacroExtend)
848 GetPcdValue = staticmethod(GetPcdValue)
849
850 ## FindExtendTool()
851 #
852 # Find location of tools to process data
853 #
854 # @param KeyStringList Filter for inputs of section generation
855 # @param CurrentArchList Arch list
856 # @param NameGuid The Guid name
857 #
858 def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
859 ToolDb = ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase
860 # if user not specify filter, try to deduce it from global data.
861 if KeyStringList is None or KeyStringList == []:
862 Target = GenFdsGlobalVariable.TargetName
863 ToolChain = GenFdsGlobalVariable.ToolChainTag
864 if ToolChain not in ToolDb['TOOL_CHAIN_TAG']:
865 EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain)
866 KeyStringList = [Target + '_' + ToolChain + '_' + CurrentArchList[0]]
867 for Arch in CurrentArchList:
868 if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
869 KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
870
871 if GenFdsGlobalVariable.GuidToolDefinition:
872 if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
873 return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
874
875 ToolDefinition = ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary
876 ToolPathTmp = None
877 ToolOption = None
878 ToolPathKey = None
879 ToolOptionKey = None
880 KeyList = None
881 for ToolDef in ToolDefinition.items():
882 if NameGuid.lower() == ToolDef[1].lower() :
883 KeyList = ToolDef[0].split('_')
884 Key = KeyList[0] + \
885 '_' + \
886 KeyList[1] + \
887 '_' + \
888 KeyList[2]
889 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
890 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
891 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
892 ToolPath = ToolDefinition.get(ToolPathKey)
893 ToolOption = ToolDefinition.get(ToolOptionKey)
894 if ToolPathTmp is None:
895 ToolPathTmp = ToolPath
896 else:
897 if ToolPathTmp != ToolPath:
898 EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
899
900 BuildOption = {}
901 for Arch in CurrentArchList:
902 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
903 # key is (ToolChainFamily, ToolChain, CodeBase)
904 for item in Platform.BuildOptions:
905 if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]:
906 if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]):
907 if item[1] not in BuildOption:
908 BuildOption[item[1]] = Platform.BuildOptions[item]
909 if BuildOption:
910 ToolList = [DataType.TAB_TOD_DEFINES_TARGET, DataType.TAB_TOD_DEFINES_TOOL_CHAIN_TAG, DataType.TAB_TOD_DEFINES_TARGET_ARCH]
911 for Index in range(2, -1, -1):
912 for Key in list(BuildOption.keys()):
913 List = Key.split('_')
914 if List[Index] == '*':
915 for String in ToolDb[ToolList[Index]]:
916 if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]:
917 List[Index] = String
918 NewKey = '%s_%s_%s_%s_%s' % tuple(List)
919 if NewKey not in BuildOption:
920 BuildOption[NewKey] = BuildOption[Key]
921 continue
922 del BuildOption[Key]
923 elif List[Index] not in ToolDb[ToolList[Index]]:
924 del BuildOption[Key]
925 if BuildOption:
926 if not KeyList:
927 for Op in BuildOption:
928 if NameGuid == BuildOption[Op]:
929 KeyList = Op.split('_')
930 Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2]
931 if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
932 ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
933 ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
934 if ToolPathKey in BuildOption:
935 ToolPathTmp = BuildOption[ToolPathKey]
936 if ToolOptionKey in BuildOption:
937 ToolOption = BuildOption[ToolOptionKey]
938
939 GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
940 return ToolPathTmp, ToolOption