]>
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
20 from io
import BytesIO
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 for i
in range(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
= GenFdsGlobalVariable
.GetAlignment(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
))
131 FvBaseAddress
= '0x%X' % self
.FvAddress
134 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
, Flag
=Flag
)
138 FvBufferLen
= len(FvBuffer
.getvalue())
139 if FvBufferLen
> Size
:
141 EdkLogger
.error("GenFds", GENFDS_ERROR
,
142 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
144 # Put the generated image into FD buffer.
146 Buffer
.write(FvBuffer
.getvalue())
148 FvOffset
= FvOffset
+ FvBufferLen
149 Size
= Size
- FvBufferLen
152 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
154 # Add the exist Fv image into FD buffer
157 if FileName
is not None:
158 FileLength
= os
.stat(FileName
)[ST_SIZE
]
159 if FileLength
> Size
:
160 EdkLogger
.error("GenFds", GENFDS_ERROR
,
161 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
162 % (RegionData
, Size
))
163 BinFile
= open(FileName
, 'rb')
164 Buffer
.write(BinFile
.read())
166 Size
= Size
- FileLength
168 # Pad the left buffer
171 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
173 if self
.RegionType
== 'CAPSULE':
175 # Get Capsule from Capsule Dict
177 for RegionData
in self
.RegionDataList
:
178 if RegionData
.endswith(".cap"):
179 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
180 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
181 if RegionData
[1] != ':' :
182 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
183 if not os
.path
.exists(RegionData
):
184 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
186 FileName
= RegionData
187 elif RegionData
.upper() + 'cap' in ImageBinDict
:
188 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
189 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
192 # Generate Capsule image and Put it into FD buffer
195 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
:
196 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
198 if CapsuleObj
is not None :
199 CapsuleObj
.CapsuleName
= RegionData
.upper()
200 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
202 # Call GenFv tool to generate Capsule Image
204 FileName
= CapsuleObj
.GenCapsule()
205 CapsuleObj
.CapsuleName
= None
207 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
210 # Add the capsule image into FD buffer
212 FileLength
= os
.stat(FileName
)[ST_SIZE
]
213 if FileLength
> Size
:
214 EdkLogger
.error("GenFds", GENFDS_ERROR
,
215 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
216 % (FileLength
, RegionData
, Size
))
217 BinFile
= open(FileName
, 'rb')
218 Buffer
.write(BinFile
.read())
220 Size
= Size
- FileLength
222 # Pad the left buffer
224 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
226 if self
.RegionType
in ('FILE', 'INF'):
227 for RegionData
in self
.RegionDataList
:
228 if self
.RegionType
== 'INF':
229 RegionData
.__InfParse
__(None)
230 if len(RegionData
.BinFileList
) != 1:
231 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
232 File
= RegionData
.BinFileList
[0]
233 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
235 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
236 if RegionData
[1] != ':' :
237 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
238 if not os
.path
.exists(RegionData
):
239 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
241 # Add the file image into FD buffer
243 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
244 if FileLength
> Size
:
245 EdkLogger
.error("GenFds", GENFDS_ERROR
,
246 "Size of File (%s) is larger than Region Size 0x%X specified." \
247 % (RegionData
, Size
))
248 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
249 BinFile
= open(RegionData
, 'rb')
250 Buffer
.write(BinFile
.read())
252 Size
= Size
- FileLength
254 # Pad the left buffer
256 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
258 if self
.RegionType
== 'DATA' :
259 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
261 for RegionData
in self
.RegionDataList
:
262 Data
= RegionData
.split(',')
263 DataSize
= DataSize
+ len(Data
)
265 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
268 Buffer
.write(pack('B', int(item
, 16)))
269 Size
= Size
- DataSize
271 # Pad the left buffer
273 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
275 if self
.RegionType
is None:
276 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
277 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
279 ## BlockSizeOfRegion()
281 # @param BlockSizeList List of block information
282 # @param FvObj The object for FV
284 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
287 RemindingSize
= self
.Size
289 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
290 End
= Start
+ BlockSize
* BlockNum
291 # region not started yet
292 if self
.Offset
>= End
:
295 # region located in current blocks
297 # region ended within current blocks
298 if self
.Offset
+ self
.Size
<= End
:
299 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
301 # region not ended yet
303 # region not started in middle of current blocks
304 if self
.Offset
<= Start
:
305 UsedBlockNum
= BlockNum
306 # region started in middle of current blocks
308 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
310 ExpectedList
.append((BlockSize
, UsedBlockNum
))
311 RemindingSize
-= BlockSize
* UsedBlockNum
313 if FvObj
.BlockSizeList
== []:
314 FvObj
.BlockSizeList
= ExpectedList
316 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
317 # if so, use ExpectedList
318 for Item
in FvObj
.BlockSizeList
:
319 if Item
[0] is None or Item
[1] is None:
320 FvObj
.BlockSizeList
= ExpectedList
322 # make sure region size is no smaller than the summed block size in FV
324 for Item
in FvObj
.BlockSizeList
:
325 Sum
+= Item
[0] * Item
[1]
327 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
328 % (FvObj
.UiFvName
, Sum
, self
.Size
))
329 # check whether the BlockStatements in FV section is appropriate
330 ExpectedListData
= ''
331 for Item
in ExpectedList
:
332 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
334 for Item
in FvObj
.BlockSizeList
:
335 if Item
[0] != ExpectedList
[Index
][0]:
336 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
337 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
338 elif Item
[1] != ExpectedList
[Index
][1]:
339 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
342 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
343 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)