]>
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
21 from CommonDataClass
.FdfClass
import RegionClassObject
22 import Common
.LongFilePathOs
as os
24 from Common
import EdkLogger
25 from Common
.BuildToolError
import *
26 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
27 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
32 class Region(RegionClassObject
):
36 # @param self The object pointer
39 RegionClassObject
.__init
__(self
)
44 # Add region data to the Buffer
46 # @param self The object pointer
47 # @param Buffer The buffer generated region data will be put
48 # @param BaseAddress base address of region
49 # @param BlockSize block size of region
50 # @param BlockNum How many blocks in region
51 # @param ErasePolarity Flash erase polarity
52 # @param VtfDict VTF objects
53 # @param MacroDict macro value pair
54 # @retval string Generated FV file path
57 def AddToBuffer(self
, Buffer
, BaseAddress
, BlockSizeList
, ErasePolarity
, ImageBinDict
, vtfDict
=None, MacroDict
={}):
59 GenFdsGlobalVariable
.InfLogger('\nGenerate Region at Offset 0x%X' % self
.Offset
)
60 GenFdsGlobalVariable
.InfLogger(" Region Size = 0x%X" % Size
)
61 GenFdsGlobalVariable
.SharpCounter
= 0
63 if self
.RegionType
== 'FV':
67 self
.FvAddress
= int(BaseAddress
, 16) + self
.Offset
68 FvBaseAddress
= '0x%X' % self
.FvAddress
70 for RegionData
in self
.RegionDataList
:
72 if RegionData
.endswith(".fv"):
73 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
74 GenFdsGlobalVariable
.InfLogger(' Region FV File Name = .fv : %s' % RegionData
)
75 if RegionData
[1] != ':' :
76 RegionData
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
77 if not os
.path
.exists(RegionData
):
78 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
81 elif RegionData
.upper() + 'fv' in ImageBinDict
.keys():
82 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
83 FileName
= ImageBinDict
[RegionData
.upper() + 'fv']
89 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.keys():
90 FvObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.FvDict
.get(RegionData
.upper())
93 GenFdsGlobalVariable
.InfLogger(' Region Name = FV')
97 self
.BlockInfoOfRegion(BlockSizeList
, FvObj
)
98 self
.FvAddress
= self
.FvAddress
+ FvOffset
99 FvAlignValue
= self
.GetFvAlignValue(FvObj
.FvAlignment
)
100 if self
.FvAddress
% FvAlignValue
!= 0:
101 EdkLogger
.error("GenFds", GENFDS_ERROR
,
102 "FV (%s) is NOT %s Aligned!" % (FvObj
.UiFvName
, FvObj
.FvAlignment
))
103 FvBuffer
= StringIO
.StringIO('')
104 FvBaseAddress
= '0x%X' % self
.FvAddress
107 FvObj
.AddToBuffer(FvBuffer
, FvBaseAddress
, BlockSize
, BlockNum
, ErasePolarity
, vtfDict
)
108 if FvBuffer
.len > Size
:
110 EdkLogger
.error("GenFds", GENFDS_ERROR
,
111 "Size of FV (%s) is larger than Region Size 0x%X specified." % (RegionData
, Size
))
113 # Put the generated image into FD buffer.
115 Buffer
.write(FvBuffer
.getvalue())
117 FvOffset
= FvOffset
+ FvBuffer
.len
118 Size
= Size
- FvBuffer
.len
121 EdkLogger
.error("GenFds", GENFDS_ERROR
, "FV (%s) is NOT described in FDF file!" % (RegionData
))
123 # Add the exist Fv image into FD buffer
126 FileLength
= os
.stat(FileName
)[ST_SIZE
]
127 if FileLength
> Size
:
128 EdkLogger
.error("GenFds", GENFDS_ERROR
,
129 "Size of FV File (%s) is larger than Region Size 0x%X specified." \
130 % (RegionData
, Size
))
131 BinFile
= open(FileName
, 'r+b')
132 Buffer
.write(BinFile
.read())
134 Size
= Size
- FileLength
136 # Pad the left buffer
139 if (ErasePolarity
== '1') :
143 for i
in range(0, Size
):
144 Buffer
.write(pack('B', PadData
))
146 if self
.RegionType
== 'CAPSULE':
148 # Get Capsule from Capsule Dict
150 for RegionData
in self
.RegionDataList
:
151 if RegionData
.endswith(".cap"):
152 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
153 GenFdsGlobalVariable
.InfLogger(' Region CAPSULE Image Name = .cap : %s' % RegionData
)
154 if RegionData
[1] != ':' :
155 RegionData
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
156 if not os
.path
.exists(RegionData
):
157 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
159 FileName
= RegionData
160 elif RegionData
.upper() + 'cap' in ImageBinDict
.keys():
161 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
162 FileName
= ImageBinDict
[RegionData
.upper() + 'cap']
165 # Generate Capsule image and Put it into FD buffer
168 if RegionData
.upper() in GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
.keys():
169 CapsuleObj
= GenFdsGlobalVariable
.FdfParser
.Profile
.CapsuleDict
[RegionData
.upper()]
171 if CapsuleObj
!= None :
172 CapsuleObj
.CapsuleName
= RegionData
.upper()
173 GenFdsGlobalVariable
.InfLogger(' Region Name = CAPSULE')
175 # Call GenFv tool to generate Capsule Image
177 FileName
= CapsuleObj
.GenCapsule()
178 CapsuleObj
.CapsuleName
= None
180 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Capsule (%s) is NOT described in FDF file!" % (RegionData
))
183 # Add the capsule image into FD buffer
185 FileLength
= os
.stat(FileName
)[ST_SIZE
]
186 if FileLength
> Size
:
187 EdkLogger
.error("GenFds", GENFDS_ERROR
,
188 "Size 0x%X of Capsule File (%s) is larger than Region Size 0x%X specified." \
189 % (FileLength
, RegionData
, Size
))
190 BinFile
= open(FileName
, 'r+b')
191 Buffer
.write(BinFile
.read())
193 Size
= Size
- FileLength
195 # Pad the left buffer
198 if (ErasePolarity
== '1') :
202 for i
in range(0, Size
):
203 Buffer
.write(pack('B', PadData
))
205 if self
.RegionType
in ('FILE', 'INF'):
206 for RegionData
in self
.RegionDataList
:
207 if self
.RegionType
== 'INF':
208 RegionData
.__InfParse
__(None)
209 if len(RegionData
.BinFileList
) != 1:
210 EdkLogger
.error('GenFds', GENFDS_ERROR
, 'INF in FD region can only contain one binary: %s' % RegionData
)
211 File
= RegionData
.BinFileList
[0]
212 RegionData
= RegionData
.PatchEfiFile(File
.Path
, File
.Type
)
214 RegionData
= GenFdsGlobalVariable
.MacroExtend(RegionData
, MacroDict
)
215 if RegionData
[1] != ':' :
216 RegionData
= os
.path
.join (GenFdsGlobalVariable
.WorkSpaceDir
, RegionData
)
217 if not os
.path
.exists(RegionData
):
218 EdkLogger
.error("GenFds", FILE_NOT_FOUND
, ExtraData
=RegionData
)
220 # Add the file image into FD buffer
222 FileLength
= os
.stat(RegionData
)[ST_SIZE
]
223 if FileLength
> Size
:
224 EdkLogger
.error("GenFds", GENFDS_ERROR
,
225 "Size of File (%s) is larger than Region Size 0x%X specified." \
226 % (RegionData
, Size
))
227 GenFdsGlobalVariable
.InfLogger(' Region File Name = %s' % RegionData
)
228 BinFile
= open(RegionData
, 'rb')
229 Buffer
.write(BinFile
.read())
231 Size
= Size
- FileLength
233 # Pad the left buffer
236 if (ErasePolarity
== '1') :
240 for i
in range(0, Size
):
241 Buffer
.write(pack('B', PadData
))
243 if self
.RegionType
== 'DATA' :
244 GenFdsGlobalVariable
.InfLogger(' Region Name = DATA')
246 for RegionData
in self
.RegionDataList
:
247 Data
= RegionData
.split(',')
248 DataSize
= DataSize
+ len(Data
)
250 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Size of DATA is larger than Region Size ")
253 Buffer
.write(pack('B', int(item
, 16)))
254 Size
= Size
- DataSize
256 # Pad the left buffer
259 if (ErasePolarity
== '1') :
263 for i
in range(0, Size
):
264 Buffer
.write(pack('B', PadData
))
266 if self
.RegionType
== None:
267 GenFdsGlobalVariable
.InfLogger(' Region Name = None')
268 if (ErasePolarity
== '1') :
272 for i
in range(0, Size
):
273 Buffer
.write(pack('B', PadData
))
275 def GetFvAlignValue(self
, Str
):
278 Str
= Str
.strip().upper()
279 if Str
.endswith('K'):
282 elif Str
.endswith('M'):
285 elif Str
.endswith('G'):
286 Granu
= 1024 * 1024 * 1024
291 AlignValue
= int(Str
) * Granu
294 ## BlockSizeOfRegion()
296 # @param BlockSizeList List of block information
297 # @param FvObj The object for FV
299 def BlockInfoOfRegion(self
, BlockSizeList
, FvObj
):
302 RemindingSize
= self
.Size
304 for (BlockSize
, BlockNum
, pcd
) in BlockSizeList
:
305 End
= Start
+ BlockSize
* BlockNum
306 # region not started yet
307 if self
.Offset
>= End
:
310 # region located in current blocks
312 # region ended within current blocks
313 if self
.Offset
+ self
.Size
<= End
:
314 ExpectedList
.append((BlockSize
, (RemindingSize
+ BlockSize
- 1) / BlockSize
))
316 # region not ended yet
318 # region not started in middle of current blocks
319 if self
.Offset
<= Start
:
320 UsedBlockNum
= BlockNum
321 # region started in middle of current blocks
323 UsedBlockNum
= (End
- self
.Offset
) / BlockSize
325 ExpectedList
.append((BlockSize
, UsedBlockNum
))
326 RemindingSize
-= BlockSize
* UsedBlockNum
328 if FvObj
.BlockSizeList
== []:
329 FvObj
.BlockSizeList
= ExpectedList
331 # first check whether FvObj.BlockSizeList items have only "BlockSize" or "NumBlocks",
332 # if so, use ExpectedList
333 for Item
in FvObj
.BlockSizeList
:
334 if Item
[0] == None or Item
[1] == None:
335 FvObj
.BlockSizeList
= ExpectedList
337 # make sure region size is no smaller than the summed block size in FV
339 for Item
in FvObj
.BlockSizeList
:
340 Sum
+= Item
[0] * Item
[1]
342 EdkLogger
.error("GenFds", GENFDS_ERROR
, "Total Size of FV %s 0x%x is larger than Region Size 0x%x "
343 % (FvObj
.UiFvName
, Sum
, self
.Size
))
344 # check whether the BlockStatements in FV section is appropriate
345 ExpectedListData
= ''
346 for Item
in ExpectedList
:
347 ExpectedListData
+= "BlockSize = 0x%x\n\tNumBlocks = 0x%x\n\t" % Item
349 for Item
in FvObj
.BlockSizeList
:
350 if Item
[0] != ExpectedList
[Index
][0]:
351 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
352 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)
353 elif Item
[1] != ExpectedList
[Index
][1]:
354 if (Item
[1] < ExpectedList
[Index
][1]) and (Index
== len(FvObj
.BlockSizeList
) - 1):
357 EdkLogger
.error("GenFds", GENFDS_ERROR
, "BlockStatements of FV %s are not align with FD's, suggested FV BlockStatement"
358 % FvObj
.UiFvName
, ExtraData
=ExpectedListData
)