]>
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 MacroDict macro value pair
79 # @retval string Generated FV file path
82 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, MacroDict
={}, Flag
=False):
85 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
86 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
87 GenFdsGlobalVariable
.SharpCounter
= 0
88 if Flag
and (self
.RegionType
!= BINARY_FILE_TYPE_FV
):
91 if self
.RegionType
== BINARY_FILE_TYPE_FV
:
95 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
96 FvBaseAddress
= '0x%X' % self
.FvAddress
98 for RegionData
in self
.RegionDataList
:
100 if RegionData
.endswith(".fv"):
101 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
103 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
104 if RegionData
[1] != ':' :
105 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
106 if not os
.path
.exists(RegionData
):
107 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
109 FileName
= RegionData
110 elif RegionData
.upper() + 'fv' in ImageBinDict
:
112 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
113 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
119 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
120 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[RegionData
.upper()]
122 if FvObj
is not None :
124 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
128 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
129 self
.FvAddress
= self
.FvAddress
+ FvOffset
130 FvAlignValue
= GenFdsGlobalVariable
.GetAlignment(FvObj
.FvAlignment
)
131 if self
.FvAddress
% FvAlignValue
!= 0:
132 EdkLogger
.error("GenFds", GENFDS_ERROR
,
133 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
134 FvBuffer
= BytesIO('')
135 FvBaseAddress
= '0x%X' % self
.FvAddress
138 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, Flag
=Flag
)
142 FvBufferLen
= len(FvBuffer
.getvalue())
143 if FvBufferLen
> Size
:
145 EdkLogger
.error("GenFds", GENFDS_ERROR
,
146 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
148 # Put the generated image into FD buffer.
150 Buffer
.write(FvBuffer
.getvalue())
152 FvOffset
= FvOffset
+ FvBufferLen
153 Size
= Size
- FvBufferLen
156 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
158 # Add the exist Fv image into FD buffer
161 if FileName
is not None:
162 FileLength
= os
.stat(FileName
)[ST_SIZE
]
163 if FileLength
> Size
:
164 EdkLogger
.error("GenFds", GENFDS_ERROR
,
165 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
166 % (RegionData
, Size
))
167 BinFile
= open(FileName
, 'rb')
168 Buffer
.write(BinFile
.read())
170 Size
= Size
- FileLength
172 # Pad the left buffer
175 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
177 if self
.RegionType
== 'CAPSULE':
179 # Get Capsule from Capsule Dict
181 for RegionData
in self
.RegionDataList
:
182 if RegionData
.endswith(".cap"):
183 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
184 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
185 if RegionData
[1] != ':' :
186 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
187 if not os
.path
.exists(RegionData
):
188 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
190 FileName
= RegionData
191 elif RegionData
.upper() + 'cap' in ImageBinDict
:
192 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
193 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
196 # Generate Capsule image and Put it into FD buffer
199 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
200 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
202 if CapsuleObj
is not None :
203 CapsuleObj
.CapsuleName
= RegionData
.upper()
204 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
206 # Call GenFv tool to generate Capsule Image
208 FileName
= CapsuleObj
.GenCapsule()
209 CapsuleObj
.CapsuleName
= None
211 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
214 # Add the capsule image into FD buffer
216 FileLength
= os
.stat(FileName
)[ST_SIZE
]
217 if FileLength
> Size
:
218 EdkLogger
.error("GenFds", GENFDS_ERROR
,
219 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
220 % (FileLength
, RegionData
, Size
))
221 BinFile
= open(FileName
, 'rb')
222 Buffer
.write(BinFile
.read())
224 Size
= Size
- FileLength
226 # Pad the left buffer
228 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
230 if self
.RegionType
in ('FILE', 'INF'):
231 for RegionData
in self
.RegionDataList
:
232 if self
.RegionType
== 'INF':
233 RegionData
.__InfParse
__(None)
234 if len(RegionData
.BinFileList
) != 1:
235 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
236 File
= RegionData
.BinFileList
[0]
237 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
239 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
240 if RegionData
[1] != ':' :
241 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
242 if not os
.path
.exists(RegionData
):
243 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
245 # Add the file image into FD buffer
247 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
248 if FileLength
> Size
:
249 EdkLogger
.error("GenFds", GENFDS_ERROR
,
250 "Size of File (%s) is larger than Region Size 0x%X specified." \
251 % (RegionData
, Size
))
252 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
253 BinFile
= open(RegionData
, 'rb')
254 Buffer
.write(BinFile
.read())
256 Size
= Size
- FileLength
258 # Pad the left buffer
260 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
262 if self
.RegionType
== 'DATA' :
263 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
265 for RegionData
in self
.RegionDataList
:
266 Data
= RegionData
.split(',')
267 DataSize
= DataSize
+ len(Data
)
269 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
272 Buffer
.write(pack('B', int(item
, 16)))
273 Size
= Size
- DataSize
275 # Pad the left buffer
277 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
279 if self
.RegionType
is None:
280 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
281 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
283 ## BlockSizeOfRegion()
285 # @param BlockSizeList List of block information
286 # @param FvObj The object for FV
288 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
291 RemindingSize
= self
.Size
293 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
294 End
= Start
+ BlockSize
* BlockNum
295 # region not started yet
296 if self
.Offset
>= End
:
299 # region located in current blocks
301 # region ended within current blocks
302 if self
.Offset
+ self
.Size
<= End
:
303 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
305 # region not ended yet
307 # region not started in middle of current blocks
308 if self
.Offset
<= Start
:
309 UsedBlockNum
= BlockNum
310 # region started in middle of current blocks
312 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
314 ExpectedList
.append((BlockSize
, UsedBlockNum
))
315 RemindingSize
-= BlockSize
* UsedBlockNum
317 if FvObj
.BlockSizeList
== []:
318 FvObj
.BlockSizeList
= ExpectedList
320 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
321 # if so, use ExpectedList
322 for Item
in FvObj
.BlockSizeList
:
323 if Item
[0] is None or Item
[1] is None:
324 FvObj
.BlockSizeList
= ExpectedList
326 # make sure region size is no smaller than the summed block size in FV
328 for Item
in FvObj
.BlockSizeList
:
329 Sum
+= Item
[0] * Item
[1]
331 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
332 % (FvObj
.UiFvName
, Sum
, self
.Size
))
333 # check whether the BlockStatements in FV section is appropriate
334 ExpectedListData
= ''
335 for Item
in ExpectedList
:
336 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
338 for Item
in FvObj
.BlockSizeList
:
339 if Item
[0] != ExpectedList
[Index
][0]:
340 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
341 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
342 elif Item
[1] != ExpectedList
[Index
][1]:
343 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
346 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
347 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)