2 # process FV generation
4 # Copyright (c) 2007 - 2010, 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.
26 from GenFdsGlobalVariable
import GenFdsGlobalVariable
27 from GenFds
import GenFds
28 from CommonDataClass
.FdfClass
import FvClassObject
29 from Common
.Misc
import SaveFileOnChange
36 class FV (FvClassObject
):
39 # @param self The object pointer
42 FvClassObject
.__init
__(self
)
44 self
.FvAddressFile
= None
45 self
.BaseAddress
= None
46 self
.InfFileName
= None
47 self
.FvAddressFileName
= None
48 self
.CapsuleName
= None
49 self
.FvBaseAddress
= None
50 self
.FvForceRebase
= None
54 # Generate Fv and add it to the Buffer
56 # @param self The object pointer
57 # @param Buffer The buffer generated FV data will be put
58 # @param BaseAddress base address of FV
59 # @param BlockSize block size of FV
60 # @param BlockNum How many blocks in FV
61 # @param ErasePolarity Flash erase polarity
62 # @param VtfDict VTF objects
63 # @param MacroDict macro value pair
64 # @retval string Generated FV file path
66 def AddToBuffer (self
, Buffer
, BaseAddress
=None, BlockSize
= None, BlockNum
=None, ErasePloarity
='1', VtfDict
=None, MacroDict
= {}) :
68 if BaseAddress
== None and self
.UiFvName
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
69 return GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv']
72 # Check whether FV in Capsule is in FD flash region.
73 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
75 if self
.CapsuleName
!= None:
76 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
77 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
78 for RegionObj
in FdObj
.RegionList
:
79 if RegionObj
.RegionType
== 'FV':
80 for RegionData
in RegionObj
.RegionDataList
:
81 if RegionData
.endswith(".fv"):
83 elif RegionData
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
85 elif self
.UiFvName
.upper() == RegionData
.upper():
86 GenFdsGlobalVariable
.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self
.CapsuleName
, self
.UiFvName
.upper()))
88 GenFdsGlobalVariable
.InfLogger( "\nGenerating %s FV" %self
.UiFvName
)
89 GenFdsGlobalVariable
.LargeFileInFvFlags
.append(False)
92 if self
.FvBaseAddress
!= None:
93 BaseAddress
= self
.FvBaseAddress
95 self
.__InitializeInf
__(BaseAddress
, BlockSize
, BlockNum
, ErasePloarity
, VtfDict
)
97 # First Process the Apriori section
99 MacroDict
.update(self
.DefineVarDict
)
101 GenFdsGlobalVariable
.VerboseLogger('First generate Apriori file !')
103 for AprSection
in self
.AprioriSectionList
:
104 FileName
= AprSection
.GenFfs (self
.UiFvName
, MacroDict
)
105 FfsFileList
.append(FileName
)
106 # Add Apriori file name to Inf file
107 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
111 # Process Modules in FfsList
112 for FfsFile
in self
.FfsList
:
113 FileName
= FfsFile
.GenFfs(MacroDict
, FvParentAddr
=BaseAddress
)
114 FfsFileList
.append(FileName
)
115 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
119 SaveFileOnChange(self
.InfFileName
, self
.FvInfFile
.getvalue(), False)
120 self
.FvInfFile
.close()
124 FvOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
)
125 FvOutputFile
= FvOutputFile
+ '.Fv'
126 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
127 if self
.CreateFileName
!= None:
128 FvOutputFile
= self
.CreateFileName
130 FvInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, self
.UiFvName
+ '.inf')
131 shutil
.copy(GenFdsGlobalVariable
.FvAddressFileName
, FvInfoFileName
)
133 if os
.path
.exists (FvInfoFileName
):
134 OrigFvInfo
= open(FvInfoFileName
, 'r').read()
135 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
136 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
137 GenFdsGlobalVariable
.GenerateFirmwareVolume(
140 AddressFile
=FvInfoFileName
,
142 ForceRebase
=self
.FvForceRebase
,
143 FileSystemGuid
=FFSGuid
147 if os
.path
.exists (FvInfoFileName
):
148 NewFvInfo
= open(FvInfoFileName
, 'r').read()
149 if NewFvInfo
!= None and NewFvInfo
!= OrigFvInfo
:
151 AddFileObj
= open(FvInfoFileName
, 'r')
152 AddrStrings
= AddFileObj
.readlines()
154 for AddrString
in AddrStrings
:
156 #get base address for the inside FvImage
157 FvChildAddr
.append (AddrString
)
158 elif AddrString
.find ("[FV_BASE_ADDRESS]") != -1:
162 if FvChildAddr
!= []:
164 for FfsFile
in self
.FfsList
:
165 FileName
= FfsFile
.GenFfs(MacroDict
, FvChildAddr
, BaseAddress
)
167 if GenFdsGlobalVariable
.LargeFileInFvFlags
[-1]:
168 FFSGuid
= GenFdsGlobalVariable
.EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
170 GenFdsGlobalVariable
.GenerateFirmwareVolume(
173 AddressFile
=FvInfoFileName
,
175 ForceRebase
=self
.FvForceRebase
,
176 FileSystemGuid
=FFSGuid
180 # Write the Fv contents to Buffer
182 FvFileObj
= open ( FvOutputFile
,'r+b')
184 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s FV Successfully" %self
.UiFvName
)
185 GenFdsGlobalVariable
.SharpCounter
= 0
187 Buffer
.write(FvFileObj
.read())
189 # PI FvHeader is 0x48 byte
190 FvHeaderBuffer
= FvFileObj
.read(0x48)
191 # FV alignment position.
192 FvAlignmentValue
= 1 << (ord (FvHeaderBuffer
[0x2E]) & 0x1F)
193 # FvAlignmentValue is larger than or equal to 1K
194 if FvAlignmentValue
>= 0x400:
195 if FvAlignmentValue
>= 0x10000:
196 #The max alignment supported by FFS is 64K.
197 self
.FvAlignment
= "64K"
199 self
.FvAlignment
= str (FvAlignmentValue
/ 0x400) + "K"
201 # FvAlignmentValue is less than 1K
202 self
.FvAlignment
= str (FvAlignmentValue
)
204 GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv'] = FvOutputFile
205 GenFdsGlobalVariable
.LargeFileInFvFlags
.pop()
208 ## __InitializeInf__()
210 # Initilize the inf file to create FV
212 # @param self The object pointer
213 # @param BaseAddress base address of FV
214 # @param BlockSize block size of FV
215 # @param BlockNum How many blocks in FV
216 # @param ErasePolarity Flash erase polarity
217 # @param VtfDict VTF objects
219 def __InitializeInf__ (self
, BaseAddress
= None, BlockSize
= None, BlockNum
= None, ErasePloarity
='1', VtfDict
=None) :
223 self
.InfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
224 self
.UiFvName
+ '.inf')
225 self
.FvInfFile
= StringIO
.StringIO()
230 self
.FvInfFile
.writelines("[options]" + T_CHAR_LF
)
231 if BaseAddress
!= None :
232 self
.FvInfFile
.writelines("EFI_BASE_ADDRESS = " + \
236 if BlockSize
!= None:
237 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
238 '0x%X' %BlockSize
+ \
241 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
242 ' 0x%X' %BlockNum
+ \
245 if self
.BlockSizeList
== []:
246 #set default block size is 1
247 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF
)
249 for BlockSize
in self
.BlockSizeList
:
250 if BlockSize
[0] != None:
251 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
252 '0x%X' %BlockSize
[0] + \
255 if BlockSize
[1] != None:
256 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
257 ' 0x%X' %BlockSize
[1] + \
260 if self
.BsBaseAddress
!= None:
261 self
.FvInfFile
.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
262 '0x%X' %self
.BsBaseAddress
)
263 if self
.RtBaseAddress
!= None:
264 self
.FvInfFile
.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
265 '0x%X' %self
.RtBaseAddress
)
269 self
.FvInfFile
.writelines("[attributes]" + T_CHAR_LF
)
271 self
.FvInfFile
.writelines("EFI_ERASE_POLARITY = " + \
272 ' %s' %ErasePloarity
+ \
274 if not (self
.FvAttributeDict
== None):
275 for FvAttribute
in self
.FvAttributeDict
.keys() :
276 self
.FvInfFile
.writelines("EFI_" + \
279 self
.FvAttributeDict
[FvAttribute
] + \
281 if self
.FvAlignment
!= None:
282 self
.FvInfFile
.writelines("EFI_FVB2_ALIGNMENT_" + \
283 self
.FvAlignment
.strip() + \
288 # Generate FV extension header file
290 if self
.FvNameGuid
== None or self
.FvNameGuid
== '':
291 if len(self
.FvExtEntryType
) > 0:
292 GenFdsGlobalVariable
.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self
.UiFvName
))
294 if self
.FvNameGuid
<> None and self
.FvNameGuid
<> '':
297 for Index
in range (0, len(self
.FvExtEntryType
)):
298 if self
.FvExtEntryType
[Index
] == 'FILE':
299 # check if the path is absolute or relative
300 if os
.path
.isabs(self
.FvExtEntryData
[Index
]):
301 FileFullPath
= os
.path
.normpath(self
.FvExtEntryData
[Index
])
303 FileFullPath
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.FvExtEntryData
[Index
]))
304 # check if the file path exists or not
305 if not os
.path
.isfile(FileFullPath
):
306 GenFdsGlobalVariable
.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self
.FvExtEntryData
[Index
]))
307 FvExtFile
= open (FileFullPath
,'rb')
309 Size
= FvExtFile
.tell()
311 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
312 TotalSize
+= (Size
+ 4)
314 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
315 Buffer
+= FvExtFile
.read()
317 if self
.FvExtEntryType
[Index
] == 'DATA':
318 ByteList
= self
.FvExtEntryData
[Index
].split(',')
319 Size
= len (ByteList
)
321 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
322 TotalSize
+= (Size
+ 4)
323 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
324 for Index1
in range (0, Size
):
325 Buffer
+= pack('B', int(ByteList
[Index1
], 16))
327 Guid
= self
.FvNameGuid
.split('-')
328 Buffer
= pack('=LHHBBBBBBBBL',
332 int(Guid
[3][-4:-2], 16),
333 int(Guid
[3][-2:], 16),
334 int(Guid
[4][-12:-10], 16),
335 int(Guid
[4][-10:-8], 16),
336 int(Guid
[4][-8:-6], 16),
337 int(Guid
[4][-6:-4], 16),
338 int(Guid
[4][-4:-2], 16),
339 int(Guid
[4][-2:], 16),
344 # Generate FV extension header file if the total size is not zero
347 FvExtHeaderFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
+ '.ext')
348 FvExtHeaderFile
= StringIO
.StringIO()
349 FvExtHeaderFile
.write(Buffer
)
350 Changed
= SaveFileOnChange(FvExtHeaderFileName
, FvExtHeaderFile
.getvalue(), True)
351 FvExtHeaderFile
.close()
353 if os
.path
.exists (self
.InfFileName
):
354 os
.remove (self
.InfFileName
)
355 self
.FvInfFile
.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
356 FvExtHeaderFileName
+ \
363 self
.FvInfFile
.writelines("[files]" + T_CHAR_LF
)
364 if VtfDict
!= None and self
.UiFvName
in VtfDict
.keys():
365 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
366 VtfDict
.get(self
.UiFvName
) + \