2 # process FV generation
4 # Copyright (c) 2007 - 2017, 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
53 self
.FvRegionInFD
= None
54 self
.UsedSizeEnable
= False
58 # Generate Fv and add it to the Buffer
60 # @param self The object pointer
61 # @param Buffer The buffer generated FV data will be put
62 # @param BaseAddress base address of FV
63 # @param BlockSize block size of FV
64 # @param BlockNum How many blocks in FV
65 # @param ErasePolarity Flash erase polarity
66 # @param VtfDict VTF objects
67 # @param MacroDict macro value pair
68 # @retval string Generated FV file path
70 def AddToBuffer (self
, Buffer
, BaseAddress
=None, BlockSize
= None, BlockNum
=None, ErasePloarity
='1', VtfDict
=None, MacroDict
= {}) :
72 if BaseAddress
== None and self
.UiFvName
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
73 return GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv']
76 # Check whether FV in Capsule is in FD flash region.
77 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
79 if self
.CapsuleName
!= None:
80 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
81 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
82 for RegionObj
in FdObj
.RegionList
:
83 if RegionObj
.RegionType
== 'FV':
84 for RegionData
in RegionObj
.RegionDataList
:
85 if RegionData
.endswith(".fv"):
87 elif RegionData
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
89 elif self
.UiFvName
.upper() == RegionData
.upper():
90 GenFdsGlobalVariable
.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self
.CapsuleName
, self
.UiFvName
.upper()))
92 GenFdsGlobalVariable
.InfLogger( "\nGenerating %s FV" %self
.UiFvName
)
93 GenFdsGlobalVariable
.LargeFileInFvFlags
.append(False)
96 if self
.FvBaseAddress
!= None:
97 BaseAddress
= self
.FvBaseAddress
99 self
.__InitializeInf
__(BaseAddress
, BlockSize
, BlockNum
, ErasePloarity
, VtfDict
)
101 # First Process the Apriori section
103 MacroDict
.update(self
.DefineVarDict
)
105 GenFdsGlobalVariable
.VerboseLogger('First generate Apriori file !')
107 for AprSection
in self
.AprioriSectionList
:
108 FileName
= AprSection
.GenFfs (self
.UiFvName
, MacroDict
)
109 FfsFileList
.append(FileName
)
110 # Add Apriori file name to Inf file
111 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
115 # Process Modules in FfsList
116 for FfsFile
in self
.FfsList
:
117 FileName
= FfsFile
.GenFfs(MacroDict
, FvParentAddr
=BaseAddress
)
118 FfsFileList
.append(FileName
)
119 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
123 SaveFileOnChange(self
.InfFileName
, self
.FvInfFile
.getvalue(), False)
124 self
.FvInfFile
.close()
128 FvOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
)
129 FvOutputFile
= FvOutputFile
+ '.Fv'
130 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
131 if self
.CreateFileName
!= None:
132 FvOutputFile
= self
.CreateFileName
134 FvInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, self
.UiFvName
+ '.inf')
135 CopyLongFilePath(GenFdsGlobalVariable
.FvAddressFileName
, FvInfoFileName
)
137 if os
.path
.exists (FvInfoFileName
):
138 OrigFvInfo
= open(FvInfoFileName
, 'r').read()
139 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
140 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
141 GenFdsGlobalVariable
.GenerateFirmwareVolume(
144 AddressFile
=FvInfoFileName
,
146 ForceRebase
=self
.FvForceRebase
,
147 FileSystemGuid
=FFSGuid
151 if os
.path
.exists (FvInfoFileName
):
152 NewFvInfo
= open(FvInfoFileName
, 'r').read()
153 if NewFvInfo
!= None and NewFvInfo
!= OrigFvInfo
:
155 AddFileObj
= open(FvInfoFileName
, 'r')
156 AddrStrings
= AddFileObj
.readlines()
158 for AddrString
in AddrStrings
:
160 #get base address for the inside FvImage
161 FvChildAddr
.append (AddrString
)
162 elif AddrString
.find ("[FV_BASE_ADDRESS]") != -1:
166 if FvChildAddr
!= []:
168 for FfsFile
in self
.FfsList
:
169 FileName
= FfsFile
.GenFfs(MacroDict
, FvChildAddr
, BaseAddress
)
171 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
172 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
174 GenFdsGlobalVariable
.GenerateFirmwareVolume(
177 AddressFile
=FvInfoFileName
,
179 ForceRebase
=self
.FvForceRebase
,
180 FileSystemGuid
=FFSGuid
184 # Write the Fv contents to Buffer
186 if os
.path
.isfile(FvOutputFile
):
187 FvFileObj
= open ( FvOutputFile
,'rb')
189 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s FV Successfully" %self
.UiFvName
)
190 GenFdsGlobalVariable
.SharpCounter
= 0
192 Buffer
.write(FvFileObj
.read())
194 # PI FvHeader is 0x48 byte
195 FvHeaderBuffer
= FvFileObj
.read(0x48)
196 # FV alignment position.
197 FvAlignmentValue
= 1 << (ord (FvHeaderBuffer
[0x2E]) & 0x1F)
198 # FvAlignmentValue is larger than or equal to 1K
199 if FvAlignmentValue
>= 0x400:
200 if FvAlignmentValue
>= 0x100000:
201 #The max alignment supported by FFS is 16M.
202 if FvAlignmentValue
>= 0x1000000:
203 self
.FvAlignment
= "16M"
205 self
.FvAlignment
= str(FvAlignmentValue
/ 0x100000) + "M"
207 self
.FvAlignment
= str (FvAlignmentValue
/ 0x400) + "K"
209 # FvAlignmentValue is less than 1K
210 self
.FvAlignment
= str (FvAlignmentValue
)
212 GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv'] = FvOutputFile
213 GenFdsGlobalVariable
.LargeFileInFvFlags
.pop()
215 GenFdsGlobalVariable
.ErrorLogger("Failed to generate %s FV file." %self
.UiFvName
)
220 # Calculate FV's block size
221 # Inherit block size from FD if no block size specified in FV
223 def _GetBlockSize(self
):
224 if self
.BlockSizeList
:
227 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
228 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
229 for RegionObj
in FdObj
.RegionList
:
230 if RegionObj
.RegionType
!= 'FV':
232 for RegionData
in RegionObj
.RegionDataList
:
234 # Found the FD and region that contain this FV
236 if self
.UiFvName
.upper() == RegionData
.upper():
237 RegionObj
.BlockInfoOfRegion(FdObj
.BlockSizeList
, self
)
238 if self
.BlockSizeList
:
242 ## __InitializeInf__()
244 # Initilize the inf file to create FV
246 # @param self The object pointer
247 # @param BaseAddress base address of FV
248 # @param BlockSize block size of FV
249 # @param BlockNum How many blocks in FV
250 # @param ErasePolarity Flash erase polarity
251 # @param VtfDict VTF objects
253 def __InitializeInf__ (self
, BaseAddress
= None, BlockSize
= None, BlockNum
= None, ErasePloarity
='1', VtfDict
=None) :
257 self
.InfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
258 self
.UiFvName
+ '.inf')
259 self
.FvInfFile
= StringIO
.StringIO()
264 self
.FvInfFile
.writelines("[options]" + T_CHAR_LF
)
265 if BaseAddress
!= None :
266 self
.FvInfFile
.writelines("EFI_BASE_ADDRESS = " + \
270 if BlockSize
!= None:
271 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
272 '0x%X' %BlockSize
+ \
275 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
276 ' 0x%X' %BlockNum
+ \
279 if self
.BlockSizeList
== []:
280 if not self
._GetBlockSize
():
281 #set default block size is 1
282 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF
)
284 for BlockSize
in self
.BlockSizeList
:
285 if BlockSize
[0] != None:
286 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
287 '0x%X' %BlockSize
[0] + \
290 if BlockSize
[1] != None:
291 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
292 ' 0x%X' %BlockSize
[1] + \
295 if self
.BsBaseAddress
!= None:
296 self
.FvInfFile
.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
297 '0x%X' %self
.BsBaseAddress
)
298 if self
.RtBaseAddress
!= None:
299 self
.FvInfFile
.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
300 '0x%X' %self
.RtBaseAddress
)
304 self
.FvInfFile
.writelines("[attributes]" + T_CHAR_LF
)
306 self
.FvInfFile
.writelines("EFI_ERASE_POLARITY = " + \
307 ' %s' %ErasePloarity
+ \
309 if not (self
.FvAttributeDict
== None):
310 for FvAttribute
in self
.FvAttributeDict
.keys() :
311 if FvAttribute
== "FvUsedSizeEnable":
312 if self
.FvAttributeDict
[FvAttribute
].upper() in ('TRUE', '1') :
313 self
.UsedSizeEnable
= True
315 self
.FvInfFile
.writelines("EFI_" + \
318 self
.FvAttributeDict
[FvAttribute
] + \
320 if self
.FvAlignment
!= None:
321 self
.FvInfFile
.writelines("EFI_FVB2_ALIGNMENT_" + \
322 self
.FvAlignment
.strip() + \
327 # Generate FV extension header file
329 if self
.FvNameGuid
== None or self
.FvNameGuid
== '':
330 if len(self
.FvExtEntryType
) > 0 or self
.UsedSizeEnable
:
331 GenFdsGlobalVariable
.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self
.UiFvName
))
333 if self
.FvNameGuid
<> None and self
.FvNameGuid
<> '':
336 if self
.UsedSizeEnable
:
338 ## define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03
341 # EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr;
343 # } EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE;
344 Buffer
+= pack('HHL', 8, 3, 0)
346 if self
.FvNameString
== 'TRUE':
348 # Create EXT entry for FV UI name
349 # This GUID is used: A67DF1FA-8DE8-4E98-AF09-4BDF2EFFBC7C
351 FvUiLen
= len(self
.UiFvName
)
352 TotalSize
+= (FvUiLen
+ 16 + 4)
353 Guid
= FV_UI_EXT_ENTY_GUID
.split('-')
356 # EFI_FIRMWARE_VOLUME_EXT_ENTRY : size 4
360 Buffer
+= (pack('HH', (FvUiLen
+ 16 + 4), 0x0002)
361 + pack('=LHHBBBBBBBB', int(Guid
[0], 16), int(Guid
[1], 16), int(Guid
[2], 16),
362 int(Guid
[3][-4:-2], 16), int(Guid
[3][-2:], 16), int(Guid
[4][-12:-10], 16),
363 int(Guid
[4][-10:-8], 16), int(Guid
[4][-8:-6], 16), int(Guid
[4][-6:-4], 16),
364 int(Guid
[4][-4:-2], 16), int(Guid
[4][-2:], 16))
367 for Index
in range (0, len(self
.FvExtEntryType
)):
368 if self
.FvExtEntryType
[Index
] == 'FILE':
369 # check if the path is absolute or relative
370 if os
.path
.isabs(self
.FvExtEntryData
[Index
]):
371 FileFullPath
= os
.path
.normpath(self
.FvExtEntryData
[Index
])
373 FileFullPath
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.FvExtEntryData
[Index
]))
374 # check if the file path exists or not
375 if not os
.path
.isfile(FileFullPath
):
376 GenFdsGlobalVariable
.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self
.FvExtEntryData
[Index
]))
377 FvExtFile
= open (FileFullPath
,'rb')
379 Size
= FvExtFile
.tell()
381 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
382 TotalSize
+= (Size
+ 4)
384 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
385 Buffer
+= FvExtFile
.read()
387 if self
.FvExtEntryType
[Index
] == 'DATA':
388 ByteList
= self
.FvExtEntryData
[Index
].split(',')
389 Size
= len (ByteList
)
391 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
392 TotalSize
+= (Size
+ 4)
393 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
394 for Index1
in range (0, Size
):
395 Buffer
+= pack('B', int(ByteList
[Index1
], 16))
397 Guid
= self
.FvNameGuid
.split('-')
398 Buffer
= pack('=LHHBBBBBBBBL',
402 int(Guid
[3][-4:-2], 16),
403 int(Guid
[3][-2:], 16),
404 int(Guid
[4][-12:-10], 16),
405 int(Guid
[4][-10:-8], 16),
406 int(Guid
[4][-8:-6], 16),
407 int(Guid
[4][-6:-4], 16),
408 int(Guid
[4][-4:-2], 16),
409 int(Guid
[4][-2:], 16),
414 # Generate FV extension header file if the total size is not zero
417 FvExtHeaderFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
+ '.ext')
418 FvExtHeaderFile
= StringIO
.StringIO()
419 FvExtHeaderFile
.write(Buffer
)
420 Changed
= SaveFileOnChange(FvExtHeaderFileName
, FvExtHeaderFile
.getvalue(), True)
421 FvExtHeaderFile
.close()
423 if os
.path
.exists (self
.InfFileName
):
424 os
.remove (self
.InfFileName
)
425 self
.FvInfFile
.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
426 FvExtHeaderFileName
+ \
433 self
.FvInfFile
.writelines("[files]" + T_CHAR_LF
)
434 if VtfDict
!= None and self
.UiFvName
in VtfDict
.keys():
435 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
436 VtfDict
.get(self
.UiFvName
) + \