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