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