]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/Region.py
2 # process FD Region generation
4 # Copyright (c) 2007 - 2015, 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
={}):
79 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
80 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
81 GenFdsGlobalVariable
.SharpCounter
= 0
83 if self
.RegionType
== 'FV':
87 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
88 FvBaseAddress
= '0x%X' % self
.FvAddress
90 for RegionData
in self
.RegionDataList
:
92 if RegionData
.endswith(".fv"):
93 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
94 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
95 if RegionData
[1] != ':' :
96 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
97 if not os
.path
.exists(RegionData
):
98 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
100 FileName
= RegionData
101 elif RegionData
.upper() + 'fv' in ImageBinDict
.keys():
102 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
103 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
109 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
110 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(RegionData
.upper())
113 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
117 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
118 self
.FvAddress
= self
.FvAddress
+ FvOffset
119 FvAlignValue
= self
.GetFvAlignValue(FvObj
.FvAlignment
)
120 if self
.FvAddress
% FvAlignValue
!= 0:
121 EdkLogger
.error("GenFds", GENFDS_ERROR
,
122 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
123 FvBuffer
= StringIO
.StringIO('')
124 FvBaseAddress
= '0x%X' % self
.FvAddress
127 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
)
128 if FvBuffer
.len > Size
:
130 EdkLogger
.error("GenFds", GENFDS_ERROR
,
131 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
133 # Put the generated image into FD buffer.
135 Buffer
.write(FvBuffer
.getvalue())
137 FvOffset
= FvOffset
+ FvBuffer
.len
138 Size
= Size
- FvBuffer
.len
141 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
143 # Add the exist Fv image into FD buffer
146 FileLength
= os
.stat(FileName
)[ST_SIZE
]
147 if FileLength
> Size
:
148 EdkLogger
.error("GenFds", GENFDS_ERROR
,
149 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
150 % (RegionData
, Size
))
151 BinFile
= open(FileName
, 'rb')
152 Buffer
.write(BinFile
.read())
154 Size
= Size
- FileLength
156 # Pad the left buffer
158 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
160 if self
.RegionType
== 'CAPSULE':
162 # Get Capsule from Capsule Dict
164 for RegionData
in self
.RegionDataList
:
165 if RegionData
.endswith(".cap"):
166 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
167 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
168 if RegionData
[1] != ':' :
169 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
170 if not os
.path
.exists(RegionData
):
171 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
173 FileName
= RegionData
174 elif RegionData
.upper() + 'cap' in ImageBinDict
.keys():
175 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
176 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
179 # Generate Capsule image and Put it into FD buffer
182 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
183 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
185 if CapsuleObj
!= None :
186 CapsuleObj
.CapsuleName
= RegionData
.upper()
187 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
189 # Call GenFv tool to generate Capsule Image
191 FileName
= CapsuleObj
.GenCapsule()
192 CapsuleObj
.CapsuleName
= None
194 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
197 # Add the capsule image into FD buffer
199 FileLength
= os
.stat(FileName
)[ST_SIZE
]
200 if FileLength
> Size
:
201 EdkLogger
.error("GenFds", GENFDS_ERROR
,
202 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
203 % (FileLength
, RegionData
, Size
))
204 BinFile
= open(FileName
, 'rb')
205 Buffer
.write(BinFile
.read())
207 Size
= Size
- FileLength
209 # Pad the left buffer
211 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
213 if self
.RegionType
in ('FILE', 'INF'):
214 for RegionData
in self
.RegionDataList
:
215 if self
.RegionType
== 'INF':
216 RegionData
.__InfParse
__(None)
217 if len(RegionData
.BinFileList
) != 1:
218 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
219 File
= RegionData
.BinFileList
[0]
220 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
222 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
223 if RegionData
[1] != ':' :
224 RegionData
= mws
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
225 if not os
.path
.exists(RegionData
):
226 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
228 # Add the file image into FD buffer
230 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
231 if FileLength
> Size
:
232 EdkLogger
.error("GenFds", GENFDS_ERROR
,
233 "Size of File (%s) is larger than Region Size 0x%X specified." \
234 % (RegionData
, Size
))
235 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
236 BinFile
= open(RegionData
, 'rb')
237 Buffer
.write(BinFile
.read())
239 Size
= Size
- FileLength
241 # Pad the left buffer
243 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
245 if self
.RegionType
== 'DATA' :
246 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
248 for RegionData
in self
.RegionDataList
:
249 Data
= RegionData
.split(',')
250 DataSize
= DataSize
+ len(Data
)
252 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
255 Buffer
.write(pack('B', int(item
, 16)))
256 Size
= Size
- DataSize
258 # Pad the left buffer
260 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
262 if self
.RegionType
== None:
263 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
264 self
.PadBuffer(Buffer
, ErasePolarity
, Size
)
266 def GetFvAlignValue(self
, Str
):
269 Str
= Str
.strip().upper()
270 if Str
.endswith('K'):
273 elif Str
.endswith('M'):
276 elif Str
.endswith('G'):
277 Granu
= 1024 * 1024 * 1024
282 AlignValue
= int(Str
) * Granu
285 ## BlockSizeOfRegion()
287 # @param BlockSizeList List of block information
288 # @param FvObj The object for FV
290 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
293 RemindingSize
= self
.Size
295 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
296 End
= Start
+ BlockSize
* BlockNum
297 # region not started yet
298 if self
.Offset
>= End
:
301 # region located in current blocks
303 # region ended within current blocks
304 if self
.Offset
+ self
.Size
<= End
:
305 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
307 # region not ended yet
309 # region not started in middle of current blocks
310 if self
.Offset
<= Start
:
311 UsedBlockNum
= BlockNum
312 # region started in middle of current blocks
314 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
316 ExpectedList
.append((BlockSize
, UsedBlockNum
))
317 RemindingSize
-= BlockSize
* UsedBlockNum
319 if FvObj
.BlockSizeList
== []:
320 FvObj
.BlockSizeList
= ExpectedList
322 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
323 # if so, use ExpectedList
324 for Item
in FvObj
.BlockSizeList
:
325 if Item
[0] == None or Item
[1] == None:
326 FvObj
.BlockSizeList
= ExpectedList
328 # make sure region size is no smaller than the summed block size in FV
330 for Item
in FvObj
.BlockSizeList
:
331 Sum
+= Item
[0] * Item
[1]
333 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
334 % (FvObj
.UiFvName
, Sum
, self
.Size
))
335 # check whether the BlockStatements in FV section is appropriate
336 ExpectedListData
= ''
337 for Item
in ExpectedList
:
338 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
340 for Item
in FvObj
.BlockSizeList
:
341 if Item
[0] != ExpectedList
[Index
][0]:
342 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
343 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
344 elif Item
[1] != ExpectedList
[Index
][1]:
345 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
348 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
349 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)