]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Fv.py
2 # process FV generation
4 # Copyright (c) 2007 - 2010, Intel Corporation
6 # All rights reserved. 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
52 # Generate Fv and add it to the Buffer
54 # @param self The object pointer
55 # @param Buffer The buffer generated FV data will be put
56 # @param BaseAddress base address of FV
57 # @param BlockSize block size of FV
58 # @param BlockNum How many blocks in FV
59 # @param ErasePolarity Flash erase polarity
60 # @param VtfDict VTF objects
61 # @param MacroDict macro value pair
62 # @retval string Generated FV file path
64 def AddToBuffer (self
, Buffer
, BaseAddress
=None, BlockSize
= None, BlockNum
=None, ErasePloarity
='1', VtfDict
=None, MacroDict
= {}) :
66 if BaseAddress
== None and self
.UiFvName
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
67 return GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv']
70 # Check whether FV in Capsule is in FD flash region.
71 # If yes, return error. Doesn't support FV in Capsule image is also in FD flash region.
73 if self
.CapsuleName
!= None:
74 for FdName
in GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
.keys():
75 FdObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FdDict
[FdName
]
76 for RegionObj
in FdObj
.RegionList
:
77 if RegionObj
.RegionType
== 'FV':
78 for RegionData
in RegionObj
.RegionDataList
:
79 if RegionData
.endswith(".fv"):
81 elif RegionData
.upper() + 'fv' in GenFds
.ImageBinDict
.keys():
83 elif self
.UiFvName
.upper() == RegionData
.upper():
84 GenFdsGlobalVariable
.ErrorLogger("Capsule %s in FD region can't contain a FV %s in FD region." % (self
.CapsuleName
, self
.UiFvName
.upper()))
86 GenFdsGlobalVariable
.InfLogger( "\nGenerating %s FV" %self
.UiFvName
)
88 self
.__InitializeInf
__(BaseAddress
, BlockSize
, BlockNum
, ErasePloarity
, VtfDict
)
90 # First Process the Apriori section
92 MacroDict
.update(self
.DefineVarDict
)
94 GenFdsGlobalVariable
.VerboseLogger('First generate Apriori file !')
96 for AprSection
in self
.AprioriSectionList
:
97 FileName
= AprSection
.GenFfs (self
.UiFvName
, MacroDict
)
98 FfsFileList
.append(FileName
)
99 # Add Apriori file name to Inf file
100 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
104 # Process Modules in FfsList
105 for FfsFile
in self
.FfsList
:
106 FileName
= FfsFile
.GenFfs(MacroDict
, FvParentAddr
=BaseAddress
)
107 FfsFileList
.append(FileName
)
108 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
112 SaveFileOnChange(self
.InfFileName
, self
.FvInfFile
.getvalue(), False)
113 self
.FvInfFile
.close()
117 FvOutputFile
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
)
118 FvOutputFile
= FvOutputFile
+ '.Fv'
119 # BUGBUG: FvOutputFile could be specified from FDF file (FV section, CreateFile statement)
120 if self
.CreateFileName
!= None:
121 FvOutputFile
= self
.CreateFileName
123 FvInfoFileName
= os
.path
.join(GenFdsGlobalVariable
.FfsDir
, self
.UiFvName
+ '.inf')
124 shutil
.copy(GenFdsGlobalVariable
.FvAddressFileName
, FvInfoFileName
)
126 if os
.path
.exists (FvInfoFileName
):
127 OrigFvInfo
= open(FvInfoFileName
, 'r').read()
128 GenFdsGlobalVariable
.GenerateFirmwareVolume(
131 AddressFile
=FvInfoFileName
,
136 if os
.path
.exists (FvInfoFileName
):
137 NewFvInfo
= open(FvInfoFileName
, 'r').read()
138 if NewFvInfo
!= None and NewFvInfo
!= OrigFvInfo
:
140 AddFileObj
= open(FvInfoFileName
, 'r')
141 AddrStrings
= AddFileObj
.readlines()
143 for AddrString
in AddrStrings
:
145 #get base address for the inside FvImage
146 FvChildAddr
.append (AddrString
)
147 elif AddrString
.find ("[FV_BASE_ADDRESS]") != -1:
151 if FvChildAddr
!= []:
153 for FfsFile
in self
.FfsList
:
154 FileName
= FfsFile
.GenFfs(MacroDict
, FvChildAddr
, BaseAddress
)
157 GenFdsGlobalVariable
.GenerateFirmwareVolume(
160 AddressFile
=FvInfoFileName
,
165 # Write the Fv contents to Buffer
167 FvFileObj
= open ( FvOutputFile
,'r+b')
169 GenFdsGlobalVariable
.VerboseLogger( "\nGenerate %s FV Successfully" %self
.UiFvName
)
170 GenFdsGlobalVariable
.SharpCounter
= 0
172 Buffer
.write(FvFileObj
.read())
174 # PI FvHeader is 0x48 byte
175 FvHeaderBuffer
= FvFileObj
.read(0x48)
176 # FV alignment position.
177 FvAlignmentValue
= 1 << (ord (FvHeaderBuffer
[0x2E]) & 0x1F)
178 # FvAlignmentValue is larger than or equal to 1K
179 if FvAlignmentValue
>= 0x400:
180 if FvAlignmentValue
>= 0x10000:
181 #The max alignment supported by FFS is 64K.
182 self
.FvAlignment
= "64K"
184 self
.FvAlignment
= str (FvAlignmentValue
/ 0x400) + "K"
186 # FvAlignmentValue is less than 1K
187 self
.FvAlignment
= str (FvAlignmentValue
)
189 GenFds
.ImageBinDict
[self
.UiFvName
.upper() + 'fv'] = FvOutputFile
192 ## __InitializeInf__()
194 # Initilize the inf file to create FV
196 # @param self The object pointer
197 # @param BaseAddress base address of FV
198 # @param BlockSize block size of FV
199 # @param BlockNum How many blocks in FV
200 # @param ErasePolarity Flash erase polarity
201 # @param VtfDict VTF objects
203 def __InitializeInf__ (self
, BaseAddress
= None, BlockSize
= None, BlockNum
= None, ErasePloarity
='1', VtfDict
=None) :
207 self
.InfFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
,
208 self
.UiFvName
+ '.inf')
209 self
.FvInfFile
= StringIO
.StringIO()
214 self
.FvInfFile
.writelines("[options]" + T_CHAR_LF
)
215 if BaseAddress
!= None :
216 self
.FvInfFile
.writelines("EFI_BASE_ADDRESS = " + \
220 if BlockSize
!= None:
221 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
222 '0x%X' %BlockSize
+ \
225 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
226 ' 0x%X' %BlockNum
+ \
229 if self
.BlockSizeList
== []:
230 #set default block size is 1
231 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = 0x1" + T_CHAR_LF
)
233 for BlockSize
in self
.BlockSizeList
:
234 if BlockSize
[0] != None:
235 self
.FvInfFile
.writelines("EFI_BLOCK_SIZE = " + \
236 '0x%X' %BlockSize
[0] + \
239 if BlockSize
[1] != None:
240 self
.FvInfFile
.writelines("EFI_NUM_BLOCKS = " + \
241 ' 0x%X' %BlockSize
[1] + \
244 if self
.BsBaseAddress
!= None:
245 self
.FvInfFile
.writelines('EFI_BOOT_DRIVER_BASE_ADDRESS = ' + \
246 '0x%X' %self
.BsBaseAddress
)
247 if self
.RtBaseAddress
!= None:
248 self
.FvInfFile
.writelines('EFI_RUNTIME_DRIVER_BASE_ADDRESS = ' + \
249 '0x%X' %self
.RtBaseAddress
)
253 self
.FvInfFile
.writelines("[attributes]" + T_CHAR_LF
)
255 self
.FvInfFile
.writelines("EFI_ERASE_POLARITY = " + \
256 ' %s' %ErasePloarity
+ \
258 if not (self
.FvAttributeDict
== None):
259 for FvAttribute
in self
.FvAttributeDict
.keys() :
260 self
.FvInfFile
.writelines("EFI_" + \
263 self
.FvAttributeDict
[FvAttribute
] + \
265 if self
.FvAlignment
!= None:
266 self
.FvInfFile
.writelines("EFI_FVB2_ALIGNMENT_" + \
267 self
.FvAlignment
.strip() + \
272 # Generate FV extension header file
274 if self
.FvNameGuid
== None or self
.FvNameGuid
== '':
275 if len(self
.FvExtEntryType
) > 0:
276 GenFdsGlobalVariable
.ErrorLogger("FV Extension Header Entries declared for %s with no FvNameGuid declaration." % (self
.UiFvName
))
278 if self
.FvNameGuid
<> None and self
.FvNameGuid
<> '':
281 for Index
in range (0, len(self
.FvExtEntryType
)):
282 if self
.FvExtEntryType
[Index
] == 'FILE':
283 # check if the path is absolute or relative
284 if os
.path
.isabs(self
.FvExtEntryData
[Index
]):
285 FileFullPath
= os
.path
.normpath(self
.FvExtEntryData
[Index
])
287 FileFullPath
= os
.path
.normpath(os
.path
.join(GenFdsGlobalVariable
.WorkSpaceDir
, self
.FvExtEntryData
[Index
]))
288 # check if the file path exists or not
289 if not os
.path
.isfile(FileFullPath
):
290 GenFdsGlobalVariable
.ErrorLogger("Error opening FV Extension Header Entry file %s." % (self
.FvExtEntryData
[Index
]))
291 FvExtFile
= open (FileFullPath
,'rb')
293 Size
= FvExtFile
.tell()
295 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry file %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
296 TotalSize
+= (Size
+ 4)
298 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
299 Buffer
+= FvExtFile
.read()
301 if self
.FvExtEntryType
[Index
] == 'DATA':
302 ByteList
= self
.FvExtEntryData
[Index
].split(',')
303 Size
= len (ByteList
)
305 GenFdsGlobalVariable
.ErrorLogger("The size of FV Extension Header Entry data %s exceeds 0x10000." % (self
.FvExtEntryData
[Index
]))
306 TotalSize
+= (Size
+ 4)
307 Buffer
+= pack('HH', (Size
+ 4), int(self
.FvExtEntryTypeValue
[Index
], 16))
308 for Index1
in range (0, Size
):
309 Buffer
+= pack('B', int(ByteList
[Index1
], 16))
311 Guid
= self
.FvNameGuid
.split('-')
312 Buffer
= pack('LHHBBBBBBBBL',
316 int(Guid
[3][-4:-2], 16),
317 int(Guid
[3][-2:], 16),
318 int(Guid
[4][-12:-10], 16),
319 int(Guid
[4][-10:-8], 16),
320 int(Guid
[4][-8:-6], 16),
321 int(Guid
[4][-6:-4], 16),
322 int(Guid
[4][-4:-2], 16),
323 int(Guid
[4][-2:], 16),
328 # Generate FV extension header file if the total size is not zero
331 FvExtHeaderFileName
= os
.path
.join(GenFdsGlobalVariable
.FvDir
, self
.UiFvName
+ '.ext')
332 FvExtHeaderFile
= StringIO
.StringIO()
333 FvExtHeaderFile
.write(Buffer
)
334 Changed
= SaveFileOnChange(FvExtHeaderFileName
, FvExtHeaderFile
.getvalue(), True)
335 FvExtHeaderFile
.close()
337 if os
.path
.exists (self
.InfFileName
):
338 os
.remove (self
.InfFileName
)
339 self
.FvInfFile
.writelines("EFI_FV_EXT_HEADER_FILE_NAME = " + \
340 FvExtHeaderFileName
+ \
347 self
.FvInfFile
.writelines("[files]" + T_CHAR_LF
)
348 if VtfDict
!= None and self
.UiFvName
in VtfDict
.keys():
349 self
.FvInfFile
.writelines("EFI_FILE_NAME = " + \
350 VtfDict
.get(self
.UiFvName
) + \