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