]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Fv.py
Sync tool code to BuildTools project r1739.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Fv.py
1 ## @file
2 # process FV generation
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 #
18 import os
19 import shutil
20 import subprocess
21 import StringIO
22 from struct import *
23
24 import Ffs
25 import AprioriSection
26 from GenFdsGlobalVariable import GenFdsGlobalVariable
27 from GenFds import GenFds
28 from CommonDataClass.FdfClass import FvClassObject
29 from Common.Misc import SaveFileOnChange
30
31 T_CHAR_LF = '\n'
32
33 ## generate FV
34 #
35 #
36 class FV (FvClassObject):
37 ## The constructor
38 #
39 # @param self The object pointer
40 #
41 def __init__(self):
42 FvClassObject.__init__(self)
43 self.FvInfFile = None
44 self.FvAddressFile = None
45 self.BaseAddress = None
46 self.InfFileName = None
47 self.FvAddressFileName = None
48 self.CapsuleName = None
49
50 ## AddToBuffer()
51 #
52 # Generate Fv and add it to the Buffer
53 #
54 # @param self The object pointer
55 # @param Buffer The buffer generated FV data will be put
56 # @param BaseAddress base address of FV
57 # @param BlockSize block size of FV
58 # @param BlockNum How many blocks in FV
59 # @param ErasePolarity Flash erase polarity
60 # @param VtfDict VTF objects
61 # @param MacroDict macro value pair
62 # @retval string Generated FV file path
63 #
64 def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', VtfDict=None, MacroDict = {}) :
65
66 if self.UiFvName.upper() + 'fv' in GenFds.ImageBinDict.keys():
67 return GenFds.ImageBinDict[self.UiFvName.upper() + 'fv']
68
69 #
70 # Check whether FV in Capsule is in FD flash region.
71 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
72 #
73 if self.CapsuleName != None:
74 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():
75 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]
76 for RegionObj in FdObj.RegionList:
77 if RegionObj.RegionType == 'FV':
78 for RegionData in RegionObj.RegionDataList:
79 if RegionData.endswith(".fv"):
80 continue
81 elif RegionData.upper() + 'fv' in GenFds.ImageBinDict.keys():
82 continue
83 elif self.UiFvName.upper() == RegionData.upper():
84 GenFdsGlobalVariable.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self.CapsuleName, self.UiFvName.upper()))
85
86 GenFdsGlobalVariable.InfLogger( "\nGenerating %s FV" %self.UiFvName)
87
88 self.__InitializeInf__(BaseAddress, BlockSize, BlockNum, ErasePloarity, VtfDict)
89 #
90 # First Process the Apriori section
91 #
92 MacroDict.update(self.DefineVarDict)
93
94 GenFdsGlobalVariable.VerboseLogger('First generate Apriori file !')
95 FfsFileList = []
96 for AprSection in self.AprioriSectionList:
97 FileName = AprSection.GenFfs (self.UiFvName, MacroDict)
98 FfsFileList.append(FileName)
99 # Add Apriori file name to Inf file
100 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
101 FileName + \
102 T_CHAR_LF)
103
104 # Process Modules in FfsList
105 for FfsFile in self.FfsList :
106 FileName = FfsFile.GenFfs(MacroDict)
107 FfsFileList.append(FileName)
108 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
109 FileName + \
110 T_CHAR_LF)
111
112 SaveFileOnChange(self.InfFileName, self.FvInfFile.getvalue(), False)
113 self.FvInfFile.close()
114 #
115 # Call GenFv tool
116 #
117 FvOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName)
118 FvOutputFile = FvOutputFile + '.Fv'
119 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
120 if self.CreateFileName != None:
121 FvOutputFile = self.CreateFileName
122
123 FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf')
124 shutil.copy(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName)
125 GenFdsGlobalVariable.GenerateFirmwareVolume(
126 FvOutputFile,
127 [self.InfFileName],
128 AddressFile=FvInfoFileName,
129 FfsList=FfsFileList
130 )
131
132 #
133 # Write the Fv contents to Buffer
134 #
135 FvFileObj = open ( FvOutputFile,'r+b')
136
137 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s FV Successfully" %self.UiFvName)
138 GenFdsGlobalVariable.SharpCounter = 0
139
140 Buffer.write(FvFileObj.read())
141 FvFileObj.close()
142 GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile
143 return FvOutputFile
144
145 ## __InitializeInf__()
146 #
147 # Initilize the inf file to create FV
148 #
149 # @param self The object pointer
150 # @param BaseAddress base address of FV
151 # @param BlockSize block size of FV
152 # @param BlockNum How many blocks in FV
153 # @param ErasePolarity Flash erase polarity
154 # @param VtfDict VTF objects
155 #
156 def __InitializeInf__ (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1', VtfDict=None) :
157 #
158 # Create FV inf file
159 #
160 self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
161 self.UiFvName + '.inf')
162 self.FvInfFile = StringIO.StringIO()
163
164 #
165 # Add [Options]
166 #
167 self.FvInfFile.writelines("[options]" + T_CHAR_LF)
168 if BaseAddress != None :
169 self.FvInfFile.writelines("EFI_BASE_ADDRESS = " + \
170 BaseAddress + \
171 T_CHAR_LF)
172
173 if BlockSize != None:
174 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \
175 '0x%X' %BlockSize + \
176 T_CHAR_LF)
177 if BlockNum != None:
178 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \
179 ' 0x%X' %BlockNum + \
180 T_CHAR_LF)
181 else:
182 for BlockSize in self.BlockSizeList :
183 if BlockSize[0] != None:
184 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \
185 '0x%X' %BlockSize[0] + \
186 T_CHAR_LF)
187
188 if BlockSize[1] != None:
189 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \
190 ' 0x%X' %BlockSize[1] + \
191 T_CHAR_LF)
192
193 if self.BsBaseAddress != None:
194 self.FvInfFile.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
195 '0x%X' %self.BsBaseAddress)
196 if self.RtBaseAddress != None:
197 self.FvInfFile.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
198 '0x%X' %self.RtBaseAddress)
199 #
200 # Add attribute
201 #
202 self.FvInfFile.writelines("[attributes]" + T_CHAR_LF)
203
204 self.FvInfFile.writelines("EFI_ERASE_POLARITY = " + \
205 ' %s' %ErasePloarity + \
206 T_CHAR_LF)
207 if not (self.FvAttributeDict == None):
208 for FvAttribute in self.FvAttributeDict.keys() :
209 self.FvInfFile.writelines("EFI_" + \
210 FvAttribute + \
211 ' = ' + \
212 self.FvAttributeDict[FvAttribute] + \
213 T_CHAR_LF )
214 if self.FvAlignment != None:
215 self.FvInfFile.writelines("EFI_FVB2_ALIGNMENT_" + \
216 self.FvAlignment.strip() + \
217 " = TRUE" + \
218 T_CHAR_LF)
219
220 #
221 # Generate FV extension header file
222 #
223 if self.FvNameGuid == None or self.FvNameGuid == '':
224 if len(self.FvExtEntryType) > 0:
225 GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))
226
227 if self.FvNameGuid <> None and self.FvNameGuid <> '':
228 TotalSize = 16 + 4
229 Buffer = ''
230 for Index in range (0, len(self.FvExtEntryType)):
231 if self.FvExtEntryType[Index] == 'FILE':
232 # check if the path is absolute or relative
233 if os.path.isabs(self.FvExtEntryData[Index]):
234 FileFullPath = os.path.normpath(self.FvExtEntryData[Index])
235 else:
236 FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))
237 # check if the file path exists or not
238 if not os.path.isfile(FileFullPath):
239 GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))
240 FvExtFile = open (FileFullPath,'rb')
241 FvExtFile.seek(0,2)
242 Size = FvExtFile.tell()
243 if Size >= 0x10000:
244 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
245 TotalSize += (Size + 4)
246 FvExtFile.seek(0)
247 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
248 Buffer += FvExtFile.read()
249 FvExtFile.close()
250 if self.FvExtEntryType[Index] == 'DATA':
251 ByteList = self.FvExtEntryData[Index].split(',')
252 Size = len (ByteList)
253 if Size >= 0x10000:
254 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))
255 TotalSize += (Size + 4)
256 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))
257 for Index1 in range (0, Size):
258 Buffer += pack('B', int(ByteList[Index1], 16))
259
260 Guid = self.FvNameGuid.split('-')
261 Buffer = pack('LHHBBBBBBBBL',
262 int(Guid[0], 16),
263 int(Guid[1], 16),
264 int(Guid[2], 16),
265 int(Guid[3][-4:-2], 16),
266 int(Guid[3][-2:], 16),
267 int(Guid[4][-12:-10], 16),
268 int(Guid[4][-10:-8], 16),
269 int(Guid[4][-8:-6], 16),
270 int(Guid[4][-6:-4], 16),
271 int(Guid[4][-4:-2], 16),
272 int(Guid[4][-2:], 16),
273 TotalSize
274 ) + Buffer
275
276 #
277 # Generate FV extension header file if the total size is not zero
278 #
279 if TotalSize > 0:
280 FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')
281 FvExtHeaderFile = open (FvExtHeaderFileName,'wb')
282 FvExtHeaderFile.write(Buffer)
283 FvExtHeaderFile.close()
284 self.FvInfFile.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
285 FvExtHeaderFileName + \
286 T_CHAR_LF)
287
288
289 #
290 # Add [Files]
291 #
292 self.FvInfFile.writelines("[files]" + T_CHAR_LF)
293 if VtfDict != None and self.UiFvName in VtfDict.keys():
294 self.FvInfFile.writelines("EFI_FILE_NAME = " + \
295 VtfDict.get(self.UiFvName) + \
296 T_CHAR_LF)