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