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
33 FV_UI_EXT_ENTY_GUID
= 'A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C'
38 class FV (FvClassObject
):
41 # @param self The object pointer
44 FvClassObject
.__init
__(self
)
46 self
.FvAddressFile
= None
47 self
.BaseAddress
= None
48 self
.InfFileName
= None
49 self
.FvAddressFileName
= None
50 self
.CapsuleName
= None
51 self
.FvBaseAddress
= None
52 self
.FvForceRebase
= None
56 # Generate Fv and add it to the Buffer
58 # @param self The object pointer
59 # @param Buffer The buffer generated FV data will be put
60 # @param BaseAddress base address of FV
61 # @param BlockSize block size of FV
62 # @param BlockNum How many blocks in FV
63 # @param ErasePolarity Flash erase polarity
64 # @param VtfDict VTF objects
65 # @param MacroDict macro value pair
66 # @retval string Generated FV file path
68 def AddToBuffer (self
, Buffer
, BaseAddress
=None, BlockSize
= None, BlockNum
=None, ErasePloarity
='1', VtfDict
=None, MacroDict
= {}) :
70 if BaseAddress
== None and self
.UiFvName
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
71 return GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv']
74 # Check whether FV in Capsule is in FD flash region.
75 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
77 if self
.CapsuleName
!= None:
78 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
79 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
80 for RegionObj
in FdObj
.RegionList
:
81 if RegionObj
.RegionType
== 'FV':
82 for RegionData
in RegionObj
.RegionDataList
:
83 if RegionData
.endswith(".fv"):
85 elif RegionData
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
87 elif self
.UiFvName
.upper() == RegionData
.upper():
88 GenFdsGlobalVariable
.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self
.CapsuleName
, self
.UiFvName
.upper()))
90 GenFdsGlobalVariable
.InfLogger( "\nGenerating %s FV" %self
.UiFvName
)
91 GenFdsGlobalVariable
.LargeFileInFvFlags
.append(False)
94 if self
.FvBaseAddress
!= None:
95 BaseAddress
= self
.FvBaseAddress
97 self
.__InitializeInf
__(BaseAddress
, BlockSize
, BlockNum
, ErasePloarity
, VtfDict
)
99 # First Process the Apriori section
101 MacroDict
.update(self
.DefineVarDict
)
103 GenFdsGlobalVariable
.VerboseLogger('First generate Apriori file !')
105 for AprSection
in self
.AprioriSectionList
:
106 FileName
= AprSection
.GenFfs (self
.UiFvName
, MacroDict
)
107 FfsFileList
.append(FileName
)
108 # Add Apriori file name to Inf file
109 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
113 # Process Modules in FfsList
114 for FfsFile
in self
.FfsList
:
115 FileName
= FfsFile
.GenFfs(MacroDict
, FvParentAddr
=BaseAddress
)
116 FfsFileList
.append(FileName
)
117 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
121 SaveFileOnChange(self
.InfFileName
, self
.FvInfFile
.getvalue(), False)
122 self
.FvInfFile
.close()
126 FvOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
)
127 FvOutputFile
= FvOutputFile
+ '.Fv'
128 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
129 if self
.CreateFileName
!= None:
130 FvOutputFile
= self
.CreateFileName
132 FvInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, self
.UiFvName
+ '.inf')
133 CopyLongFilePath(GenFdsGlobalVariable
.FvAddressFileName
, FvInfoFileName
)
135 if os
.path
.exists (FvInfoFileName
):
136 OrigFvInfo
= open(FvInfoFileName
, 'r').read()
137 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
138 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
139 GenFdsGlobalVariable
.GenerateFirmwareVolume(
142 AddressFile
=FvInfoFileName
,
144 ForceRebase
=self
.FvForceRebase
,
145 FileSystemGuid
=FFSGuid
149 if os
.path
.exists (FvInfoFileName
):
150 NewFvInfo
= open(FvInfoFileName
, 'r').read()
151 if NewFvInfo
!= None and NewFvInfo
!= OrigFvInfo
:
153 AddFileObj
= open(FvInfoFileName
, 'r')
154 AddrStrings
= AddFileObj
.readlines()
156 for AddrString
in AddrStrings
:
158 #get base address for the inside FvImage
159 FvChildAddr
.append (AddrString
)
160 elif AddrString
.find ("[FV_BASE_ADDRESS]") != -1:
164 if FvChildAddr
!= []:
166 for FfsFile
in self
.FfsList
:
167 FileName
= FfsFile
.GenFfs(MacroDict
, FvChildAddr
, BaseAddress
)
169 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
170 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
172 GenFdsGlobalVariable
.GenerateFirmwareVolume(
175 AddressFile
=FvInfoFileName
,
177 ForceRebase
=self
.FvForceRebase
,
178 FileSystemGuid
=FFSGuid
182 # Write the Fv contents to Buffer
184 FvFileObj
= open ( FvOutputFile
,'r+b')
186 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s FV Successfully" %self
.UiFvName
)
187 GenFdsGlobalVariable
.SharpCounter
= 0
189 Buffer
.write(FvFileObj
.read())
191 # PI FvHeader is 0x48 byte
192 FvHeaderBuffer
= FvFileObj
.read(0x48)
193 # FV alignment position.
194 FvAlignmentValue
= 1 << (ord (FvHeaderBuffer
[0x2E]) & 0x1F)
195 # FvAlignmentValue is larger than or equal to 1K
196 if FvAlignmentValue
>= 0x400:
197 if FvAlignmentValue
>= 0x10000:
198 #The max alignment supported by FFS is 64K.
199 self
.FvAlignment
= "64K"
201 self
.FvAlignment
= str (FvAlignmentValue
/ 0x400) + "K"
203 # FvAlignmentValue is less than 1K
204 self
.FvAlignment
= str (FvAlignmentValue
)
206 GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv'] = FvOutputFile
207 GenFdsGlobalVariable
.LargeFileInFvFlags
.pop()
210 ## __InitializeInf__()
212 # Initilize the inf file to create FV
214 # @param self The object pointer
215 # @param BaseAddress base address of FV
216 # @param BlockSize block size of FV
217 # @param BlockNum How many blocks in FV
218 # @param ErasePolarity Flash erase polarity
219 # @param VtfDict VTF objects
221 def __InitializeInf__ (self
, BaseAddress
= None, BlockSize
= None, BlockNum
= None, ErasePloarity
='1', VtfDict
=None) :
225 self
.InfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
226 self
.UiFvName
+ '.inf')
227 self
.FvInfFile
= StringIO
.StringIO()
232 self
.FvInfFile
.writelines("[options]" + T_CHAR_LF
)
233 if BaseAddress
!= None :
234 self
.FvInfFile
.writelines("EFI_BASE_ADDRESS = " + \
238 if BlockSize
!= None:
239 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
240 '0x%X' %BlockSize
+ \
243 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
244 ' 0x%X' %BlockNum
+ \
247 if self
.BlockSizeList
== []:
248 #set default block size is 1
249 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF
)
251 for BlockSize
in self
.BlockSizeList
:
252 if BlockSize
[0] != None:
253 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
254 '0x%X' %BlockSize
[0] + \
257 if BlockSize
[1] != None:
258 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
259 ' 0x%X' %BlockSize
[1] + \
262 if self
.BsBaseAddress
!= None:
263 self
.FvInfFile
.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
264 '0x%X' %self
.BsBaseAddress
)
265 if self
.RtBaseAddress
!= None:
266 self
.FvInfFile
.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
267 '0x%X' %self
.RtBaseAddress
)
271 self
.FvInfFile
.writelines("[attributes]" + T_CHAR_LF
)
273 self
.FvInfFile
.writelines("EFI_ERASE_POLARITY = " + \
274 ' %s' %ErasePloarity
+ \
276 if not (self
.FvAttributeDict
== None):
277 for FvAttribute
in self
.FvAttributeDict
.keys() :
278 self
.FvInfFile
.writelines("EFI_" + \
281 self
.FvAttributeDict
[FvAttribute
] + \
283 if self
.FvAlignment
!= None:
284 self
.FvInfFile
.writelines("EFI_FVB2_ALIGNMENT_" + \
285 self
.FvAlignment
.strip() + \
290 # Generate FV extension header file
292 if self
.FvNameGuid
== None or self
.FvNameGuid
== '':
293 if len(self
.FvExtEntryType
) > 0:
294 GenFdsGlobalVariable
.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self
.UiFvName
))
296 if self
.FvNameGuid
<> None and self
.FvNameGuid
<> '':
300 # Create EXT entry for FV UI name
301 # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C
303 FvUiLen
= len(self
.UiFvName
)
304 TotalSize
+= (FvUiLen
+ 16 + 4)
305 Guid
= FV_UI_EXT_ENTY_GUID
.split('-')
308 # EFI_FIRMWARE_VOLUME_EXT_ENTRY : size 4
312 Buffer
+= (pack('HH', (FvUiLen
+ 16 + 4), 0x0002)
313 + pack('=LHHBBBBBBBB', int(Guid
[0], 16), int(Guid
[1], 16), int(Guid
[2], 16),
314 int(Guid
[3][-4:-2], 16), int(Guid
[3][-2:], 16), int(Guid
[4][-12:-10], 16),
315 int(Guid
[4][-10:-8], 16), int(Guid
[4][-8:-6], 16), int(Guid
[4][-6:-4], 16),
316 int(Guid
[4][-4:-2], 16), int(Guid
[4][-2:], 16))
319 for Index
in range (0, len(self
.FvExtEntryType
)):
320 if self
.FvExtEntryType
[Index
] == 'FILE':
321 # check if the path is absolute or relative
322 if os
.path
.isabs(self
.FvExtEntryData
[Index
]):
323 FileFullPath
= os
.path
.normpath(self
.FvExtEntryData
[Index
])
325 FileFullPath
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.FvExtEntryData
[Index
]))
326 # check if the file path exists or not
327 if not os
.path
.isfile(FileFullPath
):
328 GenFdsGlobalVariable
.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self
.FvExtEntryData
[Index
]))
329 FvExtFile
= open (FileFullPath
,'rb')
331 Size
= FvExtFile
.tell()
333 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
334 TotalSize
+= (Size
+ 4)
336 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
337 Buffer
+= FvExtFile
.read()
339 if self
.FvExtEntryType
[Index
] == 'DATA':
340 ByteList
= self
.FvExtEntryData
[Index
].split(',')
341 Size
= len (ByteList
)
343 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
344 TotalSize
+= (Size
+ 4)
345 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
346 for Index1
in range (0, Size
):
347 Buffer
+= pack('B', int(ByteList
[Index1
], 16))
349 Guid
= self
.FvNameGuid
.split('-')
350 Buffer
= pack('=LHHBBBBBBBBL',
354 int(Guid
[3][-4:-2], 16),
355 int(Guid
[3][-2:], 16),
356 int(Guid
[4][-12:-10], 16),
357 int(Guid
[4][-10:-8], 16),
358 int(Guid
[4][-8:-6], 16),
359 int(Guid
[4][-6:-4], 16),
360 int(Guid
[4][-4:-2], 16),
361 int(Guid
[4][-2:], 16),
366 # Generate FV extension header file if the total size is not zero
369 FvExtHeaderFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
+ '.ext')
370 FvExtHeaderFile
= StringIO
.StringIO()
371 FvExtHeaderFile
.write(Buffer
)
372 Changed
= SaveFileOnChange(FvExtHeaderFileName
, FvExtHeaderFile
.getvalue(), True)
373 FvExtHeaderFile
.close()
375 if os
.path
.exists (self
.InfFileName
):
376 os
.remove (self
.InfFileName
)
377 self
.FvInfFile
.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
378 FvExtHeaderFileName
+ \
385 self
.FvInfFile
.writelines("[files]" + T_CHAR_LF
)
386 if VtfDict
!= None and self
.UiFvName
in VtfDict
.keys():
387 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
388 VtfDict
.get(self
.UiFvName
) + \