]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Fv.py
BaseTools: fix None comparisons
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Fv.py
1 ## @file
2 # process FV generation
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 subprocess
20 import StringIO
21 from struct import *
22
23 import Ffs
24 import AprioriSection
25 import FfsFileStatement
26 from GenFdsGlobalVariable import GenFdsGlobalVariable
27 from GenFds import GenFds
28 from CommonDataClass.FdfClass import FvClassObject
29 from Common.Misc import SaveFileOnChange
30 from Common.LongFilePathSupport import CopyLongFilePath
31 from Common.LongFilePathSupport import OpenLongFilePath as open
32
33 T_CHAR_LF = '\n'
34 FV_UI_EXT_ENTY_GUID = 'A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C'
35
36 ## generate FV
37 #
38 #
39 class FV (FvClassObject):
40 ## The constructor
41 #
42 # @param self The object pointer
43 #
44 def __init__(self):
45 FvClassObject.__init__(self)
46 self.FvInfFile = None
47 self.FvAddressFile = None
48 self.BaseAddress = None
49 self.InfFileName = None
50 self.FvAddressFileName = None
51 self.CapsuleName = None
52 self.FvBaseAddress = None
53 self.FvForceRebase = None
54 self.FvRegionInFD = None
55 self.UsedSizeEnable = False
56
57 ## AddToBuffer()
58 #
59 # Generate Fv and add it to the Buffer
60 #
61 # @param self The object pointer
62 # @param Buffer The buffer generated FV data will be put
63 # @param BaseAddress base address of FV
64 # @param BlockSize block size of FV
65 # @param BlockNum How many blocks in FV
66 # @param ErasePolarity Flash erase polarity
67 # @param VtfDict VTF objects
68 # @param MacroDict macro value pair
69 # @retval string Generated FV file path
70 #
71 def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', VtfDict=None, MacroDict = {}, Flag=False) :
72
73 if BaseAddress is None and self.UiFvName.upper() + 'fv' in GenFds.ImageBinDict.keys():
74 return GenFds.ImageBinDict[self.UiFvName.upper() + 'fv']
75
76 #
77 # Check whether FV in Capsule is in FD flash region.
78 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
79 #
80 if self.CapsuleName is not None:
81 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
82 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]
83 for RegionObj in FdObj.RegionList:
84 if RegionObj.RegionType == 'FV':
85 for RegionData in RegionObj.RegionDataList:
86 if RegionData.endswith(".fv"):
87 continue
88 elif RegionData.upper() + 'fv' in GenFds.ImageBinDict.keys():
89 continue
90 elif self.UiFvName.upper() == RegionData.upper():
91 GenFdsGlobalVariable.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self.CapsuleName, self.UiFvName.upper()))
92 if not Flag:
93 GenFdsGlobalVariable.InfLogger( "\nGenerating %s FV" %self.UiFvName)
94 GenFdsGlobalVariable.LargeFileInFvFlags.append(False)
95 FFSGuid = None
96
97 if self.FvBaseAddress is not None:
98 BaseAddress = self.FvBaseAddress
99 if not Flag:
100 self.__InitializeInf__(BaseAddress, BlockSize, BlockNum, ErasePloarity, VtfDict)
101 #
102 # First Process the Apriori section
103 #
104 MacroDict.update(self.DefineVarDict)
105
106 GenFdsGlobalVariable.VerboseLogger('First generate Apriori file !')
107 FfsFileList = []
108 for AprSection in self.AprioriSectionList:
109 FileName = AprSection.GenFfs (self.UiFvName, MacroDict, IsMakefile=Flag)
110 FfsFileList.append(FileName)
111 # Add Apriori file name to Inf file
112 if not Flag:
113 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
114 FileName + \
115 T_CHAR_LF)
116
117 # Process Modules in FfsList
118 for FfsFile in self.FfsList :
119 if Flag:
120 if isinstance(FfsFile, FfsFileStatement.FileStatement):
121 continue
122 if GenFdsGlobalVariable.EnableGenfdsMultiThread and GenFdsGlobalVariable.ModuleFile and GenFdsGlobalVariable.ModuleFile.Path.find(os.path.normpath(FfsFile.InfFileName)) == -1:
123 continue
124 FileName = FfsFile.GenFfs(MacroDict, FvParentAddr=BaseAddress, IsMakefile=Flag, FvName=self.UiFvName)
125 FfsFileList.append(FileName)
126 if not Flag:
127 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
128 FileName + \
129 T_CHAR_LF)
130 if not Flag:
131 SaveFileOnChange(self.InfFileName, self.FvInfFile.getvalue(), False)
132 self.FvInfFile.close()
133 #
134 # Call GenFv tool
135 #
136 FvOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName)
137 FvOutputFile = FvOutputFile + '.Fv'
138 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
139 if self.CreateFileName is not None:
140 FvOutputFile = self.CreateFileName
141
142 if Flag:
143 GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile
144 return FvOutputFile
145
146 FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf')
147 if not Flag:
148 CopyLongFilePath(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName)
149 OrigFvInfo = None
150 if os.path.exists (FvInfoFileName):
151 OrigFvInfo = open(FvInfoFileName, 'r').read()
152 if GenFdsGlobalVariable.LargeFileInFvFlags[-1]:
153 FFSGuid = GenFdsGlobalVariable.EFI_FIRMWARE_FILE_SYSTEM3_GUID
154 GenFdsGlobalVariable.GenerateFirmwareVolume(
155 FvOutputFile,
156 [self.InfFileName],
157 AddressFile=FvInfoFileName,
158 FfsList=FfsFileList,
159 ForceRebase=self.FvForceRebase,
160 FileSystemGuid=FFSGuid
161 )
162
163 NewFvInfo = None
164 if os.path.exists (FvInfoFileName):
165 NewFvInfo = open(FvInfoFileName, 'r').read()
166 if NewFvInfo is not None and NewFvInfo != OrigFvInfo:
167 FvChildAddr = []
168 AddFileObj = open(FvInfoFileName, 'r')
169 AddrStrings = AddFileObj.readlines()
170 AddrKeyFound = False
171 for AddrString in AddrStrings:
172 if AddrKeyFound:
173 #get base address for the inside FvImage
174 FvChildAddr.append (AddrString)
175 elif AddrString.find ("[FV_BASE_ADDRESS]") != -1:
176 AddrKeyFound = True
177 AddFileObj.close()
178
179 if FvChildAddr != []:
180 # Update Ffs again
181 for FfsFile in self.FfsList :
182 FileName = FfsFile.GenFfs(MacroDict, FvChildAddr, BaseAddress, IsMakefile=Flag, FvName=self.UiFvName)
183
184 if GenFdsGlobalVariable.LargeFileInFvFlags[-1]:
185 FFSGuid = GenFdsGlobalVariable.EFI_FIRMWARE_FILE_SYSTEM3_GUID;
186 #Update GenFv again
187 GenFdsGlobalVariable.GenerateFirmwareVolume(
188 FvOutputFile,
189 [self.InfFileName],
190 AddressFile=FvInfoFileName,
191 FfsList=FfsFileList,
192 ForceRebase=self.FvForceRebase,
193 FileSystemGuid=FFSGuid
194 )
195
196 #
197 # Write the Fv contents to Buffer
198 #
199 if os.path.isfile(FvOutputFile):
200 FvFileObj = open(FvOutputFile, 'rb')
201 GenFdsGlobalVariable.VerboseLogger("\nGenerate %s FV Successfully" % self.UiFvName)
202 GenFdsGlobalVariable.SharpCounter = 0
203
204 Buffer.write(FvFileObj.read())
205 FvFileObj.seek(0)
206 # PI FvHeader is 0x48 byte
207 FvHeaderBuffer = FvFileObj.read(0x48)
208 # FV alignment position.
209 FvAlignmentValue = 1 << (ord(FvHeaderBuffer[0x2E]) & 0x1F)
210 if FvAlignmentValue >= 0x400:
211 if FvAlignmentValue >= 0x100000:
212 if FvAlignmentValue >= 0x1000000:
213 #The max alignment supported by FFS is 16M.
214 self.FvAlignment = "16M"
215 else:
216 self.FvAlignment = str(FvAlignmentValue / 0x100000) + "M"
217 else:
218 self.FvAlignment = str(FvAlignmentValue / 0x400) + "K"
219 else:
220 # FvAlignmentValue is less than 1K
221 self.FvAlignment = str (FvAlignmentValue)
222 FvFileObj.close()
223 GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile
224 GenFdsGlobalVariable.LargeFileInFvFlags.pop()
225 else:
226 GenFdsGlobalVariable.ErrorLogger("Failed to generate %s FV file." %self.UiFvName)
227 return FvOutputFile
228
229 ## _GetBlockSize()
230 #
231 # Calculate FV's block size
232 # Inherit block size from FD if no block size specified in FV
233 #
234 def _GetBlockSize(self):
235 if self.BlockSizeList:
236 return True
237
238 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
239 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]
240 for RegionObj in FdObj.RegionList:
241 if RegionObj.RegionType != 'FV':
242 continue
243 for RegionData in RegionObj.RegionDataList:
244 #
245 # Found the FD and region that contain this FV
246 #
247 if self.UiFvName.upper() == RegionData.upper():
248 RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, self)
249 if self.BlockSizeList:
250 return True
251 return False
252
253 ## __InitializeInf__()
254 #
255 # Initilize the inf file to create FV
256 #
257 # @param self The object pointer
258 # @param BaseAddress base address of FV
259 # @param BlockSize block size of FV
260 # @param BlockNum How many blocks in FV
261 # @param ErasePolarity Flash erase polarity
262 # @param VtfDict VTF objects
263 #
264 def __InitializeInf__ (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1', VtfDict=None) :
265 #
266 # Create FV inf file
267 #
268 self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
269 self.UiFvName + '.inf')
270 self.FvInfFile = StringIO.StringIO()
271
272 #
273 # Add [Options]
274 #
275 self.FvInfFile.writelines("[options]" + T_CHAR_LF)
276 if BaseAddress is not None :
277 self.FvInfFile.writelines("EFI_BASE_ADDRESS = " + \
278 BaseAddress + \
279 T_CHAR_LF)
280
281 if BlockSize is not None:
282 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \
283 '0x%X' %BlockSize + \
284 T_CHAR_LF)
285 if BlockNum is not None:
286 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \
287 ' 0x%X' %BlockNum + \
288 T_CHAR_LF)
289 else:
290 if self.BlockSizeList == []:
291 if not self._GetBlockSize():
292 #set default block size is 1
293 self.FvInfFile.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF)
294
295 for BlockSize in self.BlockSizeList :
296 if BlockSize[0] is not None:
297 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \
298 '0x%X' %BlockSize[0] + \
299 T_CHAR_LF)
300
301 if BlockSize[1] is not None:
302 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \
303 ' 0x%X' %BlockSize[1] + \
304 T_CHAR_LF)
305
306 if self.BsBaseAddress is not None:
307 self.FvInfFile.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
308 '0x%X' %self.BsBaseAddress)
309 if self.RtBaseAddress is not None:
310 self.FvInfFile.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
311 '0x%X' %self.RtBaseAddress)
312 #
313 # Add attribute
314 #
315 self.FvInfFile.writelines("[attributes]" + T_CHAR_LF)
316
317 self.FvInfFile.writelines("EFI_ERASE_POLARITY = " + \
318 ' %s' %ErasePloarity + \
319 T_CHAR_LF)
320 if not (self.FvAttributeDict is None):
321 for FvAttribute in self.FvAttributeDict:
322 if FvAttribute == "FvUsedSizeEnable":
323 if self.FvAttributeDict[FvAttribute].upper() in ('TRUE', '1') :
324 self.UsedSizeEnable = True
325 continue
326 self.FvInfFile.writelines("EFI_" + \
327 FvAttribute + \
328 ' = ' + \
329 self.FvAttributeDict[FvAttribute] + \
330 T_CHAR_LF )
331 if self.FvAlignment is not None:
332 self.FvInfFile.writelines("EFI_FVB2_ALIGNMENT_" + \
333 self.FvAlignment.strip() + \
334 " = TRUE" + \
335 T_CHAR_LF)
336
337 #
338 # Generate FV extension header file
339 #
340 if not self.FvNameGuid:
341 if len(self.FvExtEntryType) > 0 or self.UsedSizeEnable:
342 GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))
343 else:
344 TotalSize = 16 + 4
345 Buffer = ''
346 if self.UsedSizeEnable:
347 TotalSize += (4 + 4)
348 ## define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03
349 #typedef struct
350 # {
351 # EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
352 # UINT32 UsedSize;
353 # } EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE;
354 Buffer += pack('HHL', 8, 3, 0)
355
356 if self.FvNameString == 'TRUE':
357 #
358 # Create EXT entry for FV UI name
359 # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C
360 #
361 FvUiLen = len(self.UiFvName)
362 TotalSize += (FvUiLen + 16 + 4)
363 Guid = FV_UI_EXT_ENTY_GUID.split('-')
364 #
365 # Layout:
366 # EFI_FIRMWARE_VOLUME_EXT_ENTRY : size 4
367 # GUID : size 16
368 # FV UI name
369 #
370 Buffer += (pack('HH', (FvUiLen + 16 + 4), 0x0002)
371 + pack('=LHHBBBBBBBB', int(Guid[0], 16), int(Guid[1], 16), int(Guid[2], 16),
372 int(Guid[3][-4:-2], 16), int(Guid[3][-2:], 16), int(Guid[4][-12:-10], 16),
373 int(Guid[4][-10:-8], 16), int(Guid[4][-8:-6], 16), int(Guid[4][-6:-4], 16),
374 int(Guid[4][-4:-2], 16), int(Guid[4][-2:], 16))
375 + self.UiFvName)
376
377 for Index in range (0, len(self.FvExtEntryType)):
378 if self.FvExtEntryType[Index] == 'FILE':
379 # check if the path is absolute or relative
380 if os.path.isabs(self.FvExtEntryData[Index]):
381 FileFullPath = os.path.normpath(self.FvExtEntryData[Index])
382 else:
383 FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))
384 # check if the file path exists or not
385 if not os.path.isfile(FileFullPath):
386 GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))
387 FvExtFile = open (FileFullPath,'rb')
388 FvExtFile.seek(0,2)
389 Size = FvExtFile.tell()
390 if Size >= 0x10000:
391 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
392 TotalSize += (Size + 4)
393 FvExtFile.seek(0)
394 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
395 Buffer += FvExtFile.read()
396 FvExtFile.close()
397 if self.FvExtEntryType[Index] == 'DATA':
398 ByteList = self.FvExtEntryData[Index].split(',')
399 Size = len (ByteList)
400 if Size >= 0x10000:
401 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
402 TotalSize += (Size + 4)
403 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
404 for Index1 in range (0, Size):
405 Buffer += pack('B', int(ByteList[Index1], 16))
406
407 Guid = self.FvNameGuid.split('-')
408 Buffer = pack('=LHHBBBBBBBBL',
409 int(Guid[0], 16),
410 int(Guid[1], 16),
411 int(Guid[2], 16),
412 int(Guid[3][-4:-2], 16),
413 int(Guid[3][-2:], 16),
414 int(Guid[4][-12:-10], 16),
415 int(Guid[4][-10:-8], 16),
416 int(Guid[4][-8:-6], 16),
417 int(Guid[4][-6:-4], 16),
418 int(Guid[4][-4:-2], 16),
419 int(Guid[4][-2:], 16),
420 TotalSize
421 ) + Buffer
422
423 #
424 # Generate FV extension header file if the total size is not zero
425 #
426 if TotalSize > 0:
427 FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')
428 FvExtHeaderFile = StringIO.StringIO()
429 FvExtHeaderFile.write(Buffer)
430 Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True)
431 FvExtHeaderFile.close()
432 if Changed:
433 if os.path.exists (self.InfFileName):
434 os.remove (self.InfFileName)
435 self.FvInfFile.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
436 FvExtHeaderFileName + \
437 T_CHAR_LF)
438
439
440 #
441 # Add [Files]
442 #
443 self.FvInfFile.writelines("[files]" + T_CHAR_LF)
444 if VtfDict is not None and self.UiFvName in VtfDict.keys():
445 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
446 VtfDict.get(self.UiFvName) + \
447 T_CHAR_LF)