]>
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.
19 from GenFdsGlobalVariable
import GenFdsGlobalVariable
22 from CommonDataClass
.FdfClass
import RegionClassObject
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
34 class Region(RegionClassObject
):
38 # @param self The object pointer
41 RegionClassObject
.__init
__(self
)
46 # Add padding bytes to the Buffer
48 # @param Buffer The buffer the generated region data will be put
50 # @param ErasePolarity Flash erase polarity
51 # @param Size Number of padding bytes requested
54 def PadBuffer(self
, Buffer
, ErasePolarity
, Size
):
56 if (ErasePolarity
== '1') :
57 PadByte
= pack('B', 0xFF)
59 PadByte
= pack('B', 0)
60 PadData
= ''.join(PadByte
for i
in xrange(0, Size
))
65 # Add region data to the Buffer
67 # @param self The object pointer
68 # @param Buffer The buffer generated region data will be put
69 # @param BaseAddress base address of region
70 # @param BlockSize block size of region
71 # @param BlockNum How many blocks in region
72 # @param ErasePolarity Flash erase polarity
73 # @param VtfDict VTF objects
74 # @param MacroDict macro value pair
75 # @retval string Generated FV file path
78 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, vtfDict
=None, MacroDict
={}, Flag
=False):
81 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
82 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
83 GenFdsGlobalVariable
.SharpCounter
= 0
84 if Flag
and (self
.RegionType
!= BINARY_FILE_TYPE_FV
):
87 if self
.RegionType
== BINARY_FILE_TYPE_FV
:
91 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
92 FvBaseAddress
= '0x%X' % self
.FvAddress
94 for RegionData
in self
.RegionDataList
:
96 if RegionData
.endswith(".fv"):
97 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
99 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
100 if RegionData
[1] != ':' :
101 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
102 if not os
.path
.exists(RegionData
):
103 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
105 FileName
= RegionData
106 elif RegionData
.upper() + 'fv' in ImageBinDict
:
108 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
109 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
115 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
:
116 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
[RegionData
.upper()]
118 if FvObj
is not None :
120 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
124 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
125 self
.FvAddress
= self
.FvAddress
+ FvOffset
126 FvAlignValue
= self
.GetFvAlignValue(FvObj
.FvAlignment
)
127 if self
.FvAddress
% FvAlignValue
!= 0:
128 EdkLogger
.error("GenFds", GENFDS_ERROR
,
129 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
130 FvBuffer
= StringIO
.StringIO('')
131 FvBaseAddress
= '0x%X' % self
.FvAddress
134 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
, Flag
=Flag
)
138 if FvBuffer
.len > Size
:
140 EdkLogger
.error("GenFds", GENFDS_ERROR
,
141 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
143 # Put the generated image into FD buffer.
145 Buffer
.write(FvBuffer
.getvalue())
147 FvOffset
= FvOffset
+ FvBuffer
.len
148 Size
= Size
- FvBuffer
.len
151 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
153 # Add the exist Fv image into FD buffer
156 if FileName
is not None:
157 FileLength
= os
.stat(FileName
)[ST_SIZE
]
158 if FileLength
> Size
:
159 EdkLogger
.error("GenFds", GENFDS_ERROR
,
160 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
161 % (RegionData
, Size
))
162 BinFile
= open(FileName
, 'rb')
163 Buffer
.write(BinFile
.read())
165 Size
= Size
- FileLength
167 # Pad the left buffer
170 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
172 if self
.RegionType
== 'CAPSULE':
174 # Get Capsule from Capsule Dict
176 for RegionData
in self
.RegionDataList
:
177 if RegionData
.endswith(".cap"):
178 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
179 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
180 if RegionData
[1] != ':' :
181 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
182 if not os
.path
.exists(RegionData
):
183 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
185 FileName
= RegionData
186 elif RegionData
.upper() + 'cap' in ImageBinDict
:
187 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
188 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
191 # Generate Capsule image and Put it into FD buffer
194 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
195 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
197 if CapsuleObj
is not None :
198 CapsuleObj
.CapsuleName
= RegionData
.upper()
199 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
201 # Call GenFv tool to generate Capsule Image
203 FileName
= CapsuleObj
.GenCapsule()
204 CapsuleObj
.CapsuleName
= None
206 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
209 # Add the capsule image into FD buffer
211 FileLength
= os
.stat(FileName
)[ST_SIZE
]
212 if FileLength
> Size
:
213 EdkLogger
.error("GenFds", GENFDS_ERROR
,
214 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
215 % (FileLength
, RegionData
, Size
))
216 BinFile
= open(FileName
, 'rb')
217 Buffer
.write(BinFile
.read())
219 Size
= Size
- FileLength
221 # Pad the left buffer
223 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
225 if self
.RegionType
in ('FILE', 'INF'):
226 for RegionData
in self
.RegionDataList
:
227 if self
.RegionType
== 'INF':
228 RegionData
.__InfParse
__(None)
229 if len(RegionData
.BinFileList
) != 1:
230 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
231 File
= RegionData
.BinFileList
[0]
232 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
234 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
235 if RegionData
[1] != ':' :
236 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
237 if not os
.path
.exists(RegionData
):
238 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
240 # Add the file image into FD buffer
242 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
243 if FileLength
> Size
:
244 EdkLogger
.error("GenFds", GENFDS_ERROR
,
245 "Size of File (%s) is larger than Region Size 0x%X specified." \
246 % (RegionData
, Size
))
247 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
248 BinFile
= open(RegionData
, 'rb')
249 Buffer
.write(BinFile
.read())
251 Size
= Size
- FileLength
253 # Pad the left buffer
255 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
257 if self
.RegionType
== 'DATA' :
258 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
260 for RegionData
in self
.RegionDataList
:
261 Data
= RegionData
.split(',')
262 DataSize
= DataSize
+ len(Data
)
264 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
267 Buffer
.write(pack('B', int(item
, 16)))
268 Size
= Size
- DataSize
270 # Pad the left buffer
272 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
274 if self
.RegionType
is None:
275 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
276 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
278 def GetFvAlignValue(self
, Str
):
281 Str
= Str
.strip().upper()
282 if Str
.endswith('K'):
285 elif Str
.endswith('M'):
288 elif Str
.endswith('G'):
289 Granu
= 1024 * 1024 * 1024
294 AlignValue
= int(Str
) * Granu
297 ## BlockSizeOfRegion()
299 # @param BlockSizeList List of block information
300 # @param FvObj The object for FV
302 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
305 RemindingSize
= self
.Size
307 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
308 End
= Start
+ BlockSize
* BlockNum
309 # region not started yet
310 if self
.Offset
>= End
:
313 # region located in current blocks
315 # region ended within current blocks
316 if self
.Offset
+ self
.Size
<= End
:
317 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
319 # region not ended yet
321 # region not started in middle of current blocks
322 if self
.Offset
<= Start
:
323 UsedBlockNum
= BlockNum
324 # region started in middle of current blocks
326 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
328 ExpectedList
.append((BlockSize
, UsedBlockNum
))
329 RemindingSize
-= BlockSize
* UsedBlockNum
331 if FvObj
.BlockSizeList
== []:
332 FvObj
.BlockSizeList
= ExpectedList
334 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
335 # if so, use ExpectedList
336 for Item
in FvObj
.BlockSizeList
:
337 if Item
[0] is None or Item
[1] is None:
338 FvObj
.BlockSizeList
= ExpectedList
340 # make sure region size is no smaller than the summed block size in FV
342 for Item
in FvObj
.BlockSizeList
:
343 Sum
+= Item
[0] * Item
[1]
345 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
346 % (FvObj
.UiFvName
, Sum
, self
.Size
))
347 # check whether the BlockStatements in FV section is appropriate
348 ExpectedListData
= ''
349 for Item
in ExpectedList
:
350 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
352 for Item
in FvObj
.BlockSizeList
:
353 if Item
[0] != ExpectedList
[Index
][0]:
354 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
355 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
356 elif Item
[1] != ExpectedList
[Index
][1]:
357 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
360 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
361 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)