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