]>
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
= self
.GetFvAlignValue(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 def GetFvAlignValue(self
, Str
):
283 Str
= Str
.strip().upper()
284 if Str
.endswith('K'):
287 elif Str
.endswith('M'):
290 elif Str
.endswith('G'):
291 Granu
= 1024 * 1024 * 1024
296 AlignValue
= int(Str
) * Granu
299 ## BlockSizeOfRegion()
301 # @param BlockSizeList List of block information
302 # @param FvObj The object for FV
304 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
307 RemindingSize
= self
.Size
309 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
310 End
= Start
+ BlockSize
* BlockNum
311 # region not started yet
312 if self
.Offset
>= End
:
315 # region located in current blocks
317 # region ended within current blocks
318 if self
.Offset
+ self
.Size
<= End
:
319 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
321 # region not ended yet
323 # region not started in middle of current blocks
324 if self
.Offset
<= Start
:
325 UsedBlockNum
= BlockNum
326 # region started in middle of current blocks
328 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
330 ExpectedList
.append((BlockSize
, UsedBlockNum
))
331 RemindingSize
-= BlockSize
* UsedBlockNum
333 if FvObj
.BlockSizeList
== []:
334 FvObj
.BlockSizeList
= ExpectedList
336 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
337 # if so, use ExpectedList
338 for Item
in FvObj
.BlockSizeList
:
339 if Item
[0] is None or Item
[1] is None:
340 FvObj
.BlockSizeList
= ExpectedList
342 # make sure region size is no smaller than the summed block size in FV
344 for Item
in FvObj
.BlockSizeList
:
345 Sum
+= Item
[0] * Item
[1]
347 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
348 % (FvObj
.UiFvName
, Sum
, self
.Size
))
349 # check whether the BlockStatements in FV section is appropriate
350 ExpectedListData
= ''
351 for Item
in ExpectedList
:
352 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
354 for Item
in FvObj
.BlockSizeList
:
355 if Item
[0] != ExpectedList
[Index
][0]:
356 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
357 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
358 elif Item
[1] != ExpectedList
[Index
][1]:
359 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
362 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
363 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)