]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
BaseTools: use set instead of list for a variable to be used with in
[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 if Ui == "$(MODULE_NAME)":
468 Cmd += ['-n', Ui]
469 else:
470 Cmd += ["-n", '"' + Ui + '"']
471 Cmd += ["-o", Output]
472 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
473 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
474 else:
475 SectionData = array.array('B', [0, 0, 0, 0])
476 SectionData.fromstring(Ui.encode("utf_16_le"))
477 SectionData.append(0)
478 SectionData.append(0)
479 Len = len(SectionData)
480 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
481 SaveFileOnChange(Output, SectionData.tostring())
482
483 elif Ver not in [None, '']:
484 Cmd += ["-n", Ver]
485 if BuildNumber:
486 Cmd += ["-j", BuildNumber]
487 Cmd += ["-o", Output]
488
489 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
490 if IsMakefile:
491 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
492 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
493 else:
494 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
495 return
496 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
497 else:
498 Cmd += ["-o", Output]
499 Cmd += Input
500
501 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
502 if IsMakefile:
503 if ' '.join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
504 GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
505 elif GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
506 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
507 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
508 if (os.path.getsize(Output) >= GenFdsGlobalVariable.LARGE_FILE_SIZE and
509 GenFdsGlobalVariable.LargeFileInFvFlags):
510 GenFdsGlobalVariable.LargeFileInFvFlags[-1] = True
511
512 @staticmethod
513 def GetAlignment (AlignString):
514 if AlignString is None:
515 return 0
516 if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K"):
517 return int (AlignString.rstrip('K')) * 1024
518 elif AlignString in ("1M", "2M", "4M", "8M", "16M"):
519 return int (AlignString.rstrip('M')) * 1024 * 1024
520 else:
521 return int (AlignString)
522
523 @staticmethod
524 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
525 SectionAlign=None, MakefilePath=None):
526 Cmd = ["GenFfs", "-t", Type, "-g", Guid]
527 mFfsValidAlign = ["0", "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M", "16M"]
528 if Fixed == True:
529 Cmd += ["-x"]
530 if CheckSum:
531 Cmd += ["-s"]
532 if Align not in [None, '']:
533 if Align not in mFfsValidAlign:
534 Align = GenFdsGlobalVariable.GetAlignment (Align)
535 for index in range(0, len(mFfsValidAlign) - 1):
536 if ((Align > GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index])) and (Align <= GenFdsGlobalVariable.GetAlignment(mFfsValidAlign[index + 1]))):
537 break
538 Align = mFfsValidAlign[index + 1]
539 Cmd += ["-a", Align]
540
541 Cmd += ["-o", Output]
542 for I in range(0, len(Input)):
543 Cmd += ("-i", Input[I])
544 if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']:
545 Cmd += ("-n", SectionAlign[I])
546
547 CommandFile = Output + '.txt'
548 SaveFileOnChange(CommandFile, ' '.join(Cmd), False)
549
550 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
551 if MakefilePath:
552 if (tuple(Cmd),tuple(GenFdsGlobalVariable.SecCmdList),tuple(GenFdsGlobalVariable.CopyList)) not in GenFdsGlobalVariable.FfsCmdDict.keys():
553 GenFdsGlobalVariable.FfsCmdDict[tuple(Cmd), tuple(GenFdsGlobalVariable.SecCmdList), tuple(GenFdsGlobalVariable.CopyList)] = MakefilePath
554 GenFdsGlobalVariable.SecCmdList = []
555 GenFdsGlobalVariable.CopyList = []
556 else:
557 if not GenFdsGlobalVariable.NeedsUpdate(Output, list(Input) + [CommandFile]):
558 return
559 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
560
561 @staticmethod
562 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, ForceRebase=None, Capsule=False, Dump=False,
563 AddressFile=None, MapFile=None, FfsList=[], FileSystemGuid=None):
564 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
565 return
566 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
567
568 Cmd = ["GenFv"]
569 if BaseAddress not in [None, '']:
570 Cmd += ["-r", BaseAddress]
571
572 if ForceRebase == False:
573 Cmd += ["-F", "FALSE"]
574 elif ForceRebase == True:
575 Cmd += ["-F", "TRUE"]
576
577 if Capsule:
578 Cmd += ["-c"]
579 if Dump:
580 Cmd += ["-p"]
581 if AddressFile not in [None, '']:
582 Cmd += ["-a", AddressFile]
583 if MapFile not in [None, '']:
584 Cmd += ["-m", MapFile]
585 if FileSystemGuid:
586 Cmd += ["-g", FileSystemGuid]
587 Cmd += ["-o", Output]
588 for I in Input:
589 Cmd += ["-i", I]
590
591 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
592
593 @staticmethod
594 def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None):
595 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
596 return
597 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
598
599 Cmd = ["GenVtf"]
600 if BaseAddress not in [None, ''] and FvSize not in [None, ''] \
601 and len(BaseAddress) == len(FvSize):
602 for I in range(0, len(BaseAddress)):
603 Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]]
604 Cmd += ["-o", Output]
605 for F in Input:
606 Cmd += ["-f", F]
607
608 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF")
609
610 @staticmethod
611 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
612 Strip=False, Replace=False, TimeStamp=None, Join=False,
613 Align=None, Padding=None, Convert=False, IsMakefile=False):
614 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
615 return
616 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
617
618 Cmd = ["GenFw"]
619 if Type.lower() == "te":
620 Cmd += ["-t"]
621 if SubType not in [None, '']:
622 Cmd += ["-e", SubType]
623 if TimeStamp not in [None, '']:
624 Cmd += ["-s", TimeStamp]
625 if Align not in [None, '']:
626 Cmd += ["-a", Align]
627 if Padding not in [None, '']:
628 Cmd += ["-p", Padding]
629 if Zero:
630 Cmd += ["-z"]
631 if Strip:
632 Cmd += ["-l"]
633 if Replace:
634 Cmd += ["-r"]
635 if Join:
636 Cmd += ["-j"]
637 if Convert:
638 Cmd += ["-m"]
639 Cmd += ["-o", Output]
640 Cmd += Input
641 if IsMakefile:
642 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
643 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
644 else:
645 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
646
647 @staticmethod
648 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
649 Revision=None, DeviceId=None, VendorId=None, IsMakefile=False):
650 InputList = []
651 Cmd = ["EfiRom"]
652 if len(EfiInput) > 0:
653
654 if Compress:
655 Cmd += ["-ec"]
656 else:
657 Cmd += ["-e"]
658
659 for EfiFile in EfiInput:
660 Cmd += [EfiFile]
661 InputList.append (EfiFile)
662
663 if len(BinaryInput) > 0:
664 Cmd += ["-b"]
665 for BinFile in BinaryInput:
666 Cmd += [BinFile]
667 InputList.append (BinFile)
668
669 # Check List
670 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList) and not IsMakefile:
671 return
672 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
673
674 if ClassCode is not None:
675 Cmd += ["-l", ClassCode]
676 if Revision is not None:
677 Cmd += ["-r", Revision]
678 if DeviceId is not None:
679 Cmd += ["-i", DeviceId]
680 if VendorId is not None:
681 Cmd += ["-f", VendorId]
682
683 Cmd += ["-o", Output]
684 if IsMakefile:
685 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
686 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
687 else:
688 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
689
690 @staticmethod
691 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[], IsMakefile=False):
692 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input) and not IsMakefile:
693 return
694 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
695
696 Cmd = [ToolPath, ]
697 Cmd += Options.split(' ')
698 Cmd += ["-o", Output]
699 Cmd += Input
700 if IsMakefile:
701 if " ".join(Cmd).strip() not in GenFdsGlobalVariable.SecCmdList:
702 GenFdsGlobalVariable.SecCmdList.append(" ".join(Cmd).strip())
703 else:
704 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
705
706 def CallExternalTool (cmd, errorMess, returnValue=[]):
707
708 if type(cmd) not in (tuple, list):
709 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
710
711 if GenFdsGlobalVariable.DebugLevel != -1:
712 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
713 GenFdsGlobalVariable.InfLogger (cmd)
714
715 if GenFdsGlobalVariable.VerboseMode:
716 cmd += ('-v',)
717 GenFdsGlobalVariable.InfLogger (cmd)
718 else:
719 sys.stdout.write ('#')
720 sys.stdout.flush()
721 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
722 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
723 sys.stdout.write('\n')
724
725 try:
726 PopenObject = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
727 except Exception, X:
728 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
729 (out, error) = PopenObject.communicate()
730
731 while PopenObject.returncode is None :
732 PopenObject.wait()
733 if returnValue != [] and returnValue[0] != 0:
734 #get command return value
735 returnValue[0] = PopenObject.returncode
736 return
737 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
738 GenFdsGlobalVariable.InfLogger ("Return Value = %d" % PopenObject.returncode)
739 GenFdsGlobalVariable.InfLogger (out)
740 GenFdsGlobalVariable.InfLogger (error)
741 if PopenObject.returncode != 0:
742 print "###", cmd
743 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
744
745 def VerboseLogger (msg):
746 EdkLogger.verbose(msg)
747
748 def InfLogger (msg):
749 EdkLogger.info(msg)
750
751 def ErrorLogger (msg, File=None, Line=None, ExtraData=None):
752 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
753
754 def DebugLogger (Level, msg):
755 EdkLogger.debug(Level, msg)
756
757 ## ReplaceWorkspaceMacro()
758 #
759 # @param Str String that may contain macro
760 # @param MacroDict Dictionary that contains macro value pair
761 #
762 def MacroExtend (Str, MacroDict={}, Arch='COMMON'):
763 if Str is None :
764 return None
765
766 Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir,
767 '$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir,
768 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
769 '$(TARGET)' : GenFdsGlobalVariable.TargetName,
770 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag,
771 '$(SPACE)' : ' '
772 }
773 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
774 if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList:
775 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
776
777 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
778
779 if MacroDict is not None and len (MacroDict) != 0:
780 Dict.update(MacroDict)
781
782 for key in Dict.keys():
783 if Str.find(key) >= 0 :
784 Str = Str.replace (key, Dict[key])
785
786 if Str.find('$(ARCH)') >= 0:
787 if len(GenFdsGlobalVariable.ArchList) == 1:
788 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
789 else:
790 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
791
792 return Str
793
794 ## GetPcdValue()
795 #
796 # @param PcdPattern pattern that labels a PCD.
797 #
798 def GetPcdValue (PcdPattern):
799 if PcdPattern is None :
800 return None
801 PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.')
802 TokenSpace = PcdPair[0]
803 TokenCName = PcdPair[1]
804
805 PcdValue = ''
806 for Arch in GenFdsGlobalVariable.ArchList:
807 Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
808 PcdDict = Platform.Pcds
809 for Key in PcdDict:
810 PcdObj = PcdDict[Key]
811 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
812 if PcdObj.Type != 'FixedAtBuild':
813 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
814 if PcdObj.DatumType != 'VOID*':
815 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
816
817 PcdValue = PcdObj.DefaultValue
818 return PcdValue
819
820 for Package in GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform,
821 Arch,
822 GenFdsGlobalVariable.TargetName,
823 GenFdsGlobalVariable.ToolChainTag):
824 PcdDict = Package.Pcds
825 for Key in PcdDict:
826 PcdObj = PcdDict[Key]
827 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
828 if PcdObj.Type != 'FixedAtBuild':
829 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
830 if PcdObj.DatumType != 'VOID*':
831 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
832
833 PcdValue = PcdObj.DefaultValue
834 return PcdValue
835
836 return PcdValue
837
838 SetDir = staticmethod(SetDir)
839 SetEnv = staticmethod(SetEnv)
840 ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro)
841 CallExternalTool = staticmethod(CallExternalTool)
842 VerboseLogger = staticmethod(VerboseLogger)
843 InfLogger = staticmethod(InfLogger)
844 ErrorLogger = staticmethod(ErrorLogger)
845 DebugLogger = staticmethod(DebugLogger)
846 MacroExtend = staticmethod (MacroExtend)
847 GetPcdValue = staticmethod(GetPcdValue)