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