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