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 2.0 image.
25 - Display FSP 2.0 information header
26 - Split FSP 2.0 image into individual FSP-T/M/S/O component
27 - Rebase FSP 2.0 components to a different base address
28 - Generate FSP mapping C header file
31 CopyRightHeaderFile
= """/*
33 * Automatically generated file; DO NOT EDIT.
39 class c_uint24(Structure
):
40 """Little-Endian 24-bit Unsigned Integer"""
42 _fields_
= [('Data', (c_uint8
* 3))]
44 def __init__(self
, val
=0):
47 def __str__(self
, indent
=0):
48 return '0x%.6x' % self
.value
51 return self
.get_value()
53 def set_value(self
, val
):
54 self
.Data
[0:3] = Val2Bytes(val
, 3)
57 return Bytes2Val(self
.Data
[0:3])
59 value
= property(get_value
, set_value
)
61 class EFI_FIRMWARE_VOLUME_HEADER(Structure
):
63 ('ZeroVector', ARRAY(c_uint8
, 16)),
64 ('FileSystemGuid', ARRAY(c_uint8
, 16)),
65 ('FvLength', c_uint64
),
66 ('Signature', ARRAY(c_char
, 4)),
67 ('Attributes', c_uint32
),
68 ('HeaderLength', c_uint16
),
69 ('Checksum', c_uint16
),
70 ('ExtHeaderOffset', c_uint16
),
71 ('Reserved', c_uint8
),
75 class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure
):
77 ('FvName', ARRAY(c_uint8
, 16)),
78 ('ExtHeaderSize', c_uint32
)
81 class EFI_FFS_INTEGRITY_CHECK(Structure
):
87 class EFI_FFS_FILE_HEADER(Structure
):
89 ('Name', ARRAY(c_uint8
, 16)),
90 ('IntegrityCheck', EFI_FFS_INTEGRITY_CHECK
),
92 ('Attributes', c_uint8
),
97 class EFI_COMMON_SECTION_HEADER(Structure
):
103 class FSP_COMMON_HEADER(Structure
):
105 ('Signature', ARRAY(c_char
, 4)),
106 ('HeaderLength', c_uint32
)
109 class FSP_INFORMATION_HEADER(Structure
):
111 ('Signature', ARRAY(c_char
, 4)),
112 ('HeaderLength', c_uint32
),
113 ('Reserved1', c_uint16
),
114 ('SpecVersion', c_uint8
),
115 ('HeaderRevision', c_uint8
),
116 ('ImageRevision', c_uint32
),
117 ('ImageId', ARRAY(c_char
, 8)),
118 ('ImageSize', c_uint32
),
119 ('ImageBase', c_uint32
),
120 ('ImageAttribute', c_uint16
),
121 ('ComponentAttribute', c_uint16
),
122 ('CfgRegionOffset', c_uint32
),
123 ('CfgRegionSize', c_uint32
),
124 ('Reserved2', c_uint32
),
125 ('TempRamInitEntryOffset', c_uint32
),
126 ('Reserved3', c_uint32
),
127 ('NotifyPhaseEntryOffset', c_uint32
),
128 ('FspMemoryInitEntryOffset', c_uint32
),
129 ('TempRamExitEntryOffset', c_uint32
),
130 ('FspSiliconInitEntryOffset', c_uint32
)
133 class FSP_PATCH_TABLE(Structure
):
135 ('Signature', ARRAY(c_char
, 4)),
136 ('HeaderLength', c_uint16
),
137 ('HeaderRevision', c_uint8
),
138 ('Reserved', c_uint8
),
139 ('PatchEntryNum', c_uint32
)
142 class EFI_IMAGE_DATA_DIRECTORY(Structure
):
144 ('VirtualAddress', c_uint32
),
148 class EFI_TE_IMAGE_HEADER(Structure
):
150 ('Signature', ARRAY(c_char
, 2)),
151 ('Machine', c_uint16
),
152 ('NumberOfSections', c_uint8
),
153 ('Subsystem', c_uint8
),
154 ('StrippedSize', c_uint16
),
155 ('AddressOfEntryPoint', c_uint32
),
156 ('BaseOfCode', c_uint32
),
157 ('ImageBase', c_uint64
),
158 ('DataDirectoryBaseReloc', EFI_IMAGE_DATA_DIRECTORY
),
159 ('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY
)
162 class PE_RELOC_BLOCK_HEADER(Structure
):
164 ('PageRVA', c_uint32
),
165 ('BlockSize', c_uint32
)
168 class EFI_FV_FILETYPE
:
177 COMBINED_PEIM_DRIVER
= 0x08
180 FIRMWARE_VOLUME_IMAGE
= 0x0b
181 COMBINED_SMM_DXE
= 0x0c
191 class EFI_SECTION_TYPE
:
192 """Enumeration of all valid firmware file section types."""
202 USER_INTERFACE
= 0x15
203 COMPATIBILITY16
= 0x16
204 FIRMWARE_VOLUME_IMAGE
= 0x17
205 FREEFORM_SUBTYPE_GUID
= 0x18
210 def AlignPtr (offset
, alignment
= 8):
211 return (offset
+ alignment
- 1) & ~
(alignment
- 1)
213 def Bytes2Val (bytes
):
214 return reduce(lambda x
,y
: (x
<<8)|y
, bytes
[::-1] )
216 def Val2Bytes (value
, blen
):
217 return [(value
>>(i
*8) & 0xff) for i
in range(blen
)]
219 def OutputStruct (obj
, indent
= 0, plen
= 0):
223 body
= (' ' * indent
+ '<%s>:\n') % obj
.__class
__.__name
__
229 pstr
= (' ' * (indent
+ 1) + '{0:<%d} = {1}\n') % max_key_len
231 for field
in obj
._fields
_:
233 val
= getattr(obj
, key
)
235 if not isinstance(val
, c_uint24
) and isinstance(val
, Structure
):
236 body
+= pstr
.format(key
, val
.__class
__.__name
__)
237 body
+= OutputStruct (val
, indent
+ 1)
241 rep
= "0x%X ('%s')" % (Bytes2Val(bytearray(val
)), val
)
242 elif type(val
) in (int, long):
244 elif isinstance(val
, c_uint24
):
245 rep
= '0x%X' % val
.get_value()
246 elif 'c_ubyte_Array' in str(type(val
)):
247 if sizeof(val
) == 16:
248 rep
= str(uuid
.UUID(bytes
= str(bytearray(val
)))).upper()
250 res
= ['0x%02X'%i for i
in bytearray(val
)]
251 rep
= '[%s]' % (','.join(res
))
254 plen
-= sizeof(field
[1])
255 body
+= pstr
.format(key
, rep
)
261 def __init__(self
, offset
, secdata
):
262 self
.SecHdr
= EFI_COMMON_SECTION_HEADER
.from_buffer (secdata
, 0)
263 self
.SecData
= secdata
[0:int(self
.SecHdr
.Size
)]
267 def __init__(self
, offset
, filedata
):
268 self
.FfsHdr
= EFI_FFS_FILE_HEADER
.from_buffer (filedata
, 0)
269 self
.FfsData
= filedata
[0:int(self
.FfsHdr
.Size
)]
274 ffssize
= len(self
.FfsData
)
275 offset
= sizeof(self
.FfsHdr
)
276 if self
.FfsHdr
.Name
!= '\xff' * 16:
277 while offset
< ffssize
:
278 sechdr
= EFI_COMMON_SECTION_HEADER
.from_buffer (self
.FfsData
, offset
)
279 sec
= Section (offset
, self
.FfsData
[offset
:offset
+ int(sechdr
.Size
)])
280 self
.SecList
.append(sec
)
281 offset
+= int(sechdr
.Size
)
282 offset
= AlignPtr(offset
, 4)
284 class FirmwareVolume
:
285 def __init__(self
, offset
, fvdata
):
286 self
.FvHdr
= EFI_FIRMWARE_VOLUME_HEADER
.from_buffer (fvdata
, 0)
287 self
.FvData
= fvdata
[0 : self
.FvHdr
.FvLength
]
289 if self
.FvHdr
.ExtHeaderOffset
> 0:
290 self
.FvExtHdr
= EFI_FIRMWARE_VOLUME_EXT_HEADER
.from_buffer (self
.FvData
, self
.FvHdr
.ExtHeaderOffset
)
296 fvsize
= len(self
.FvData
)
298 offset
= self
.FvHdr
.ExtHeaderOffset
+ self
.FvExtHdr
.ExtHeaderSize
300 offset
= self
.FvHdr
.HeaderLength
301 offset
= AlignPtr(offset
)
302 while offset
< fvsize
:
303 ffshdr
= EFI_FFS_FILE_HEADER
.from_buffer (self
.FvData
, offset
)
304 if (ffshdr
.Name
== '\xff' * 16) and (int(ffshdr
.Size
) == 0xFFFFFF):
307 ffs
= FirmwareFile (offset
, self
.FvData
[offset
:offset
+ int(ffshdr
.Size
)])
309 self
.FfsList
.append(ffs
)
310 offset
+= int(ffshdr
.Size
)
311 offset
= AlignPtr(offset
)
314 def __init__(self
, offset
, fih
, fihoff
, patch
):
316 self
.FihOffset
= fihoff
319 self
.Type
= "XTMSXXXXOXXXXXXX"[(fih
.ComponentAttribute
>> 12) & 0x0F]
320 self
.PatchList
= patch
321 self
.PatchList
.append(fihoff
+ 0x1C)
323 def AppendFv(self
, FvIdx
):
324 self
.FvIdxList
.append(FvIdx
)
326 def Patch(self
, delta
, fdbin
):
329 for idx
, patch
in enumerate(self
.PatchList
):
330 ptype
= (patch
>>24) & 0x0F
331 if ptype
not in [0x00, 0x0F]:
332 raise Exception('ERROR: Invalid patch type %d !' % ptype
)
333 if patch
& 0x80000000:
334 patch
= self
.Fih
.ImageSize
- (0x1000000 - (patch
& 0xFFFFFF))
336 patch
= patch
& 0xFFFFFF
337 if (patch
< self
.Fih
.ImageSize
) and (patch
+ sizeof(c_uint32
) <= self
.Fih
.ImageSize
):
338 offset
= patch
+ self
.Offset
339 value
= Bytes2Val(fdbin
[offset
:offset
+sizeof(c_uint32
)])
341 fdbin
[offset
:offset
+sizeof(c_uint32
)] = Val2Bytes(value
, sizeof(c_uint32
))
344 # Don't count the FSP base address patch entry appended at the end
348 return (count
, applied
)
350 class FirmwareDevice
:
351 def __init__(self
, offset
, fdfile
):
356 hfsp
= open (self
.FdFile
, 'rb')
357 self
.FdData
= bytearray(hfsp
.read())
362 fdsize
= len(self
.FdData
)
364 while offset
< fdsize
:
365 fvh
= EFI_FIRMWARE_VOLUME_HEADER
.from_buffer (self
.FdData
, offset
)
366 if '_FVH' != fvh
.Signature
:
367 raise Exception("ERROR: Invalid FV header !")
368 fv
= FirmwareVolume (offset
, self
.FdData
[offset
:offset
+ fvh
.FvLength
])
370 self
.FvList
.append(fv
)
371 offset
+= fv
.FvHdr
.FvLength
374 if len(self
.FspList
) == 0:
378 for fsp
in self
.FspList
:
379 if fsp
.Fih
.HeaderRevision
< 3:
380 raise Exception("ERROR: FSP 1.x is not supported by this tool !")
385 if (newfih
.ImageId
!= fih
.ImageId
) or (newfih
.ImageRevision
!= fih
.ImageRevision
):
386 raise Exception("ERROR: Inconsistent FSP ImageId or ImageRevision detected !")
390 for idx
, fv
in enumerate(self
.FvList
):
391 # Check if this FV contains FSP header
393 if len(fv
.FfsList
) == 0:
396 if len(ffs
.SecList
) == 0:
399 if sec
.SecHdr
.Type
!= EFI_SECTION_TYPE
.RAW
:
401 fihoffset
= ffs
.Offset
+ sec
.Offset
+ sizeof(sec
.SecHdr
)
402 fspoffset
= fv
.Offset
403 offset
= fspoffset
+ fihoffset
404 fih
= FSP_INFORMATION_HEADER
.from_buffer (self
.FdData
, offset
)
405 if 'FSPH' != fih
.Signature
:
408 offset
+= fih
.HeaderLength
409 offset
= AlignPtr(offset
, 4)
412 fch
= FSP_COMMON_HEADER
.from_buffer (self
.FdData
, offset
)
413 if 'FSPP' != fch
.Signature
:
414 offset
+= fch
.HeaderLength
415 offset
= AlignPtr(offset
, 4)
417 fspp
= FSP_PATCH_TABLE
.from_buffer (self
.FdData
, offset
)
418 offset
+= sizeof(fspp
)
419 pdata
= (c_uint32
* fspp
.PatchEntryNum
).from_buffer(self
.FdData
, offset
)
423 fsp
= FspImage (fspoffset
, fih
, fihoffset
, plist
)
425 self
.FspList
.append(fsp
)
426 flen
= fsp
.Fih
.ImageSize
- fv
.FvHdr
.FvLength
429 flen
-= fv
.FvHdr
.FvLength
431 raise Exception("ERROR: Incorrect FV size in image !")
435 def __init__(self
, offset
, tedata
):
437 self
.TeHdr
= EFI_TE_IMAGE_HEADER
.from_buffer (tedata
, 0)
441 def ParseReloc(self
):
442 rsize
= self
.TeHdr
.DataDirectoryBaseReloc
.Size
443 roffset
= sizeof(self
.TeHdr
) - self
.TeHdr
.StrippedSize
+ self
.TeHdr
.DataDirectoryBaseReloc
.VirtualAddress
446 while offset
< roffset
+ rsize
:
447 offset
= AlignPtr(offset
, 4)
448 blkhdr
= PE_RELOC_BLOCK_HEADER
.from_buffer(self
.TeData
, offset
)
449 offset
+= sizeof(blkhdr
)
450 # Read relocation type,offset pairs
451 rlen
= blkhdr
.BlockSize
- sizeof(PE_RELOC_BLOCK_HEADER
)
452 rnum
= rlen
/sizeof(c_uint16
)
453 rdata
= (c_uint16
* rnum
).from_buffer(self
.TeData
, offset
)
457 if rtype
== 0: # IMAGE_REL_BASED.ABSOLUTE:
459 if rtype
!= 3: # IMAGE_REL_BASED_HIGHLOW
460 raise Exception("ERROR: Unsupported relocation type %d!" % rtype
)
461 # Calculate the offset of the relocation
462 aoff
= sizeof(self
.TeHdr
) - self
.TeHdr
.StrippedSize
+ blkhdr
.PageRVA
+ roff
463 self
.RelocList
.append((rtype
, aoff
))
464 offset
+= sizeof(rdata
)
466 def Rebase(self
, delta
, fdbin
):
471 for (rtype
, roff
) in self
.RelocList
:
472 if rtype
== 0x03: # HIGHLOW
473 offset
= roff
+ self
.Offset
474 value
= Bytes2Val(fdbin
[offset
:offset
+sizeof(c_uint32
)])
476 fdbin
[offset
:offset
+sizeof(c_uint32
)] = Val2Bytes(value
, sizeof(c_uint32
))
479 raise Exception('ERROR: Unknown relocation type %d !' % rtype
)
482 tehdr
.ImageBase
+= delta
484 fdbin
[offset
:offset
+sizeof(tehdr
)] = bytearray(tehdr
)
488 def ShowFspInfo (fspfile
):
489 fd
= FirmwareDevice(0, fspfile
)
493 print ("\nFound the following %d Firmware Volumes in FSP binary:" % (len(fd
.FvList
)))
494 for idx
, fv
in enumerate(fd
.FvList
):
495 name
= fv
.FvExtHdr
.FvName
499 name
= str(bytearray(name
))
500 guid
= uuid
.UUID(bytes
= name
)
501 print ("FV%d:" % idx
)
502 print (" GUID : %s" % str(guid
).upper())
503 print (" Offset : 0x%08X" % fv
.Offset
)
504 print (" Length : 0x%08X" % fv
.FvHdr
.FvLength
)
507 for fsp
in fd
.FspList
:
508 fvlist
= map(lambda x
: 'FV%d' % x
, fsp
.FvIdxList
)
509 print ("FSP_%s contains %s" % (fsp
.Type
, ','.join(fvlist
)))
510 print ("%s" % (OutputStruct(fsp
.Fih
, 0, fsp
.Fih
.HeaderLength
)))
512 def GenFspHdr (fspfile
, outdir
, hfile
):
513 fd
= FirmwareDevice(0, fspfile
)
518 hfile
= os
.path
.splitext(os
.path
.basename(fspfile
))[0] + '.h'
519 fspname
, ext
= os
.path
.splitext(os
.path
.basename(hfile
))
520 filename
= os
.path
.join(outdir
, fspname
+ ext
)
521 hfsp
= open(filename
, 'w')
522 hfsp
.write ('%s\n\n' % CopyRightHeaderFile
)
525 for fsp
in fd
.FspList
:
528 hfsp
.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih
.ImageId
)), fih
.ImageId
))
529 hfsp
.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih
.ImageRevision
)
531 fv
= fd
.FvList
[fsp
.FvIdxList
[0]]
532 hfsp
.write ('#define FSP%s_BASE 0x%08X\n' % (fsp
.Type
, fih
.ImageBase
))
533 hfsp
.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp
.Type
, fv
.Offset
))
534 hfsp
.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp
.Type
, fih
.ImageSize
))
538 def SplitFspBin (fspfile
, outdir
, nametemplate
):
539 fd
= FirmwareDevice(0, fspfile
)
543 for fsp
in fd
.FspList
:
546 nametemplate
= fspfile
547 fspname
, ext
= os
.path
.splitext(os
.path
.basename(nametemplate
))
548 filename
= os
.path
.join(outdir
, fspname
+ '_' + fsp
.Type
+ ext
)
549 hfsp
= open(filename
, 'wb')
550 print ("Ceate FSP component file '%s'" % filename
)
551 for fvidx
in fsp
.FvIdxList
:
552 fv
= fd
.FvList
[fvidx
]
553 hfsp
.write(fv
.FvData
)
556 def RebaseFspBin (FspBinary
, FspComponent
, FspBase
, OutputDir
, OutputFile
):
557 fd
= FirmwareDevice(0, FspBinary
)
561 numcomp
= len(FspComponent
)
563 if numcomp
!= len(baselist
):
564 print "ERROR: Required number of base does not match number of FSP component !"
567 newfspbin
= fd
.FdData
[:]
569 for idx
, fspcomp
in enumerate(FspComponent
):
572 for fsp
in fd
.FspList
:
573 ftype
= fsp
.Type
.lower()
579 print "ERROR: Could not find FSP_%c component to rebase !" % fspcomp
.upper()
582 fspbase
= baselist
[idx
]
583 if fspbase
.startswith('0x'):
584 newbase
= int(fspbase
, 16)
586 newbase
= int(fspbase
)
587 oldbase
= fsp
.Fih
.ImageBase
588 delta
= newbase
- oldbase
589 print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype
.upper(),oldbase
,newbase
)
592 for fvidx
in fsp
.FvIdxList
:
593 fv
= fd
.FvList
[fvidx
]
594 for ffs
in fv
.FfsList
:
595 for sec
in ffs
.SecList
:
596 if sec
.SecHdr
.Type
== EFI_SECTION_TYPE
.TE
: # TE
597 offset
= fd
.Offset
+ fv
.Offset
+ ffs
.Offset
+ sec
.Offset
+ sizeof(sec
.SecHdr
)
598 telist
.append ((offset
, len(sec
.SecData
) - sizeof(sec
.SecHdr
)))
599 elif sec
.SecHdr
.Type
== EFI_SECTION_TYPE
.PE32
: # PE
600 raise Exception("ERROR: PE32 Section is not supported !")
604 for (teoffset
, telen
) in telist
:
605 tehdr
= EFI_TE_IMAGE_HEADER
.from_buffer (fd
.FdData
, teoffset
)
606 if 'VZ' != tehdr
.Signature
:
607 raise Exception("ERROR: Invalid TE header !")
608 te
= TeImage(teoffset
, fd
.FdData
[teoffset
:teoffset
+ telen
])
610 tecount
+= te
.Rebase(delta
, newfspbin
)
612 print " Patched %d entries in %d TE images." % (tecount
, fcount
)
614 (count
, applied
) = fsp
.Patch(delta
, newfspbin
)
615 print " Patched %d entries using FSP patch table." % applied
617 print " %d invalid entries are ignored !" % (count
- applied
)
620 filename
= os
.path
.basename(FspBinary
)
621 base
, ext
= os
.path
.splitext(filename
)
622 OutputFile
= base
+ "_%08X" % newbase
+ ext
624 fspname
, ext
= os
.path
.splitext(os
.path
.basename(OutputFile
))
625 filename
= os
.path
.join(OutputDir
, fspname
+ ext
)
626 fd
= open(filename
, "wb")
631 parser
= argparse
.ArgumentParser()
632 subparsers
= parser
.add_subparsers(title
='commands')
634 parser_rebase
= subparsers
.add_parser('rebase', help='rebase a FSP into a new base address')
635 parser_rebase
.set_defaults(which
='rebase')
636 parser_rebase
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
637 parser_rebase
.add_argument('-c', '--fspcomp', choices
=['t','m','s','o'], nargs
='+', dest
='FspComponent', type=str, help='FSP component to rebase', default
= "['t']", required
= True)
638 parser_rebase
.add_argument('-b', '--newbase', dest
='FspBase', nargs
='+', type=str, help='Rebased FSP binary file name', default
= '', required
= True)
639 parser_rebase
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
640 parser_rebase
.add_argument('-n', '--outfile', dest
='OutputFile', type=str, help='Rebased FSP binary file name', default
= '')
642 parser_split
= subparsers
.add_parser('split', help='split a FSP into multiple components')
643 parser_split
.set_defaults(which
='split')
644 parser_split
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
645 parser_split
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
646 parser_split
.add_argument('-n', '--nametpl', dest
='NameTemplate', type=str, help='Output name template', default
= '')
648 parser_genhdr
= subparsers
.add_parser('genhdr', help='generate a header file for FSP binary')
649 parser_genhdr
.set_defaults(which
='genhdr')
650 parser_genhdr
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
651 parser_genhdr
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
652 parser_genhdr
.add_argument('-n', '--hfile', dest
='HFileName', type=str, help='Output header file name', default
= '')
654 parser_info
= subparsers
.add_parser('info', help='display FSP information')
655 parser_info
.set_defaults(which
='info')
656 parser_info
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
658 args
= parser
.parse_args()
659 if args
.which
in ['rebase', 'split', 'genhdr', 'info']:
660 if not os
.path
.exists(args
.FspBinary
):
661 raise Exception ("ERROR: Could not locate FSP binary file '%s' !" % args
.FspBinary
)
662 if hasattr(args
, 'OutputDir') and not os
.path
.exists(args
.OutputDir
):
663 raise Exception ("ERROR: Invalid output directory '%s' !" % args
.OutputDir
)
665 if args
.which
== 'rebase':
666 RebaseFspBin (args
.FspBinary
, args
.FspComponent
, args
.FspBase
, args
.OutputDir
, args
.OutputFile
)
667 elif args
.which
== 'split':
668 SplitFspBin (args
.FspBinary
, args
.OutputDir
, args
.NameTemplate
)
669 elif args
.which
== 'genhdr':
670 GenFspHdr (args
.FspBinary
, args
.OutputDir
, args
.HFileName
)
671 elif args
.which
== 'info':
672 ShowFspInfo (args
.FspBinary
)
678 if __name__
== '__main__':