2 # process FV generation
4 # Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
6 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 import Common
.LongFilePathOs
as os
25 from GenFdsGlobalVariable
import GenFdsGlobalVariable
26 from GenFds
import GenFds
27 from CommonDataClass
.FdfClass
import FvClassObject
28 from Common
.Misc
import SaveFileOnChange
29 from Common
.LongFilePathSupport
import CopyLongFilePath
30 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
37 class FV (FvClassObject
):
40 # @param self The object pointer
43 FvClassObject
.__init
__(self
)
45 self
.FvAddressFile
= None
46 self
.BaseAddress
= None
47 self
.InfFileName
= None
48 self
.FvAddressFileName
= None
49 self
.CapsuleName
= None
50 self
.FvBaseAddress
= None
51 self
.FvForceRebase
= None
55 # Generate Fv and add it to the Buffer
57 # @param self The object pointer
58 # @param Buffer The buffer generated FV data will be put
59 # @param BaseAddress base address of FV
60 # @param BlockSize block size of FV
61 # @param BlockNum How many blocks in FV
62 # @param ErasePolarity Flash erase polarity
63 # @param VtfDict VTF objects
64 # @param MacroDict macro value pair
65 # @retval string Generated FV file path
67 def AddToBuffer (self
, Buffer
, BaseAddress
=None, BlockSize
= None, BlockNum
=None, ErasePloarity
='1', VtfDict
=None, MacroDict
= {}) :
69 if BaseAddress
== None and self
.UiFvName
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
70 return GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv']
73 # Check whether FV in Capsule is in FD flash region.
74 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
76 if self
.CapsuleName
!= None:
77 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
78 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
79 for RegionObj
in FdObj
.RegionList
:
80 if RegionObj
.RegionType
== 'FV':
81 for RegionData
in RegionObj
.RegionDataList
:
82 if RegionData
.endswith(".fv"):
84 elif RegionData
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
86 elif self
.UiFvName
.upper() == RegionData
.upper():
87 GenFdsGlobalVariable
.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self
.CapsuleName
, self
.UiFvName
.upper()))
89 GenFdsGlobalVariable
.InfLogger( "\nGenerating %s FV" %self
.UiFvName
)
90 GenFdsGlobalVariable
.LargeFileInFvFlags
.append(False)
93 if self
.FvBaseAddress
!= None:
94 BaseAddress
= self
.FvBaseAddress
96 self
.__InitializeInf
__(BaseAddress
, BlockSize
, BlockNum
, ErasePloarity
, VtfDict
)
98 # First Process the Apriori section
100 MacroDict
.update(self
.DefineVarDict
)
102 GenFdsGlobalVariable
.VerboseLogger('First generate Apriori file !')
104 for AprSection
in self
.AprioriSectionList
:
105 FileName
= AprSection
.GenFfs (self
.UiFvName
, MacroDict
)
106 FfsFileList
.append(FileName
)
107 # Add Apriori file name to Inf file
108 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
112 # Process Modules in FfsList
113 for FfsFile
in self
.FfsList
:
114 FileName
= FfsFile
.GenFfs(MacroDict
, FvParentAddr
=BaseAddress
)
115 FfsFileList
.append(FileName
)
116 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
120 SaveFileOnChange(self
.InfFileName
, self
.FvInfFile
.getvalue(), False)
121 self
.FvInfFile
.close()
125 FvOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
)
126 FvOutputFile
= FvOutputFile
+ '.Fv'
127 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
128 if self
.CreateFileName
!= None:
129 FvOutputFile
= self
.CreateFileName
131 FvInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, self
.UiFvName
+ '.inf')
132 CopyLongFilePath(GenFdsGlobalVariable
.FvAddressFileName
, FvInfoFileName
)
134 if os
.path
.exists (FvInfoFileName
):
135 OrigFvInfo
= open(FvInfoFileName
, 'r').read()
136 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
137 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
138 GenFdsGlobalVariable
.GenerateFirmwareVolume(
141 AddressFile
=FvInfoFileName
,
143 ForceRebase
=self
.FvForceRebase
,
144 FileSystemGuid
=FFSGuid
148 if os
.path
.exists (FvInfoFileName
):
149 NewFvInfo
= open(FvInfoFileName
, 'r').read()
150 if NewFvInfo
!= None and NewFvInfo
!= OrigFvInfo
:
152 AddFileObj
= open(FvInfoFileName
, 'r')
153 AddrStrings
= AddFileObj
.readlines()
155 for AddrString
in AddrStrings
:
157 #get base address for the inside FvImage
158 FvChildAddr
.append (AddrString
)
159 elif AddrString
.find ("[FV_BASE_ADDRESS]") != -1:
163 if FvChildAddr
!= []:
165 for FfsFile
in self
.FfsList
:
166 FileName
= FfsFile
.GenFfs(MacroDict
, FvChildAddr
, BaseAddress
)
168 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
169 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
171 GenFdsGlobalVariable
.GenerateFirmwareVolume(
174 AddressFile
=FvInfoFileName
,
176 ForceRebase
=self
.FvForceRebase
,
177 FileSystemGuid
=FFSGuid
181 # Write the Fv contents to Buffer
183 FvFileObj
= open ( FvOutputFile
,'r+b')
185 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s FV Successfully" %self
.UiFvName
)
186 GenFdsGlobalVariable
.SharpCounter
= 0
188 Buffer
.write(FvFileObj
.read())
190 # PI FvHeader is 0x48 byte
191 FvHeaderBuffer
= FvFileObj
.read(0x48)
192 # FV alignment position.
193 FvAlignmentValue
= 1 << (ord (FvHeaderBuffer
[0x2E]) & 0x1F)
194 # FvAlignmentValue is larger than or equal to 1K
195 if FvAlignmentValue
>= 0x400:
196 if FvAlignmentValue
>= 0x10000:
197 #The max alignment supported by FFS is 64K.
198 self
.FvAlignment
= "64K"
200 self
.FvAlignment
= str (FvAlignmentValue
/ 0x400) + "K"
202 # FvAlignmentValue is less than 1K
203 self
.FvAlignment
= str (FvAlignmentValue
)
205 GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv'] = FvOutputFile
206 GenFdsGlobalVariable
.LargeFileInFvFlags
.pop()
209 ## __InitializeInf__()
211 # Initilize the inf file to create FV
213 # @param self The object pointer
214 # @param BaseAddress base address of FV
215 # @param BlockSize block size of FV
216 # @param BlockNum How many blocks in FV
217 # @param ErasePolarity Flash erase polarity
218 # @param VtfDict VTF objects
220 def __InitializeInf__ (self
, BaseAddress
= None, BlockSize
= None, BlockNum
= None, ErasePloarity
='1', VtfDict
=None) :
224 self
.InfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
225 self
.UiFvName
+ '.inf')
226 self
.FvInfFile
= StringIO
.StringIO()
231 self
.FvInfFile
.writelines("[options]" + T_CHAR_LF
)
232 if BaseAddress
!= None :
233 self
.FvInfFile
.writelines("EFI_BASE_ADDRESS = " + \
237 if BlockSize
!= None:
238 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
239 '0x%X' %BlockSize
+ \
242 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
243 ' 0x%X' %BlockNum
+ \
246 if self
.BlockSizeList
== []:
247 #set default block size is 1
248 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF
)
250 for BlockSize
in self
.BlockSizeList
:
251 if BlockSize
[0] != None:
252 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
253 '0x%X' %BlockSize
[0] + \
256 if BlockSize
[1] != None:
257 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
258 ' 0x%X' %BlockSize
[1] + \
261 if self
.BsBaseAddress
!= None:
262 self
.FvInfFile
.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
263 '0x%X' %self
.BsBaseAddress
)
264 if self
.RtBaseAddress
!= None:
265 self
.FvInfFile
.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
266 '0x%X' %self
.RtBaseAddress
)
270 self
.FvInfFile
.writelines("[attributes]" + T_CHAR_LF
)
272 self
.FvInfFile
.writelines("EFI_ERASE_POLARITY = " + \
273 ' %s' %ErasePloarity
+ \
275 if not (self
.FvAttributeDict
== None):
276 for FvAttribute
in self
.FvAttributeDict
.keys() :
277 self
.FvInfFile
.writelines("EFI_" + \
280 self
.FvAttributeDict
[FvAttribute
] + \
282 if self
.FvAlignment
!= None:
283 self
.FvInfFile
.writelines("EFI_FVB2_ALIGNMENT_" + \
284 self
.FvAlignment
.strip() + \
289 # Generate FV extension header file
291 if self
.FvNameGuid
== None or self
.FvNameGuid
== '':
292 if len(self
.FvExtEntryType
) > 0:
293 GenFdsGlobalVariable
.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self
.UiFvName
))
295 if self
.FvNameGuid
<> None and self
.FvNameGuid
<> '':
298 for Index
in range (0, len(self
.FvExtEntryType
)):
299 if self
.FvExtEntryType
[Index
] == 'FILE':
300 # check if the path is absolute or relative
301 if os
.path
.isabs(self
.FvExtEntryData
[Index
]):
302 FileFullPath
= os
.path
.normpath(self
.FvExtEntryData
[Index
])
304 FileFullPath
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.FvExtEntryData
[Index
]))
305 # check if the file path exists or not
306 if not os
.path
.isfile(FileFullPath
):
307 GenFdsGlobalVariable
.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self
.FvExtEntryData
[Index
]))
308 FvExtFile
= open (FileFullPath
,'rb')
310 Size
= FvExtFile
.tell()
312 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
313 TotalSize
+= (Size
+ 4)
315 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
316 Buffer
+= FvExtFile
.read()
318 if self
.FvExtEntryType
[Index
] == 'DATA':
319 ByteList
= self
.FvExtEntryData
[Index
].split(',')
320 Size
= len (ByteList
)
322 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
323 TotalSize
+= (Size
+ 4)
324 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
325 for Index1
in range (0, Size
):
326 Buffer
+= pack('B', int(ByteList
[Index1
], 16))
328 Guid
= self
.FvNameGuid
.split('-')
329 Buffer
= pack('=LHHBBBBBBBBL',
333 int(Guid
[3][-4:-2], 16),
334 int(Guid
[3][-2:], 16),
335 int(Guid
[4][-12:-10], 16),
336 int(Guid
[4][-10:-8], 16),
337 int(Guid
[4][-8:-6], 16),
338 int(Guid
[4][-6:-4], 16),
339 int(Guid
[4][-4:-2], 16),
340 int(Guid
[4][-2:], 16),
345 # Generate FV extension header file if the total size is not zero
348 FvExtHeaderFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
+ '.ext')
349 FvExtHeaderFile
= StringIO
.StringIO()
350 FvExtHeaderFile
.write(Buffer
)
351 Changed
= SaveFileOnChange(FvExtHeaderFileName
, FvExtHeaderFile
.getvalue(), True)
352 FvExtHeaderFile
.close()
354 if os
.path
.exists (self
.InfFileName
):
355 os
.remove (self
.InfFileName
)
356 self
.FvInfFile
.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
357 FvExtHeaderFileName
+ \
364 self
.FvInfFile
.writelines("[files]" + T_CHAR_LF
)
365 if VtfDict
!= None and self
.UiFvName
in VtfDict
.keys():
366 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
367 VtfDict
.get(self
.UiFvName
) + \