]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
Sync EDKII BaseTools to BaseTools project r1903.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / GenFdsGlobalVariable.py
1 ## @file
2 # Global variables for GenFds
3 #
4 # Copyright (c) 2007 - 2010, Intel Corporation
5 #
6 # All rights reserved. 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 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 ## Global variables
29 #
30 #
31 class GenFdsGlobalVariable:
32 FvDir = ''
33 OutputDirDict = {}
34 BinDir = ''
35 # will be FvDir + os.sep + 'Ffs'
36 FfsDir = ''
37 FdfParser = None
38 LibDir = ''
39 WorkSpace = None
40 WorkSpaceDir = ''
41 EdkSourceDir = ''
42 OutputDirFromDscDict = {}
43 TargetName = ''
44 ToolChainTag = ''
45 RuleDict = {}
46 ArchList = None
47 VtfDict = {}
48 ActivePlatform = None
49 FvAddressFileName = ''
50 VerboseMode = False
51 DebugLevel = -1
52 SharpCounter = 0
53 SharpNumberPerLine = 40
54 FdfFile = ''
55 FdfFileTimeStamp = 0
56 FixedLoadAddress = False
57 PlatformName = ''
58
59 SectionHeader = struct.Struct("3B 1B")
60
61 ## SetDir()
62 #
63 # @param OutputDir Output directory
64 # @param FdfParser FDF contents parser
65 # @param Workspace The directory of workspace
66 # @param ArchList The Arch list of platform
67 #
68 def SetDir (OutputDir, FdfParser, WorkSpace, ArchList):
69 GenFdsGlobalVariable.VerboseLogger( "GenFdsGlobalVariable.OutputDir :%s" %OutputDir)
70 # GenFdsGlobalVariable.OutputDirDict = OutputDir
71 GenFdsGlobalVariable.FdfParser = FdfParser
72 GenFdsGlobalVariable.WorkSpace = WorkSpace
73 GenFdsGlobalVariable.FvDir = os.path.join(GenFdsGlobalVariable.OutputDirDict[ArchList[0]], 'FV')
74 if not os.path.exists(GenFdsGlobalVariable.FvDir) :
75 os.makedirs(GenFdsGlobalVariable.FvDir)
76 GenFdsGlobalVariable.FfsDir = os.path.join(GenFdsGlobalVariable.FvDir, 'Ffs')
77 if not os.path.exists(GenFdsGlobalVariable.FfsDir) :
78 os.makedirs(GenFdsGlobalVariable.FfsDir)
79 if ArchList != None:
80 GenFdsGlobalVariable.ArchList = ArchList
81
82 T_CHAR_LF = '\n'
83 #
84 # Create FV Address inf file
85 #
86 GenFdsGlobalVariable.FvAddressFileName = os.path.join(GenFdsGlobalVariable.FfsDir, 'FvAddress.inf')
87 FvAddressFile = open (GenFdsGlobalVariable.FvAddressFileName, 'w')
88 #
89 # Add [Options]
90 #
91 FvAddressFile.writelines("[options]" + T_CHAR_LF)
92 BsAddress = '0'
93 for Arch in ArchList:
94 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].BsBaseAddress:
95 BsAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].BsBaseAddress
96 break
97
98 FvAddressFile.writelines("EFI_BOOT_DRIVER_BASE_ADDRESS = " + \
99 BsAddress + \
100 T_CHAR_LF)
101
102 RtAddress = '0'
103 for Arch in ArchList:
104 if GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].RtBaseAddress:
105 RtAddress = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch].RtBaseAddress
106
107 FvAddressFile.writelines("EFI_RUNTIME_DRIVER_BASE_ADDRESS = " + \
108 RtAddress + \
109 T_CHAR_LF)
110
111 FvAddressFile.close()
112
113 ## ReplaceWorkspaceMacro()
114 #
115 # @param String String that may contain macro
116 #
117 def ReplaceWorkspaceMacro(String):
118 Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
119 if os.path.exists(Str):
120 if not os.path.isabs(Str):
121 Str = os.path.abspath(Str)
122 else:
123 Str = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, String)
124 return os.path.normpath(Str)
125
126 ## Check if the input files are newer than output files
127 #
128 # @param Output Path of output file
129 # @param Input Path list of input files
130 #
131 # @retval True if Output doesn't exist, or any Input is newer
132 # @retval False if all Input is older than Output
133 #
134 @staticmethod
135 def NeedsUpdate(Output, Input):
136 if not os.path.exists(Output):
137 return True
138 # always update "Output" if no "Input" given
139 if Input == None or len(Input) == 0:
140 return True
141
142 # if fdf file is changed after the 'Output" is generated, update the 'Output'
143 OutputTime = os.path.getmtime(Output)
144 if GenFdsGlobalVariable.FdfFileTimeStamp > OutputTime:
145 return True
146
147 for F in Input:
148 # always update "Output" if any "Input" doesn't exist
149 if not os.path.exists(F):
150 return True
151 # always update "Output" if any "Input" is newer than "Output"
152 if os.path.getmtime(F) > OutputTime:
153 return True
154 return False
155
156 @staticmethod
157 def GenerateSection(Output, Input, Type=None, CompressionType=None, Guid=None,
158 GuidHdrLen=None, GuidAttr=[], Ui=None, Ver=None, InputAlign=None):
159 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
160 return
161 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
162
163 Cmd = ["GenSec"]
164 if Type not in [None, '']:
165 Cmd += ["-s", Type]
166 if CompressionType not in [None, '']:
167 Cmd += ["-c", CompressionType]
168 if Guid != None:
169 Cmd += ["-g", Guid]
170 if GuidHdrLen not in [None, '']:
171 Cmd += ["-l", GuidHdrLen]
172 if len(GuidAttr) != 0:
173 #Add each guided attribute
174 for Attr in GuidAttr:
175 Cmd += ["-r", Attr]
176 if InputAlign != None:
177 #Section Align is only for dummy section without section type
178 for SecAlign in InputAlign:
179 Cmd += ["--sectionalign", SecAlign]
180
181 if Ui not in [None, '']:
182 #Cmd += ["-n", '"' + Ui + '"']
183 SectionData = array.array('B', [0,0,0,0])
184 SectionData.fromstring(Ui.encode("utf_16_le"))
185 SectionData.append(0)
186 SectionData.append(0)
187 Len = len(SectionData)
188 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
189 SaveFileOnChange(Output, SectionData.tostring())
190 elif Ver not in [None, '']:
191 #Cmd += ["-j", Ver]
192 SectionData = array.array('B', [0,0,0,0])
193 SectionData.fromstring(Ver.encode("utf_16_le"))
194 SectionData.append(0)
195 SectionData.append(0)
196 Len = len(SectionData)
197 GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x14)
198 SaveFileOnChange(Output, SectionData.tostring())
199 else:
200 Cmd += ["-o", Output]
201 Cmd += Input
202 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate section")
203
204 @staticmethod
205 def GetAlignment (AlignString):
206 if AlignString == None:
207 return 0
208 if AlignString in ("1K", "2K", "4K", "8K", "16K", "32K", "64K"):
209 return int (AlignString.rstrip('K')) * 1024
210 else:
211 return int (AlignString)
212
213 @staticmethod
214 def GenerateFfs(Output, Input, Type, Guid, Fixed=False, CheckSum=False, Align=None,
215 SectionAlign=None):
216 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
217 return
218 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
219
220 Cmd = ["GenFfs", "-t", Type, "-g", Guid]
221 if Fixed == True:
222 Cmd += ["-x"]
223 if CheckSum:
224 Cmd += ["-s"]
225 if Align not in [None, '']:
226 Cmd += ["-a", Align]
227
228 Cmd += ["-o", Output]
229 for I in range(0, len(Input)):
230 Cmd += ("-i", Input[I])
231 if SectionAlign not in [None, '', []] and SectionAlign[I] not in [None, '']:
232 Cmd += ("-n", SectionAlign[I])
233 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FFS")
234
235 @staticmethod
236 def GenerateFirmwareVolume(Output, Input, BaseAddress=None, Capsule=False, Dump=False,
237 AddressFile=None, MapFile=None, FfsList=[]):
238 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input+FfsList):
239 return
240 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
241
242 Cmd = ["GenFv"]
243 if BaseAddress not in [None, '']:
244 Cmd += ["-r", BaseAddress]
245 if Capsule:
246 Cmd += ["-c"]
247 if Dump:
248 Cmd += ["-p"]
249 if AddressFile not in [None, '']:
250 Cmd += ["-a", AddressFile]
251 if MapFile not in [None, '']:
252 Cmd += ["-m", MapFile]
253 Cmd += ["-o", Output]
254 for I in Input:
255 Cmd += ["-i", I]
256
257 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate FV")
258
259 @staticmethod
260 def GenerateVtf(Output, Input, BaseAddress=None, FvSize=None):
261 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
262 return
263 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
264
265 Cmd = ["GenVtf"]
266 if BaseAddress not in [None, ''] and FvSize not in [None, ''] \
267 and len(BaseAddress) == len(FvSize):
268 for I in range(0, len(BaseAddress)):
269 Cmd += ["-r", BaseAddress[I], "-s", FvSize[I]]
270 Cmd += ["-o", Output]
271 for F in Input:
272 Cmd += ["-f", F]
273
274 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate VTF")
275
276 @staticmethod
277 def GenerateFirmwareImage(Output, Input, Type="efi", SubType=None, Zero=False,
278 Strip=False, Replace=False, TimeStamp=None, Join=False,
279 Align=None, Padding=None, Convert=False):
280 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
281 return
282 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
283
284 Cmd = ["GenFw"]
285 if Type.lower() == "te":
286 Cmd += ["-t"]
287 if SubType not in [None, '']:
288 Cmd += ["-e", SubType]
289 if TimeStamp not in [None, '']:
290 Cmd += ["-s", TimeStamp]
291 if Align not in [None, '']:
292 Cmd += ["-a", Align]
293 if Padding not in [None, '']:
294 Cmd += ["-p", Padding]
295 if Zero:
296 Cmd += ["-z"]
297 if Strip:
298 Cmd += ["-l"]
299 if Replace:
300 Cmd += ["-r"]
301 if Join:
302 Cmd += ["-j"]
303 if Convert:
304 Cmd += ["-m"]
305 Cmd += ["-o", Output]
306 Cmd += Input
307
308 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate firmware image")
309
310 @staticmethod
311 def GenerateOptionRom(Output, EfiInput, BinaryInput, Compress=False, ClassCode=None,
312 Revision=None, DeviceId=None, VendorId=None):
313 InputList = []
314 Cmd = ["EfiRom"]
315 if len(EfiInput) > 0:
316
317 if Compress:
318 Cmd += ["-ec"]
319 else:
320 Cmd += ["-e"]
321
322 for EfiFile in EfiInput:
323 Cmd += [EfiFile]
324 InputList.append (EfiFile)
325
326 if len(BinaryInput) > 0:
327 Cmd += ["-b"]
328 for BinFile in BinaryInput:
329 Cmd += [BinFile]
330 InputList.append (BinFile)
331
332 # Check List
333 if not GenFdsGlobalVariable.NeedsUpdate(Output, InputList):
334 return
335 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, InputList))
336
337 if ClassCode != None:
338 Cmd += ["-l", ClassCode]
339 if Revision != None:
340 Cmd += ["-r", Revision]
341 if DeviceId != None:
342 Cmd += ["-i", DeviceId]
343 if VendorId != None:
344 Cmd += ["-f", VendorId]
345
346 Cmd += ["-o", Output]
347 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to generate option rom")
348
349 @staticmethod
350 def GuidTool(Output, Input, ToolPath, Options='', returnValue=[]):
351 if not GenFdsGlobalVariable.NeedsUpdate(Output, Input):
352 return
353 GenFdsGlobalVariable.DebugLogger(EdkLogger.DEBUG_5, "%s needs update because of newer %s" % (Output, Input))
354
355 Cmd = [ToolPath, ]
356 Cmd += Options.split(' ')
357 Cmd += ["-o", Output]
358 Cmd += Input
359
360 GenFdsGlobalVariable.CallExternalTool(Cmd, "Failed to call " + ToolPath, returnValue)
361
362 def CallExternalTool (cmd, errorMess, returnValue=[]):
363
364 if type(cmd) not in (tuple, list):
365 GenFdsGlobalVariable.ErrorLogger("ToolError! Invalid parameter type in call to CallExternalTool")
366
367 if GenFdsGlobalVariable.DebugLevel != -1:
368 cmd += ('--debug', str(GenFdsGlobalVariable.DebugLevel))
369 GenFdsGlobalVariable.InfLogger (cmd)
370
371 if GenFdsGlobalVariable.VerboseMode:
372 cmd += ('-v',)
373 GenFdsGlobalVariable.InfLogger (cmd)
374 else:
375 sys.stdout.write ('#')
376 sys.stdout.flush()
377 GenFdsGlobalVariable.SharpCounter = GenFdsGlobalVariable.SharpCounter + 1
378 if GenFdsGlobalVariable.SharpCounter % GenFdsGlobalVariable.SharpNumberPerLine == 0:
379 sys.stdout.write('\n')
380
381 try:
382 PopenObject = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr= subprocess.PIPE)
383 except Exception, X:
384 EdkLogger.error("GenFds", COMMAND_FAILURE, ExtraData="%s: %s" % (str(X), cmd[0]))
385 (out, error) = PopenObject.communicate()
386
387 while PopenObject.returncode == None :
388 PopenObject.wait()
389 if returnValue != [] and returnValue[0] != 0:
390 #get command return value
391 returnValue[0] = PopenObject.returncode
392 return
393 if PopenObject.returncode != 0 or GenFdsGlobalVariable.VerboseMode or GenFdsGlobalVariable.DebugLevel != -1:
394 GenFdsGlobalVariable.InfLogger ("Return Value = %d" %PopenObject.returncode)
395 GenFdsGlobalVariable.InfLogger (out)
396 GenFdsGlobalVariable.InfLogger (error)
397 if PopenObject.returncode != 0:
398 print "###", cmd
399 EdkLogger.error("GenFds", COMMAND_FAILURE, errorMess)
400
401 def VerboseLogger (msg):
402 EdkLogger.verbose(msg)
403
404 def InfLogger (msg):
405 EdkLogger.info(msg)
406
407 def ErrorLogger (msg, File = None, Line = None, ExtraData = None):
408 EdkLogger.error('GenFds', GENFDS_ERROR, msg, File, Line, ExtraData)
409
410 def DebugLogger (Level, msg):
411 EdkLogger.debug(Level, msg)
412
413 ## ReplaceWorkspaceMacro()
414 #
415 # @param Str String that may contain macro
416 # @param MacroDict Dictionary that contains macro value pair
417 #
418 def MacroExtend (Str, MacroDict = {}, Arch = 'COMMON'):
419 if Str == None :
420 return None
421
422 Dict = {'$(WORKSPACE)' : GenFdsGlobalVariable.WorkSpaceDir,
423 '$(EDK_SOURCE)' : GenFdsGlobalVariable.EdkSourceDir,
424 # '$(OUTPUT_DIRECTORY)': GenFdsGlobalVariable.OutputDirFromDsc,
425 '$(TARGET)' : GenFdsGlobalVariable.TargetName,
426 '$(TOOL_CHAIN_TAG)' : GenFdsGlobalVariable.ToolChainTag
427 }
428 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[GenFdsGlobalVariable.ArchList[0]]
429 if Arch != 'COMMON' and Arch in GenFdsGlobalVariable.ArchList:
430 OutputDir = GenFdsGlobalVariable.OutputDirFromDscDict[Arch]
431
432 Dict['$(OUTPUT_DIRECTORY)'] = OutputDir
433
434 if MacroDict != None and len (MacroDict) != 0:
435 Dict.update(MacroDict)
436
437 for key in Dict.keys():
438 if Str.find(key) >= 0 :
439 Str = Str.replace (key, Dict[key])
440
441 if Str.find('$(ARCH)') >= 0:
442 if len(GenFdsGlobalVariable.ArchList) == 1:
443 Str = Str.replace('$(ARCH)', GenFdsGlobalVariable.ArchList[0])
444 else:
445 EdkLogger.error("GenFds", GENFDS_ERROR, "No way to determine $(ARCH) for %s" % Str)
446
447 return Str
448
449 ## GetPcdValue()
450 #
451 # @param PcdPattern pattern that labels a PCD.
452 #
453 def GetPcdValue (PcdPattern):
454 if PcdPattern == None :
455 return None
456 PcdPair = PcdPattern.lstrip('PCD(').rstrip(')').strip().split('.')
457 TokenSpace = PcdPair[0]
458 TokenCName = PcdPair[1]
459
460 PcdValue = ''
461 for Platform in GenFdsGlobalVariable.WorkSpace.PlatformList:
462 PcdDict = Platform.Pcds
463 for Key in PcdDict:
464 PcdObj = PcdDict[Key]
465 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
466 if PcdObj.Type != 'FixedAtBuild':
467 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
468 if PcdObj.DatumType != 'VOID*':
469 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
470
471 PcdValue = PcdObj.DefaultValue
472 return PcdValue
473
474 for Package in GenFdsGlobalVariable.WorkSpace.PackageList:
475 PcdDict = Package.Pcds
476 for Key in PcdDict:
477 PcdObj = PcdDict[Key]
478 if (PcdObj.TokenCName == TokenCName) and (PcdObj.TokenSpaceGuidCName == TokenSpace):
479 if PcdObj.Type != 'FixedAtBuild':
480 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not FixedAtBuild type." % PcdPattern)
481 if PcdObj.DatumType != 'VOID*':
482 EdkLogger.error("GenFds", GENFDS_ERROR, "%s is not VOID* datum type." % PcdPattern)
483
484 PcdValue = PcdObj.DefaultValue
485 return PcdValue
486
487 return PcdValue
488
489 SetDir = staticmethod(SetDir)
490 ReplaceWorkspaceMacro = staticmethod(ReplaceWorkspaceMacro)
491 CallExternalTool = staticmethod(CallExternalTool)
492 VerboseLogger = staticmethod(VerboseLogger)
493 InfLogger = staticmethod(InfLogger)
494 ErrorLogger = staticmethod(ErrorLogger)
495 DebugLogger = staticmethod(DebugLogger)
496 MacroExtend = staticmethod (MacroExtend)
497 GetPcdValue = staticmethod(GetPcdValue)