]>
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 from CommonDataClass
.FdfClass
import RegionClassObject
24 import Common
.LongFilePathOs
as os
26 from Common
import EdkLogger
27 from Common
.BuildToolError
import *
28 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
29 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
30 from Common
.DataType
import BINARY_FILE_TYPE_FV
35 class Region(RegionClassObject
):
39 # @param self The object pointer
42 RegionClassObject
.__init
__(self
)
47 # Add padding bytes to the Buffer
49 # @param Buffer The buffer the generated region data will be put
51 # @param ErasePolarity Flash erase polarity
52 # @param Size Number of padding bytes requested
55 def PadBuffer(self
, Buffer
, ErasePolarity
, Size
):
57 if (ErasePolarity
== '1') :
58 PadByte
= pack('B', 0xFF)
60 PadByte
= pack('B', 0)
61 PadData
= ''.join(PadByte
for i
in xrange(0, Size
))
66 # Add region data to the Buffer
68 # @param self The object pointer
69 # @param Buffer The buffer generated region data will be put
70 # @param BaseAddress base address of region
71 # @param BlockSize block size of region
72 # @param BlockNum How many blocks in region
73 # @param ErasePolarity Flash erase polarity
74 # @param VtfDict VTF objects
75 # @param MacroDict macro value pair
76 # @retval string Generated FV file path
79 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, vtfDict
=None, MacroDict
={}, Flag
=False):
82 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
83 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
84 GenFdsGlobalVariable
.SharpCounter
= 0
85 if Flag
and (self
.RegionType
!= BINARY_FILE_TYPE_FV
):
88 if self
.RegionType
== BINARY_FILE_TYPE_FV
:
92 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
93 FvBaseAddress
= '0x%X' % self
.FvAddress
95 for RegionData
in self
.RegionDataList
:
97 if RegionData
.endswith(".fv"):
98 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
100 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
101 if RegionData
[1] != ':' :
102 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
103 if not os
.path
.exists(RegionData
):
104 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
106 FileName
= RegionData
107 elif RegionData
.upper() + 'fv' in ImageBinDict
:
109 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
110 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
116 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
117 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[RegionData
.upper()]
119 if FvObj
is not None :
121 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
125 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
126 self
.FvAddress
= self
.FvAddress
+ FvOffset
127 FvAlignValue
= GenFdsGlobalVariable
.GetAlignment(FvObj
.FvAlignment
)
128 if self
.FvAddress
% FvAlignValue
!= 0:
129 EdkLogger
.error("GenFds", GENFDS_ERROR
,
130 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
131 FvBuffer
= BytesIO('')
132 FvBaseAddress
= '0x%X' % self
.FvAddress
135 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
, Flag
=Flag
)
139 FvBufferLen
= len(FvBuffer
.getvalue())
140 if FvBufferLen
> Size
:
142 EdkLogger
.error("GenFds", GENFDS_ERROR
,
143 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
145 # Put the generated image into FD buffer.
147 Buffer
.write(FvBuffer
.getvalue())
149 FvOffset
= FvOffset
+ FvBufferLen
150 Size
= Size
- FvBufferLen
153 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
155 # Add the exist Fv image into FD buffer
158 if FileName
is not None:
159 FileLength
= os
.stat(FileName
)[ST_SIZE
]
160 if FileLength
> Size
:
161 EdkLogger
.error("GenFds", GENFDS_ERROR
,
162 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
163 % (RegionData
, Size
))
164 BinFile
= open(FileName
, 'rb')
165 Buffer
.write(BinFile
.read())
167 Size
= Size
- FileLength
169 # Pad the left buffer
172 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
174 if self
.RegionType
== 'CAPSULE':
176 # Get Capsule from Capsule Dict
178 for RegionData
in self
.RegionDataList
:
179 if RegionData
.endswith(".cap"):
180 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
181 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
182 if RegionData
[1] != ':' :
183 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
184 if not os
.path
.exists(RegionData
):
185 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
187 FileName
= RegionData
188 elif RegionData
.upper() + 'cap' in ImageBinDict
:
189 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
190 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
193 # Generate Capsule image and Put it into FD buffer
196 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
197 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
199 if CapsuleObj
is not None :
200 CapsuleObj
.CapsuleName
= RegionData
.upper()
201 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
203 # Call GenFv tool to generate Capsule Image
205 FileName
= CapsuleObj
.GenCapsule()
206 CapsuleObj
.CapsuleName
= None
208 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
211 # Add the capsule image into FD buffer
213 FileLength
= os
.stat(FileName
)[ST_SIZE
]
214 if FileLength
> Size
:
215 EdkLogger
.error("GenFds", GENFDS_ERROR
,
216 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
217 % (FileLength
, RegionData
, Size
))
218 BinFile
= open(FileName
, 'rb')
219 Buffer
.write(BinFile
.read())
221 Size
= Size
- FileLength
223 # Pad the left buffer
225 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
227 if self
.RegionType
in ('FILE', 'INF'):
228 for RegionData
in self
.RegionDataList
:
229 if self
.RegionType
== 'INF':
230 RegionData
.__InfParse
__(None)
231 if len(RegionData
.BinFileList
) != 1:
232 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
233 File
= RegionData
.BinFileList
[0]
234 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
236 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
237 if RegionData
[1] != ':' :
238 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
239 if not os
.path
.exists(RegionData
):
240 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
242 # Add the file image into FD buffer
244 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
245 if FileLength
> Size
:
246 EdkLogger
.error("GenFds", GENFDS_ERROR
,
247 "Size of File (%s) is larger than Region Size 0x%X specified." \
248 % (RegionData
, Size
))
249 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
250 BinFile
= open(RegionData
, 'rb')
251 Buffer
.write(BinFile
.read())
253 Size
= Size
- FileLength
255 # Pad the left buffer
257 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
259 if self
.RegionType
== 'DATA' :
260 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
262 for RegionData
in self
.RegionDataList
:
263 Data
= RegionData
.split(',')
264 DataSize
= DataSize
+ len(Data
)
266 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
269 Buffer
.write(pack('B', int(item
, 16)))
270 Size
= Size
- DataSize
272 # Pad the left buffer
274 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
276 if self
.RegionType
is None:
277 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
278 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
280 ## BlockSizeOfRegion()
282 # @param BlockSizeList List of block information
283 # @param FvObj The object for FV
285 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
288 RemindingSize
= self
.Size
290 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
291 End
= Start
+ BlockSize
* BlockNum
292 # region not started yet
293 if self
.Offset
>= End
:
296 # region located in current blocks
298 # region ended within current blocks
299 if self
.Offset
+ self
.Size
<= End
:
300 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
302 # region not ended yet
304 # region not started in middle of current blocks
305 if self
.Offset
<= Start
:
306 UsedBlockNum
= BlockNum
307 # region started in middle of current blocks
309 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
311 ExpectedList
.append((BlockSize
, UsedBlockNum
))
312 RemindingSize
-= BlockSize
* UsedBlockNum
314 if FvObj
.BlockSizeList
== []:
315 FvObj
.BlockSizeList
= ExpectedList
317 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
318 # if so, use ExpectedList
319 for Item
in FvObj
.BlockSizeList
:
320 if Item
[0] is None or Item
[1] is None:
321 FvObj
.BlockSizeList
= ExpectedList
323 # make sure region size is no smaller than the summed block size in FV
325 for Item
in FvObj
.BlockSizeList
:
326 Sum
+= Item
[0] * Item
[1]
328 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
329 % (FvObj
.UiFvName
, Sum
, self
.Size
))
330 # check whether the BlockStatements in FV section is appropriate
331 ExpectedListData
= ''
332 for Item
in ExpectedList
:
333 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
335 for Item
in FvObj
.BlockSizeList
:
336 if Item
[0] != ExpectedList
[Index
][0]:
337 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
338 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
339 elif Item
[1] != ExpectedList
[Index
][1]:
340 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
343 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
344 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)