]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Region.py
2 # process FD Region generation
4 # Copyright (c) 2007 - 2017, 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
33 class Region(RegionClassObject
):
37 # @param self The object pointer
40 RegionClassObject
.__init
__(self
)
45 # Add padding bytes to the Buffer
47 # @param Buffer The buffer the generated region data will be put
49 # @param ErasePolarity Flash erase polarity
50 # @param Size Number of padding bytes requested
53 def PadBuffer(self
, Buffer
, ErasePolarity
, Size
):
55 if (ErasePolarity
== '1') :
56 PadByte
= pack('B', 0xFF)
58 PadByte
= pack('B', 0)
59 PadData
= ''.join(PadByte
for i
in xrange(0, Size
))
64 # Add region data to the Buffer
66 # @param self The object pointer
67 # @param Buffer The buffer generated region data will be put
68 # @param BaseAddress base address of region
69 # @param BlockSize block size of region
70 # @param BlockNum How many blocks in region
71 # @param ErasePolarity Flash erase polarity
72 # @param VtfDict VTF objects
73 # @param MacroDict macro value pair
74 # @retval string Generated FV file path
77 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, vtfDict
=None, MacroDict
={}, Flag
=False):
80 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
81 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
82 GenFdsGlobalVariable
.SharpCounter
= 0
83 if Flag
and (self
.RegionType
!= 'FV'):
86 if self
.RegionType
== 'FV':
90 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
91 FvBaseAddress
= '0x%X' % self
.FvAddress
93 for RegionData
in self
.RegionDataList
:
95 if RegionData
.endswith(".fv"):
96 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
98 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
99 if RegionData
[1] != ':' :
100 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
101 if not os
.path
.exists(RegionData
):
102 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
104 FileName
= RegionData
105 elif RegionData
.upper() + 'fv' in ImageBinDict
.keys():
107 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
108 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
114 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
115 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(RegionData
.upper())
117 if FvObj
is not None :
119 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
123 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
124 self
.FvAddress
= self
.FvAddress
+ FvOffset
125 FvAlignValue
= self
.GetFvAlignValue(FvObj
.FvAlignment
)
126 if self
.FvAddress
% FvAlignValue
!= 0:
127 EdkLogger
.error("GenFds", GENFDS_ERROR
,
128 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
129 FvBuffer
= StringIO
.StringIO('')
130 FvBaseAddress
= '0x%X' % self
.FvAddress
133 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
, Flag
=Flag
)
137 if FvBuffer
.len > Size
:
139 EdkLogger
.error("GenFds", GENFDS_ERROR
,
140 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
142 # Put the generated image into FD buffer.
144 Buffer
.write(FvBuffer
.getvalue())
146 FvOffset
= FvOffset
+ FvBuffer
.len
147 Size
= Size
- FvBuffer
.len
150 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
152 # Add the exist Fv image into FD buffer
155 if FileName
is not None:
156 FileLength
= os
.stat(FileName
)[ST_SIZE
]
157 if FileLength
> Size
:
158 EdkLogger
.error("GenFds", GENFDS_ERROR
,
159 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
160 % (RegionData
, Size
))
161 BinFile
= open(FileName
, 'rb')
162 Buffer
.write(BinFile
.read())
164 Size
= Size
- FileLength
166 # Pad the left buffer
169 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
171 if self
.RegionType
== 'CAPSULE':
173 # Get Capsule from Capsule Dict
175 for RegionData
in self
.RegionDataList
:
176 if RegionData
.endswith(".cap"):
177 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
178 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
179 if RegionData
[1] != ':' :
180 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
181 if not os
.path
.exists(RegionData
):
182 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
184 FileName
= RegionData
185 elif RegionData
.upper() + 'cap' in ImageBinDict
.keys():
186 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
187 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
190 # Generate Capsule image and Put it into FD buffer
193 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
194 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
196 if CapsuleObj
is not None :
197 CapsuleObj
.CapsuleName
= RegionData
.upper()
198 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
200 # Call GenFv tool to generate Capsule Image
202 FileName
= CapsuleObj
.GenCapsule()
203 CapsuleObj
.CapsuleName
= None
205 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
208 # Add the capsule image into FD buffer
210 FileLength
= os
.stat(FileName
)[ST_SIZE
]
211 if FileLength
> Size
:
212 EdkLogger
.error("GenFds", GENFDS_ERROR
,
213 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
214 % (FileLength
, RegionData
, Size
))
215 BinFile
= open(FileName
, 'rb')
216 Buffer
.write(BinFile
.read())
218 Size
= Size
- FileLength
220 # Pad the left buffer
222 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
224 if self
.RegionType
in ('FILE', 'INF'):
225 for RegionData
in self
.RegionDataList
:
226 if self
.RegionType
== 'INF':
227 RegionData
.__InfParse
__(None)
228 if len(RegionData
.BinFileList
) != 1:
229 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
230 File
= RegionData
.BinFileList
[0]
231 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
233 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
234 if RegionData
[1] != ':' :
235 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
236 if not os
.path
.exists(RegionData
):
237 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
239 # Add the file image into FD buffer
241 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
242 if FileLength
> Size
:
243 EdkLogger
.error("GenFds", GENFDS_ERROR
,
244 "Size of File (%s) is larger than Region Size 0x%X specified." \
245 % (RegionData
, Size
))
246 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
247 BinFile
= open(RegionData
, 'rb')
248 Buffer
.write(BinFile
.read())
250 Size
= Size
- FileLength
252 # Pad the left buffer
254 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
256 if self
.RegionType
== 'DATA' :
257 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
259 for RegionData
in self
.RegionDataList
:
260 Data
= RegionData
.split(',')
261 DataSize
= DataSize
+ len(Data
)
263 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
266 Buffer
.write(pack('B', int(item
, 16)))
267 Size
= Size
- DataSize
269 # Pad the left buffer
271 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
273 if self
.RegionType
is None:
274 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
275 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
277 def GetFvAlignValue(self
, Str
):
280 Str
= Str
.strip().upper()
281 if Str
.endswith('K'):
284 elif Str
.endswith('M'):
287 elif Str
.endswith('G'):
288 Granu
= 1024 * 1024 * 1024
293 AlignValue
= int(Str
) * Granu
296 ## BlockSizeOfRegion()
298 # @param BlockSizeList List of block information
299 # @param FvObj The object for FV
301 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
304 RemindingSize
= self
.Size
306 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
307 End
= Start
+ BlockSize
* BlockNum
308 # region not started yet
309 if self
.Offset
>= End
:
312 # region located in current blocks
314 # region ended within current blocks
315 if self
.Offset
+ self
.Size
<= End
:
316 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
318 # region not ended yet
320 # region not started in middle of current blocks
321 if self
.Offset
<= Start
:
322 UsedBlockNum
= BlockNum
323 # region started in middle of current blocks
325 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
327 ExpectedList
.append((BlockSize
, UsedBlockNum
))
328 RemindingSize
-= BlockSize
* UsedBlockNum
330 if FvObj
.BlockSizeList
== []:
331 FvObj
.BlockSizeList
= ExpectedList
333 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
334 # if so, use ExpectedList
335 for Item
in FvObj
.BlockSizeList
:
336 if Item
[0] is None or Item
[1] is None:
337 FvObj
.BlockSizeList
= ExpectedList
339 # make sure region size is no smaller than the summed block size in FV
341 for Item
in FvObj
.BlockSizeList
:
342 Sum
+= Item
[0] * Item
[1]
344 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
345 % (FvObj
.UiFvName
, Sum
, self
.Size
))
346 # check whether the BlockStatements in FV section is appropriate
347 ExpectedListData
= ''
348 for Item
in ExpectedList
:
349 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
351 for Item
in FvObj
.BlockSizeList
:
352 if Item
[0] != ExpectedList
[Index
][0]:
353 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
354 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
355 elif Item
[1] != ExpectedList
[Index
][1]:
356 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
359 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
360 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)