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