3 # Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials are licensed and made available under
5 # the terms and conditions of the BSD License that accompanies this distribution.
6 # The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 This utility supports some operations for Intel FSP image.
25 - Split a FSP 2.0 compatibale image into individual FSP-T/M/S/C
26 and generate the mapping header file.
29 class c_uint24(Structure
):
30 """Little-Endian 24-bit Unsigned Integer"""
33 ('Data', (c_uint8
* 3))
36 def __init__(self
, val
=0):
39 def __str__(self
, indent
=0):
40 return '0x%.6x' % self
.value
49 def set_value(self
, val
):
50 self
.Data
[0] = (val
) & 0xff
51 self
.Data
[1] = (val
>> 8) & 0xff
52 self
.Data
[2] = (val
>> 16) & 0xff
54 value
= property(get_value
, set_value
)
56 class EFI_FIRMWARE_VOLUME_HEADER(Structure
):
58 ('ZeroVector', ARRAY(c_uint8
, 16)),
59 ('FileSystemGuid', ARRAY(c_char
, 16)),
60 ('FvLength', c_uint64
),
61 ('Signature', c_uint32
),
62 ('Attributes', c_uint32
),
63 ('HeaderLength', c_uint16
),
64 ('Checksum', c_uint16
),
65 ('ExtHeaderOffset', c_uint16
),
66 ('Reserved', c_uint8
),
70 class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure
):
72 ('FvName', ARRAY(c_char
, 16)),
73 ('ExtHeaderSize', c_uint32
)
76 class EFI_FFS_INTEGRITY_CHECK(Structure
):
82 class EFI_FFS_FILE_HEADER(Structure
):
84 ('Name', ARRAY(c_char
, 16)),
85 ('IntegrityCheck', EFI_FFS_INTEGRITY_CHECK
),
87 ('Attributes', c_uint8
),
92 class EFI_COMMON_SECTION_HEADER(Structure
):
98 class FSP_INFORMATION_HEADER(Structure
):
100 ('Signature', c_uint32
),
101 ('HeaderLength', c_uint32
),
102 ('Reserved1', ARRAY(c_uint8
, 3)),
103 ('HeaderRevision', c_uint8
),
104 ('ImageRevision', c_uint32
),
105 ('ImageId', c_uint64
),
106 ('ImageSize', c_uint32
),
107 ('ImageBase', c_uint32
),
108 ('ImageAttribute', c_uint32
),
109 ('CfgRegionOffset', c_uint32
),
110 ('CfgRegionSize', c_uint32
),
111 ('ApiEntryNum', c_uint32
),
112 ('NemInitEntry', c_uint32
),
113 ('FspInitEntry', c_uint32
),
114 ('NotifyPhaseEntry', c_uint32
),
115 ('FspMemoryInitEntry', c_uint32
),
116 ('TempRamExitEntry', c_uint32
),
117 ('FspSiliconInitEntry', c_uint32
)
123 * Automatically generated file; DO NOT EDIT.
135 def __init__(self
, FvBin
):
139 hfsp
= open (self
.FspBin
, 'r+b')
140 self
.FspDat
= bytearray(hfsp
.read())
143 def OutputStruct (self
, obj
, indent
= 0):
145 pstr
= (' ' * indent
+ '{0:<%d} = {1}\n') % max_key_len
149 s
= (' ' * indent
+ '<%s>:\n') % obj
.__class
__.__name
__
150 for field
in obj
._fields
_:
152 val
= getattr(obj
, key
)
155 if not isinstance(val
, c_uint24
) and isinstance(val
, Structure
):
156 s
+= pstr
.format(key
, val
.__class
__.__name
__)
157 s
+= self
.OutputStruct (val
, indent
+ 1)
159 if type(val
) in (int, long):
161 elif isinstance(val
, str) and (len(val
) == 16):
162 rep
= str(uuid
.UUID(bytes
= val
))
163 elif isinstance(val
, c_uint24
):
164 rep
= hex(val
.get_value())
165 elif 'c_ubyte_Array' in str(type(val
)):
166 rep
= str(list(bytearray(val
)))
169 s
+= pstr
.format(key
, rep
)
175 for (fvh
, fvhe
, offset
) in self
.FvList
:
176 guid
= uuid
.UUID(bytes
= fvhe
.FvName
)
177 print ("FV%d FV GUID:%s Offset:0x%08X Length:0x%08X" % (idx
, str(guid
), offset
, fvh
.FvLength
))
179 print ("\nFSP LIST:")
180 for fsp
in self
.FspFv
:
181 print "FSP%s contains FV%s" % (fsp
, str(self
.FspFv
[fsp
][1]))
182 print "\nFSP%s Info Header:" % fsp
183 fih
= self
.FspFv
[fsp
][0]
185 def AlaignPtr (self
, offset
, alignment
= 8):
186 return (offset
+ alignment
- 1) & ~
(alignment
- 1)
188 def GetFspInfoHdr (self
, fvh
, fvhe
, fvoffset
):
190 offset
= fvh
.ExtHeaderOffset
+ fvhe
.ExtHeaderSize
192 offset
= fvh
.HeaderLength
193 offset
= self
.AlaignPtr(offset
)
195 # Now it should be 1st FFS
196 ffs
= EFI_FFS_FILE_HEADER
.from_buffer (self
.FspDat
, offset
)
197 offset
+= sizeof(ffs
)
198 offset
= self
.AlaignPtr(offset
)
200 # Now it should be 1st Section
201 sec
= EFI_COMMON_SECTION_HEADER
.from_buffer (self
.FspDat
, offset
)
202 offset
+= sizeof(sec
)
204 # Now it should be FSP_INFO_HEADER
206 fih
= FSP_INFORMATION_HEADER
.from_buffer (self
.FspDat
, offset
)
207 if 'FSPH' != bytearray
.fromhex('%08X' % fih
.Signature
)[::-1]:
212 def GetFvHdr (self
, offset
):
213 fvh
= EFI_FIRMWARE_VOLUME_HEADER
.from_buffer (self
.FspDat
, offset
)
214 if '_FVH' != bytearray
.fromhex('%08X' % fvh
.Signature
)[::-1]:
216 if fvh
.ExtHeaderOffset
> 0:
217 offset
+= fvh
.ExtHeaderOffset
218 fvhe
= EFI_FIRMWARE_VOLUME_EXT_HEADER
.from_buffer (self
.FspDat
, offset
)
223 def GetFvData(self
, idx
):
224 (fvh
, fvhe
, offset
) = self
.FvList
[idx
]
225 return self
.FspDat
[offset
:offset
+fvh
.FvLength
]
228 if len(self
.FspFv
) == 0:
232 for fv
in self
.FspFv
:
234 fih
= self
.FspFv
[fv
][0]
236 newfih
= self
.FspFv
[fv
][0]
237 if (newfih
.ImageId
!= fih
.ImageId
) or (newfih
.ImageRevision
!= fih
.ImageRevision
):
238 raise Exception("Inconsistent FSP ImageId or ImageRevision detected !")
241 def WriteFsp(self
, dir, name
):
244 fspname
, ext
= os
.path
.splitext(os
.path
.basename(name
))
245 for fv
in self
.FspFv
:
246 filename
= os
.path
.join(dir, fspname
+ fv
+ ext
)
247 hfsp
= open(filename
, 'w+b')
248 for fvidx
in self
.FspFv
[fv
][1]:
249 hfsp
.write (self
.GetFvData(fvidx
))
252 def WriteMap(self
, dir, hfile
):
254 hfile
= os
.path
.splitext(os
.path
.basename(self
.FspBin
))[0] + '.h'
255 fspname
, ext
= os
.path
.splitext(os
.path
.basename(hfile
))
256 filename
= os
.path
.join(dir, fspname
+ ext
)
257 hfsp
= open(filename
, 'w')
258 hfsp
.write ('%s\n\n' % self
.HeaderFile
)
261 for fsp
in self
.FspFv
:
262 fih
= self
.FspFv
[fsp
][0]
263 fvs
= self
.FspFv
[fsp
][1]
265 IdStr
= str(bytearray
.fromhex('%016X' % fih
.ImageId
)[::-1])
266 hfsp
.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (fih
.ImageId
, IdStr
))
267 hfsp
.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih
.ImageRevision
)
269 hfsp
.write ('#define FSP%s_BASE 0x%08X\n' % (fsp
, fih
.ImageBase
))
270 hfsp
.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp
, self
.FvList
[fvs
[0]][-1]))
271 hfsp
.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp
, fih
.ImageSize
))
277 for (fvh
, fvhe
, offset
) in self
.FvList
:
278 fih
= self
.GetFspInfoHdr (fvh
, fvhe
, offset
)
281 raise Exception("Incorrect FV size in image !")
282 ftype
= str((fih
.ImageAttribute
>> 28) & 0xF)
283 if ftype
not in self
.FspNameDict
:
284 raise Exception("Unknown Attribute in image !")
285 fname
= self
.FspNameDict
[str(ftype
)]
286 if fname
in self
.FspFv
:
287 raise Exception("Multiple '%s' in image !" % fname
)
288 self
.FspFv
[fname
] = (copy
.deepcopy(fih
), [])
291 flen
= flen
- fvh
.FvLength
293 raise Exception("Incorrect FV size in image !")
294 self
.FspFv
[fname
][1].append(self
.FvList
.index((fvh
, fvhe
, offset
)))
296 def AddFv(self
, offset
):
297 fvh
, fvhe
= self
.GetFvHdr (offset
)
299 raise Exception('FV signature is not valid !')
300 fvitem
= (copy
.deepcopy(fvh
), copy
.deepcopy(fvhe
), offset
)
301 self
.FvList
.append(fvitem
)
306 while (offset
< len(self
.FspDat
)):
307 fv_len
= self
.AddFv (offset
)
310 def GenFspHdr (fspfile
, outdir
, hfile
, show
):
311 fsp_fv
= FspFv(fspfile
)
317 fsp_fv
.WriteMap(outdir
, hfile
)
319 def SplitFspBin (fspfile
, outdir
, nametemplate
, show
):
320 fsp_fv
= FspFv(fspfile
)
325 fsp_fv
.WriteFsp(outdir
, nametemplate
)
328 parser
= argparse
.ArgumentParser()
329 subparsers
= parser
.add_subparsers(title
='commands')
331 parser_split
= subparsers
.add_parser('split', help='split a FSP into multiple components')
332 parser_split
.set_defaults(which
='split')
333 parser_split
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
334 parser_split
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
335 parser_split
.add_argument('-n', '--nametpl', dest
='NameTemplate', type=str, help='Output name template', default
= '')
336 parser_split
.add_argument('-p', action
='store_true', help='Print FSP FV information', default
= False)
338 parser_genhdr
= subparsers
.add_parser('genhdr', help='generate a header file for FSP binary')
339 parser_genhdr
.set_defaults(which
='genhdr')
340 parser_genhdr
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
341 parser_genhdr
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
342 parser_genhdr
.add_argument('-n', '--hfile', dest
='HFileName', type=str, help='Output header file name', default
= '')
343 parser_genhdr
.add_argument('-p', action
='store_true', help='Print FSP FV information', default
= False)
345 args
= parser
.parse_args()
346 if args
.which
in ['split', 'genhdr']:
347 if not os
.path
.exists(args
.FspBinary
):
348 raise Exception ("Could not locate FSP binary file '%s' !" % args
.FspBinary
)
349 if not os
.path
.exists(args
.OutputDir
):
350 raise Exception ("Invalid output directory '%s' !" % args
.OutputDir
)
352 if args
.which
== 'split':
353 SplitFspBin (args
.FspBinary
, args
.OutputDir
, args
.NameTemplate
, args
.p
)
354 elif args
.which
== 'genhdr':
355 GenFspHdr (args
.FspBinary
, args
.OutputDir
, args
.HFileName
, args
.p
)
362 if __name__
== '__main__':