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