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