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