]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/Fv.py
BaseTools: Don't need to add extra quotes when UI string from file
[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
199 if FvAlignmentValue >= 0x10000:\r
200 #The max alignment supported by FFS is 64K.\r
201 self.FvAlignment = "64K"\r
202 else:\r
203 self.FvAlignment = str (FvAlignmentValue / 0x400) + "K"\r
52302d4d 204 else:\r
2ff9e575
YZ
205 # FvAlignmentValue is less than 1K\r
206 self.FvAlignment = str (FvAlignmentValue)\r
207 FvFileObj.close()\r
208 GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile\r
209 GenFdsGlobalVariable.LargeFileInFvFlags.pop()\r
52302d4d 210 else:\r
2ff9e575 211 GenFdsGlobalVariable.ErrorLogger("Failed to generate %s FV file." %self.UiFvName)\r
30fdf114
LG
212 return FvOutputFile\r
213\r
29d960f9
YL
214 ## _GetBlockSize()\r
215 #\r
216 # Calculate FV's block size\r
217 # Inherit block size from FD if no block size specified in FV\r
218 #\r
219 def _GetBlockSize(self):\r
220 if self.BlockSizeList:\r
221 return True\r
222\r
223 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():\r
224 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]\r
225 for RegionObj in FdObj.RegionList:\r
226 if RegionObj.RegionType != 'FV':\r
227 continue\r
228 for RegionData in RegionObj.RegionDataList:\r
229 #\r
230 # Found the FD and region that contain this FV\r
231 #\r
232 if self.UiFvName.upper() == RegionData.upper():\r
233 RegionObj.BlockInfoOfRegion(FdObj.BlockSizeList, self)\r
234 if self.BlockSizeList:\r
235 return True\r
236 return False\r
237\r
30fdf114
LG
238 ## __InitializeInf__()\r
239 #\r
240 # Initilize the inf file to create FV\r
241 #\r
242 # @param self The object pointer\r
243 # @param BaseAddress base address of FV\r
244 # @param BlockSize block size of FV\r
245 # @param BlockNum How many blocks in FV\r
246 # @param ErasePolarity Flash erase polarity\r
247 # @param VtfDict VTF objects\r
248 #\r
249 def __InitializeInf__ (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1', VtfDict=None) :\r
250 #\r
251 # Create FV inf file\r
252 #\r
253 self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,\r
254 self.UiFvName + '.inf')\r
255 self.FvInfFile = StringIO.StringIO()\r
256\r
257 #\r
258 # Add [Options]\r
259 #\r
260 self.FvInfFile.writelines("[options]" + T_CHAR_LF)\r
261 if BaseAddress != None :\r
262 self.FvInfFile.writelines("EFI_BASE_ADDRESS = " + \\r
263 BaseAddress + \\r
264 T_CHAR_LF)\r
265\r
266 if BlockSize != None:\r
267 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \\r
268 '0x%X' %BlockSize + \\r
269 T_CHAR_LF)\r
270 if BlockNum != None:\r
271 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \\r
272 ' 0x%X' %BlockNum + \\r
273 T_CHAR_LF)\r
274 else:\r
52302d4d 275 if self.BlockSizeList == []:\r
29d960f9
YL
276 if not self._GetBlockSize():\r
277 #set default block size is 1\r
278 self.FvInfFile.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF)\r
52302d4d 279 \r
30fdf114
LG
280 for BlockSize in self.BlockSizeList :\r
281 if BlockSize[0] != None:\r
282 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \\r
283 '0x%X' %BlockSize[0] + \\r
284 T_CHAR_LF)\r
285\r
286 if BlockSize[1] != None:\r
287 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \\r
288 ' 0x%X' %BlockSize[1] + \\r
289 T_CHAR_LF)\r
290\r
291 if self.BsBaseAddress != None:\r
292 self.FvInfFile.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \\r
293 '0x%X' %self.BsBaseAddress)\r
294 if self.RtBaseAddress != None:\r
295 self.FvInfFile.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \\r
296 '0x%X' %self.RtBaseAddress)\r
297 #\r
298 # Add attribute\r
299 #\r
300 self.FvInfFile.writelines("[attributes]" + T_CHAR_LF)\r
301\r
302 self.FvInfFile.writelines("EFI_ERASE_POLARITY = " + \\r
303 ' %s' %ErasePloarity + \\r
304 T_CHAR_LF)\r
305 if not (self.FvAttributeDict == None):\r
306 for FvAttribute in self.FvAttributeDict.keys() :\r
307 self.FvInfFile.writelines("EFI_" + \\r
308 FvAttribute + \\r
309 ' = ' + \\r
310 self.FvAttributeDict[FvAttribute] + \\r
311 T_CHAR_LF )\r
312 if self.FvAlignment != None:\r
313 self.FvInfFile.writelines("EFI_FVB2_ALIGNMENT_" + \\r
314 self.FvAlignment.strip() + \\r
315 " = TRUE" + \\r
316 T_CHAR_LF)\r
b303ea72 317 \r
30fdf114 318 #\r
b303ea72 319 # Generate FV extension header file\r
30fdf114 320 #\r
b303ea72
LG
321 if self.FvNameGuid == None or self.FvNameGuid == '':\r
322 if len(self.FvExtEntryType) > 0:\r
323 GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))\r
324 \r
325 if self.FvNameGuid <> None and self.FvNameGuid <> '':\r
326 TotalSize = 16 + 4\r
327 Buffer = ''\r
aaf8aa7b
YL
328 if self.FvNameString == 'TRUE':\r
329 #\r
330 # Create EXT entry for FV UI name\r
331 # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C\r
332 #\r
333 FvUiLen = len(self.UiFvName)\r
334 TotalSize += (FvUiLen + 16 + 4)\r
335 Guid = FV_UI_EXT_ENTY_GUID.split('-')\r
336 #\r
337 # Layout:\r
338 # EFI_FIRMWARE_VOLUME_EXT_ENTRY : size 4\r
339 # GUID : size 16\r
340 # FV UI name\r
341 #\r
342 Buffer += (pack('HH', (FvUiLen + 16 + 4), 0x0002)\r
343 + pack('=LHHBBBBBBBB', int(Guid[0], 16), int(Guid[1], 16), int(Guid[2], 16),\r
344 int(Guid[3][-4:-2], 16), int(Guid[3][-2:], 16), int(Guid[4][-12:-10], 16),\r
345 int(Guid[4][-10:-8], 16), int(Guid[4][-8:-6], 16), int(Guid[4][-6:-4], 16),\r
346 int(Guid[4][-4:-2], 16), int(Guid[4][-2:], 16))\r
347 + self.UiFvName)\r
0614d73b 348\r
b303ea72
LG
349 for Index in range (0, len(self.FvExtEntryType)):\r
350 if self.FvExtEntryType[Index] == 'FILE':\r
f51461c8
LG
351 # check if the path is absolute or relative\r
352 if os.path.isabs(self.FvExtEntryData[Index]):\r
353 FileFullPath = os.path.normpath(self.FvExtEntryData[Index])\r
354 else:\r
355 FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))\r
356 # check if the file path exists or not\r
357 if not os.path.isfile(FileFullPath):\r
b303ea72
LG
358 GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))\r
359 FvExtFile = open (FileFullPath,'rb')\r
360 FvExtFile.seek(0,2)\r
361 Size = FvExtFile.tell()\r
362 if Size >= 0x10000:\r
363 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))\r
364 TotalSize += (Size + 4)\r
365 FvExtFile.seek(0)\r
366 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))\r
367 Buffer += FvExtFile.read() \r
368 FvExtFile.close()\r
369 if self.FvExtEntryType[Index] == 'DATA':\r
370 ByteList = self.FvExtEntryData[Index].split(',')\r
371 Size = len (ByteList)\r
372 if Size >= 0x10000:\r
373 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))\r
374 TotalSize += (Size + 4)\r
375 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))\r
376 for Index1 in range (0, Size):\r
377 Buffer += pack('B', int(ByteList[Index1], 16))\r
378\r
379 Guid = self.FvNameGuid.split('-')\r
9508d0fa 380 Buffer = pack('=LHHBBBBBBBBL', \r
b303ea72
LG
381 int(Guid[0], 16), \r
382 int(Guid[1], 16), \r
383 int(Guid[2], 16), \r
384 int(Guid[3][-4:-2], 16), \r
385 int(Guid[3][-2:], 16), \r
386 int(Guid[4][-12:-10], 16),\r
387 int(Guid[4][-10:-8], 16),\r
388 int(Guid[4][-8:-6], 16),\r
389 int(Guid[4][-6:-4], 16),\r
390 int(Guid[4][-4:-2], 16),\r
391 int(Guid[4][-2:], 16),\r
392 TotalSize\r
393 ) + Buffer\r
394\r
395 #\r
396 # Generate FV extension header file if the total size is not zero\r
397 #\r
398 if TotalSize > 0:\r
399 FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')\r
a709adfa 400 FvExtHeaderFile = StringIO.StringIO()\r
b303ea72 401 FvExtHeaderFile.write(Buffer)\r
a709adfa 402 Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True)\r
b303ea72 403 FvExtHeaderFile.close()\r
a709adfa
LG
404 if Changed:\r
405 if os.path.exists (self.InfFileName):\r
406 os.remove (self.InfFileName)\r
b303ea72
LG
407 self.FvInfFile.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \\r
408 FvExtHeaderFileName + \\r
409 T_CHAR_LF)\r
30fdf114 410\r
b303ea72
LG
411 \r
412 #\r
413 # Add [Files]\r
414 #\r
30fdf114
LG
415 self.FvInfFile.writelines("[files]" + T_CHAR_LF)\r
416 if VtfDict != None and self.UiFvName in VtfDict.keys():\r
417 self.FvInfFile.writelines("EFI_FILE_NAME = " + \\r
418 VtfDict.get(self.UiFvName) + \\r
419 T_CHAR_LF)\r