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