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