]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Region.py
2 # process FD Region generation
4 # Copyright (c) 2007 - 2018, 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 from __future__
import absolute_import
20 from .GenFdsGlobalVariable
import GenFdsGlobalVariable
21 from io
import BytesIO
23 import Common
.LongFilePathOs
as os
25 from Common
import EdkLogger
26 from Common
.BuildToolError
import *
27 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
28 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
29 from Common
.DataType
import BINARY_FILE_TYPE_FV
38 # @param self The object pointer
41 self
.Offset
= None # The begin position of the Region
42 self
.Size
= None # The Size of the Region
46 self
.RegionType
= None
47 self
.RegionDataList
= []
51 # Add padding bytes to the Buffer
53 # @param Buffer The buffer the generated region data will be put
55 # @param ErasePolarity Flash erase polarity
56 # @param Size Number of padding bytes requested
59 def PadBuffer(self
, Buffer
, ErasePolarity
, Size
):
61 if (ErasePolarity
== '1') :
62 PadByte
= pack('B', 0xFF)
64 PadByte
= pack('B', 0)
65 PadData
= ''.join(PadByte
for i
in xrange(0, Size
))
70 # Add region data to the Buffer
72 # @param self The object pointer
73 # @param Buffer The buffer generated region data will be put
74 # @param BaseAddress base address of region
75 # @param BlockSize block size of region
76 # @param BlockNum How many blocks in region
77 # @param ErasePolarity Flash erase polarity
78 # @param VtfDict VTF objects
79 # @param MacroDict macro value pair
80 # @retval string Generated FV file path
83 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, vtfDict
=None, MacroDict
={}, Flag
=False):
86 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
87 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
88 GenFdsGlobalVariable
.SharpCounter
= 0
89 if Flag
and (self
.RegionType
!= BINARY_FILE_TYPE_FV
):
92 if self
.RegionType
== BINARY_FILE_TYPE_FV
:
96 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
97 FvBaseAddress
= '0x%X' % self
.FvAddress
99 for RegionData
in self
.RegionDataList
:
101 if RegionData
.endswith(".fv"):
102 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
104 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
105 if RegionData
[1] != ':' :
106 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
107 if not os
.path
.exists(RegionData
):
108 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
110 FileName
= RegionData
111 elif RegionData
.upper() + 'fv' in ImageBinDict
:
113 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
114 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
120 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
121 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[RegionData
.upper()]
123 if FvObj
is not None :
125 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
129 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
130 self
.FvAddress
= self
.FvAddress
+ FvOffset
131 FvAlignValue
= GenFdsGlobalVariable
.GetAlignment(FvObj
.FvAlignment
)
132 if self
.FvAddress
% FvAlignValue
!= 0:
133 EdkLogger
.error("GenFds", GENFDS_ERROR
,
134 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
135 FvBuffer
= BytesIO('')
136 FvBaseAddress
= '0x%X' % self
.FvAddress
139 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
, Flag
=Flag
)
143 FvBufferLen
= len(FvBuffer
.getvalue())
144 if FvBufferLen
> Size
:
146 EdkLogger
.error("GenFds", GENFDS_ERROR
,
147 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
149 # Put the generated image into FD buffer.
151 Buffer
.write(FvBuffer
.getvalue())
153 FvOffset
= FvOffset
+ FvBufferLen
154 Size
= Size
- FvBufferLen
157 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
159 # Add the exist Fv image into FD buffer
162 if FileName
is not None:
163 FileLength
= os
.stat(FileName
)[ST_SIZE
]
164 if FileLength
> Size
:
165 EdkLogger
.error("GenFds", GENFDS_ERROR
,
166 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
167 % (RegionData
, Size
))
168 BinFile
= open(FileName
, 'rb')
169 Buffer
.write(BinFile
.read())
171 Size
= Size
- FileLength
173 # Pad the left buffer
176 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
178 if self
.RegionType
== 'CAPSULE':
180 # Get Capsule from Capsule Dict
182 for RegionData
in self
.RegionDataList
:
183 if RegionData
.endswith(".cap"):
184 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
185 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
186 if RegionData
[1] != ':' :
187 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
188 if not os
.path
.exists(RegionData
):
189 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
191 FileName
= RegionData
192 elif RegionData
.upper() + 'cap' in ImageBinDict
:
193 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
194 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
197 # Generate Capsule image and Put it into FD buffer
200 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
201 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
203 if CapsuleObj
is not None :
204 CapsuleObj
.CapsuleName
= RegionData
.upper()
205 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
207 # Call GenFv tool to generate Capsule Image
209 FileName
= CapsuleObj
.GenCapsule()
210 CapsuleObj
.CapsuleName
= None
212 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
215 # Add the capsule image into FD buffer
217 FileLength
= os
.stat(FileName
)[ST_SIZE
]
218 if FileLength
> Size
:
219 EdkLogger
.error("GenFds", GENFDS_ERROR
,
220 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
221 % (FileLength
, RegionData
, Size
))
222 BinFile
= open(FileName
, 'rb')
223 Buffer
.write(BinFile
.read())
225 Size
= Size
- FileLength
227 # Pad the left buffer
229 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
231 if self
.RegionType
in ('FILE', 'INF'):
232 for RegionData
in self
.RegionDataList
:
233 if self
.RegionType
== 'INF':
234 RegionData
.__InfParse
__(None)
235 if len(RegionData
.BinFileList
) != 1:
236 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
237 File
= RegionData
.BinFileList
[0]
238 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
240 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
241 if RegionData
[1] != ':' :
242 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
243 if not os
.path
.exists(RegionData
):
244 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
246 # Add the file image into FD buffer
248 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
249 if FileLength
> Size
:
250 EdkLogger
.error("GenFds", GENFDS_ERROR
,
251 "Size of File (%s) is larger than Region Size 0x%X specified." \
252 % (RegionData
, Size
))
253 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
254 BinFile
= open(RegionData
, 'rb')
255 Buffer
.write(BinFile
.read())
257 Size
= Size
- FileLength
259 # Pad the left buffer
261 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
263 if self
.RegionType
== 'DATA' :
264 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
266 for RegionData
in self
.RegionDataList
:
267 Data
= RegionData
.split(',')
268 DataSize
= DataSize
+ len(Data
)
270 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
273 Buffer
.write(pack('B', int(item
, 16)))
274 Size
= Size
- DataSize
276 # Pad the left buffer
278 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
280 if self
.RegionType
is None:
281 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
282 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
284 ## BlockSizeOfRegion()
286 # @param BlockSizeList List of block information
287 # @param FvObj The object for FV
289 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
292 RemindingSize
= self
.Size
294 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
295 End
= Start
+ BlockSize
* BlockNum
296 # region not started yet
297 if self
.Offset
>= End
:
300 # region located in current blocks
302 # region ended within current blocks
303 if self
.Offset
+ self
.Size
<= End
:
304 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
306 # region not ended yet
308 # region not started in middle of current blocks
309 if self
.Offset
<= Start
:
310 UsedBlockNum
= BlockNum
311 # region started in middle of current blocks
313 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
315 ExpectedList
.append((BlockSize
, UsedBlockNum
))
316 RemindingSize
-= BlockSize
* UsedBlockNum
318 if FvObj
.BlockSizeList
== []:
319 FvObj
.BlockSizeList
= ExpectedList
321 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
322 # if so, use ExpectedList
323 for Item
in FvObj
.BlockSizeList
:
324 if Item
[0] is None or Item
[1] is None:
325 FvObj
.BlockSizeList
= ExpectedList
327 # make sure region size is no smaller than the summed block size in FV
329 for Item
in FvObj
.BlockSizeList
:
330 Sum
+= Item
[0] * Item
[1]
332 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
333 % (FvObj
.UiFvName
, Sum
, self
.Size
))
334 # check whether the BlockStatements in FV section is appropriate
335 ExpectedListData
= ''
336 for Item
in ExpectedList
:
337 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
339 for Item
in FvObj
.BlockSizeList
:
340 if Item
[0] != ExpectedList
[Index
][0]:
341 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
342 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
343 elif Item
[1] != ExpectedList
[Index
][1]:
344 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
347 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
348 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)