]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/GenFds/Fv.py
ShellPkg: Add checks for NULL pointers.
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / Fv.py
CommitLineData
30fdf114
LG
1## @file\r
2# process FV generation\r
3#\r
40d841f6 4# Copyright (c) 2007 - 2010, 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
18import os\r
19import shutil\r
20import subprocess\r
21import StringIO\r
b303ea72 22from struct import *\r
30fdf114
LG
23\r
24import Ffs\r
25import AprioriSection\r
26from GenFdsGlobalVariable import GenFdsGlobalVariable\r
27from GenFds import GenFds\r
28from CommonDataClass.FdfClass import FvClassObject\r
29from Common.Misc import SaveFileOnChange\r
30\r
31T_CHAR_LF = '\n'\r
32\r
33## generate FV\r
34#\r
35#\r
36class FV (FvClassObject):\r
37 ## The constructor\r
38 #\r
39 # @param self The object pointer\r
40 #\r
41 def __init__(self):\r
42 FvClassObject.__init__(self)\r
43 self.FvInfFile = None\r
44 self.FvAddressFile = None\r
45 self.BaseAddress = None\r
46 self.InfFileName = None\r
47 self.FvAddressFileName = None\r
fd171542 48 self.CapsuleName = None\r
4234283c 49 self.FvBaseAddress = None\r
30fdf114
LG
50\r
51 ## AddToBuffer()\r
52 #\r
53 # Generate Fv and add it to the Buffer\r
54 #\r
55 # @param self The object pointer\r
56 # @param Buffer The buffer generated FV data will be put\r
57 # @param BaseAddress base address of FV\r
58 # @param BlockSize block size of FV\r
59 # @param BlockNum How many blocks in FV\r
60 # @param ErasePolarity Flash erase polarity\r
61 # @param VtfDict VTF objects\r
62 # @param MacroDict macro value pair\r
63 # @retval string Generated FV file path\r
64 #\r
65 def AddToBuffer (self, Buffer, BaseAddress=None, BlockSize= None, BlockNum=None, ErasePloarity='1', VtfDict=None, MacroDict = {}) :\r
66\r
52302d4d 67 if BaseAddress == None and self.UiFvName.upper() + 'fv' in GenFds.ImageBinDict.keys():\r
fd171542 68 return GenFds.ImageBinDict[self.UiFvName.upper() + 'fv']\r
69 \r
70 #\r
71 # Check whether FV in Capsule is in FD flash region.\r
72 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.\r
73 #\r
74 if self.CapsuleName != None:\r
b303ea72
LG
75 for FdName in GenFdsGlobalVariable.FdfParser.Profile.FdDict.keys():\r
76 FdObj = GenFdsGlobalVariable.FdfParser.Profile.FdDict[FdName]\r
fd171542 77 for RegionObj in FdObj.RegionList:\r
78 if RegionObj.RegionType == 'FV':\r
79 for RegionData in RegionObj.RegionDataList:\r
80 if RegionData.endswith(".fv"):\r
81 continue\r
82 elif RegionData.upper() + 'fv' in GenFds.ImageBinDict.keys():\r
83 continue\r
84 elif self.UiFvName.upper() == RegionData.upper():\r
85 GenFdsGlobalVariable.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self.CapsuleName, self.UiFvName.upper()))\r
30fdf114 86\r
fd171542 87 GenFdsGlobalVariable.InfLogger( "\nGenerating %s FV" %self.UiFvName)\r
4234283c
LG
88 \r
89 if self.FvBaseAddress != None:\r
90 BaseAddress = self.FvBaseAddress \r
91 \r
30fdf114
LG
92 self.__InitializeInf__(BaseAddress, BlockSize, BlockNum, ErasePloarity, VtfDict)\r
93 #\r
94 # First Process the Apriori section\r
95 #\r
96 MacroDict.update(self.DefineVarDict)\r
97\r
98 GenFdsGlobalVariable.VerboseLogger('First generate Apriori file !')\r
99 FfsFileList = []\r
100 for AprSection in self.AprioriSectionList:\r
101 FileName = AprSection.GenFfs (self.UiFvName, MacroDict)\r
102 FfsFileList.append(FileName)\r
103 # Add Apriori file name to Inf file\r
104 self.FvInfFile.writelines("EFI_FILE_NAME = " + \\r
105 FileName + \\r
106 T_CHAR_LF)\r
107\r
108 # Process Modules in FfsList\r
109 for FfsFile in self.FfsList :\r
52302d4d 110 FileName = FfsFile.GenFfs(MacroDict, FvParentAddr=BaseAddress)\r
30fdf114
LG
111 FfsFileList.append(FileName)\r
112 self.FvInfFile.writelines("EFI_FILE_NAME = " + \\r
113 FileName + \\r
114 T_CHAR_LF)\r
115\r
116 SaveFileOnChange(self.InfFileName, self.FvInfFile.getvalue(), False)\r
117 self.FvInfFile.close()\r
118 #\r
119 # Call GenFv tool\r
120 #\r
121 FvOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName)\r
122 FvOutputFile = FvOutputFile + '.Fv'\r
123 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)\r
124 if self.CreateFileName != None:\r
125 FvOutputFile = self.CreateFileName\r
126\r
127 FvInfoFileName = os.path.join(GenFdsGlobalVariable.FfsDir, self.UiFvName + '.inf')\r
128 shutil.copy(GenFdsGlobalVariable.FvAddressFileName, FvInfoFileName)\r
52302d4d
LG
129 OrigFvInfo = None\r
130 if os.path.exists (FvInfoFileName):\r
131 OrigFvInfo = open(FvInfoFileName, 'r').read()\r
30fdf114
LG
132 GenFdsGlobalVariable.GenerateFirmwareVolume(\r
133 FvOutputFile,\r
134 [self.InfFileName],\r
135 AddressFile=FvInfoFileName,\r
136 FfsList=FfsFileList\r
137 )\r
138\r
52302d4d
LG
139 NewFvInfo = None\r
140 if os.path.exists (FvInfoFileName):\r
141 NewFvInfo = open(FvInfoFileName, 'r').read()\r
142 if NewFvInfo != None and NewFvInfo != OrigFvInfo:\r
143 FvChildAddr = []\r
144 AddFileObj = open(FvInfoFileName, 'r')\r
145 AddrStrings = AddFileObj.readlines()\r
146 AddrKeyFound = False\r
147 for AddrString in AddrStrings:\r
148 if AddrKeyFound:\r
149 #get base address for the inside FvImage\r
150 FvChildAddr.append (AddrString)\r
151 elif AddrString.find ("[FV_BASE_ADDRESS]") != -1:\r
152 AddrKeyFound = True\r
153 AddFileObj.close()\r
154\r
155 if FvChildAddr != []:\r
156 # Update Ffs again\r
157 for FfsFile in self.FfsList :\r
158 FileName = FfsFile.GenFfs(MacroDict, FvChildAddr, BaseAddress)\r
159 \r
160 #Update GenFv again\r
161 GenFdsGlobalVariable.GenerateFirmwareVolume(\r
162 FvOutputFile,\r
163 [self.InfFileName],\r
164 AddressFile=FvInfoFileName,\r
165 FfsList=FfsFileList\r
166 )\r
167\r
30fdf114
LG
168 #\r
169 # Write the Fv contents to Buffer\r
170 #\r
171 FvFileObj = open ( FvOutputFile,'r+b')\r
172\r
fd171542 173 GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s FV Successfully" %self.UiFvName)\r
30fdf114
LG
174 GenFdsGlobalVariable.SharpCounter = 0\r
175\r
176 Buffer.write(FvFileObj.read())\r
52302d4d
LG
177 FvFileObj.seek(0)\r
178 # PI FvHeader is 0x48 byte\r
179 FvHeaderBuffer = FvFileObj.read(0x48)\r
180 # FV alignment position.\r
181 FvAlignmentValue = 1 << (ord (FvHeaderBuffer[0x2E]) & 0x1F)\r
182 # FvAlignmentValue is larger than or equal to 1K\r
183 if FvAlignmentValue >= 0x400:\r
184 if FvAlignmentValue >= 0x10000:\r
185 #The max alignment supported by FFS is 64K.\r
186 self.FvAlignment = "64K"\r
187 else:\r
188 self.FvAlignment = str (FvAlignmentValue / 0x400) + "K"\r
189 else:\r
190 # FvAlignmentValue is less than 1K\r
191 self.FvAlignment = str (FvAlignmentValue)\r
30fdf114 192 FvFileObj.close()\r
fd171542 193 GenFds.ImageBinDict[self.UiFvName.upper() + 'fv'] = FvOutputFile\r
30fdf114
LG
194 return FvOutputFile\r
195\r
196 ## __InitializeInf__()\r
197 #\r
198 # Initilize the inf file to create FV\r
199 #\r
200 # @param self The object pointer\r
201 # @param BaseAddress base address of FV\r
202 # @param BlockSize block size of FV\r
203 # @param BlockNum How many blocks in FV\r
204 # @param ErasePolarity Flash erase polarity\r
205 # @param VtfDict VTF objects\r
206 #\r
207 def __InitializeInf__ (self, BaseAddress = None, BlockSize= None, BlockNum = None, ErasePloarity='1', VtfDict=None) :\r
208 #\r
209 # Create FV inf file\r
210 #\r
211 self.InfFileName = os.path.join(GenFdsGlobalVariable.FvDir,\r
212 self.UiFvName + '.inf')\r
213 self.FvInfFile = StringIO.StringIO()\r
214\r
215 #\r
216 # Add [Options]\r
217 #\r
218 self.FvInfFile.writelines("[options]" + T_CHAR_LF)\r
219 if BaseAddress != None :\r
220 self.FvInfFile.writelines("EFI_BASE_ADDRESS = " + \\r
221 BaseAddress + \\r
222 T_CHAR_LF)\r
223\r
224 if BlockSize != None:\r
225 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \\r
226 '0x%X' %BlockSize + \\r
227 T_CHAR_LF)\r
228 if BlockNum != None:\r
229 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \\r
230 ' 0x%X' %BlockNum + \\r
231 T_CHAR_LF)\r
232 else:\r
52302d4d
LG
233 if self.BlockSizeList == []:\r
234 #set default block size is 1\r
235 self.FvInfFile.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF)\r
236 \r
30fdf114
LG
237 for BlockSize in self.BlockSizeList :\r
238 if BlockSize[0] != None:\r
239 self.FvInfFile.writelines("EFI_BLOCK_SIZE = " + \\r
240 '0x%X' %BlockSize[0] + \\r
241 T_CHAR_LF)\r
242\r
243 if BlockSize[1] != None:\r
244 self.FvInfFile.writelines("EFI_NUM_BLOCKS = " + \\r
245 ' 0x%X' %BlockSize[1] + \\r
246 T_CHAR_LF)\r
247\r
248 if self.BsBaseAddress != None:\r
249 self.FvInfFile.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \\r
250 '0x%X' %self.BsBaseAddress)\r
251 if self.RtBaseAddress != None:\r
252 self.FvInfFile.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \\r
253 '0x%X' %self.RtBaseAddress)\r
254 #\r
255 # Add attribute\r
256 #\r
257 self.FvInfFile.writelines("[attributes]" + T_CHAR_LF)\r
258\r
259 self.FvInfFile.writelines("EFI_ERASE_POLARITY = " + \\r
260 ' %s' %ErasePloarity + \\r
261 T_CHAR_LF)\r
262 if not (self.FvAttributeDict == None):\r
263 for FvAttribute in self.FvAttributeDict.keys() :\r
264 self.FvInfFile.writelines("EFI_" + \\r
265 FvAttribute + \\r
266 ' = ' + \\r
267 self.FvAttributeDict[FvAttribute] + \\r
268 T_CHAR_LF )\r
269 if self.FvAlignment != None:\r
270 self.FvInfFile.writelines("EFI_FVB2_ALIGNMENT_" + \\r
271 self.FvAlignment.strip() + \\r
272 " = TRUE" + \\r
273 T_CHAR_LF)\r
b303ea72 274 \r
30fdf114 275 #\r
b303ea72 276 # Generate FV extension header file\r
30fdf114 277 #\r
b303ea72
LG
278 if self.FvNameGuid == None or self.FvNameGuid == '':\r
279 if len(self.FvExtEntryType) > 0:\r
280 GenFdsGlobalVariable.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self.UiFvName))\r
281 \r
282 if self.FvNameGuid <> None and self.FvNameGuid <> '':\r
283 TotalSize = 16 + 4\r
284 Buffer = ''\r
285 for Index in range (0, len(self.FvExtEntryType)):\r
286 if self.FvExtEntryType[Index] == 'FILE':\r
287 # check if the path is absolute or relative
288 if os.path.isabs(self.FvExtEntryData[Index]):
289 FileFullPath = os.path.normpath(self.FvExtEntryData[Index])
290 else:
291 FileFullPath = os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.FvExtEntryData[Index]))
292 # check if the file path exists or not
293 if not os.path.isfile(FileFullPath):
294 GenFdsGlobalVariable.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self.FvExtEntryData[Index]))\r
295 FvExtFile = open (FileFullPath,'rb')\r
296 FvExtFile.seek(0,2)\r
297 Size = FvExtFile.tell()\r
298 if Size >= 0x10000:\r
299 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self.FvExtEntryData[Index]))\r
300 TotalSize += (Size + 4)\r
301 FvExtFile.seek(0)\r
302 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))\r
303 Buffer += FvExtFile.read() \r
304 FvExtFile.close()\r
305 if self.FvExtEntryType[Index] == 'DATA':\r
306 ByteList = self.FvExtEntryData[Index].split(',')\r
307 Size = len (ByteList)\r
308 if Size >= 0x10000:\r
309 GenFdsGlobalVariable.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self.FvExtEntryData[Index]))\r
310 TotalSize += (Size + 4)\r
311 Buffer += pack('HH', (Size + 4), int(self.FvExtEntryTypeValue[Index], 16))\r
312 for Index1 in range (0, Size):\r
313 Buffer += pack('B', int(ByteList[Index1], 16))\r
314\r
315 Guid = self.FvNameGuid.split('-')\r
316 Buffer = pack('LHHBBBBBBBBL', \r
317 int(Guid[0], 16), \r
318 int(Guid[1], 16), \r
319 int(Guid[2], 16), \r
320 int(Guid[3][-4:-2], 16), \r
321 int(Guid[3][-2:], 16), \r
322 int(Guid[4][-12:-10], 16),\r
323 int(Guid[4][-10:-8], 16),\r
324 int(Guid[4][-8:-6], 16),\r
325 int(Guid[4][-6:-4], 16),\r
326 int(Guid[4][-4:-2], 16),\r
327 int(Guid[4][-2:], 16),\r
328 TotalSize\r
329 ) + Buffer\r
330\r
331 #\r
332 # Generate FV extension header file if the total size is not zero\r
333 #\r
334 if TotalSize > 0:\r
335 FvExtHeaderFileName = os.path.join(GenFdsGlobalVariable.FvDir, self.UiFvName + '.ext')\r
a709adfa 336 FvExtHeaderFile = StringIO.StringIO()\r
b303ea72 337 FvExtHeaderFile.write(Buffer)\r
a709adfa 338 Changed = SaveFileOnChange(FvExtHeaderFileName, FvExtHeaderFile.getvalue(), True)\r
b303ea72 339 FvExtHeaderFile.close()\r
a709adfa
LG
340 if Changed:\r
341 if os.path.exists (self.InfFileName):\r
342 os.remove (self.InfFileName)\r
b303ea72
LG
343 self.FvInfFile.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \\r
344 FvExtHeaderFileName + \\r
345 T_CHAR_LF)\r
30fdf114 346\r
b303ea72
LG
347 \r
348 #\r
349 # Add [Files]\r
350 #\r
30fdf114
LG
351 self.FvInfFile.writelines("[files]" + T_CHAR_LF)\r
352 if VtfDict != None and self.UiFvName in VtfDict.keys():\r
353 self.FvInfFile.writelines("EFI_FILE_NAME = " + \\r
354 VtfDict.get(self.UiFvName) + \\r
355 T_CHAR_LF)\r