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