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 EFI_IMAGE_DOS_HEADER(Structure
):
164 ('e_magic', c_uint16
),
165 ('e_cblp', c_uint16
),
167 ('e_crlc', c_uint16
),
168 ('e_cparhdr', c_uint16
),
169 ('e_minalloc', c_uint16
),
170 ('e_maxalloc', c_uint16
),
173 ('e_csum', c_uint16
),
176 ('e_lfarlc', c_uint16
),
177 ('e_ovno', c_uint16
),
178 ('e_res', ARRAY(c_uint16
, 4)),
179 ('e_oemid', c_uint16
),
180 ('e_oeminfo', c_uint16
),
181 ('e_res2', ARRAY(c_uint16
, 10)),
182 ('e_lfanew', c_uint16
)
185 class EFI_IMAGE_FILE_HEADER(Structure
):
187 ('Machine', c_uint16
),
188 ('NumberOfSections', c_uint16
),
189 ('TimeDateStamp', c_uint32
),
190 ('PointerToSymbolTable', c_uint32
),
191 ('NumberOfSymbols', c_uint32
),
192 ('SizeOfOptionalHeader', c_uint16
),
193 ('Characteristics', c_uint16
)
196 class PE_RELOC_BLOCK_HEADER(Structure
):
198 ('PageRVA', c_uint32
),
199 ('BlockSize', c_uint32
)
202 class EFI_IMAGE_OPTIONAL_HEADER32(Structure
):
205 ('MajorLinkerVersion', c_uint8
),
206 ('MinorLinkerVersion', c_uint8
),
207 ('SizeOfCode', c_uint32
),
208 ('SizeOfInitializedData', c_uint32
),
209 ('SizeOfUninitializedData', c_uint32
),
210 ('AddressOfEntryPoint', c_uint32
),
211 ('BaseOfCode', c_uint32
),
212 ('BaseOfData', c_uint32
),
213 ('ImageBase', c_uint32
),
214 ('SectionAlignment', c_uint32
),
215 ('FileAlignment', c_uint32
),
216 ('MajorOperatingSystemVersion', c_uint16
),
217 ('MinorOperatingSystemVersion', c_uint16
),
218 ('MajorImageVersion', c_uint16
),
219 ('MinorImageVersion', c_uint16
),
220 ('MajorSubsystemVersion', c_uint16
),
221 ('MinorSubsystemVersion', c_uint16
),
222 ('Win32VersionValue', c_uint32
),
223 ('SizeOfImage', c_uint32
),
224 ('SizeOfHeaders', c_uint32
),
225 ('CheckSum' , c_uint32
),
226 ('Subsystem', c_uint16
),
227 ('DllCharacteristics', c_uint16
),
228 ('SizeOfStackReserve', c_uint32
),
229 ('SizeOfStackCommit' , c_uint32
),
230 ('SizeOfHeapReserve', c_uint32
),
231 ('SizeOfHeapCommit' , c_uint32
),
232 ('LoaderFlags' , c_uint32
),
233 ('NumberOfRvaAndSizes', c_uint32
),
234 ('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY
, 16))
237 class EFI_IMAGE_NT_HEADERS32(Structure
):
239 ('Signature', c_uint32
),
240 ('FileHeader', EFI_IMAGE_FILE_HEADER
),
241 ('OptionalHeader', EFI_IMAGE_OPTIONAL_HEADER32
)
245 class EFI_IMAGE_DIRECTORY_ENTRY
:
258 class EFI_FV_FILETYPE
:
267 COMBINED_PEIM_DRIVER
= 0x08
270 FIRMWARE_VOLUME_IMAGE
= 0x0b
271 COMBINED_SMM_DXE
= 0x0c
281 class EFI_SECTION_TYPE
:
282 """Enumeration of all valid firmware file section types."""
292 USER_INTERFACE
= 0x15
293 COMPATIBILITY16
= 0x16
294 FIRMWARE_VOLUME_IMAGE
= 0x17
295 FREEFORM_SUBTYPE_GUID
= 0x18
300 def AlignPtr (offset
, alignment
= 8):
301 return (offset
+ alignment
- 1) & ~
(alignment
- 1)
303 def Bytes2Val (bytes
):
304 return reduce(lambda x
,y
: (x
<<8)|y
, bytes
[::-1] )
306 def Val2Bytes (value
, blen
):
307 return [(value
>>(i
*8) & 0xff) for i
in range(blen
)]
309 def OutputStruct (obj
, indent
= 0, plen
= 0):
313 body
= (' ' * indent
+ '<%s>:\n') % obj
.__class
__.__name
__
319 pstr
= (' ' * (indent
+ 1) + '{0:<%d} = {1}\n') % max_key_len
321 for field
in obj
._fields
_:
323 val
= getattr(obj
, key
)
325 if not isinstance(val
, c_uint24
) and isinstance(val
, Structure
):
326 body
+= pstr
.format(key
, val
.__class
__.__name
__)
327 body
+= OutputStruct (val
, indent
+ 1)
331 rep
= "0x%X ('%s')" % (Bytes2Val(bytearray(val
)), val
)
332 elif type(val
) in (int, long):
334 elif isinstance(val
, c_uint24
):
335 rep
= '0x%X' % val
.get_value()
336 elif 'c_ubyte_Array' in str(type(val
)):
337 if sizeof(val
) == 16:
338 rep
= str(uuid
.UUID(bytes
= str(bytearray(val
)))).upper()
340 res
= ['0x%02X'%i for i
in bytearray(val
)]
341 rep
= '[%s]' % (','.join(res
))
344 plen
-= sizeof(field
[1])
345 body
+= pstr
.format(key
, rep
)
351 def __init__(self
, offset
, secdata
):
352 self
.SecHdr
= EFI_COMMON_SECTION_HEADER
.from_buffer (secdata
, 0)
353 self
.SecData
= secdata
[0:int(self
.SecHdr
.Size
)]
357 def __init__(self
, offset
, filedata
):
358 self
.FfsHdr
= EFI_FFS_FILE_HEADER
.from_buffer (filedata
, 0)
359 self
.FfsData
= filedata
[0:int(self
.FfsHdr
.Size
)]
364 ffssize
= len(self
.FfsData
)
365 offset
= sizeof(self
.FfsHdr
)
366 if self
.FfsHdr
.Name
!= '\xff' * 16:
367 while offset
< ffssize
:
368 sechdr
= EFI_COMMON_SECTION_HEADER
.from_buffer (self
.FfsData
, offset
)
369 sec
= Section (offset
, self
.FfsData
[offset
:offset
+ int(sechdr
.Size
)])
370 self
.SecList
.append(sec
)
371 offset
+= int(sechdr
.Size
)
372 offset
= AlignPtr(offset
, 4)
374 class FirmwareVolume
:
375 def __init__(self
, offset
, fvdata
):
376 self
.FvHdr
= EFI_FIRMWARE_VOLUME_HEADER
.from_buffer (fvdata
, 0)
377 self
.FvData
= fvdata
[0 : self
.FvHdr
.FvLength
]
379 if self
.FvHdr
.ExtHeaderOffset
> 0:
380 self
.FvExtHdr
= EFI_FIRMWARE_VOLUME_EXT_HEADER
.from_buffer (self
.FvData
, self
.FvHdr
.ExtHeaderOffset
)
386 fvsize
= len(self
.FvData
)
388 offset
= self
.FvHdr
.ExtHeaderOffset
+ self
.FvExtHdr
.ExtHeaderSize
390 offset
= self
.FvHdr
.HeaderLength
391 offset
= AlignPtr(offset
)
392 while offset
< fvsize
:
393 ffshdr
= EFI_FFS_FILE_HEADER
.from_buffer (self
.FvData
, offset
)
394 if (ffshdr
.Name
== '\xff' * 16) and (int(ffshdr
.Size
) == 0xFFFFFF):
397 ffs
= FirmwareFile (offset
, self
.FvData
[offset
:offset
+ int(ffshdr
.Size
)])
399 self
.FfsList
.append(ffs
)
400 offset
+= int(ffshdr
.Size
)
401 offset
= AlignPtr(offset
)
404 def __init__(self
, offset
, fih
, fihoff
, patch
):
406 self
.FihOffset
= fihoff
409 self
.Type
= "XTMSXXXXOXXXXXXX"[(fih
.ComponentAttribute
>> 12) & 0x0F]
410 self
.PatchList
= patch
411 self
.PatchList
.append(fihoff
+ 0x1C)
413 def AppendFv(self
, FvIdx
):
414 self
.FvIdxList
.append(FvIdx
)
416 def Patch(self
, delta
, fdbin
):
419 for idx
, patch
in enumerate(self
.PatchList
):
420 ptype
= (patch
>>24) & 0x0F
421 if ptype
not in [0x00, 0x0F]:
422 raise Exception('ERROR: Invalid patch type %d !' % ptype
)
423 if patch
& 0x80000000:
424 patch
= self
.Fih
.ImageSize
- (0x1000000 - (patch
& 0xFFFFFF))
426 patch
= patch
& 0xFFFFFF
427 if (patch
< self
.Fih
.ImageSize
) and (patch
+ sizeof(c_uint32
) <= self
.Fih
.ImageSize
):
428 offset
= patch
+ self
.Offset
429 value
= Bytes2Val(fdbin
[offset
:offset
+sizeof(c_uint32
)])
431 fdbin
[offset
:offset
+sizeof(c_uint32
)] = Val2Bytes(value
, sizeof(c_uint32
))
434 # Don't count the FSP base address patch entry appended at the end
438 return (count
, applied
)
440 class FirmwareDevice
:
441 def __init__(self
, offset
, fdfile
):
446 hfsp
= open (self
.FdFile
, 'rb')
447 self
.FdData
= bytearray(hfsp
.read())
452 fdsize
= len(self
.FdData
)
454 while offset
< fdsize
:
455 fvh
= EFI_FIRMWARE_VOLUME_HEADER
.from_buffer (self
.FdData
, offset
)
456 if '_FVH' != fvh
.Signature
:
457 raise Exception("ERROR: Invalid FV header !")
458 fv
= FirmwareVolume (offset
, self
.FdData
[offset
:offset
+ fvh
.FvLength
])
460 self
.FvList
.append(fv
)
461 offset
+= fv
.FvHdr
.FvLength
464 if len(self
.FspList
) == 0:
468 for fsp
in self
.FspList
:
469 if fsp
.Fih
.HeaderRevision
< 3:
470 raise Exception("ERROR: FSP 1.x is not supported by this tool !")
475 if (newfih
.ImageId
!= fih
.ImageId
) or (newfih
.ImageRevision
!= fih
.ImageRevision
):
476 raise Exception("ERROR: Inconsistent FSP ImageId or ImageRevision detected !")
480 for idx
, fv
in enumerate(self
.FvList
):
481 # Check if this FV contains FSP header
483 if len(fv
.FfsList
) == 0:
486 if len(ffs
.SecList
) == 0:
489 if sec
.SecHdr
.Type
!= EFI_SECTION_TYPE
.RAW
:
491 fihoffset
= ffs
.Offset
+ sec
.Offset
+ sizeof(sec
.SecHdr
)
492 fspoffset
= fv
.Offset
493 offset
= fspoffset
+ fihoffset
494 fih
= FSP_INFORMATION_HEADER
.from_buffer (self
.FdData
, offset
)
495 if 'FSPH' != fih
.Signature
:
498 offset
+= fih
.HeaderLength
499 offset
= AlignPtr(offset
, 4)
502 fch
= FSP_COMMON_HEADER
.from_buffer (self
.FdData
, offset
)
503 if 'FSPP' != fch
.Signature
:
504 offset
+= fch
.HeaderLength
505 offset
= AlignPtr(offset
, 4)
507 fspp
= FSP_PATCH_TABLE
.from_buffer (self
.FdData
, offset
)
508 offset
+= sizeof(fspp
)
509 pdata
= (c_uint32
* fspp
.PatchEntryNum
).from_buffer(self
.FdData
, offset
)
513 fsp
= FspImage (fspoffset
, fih
, fihoffset
, plist
)
515 self
.FspList
.append(fsp
)
516 flen
= fsp
.Fih
.ImageSize
- fv
.FvHdr
.FvLength
519 flen
-= fv
.FvHdr
.FvLength
521 raise Exception("ERROR: Incorrect FV size in image !")
525 def __init__(self
, offset
, data
):
527 tehdr
= EFI_TE_IMAGE_HEADER
.from_buffer (data
, 0)
528 if tehdr
.Signature
== 'VZ': # TE image
530 elif tehdr
.Signature
== 'MZ': # PE32 image
532 self
.DosHdr
= EFI_IMAGE_DOS_HEADER
.from_buffer (data
, 0)
533 self
.PeHdr
= EFI_IMAGE_NT_HEADERS32
.from_buffer (data
, self
.DosHdr
.e_lfanew
)
534 if self
.PeHdr
.Signature
!= 0x4550:
535 raise Exception("ERROR: Invalid PE32 header !")
536 if self
.PeHdr
.FileHeader
.SizeOfOptionalHeader
< EFI_IMAGE_OPTIONAL_HEADER32
.DataDirectory
.offset
:
537 raise Exception("ERROR: Unsupported PE32 image !")
538 if self
.PeHdr
.OptionalHeader
.NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY
.BASERELOC
:
539 raise Exception("ERROR: No relocation information available !")
545 return self
.TeHdr
is not None
547 def ParseReloc(self
):
549 rsize
= self
.TeHdr
.DataDirectoryBaseReloc
.Size
550 roffset
= sizeof(self
.TeHdr
) - self
.TeHdr
.StrippedSize
+ self
.TeHdr
.DataDirectoryBaseReloc
.VirtualAddress
552 rsize
= self
.PeHdr
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY
.BASERELOC
].Size
553 roffset
= self
.PeHdr
.OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY
.BASERELOC
].VirtualAddress
557 while offset
< roffset
+ rsize
:
558 offset
= AlignPtr(offset
, 4)
559 blkhdr
= PE_RELOC_BLOCK_HEADER
.from_buffer(self
.Data
, offset
)
560 offset
+= sizeof(blkhdr
)
561 # Read relocation type,offset pairs
562 rlen
= blkhdr
.BlockSize
- sizeof(PE_RELOC_BLOCK_HEADER
)
563 rnum
= rlen
/sizeof(c_uint16
)
564 rdata
= (c_uint16
* rnum
).from_buffer(self
.Data
, offset
)
568 if rtype
== 0: # IMAGE_REL_BASED.ABSOLUTE:
570 if rtype
!= 3: # IMAGE_REL_BASED_HIGHLOW
571 raise Exception("ERROR: Unsupported relocation type %d!" % rtype
)
572 # Calculate the offset of the relocation
573 aoff
= blkhdr
.PageRVA
+ roff
575 aoff
+= sizeof(self
.TeHdr
) - self
.TeHdr
.StrippedSize
576 self
.RelocList
.append((rtype
, aoff
))
577 offset
+= sizeof(rdata
)
579 def Rebase(self
, delta
, fdbin
):
584 for (rtype
, roff
) in self
.RelocList
:
585 if rtype
== 0x03: # HIGHLOW
586 offset
= roff
+ self
.Offset
587 value
= Bytes2Val(fdbin
[offset
:offset
+sizeof(c_uint32
)])
589 fdbin
[offset
:offset
+sizeof(c_uint32
)] = Val2Bytes(value
, sizeof(c_uint32
))
592 raise Exception('ERROR: Unknown relocation type %d !' % rtype
)
595 offset
= self
.Offset
+ EFI_TE_IMAGE_HEADER
.ImageBase
.offset
596 size
= EFI_TE_IMAGE_HEADER
.ImageBase
.size
598 offset
= self
.Offset
+ self
.DosHdr
.e_lfanew
599 offset
+= EFI_IMAGE_NT_HEADERS32
.OptionalHeader
.offset
600 offset
+= EFI_IMAGE_OPTIONAL_HEADER32
.ImageBase
.offset
601 size
= EFI_IMAGE_OPTIONAL_HEADER32
.ImageBase
.size
603 value
= Bytes2Val(fdbin
[offset
:offset
+size
]) + delta
604 fdbin
[offset
:offset
+size
] = Val2Bytes(value
, size
)
608 def ShowFspInfo (fspfile
):
609 fd
= FirmwareDevice(0, fspfile
)
613 print ("\nFound the following %d Firmware Volumes in FSP binary:" % (len(fd
.FvList
)))
614 for idx
, fv
in enumerate(fd
.FvList
):
615 name
= fv
.FvExtHdr
.FvName
619 name
= str(bytearray(name
))
620 guid
= uuid
.UUID(bytes
= name
)
621 print ("FV%d:" % idx
)
622 print (" GUID : %s" % str(guid
).upper())
623 print (" Offset : 0x%08X" % fv
.Offset
)
624 print (" Length : 0x%08X" % fv
.FvHdr
.FvLength
)
627 for fsp
in fd
.FspList
:
628 fvlist
= map(lambda x
: 'FV%d' % x
, fsp
.FvIdxList
)
629 print ("FSP_%s contains %s" % (fsp
.Type
, ','.join(fvlist
)))
630 print ("%s" % (OutputStruct(fsp
.Fih
, 0, fsp
.Fih
.HeaderLength
)))
632 def GenFspHdr (fspfile
, outdir
, hfile
):
633 fd
= FirmwareDevice(0, fspfile
)
638 hfile
= os
.path
.splitext(os
.path
.basename(fspfile
))[0] + '.h'
639 fspname
, ext
= os
.path
.splitext(os
.path
.basename(hfile
))
640 filename
= os
.path
.join(outdir
, fspname
+ ext
)
641 hfsp
= open(filename
, 'w')
642 hfsp
.write ('%s\n\n' % CopyRightHeaderFile
)
645 for fsp
in fd
.FspList
:
648 hfsp
.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih
.ImageId
)), fih
.ImageId
))
649 hfsp
.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih
.ImageRevision
)
651 fv
= fd
.FvList
[fsp
.FvIdxList
[0]]
652 hfsp
.write ('#define FSP%s_BASE 0x%08X\n' % (fsp
.Type
, fih
.ImageBase
))
653 hfsp
.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp
.Type
, fv
.Offset
))
654 hfsp
.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp
.Type
, fih
.ImageSize
))
658 def SplitFspBin (fspfile
, outdir
, nametemplate
):
659 fd
= FirmwareDevice(0, fspfile
)
663 for fsp
in fd
.FspList
:
666 nametemplate
= fspfile
667 fspname
, ext
= os
.path
.splitext(os
.path
.basename(nametemplate
))
668 filename
= os
.path
.join(outdir
, fspname
+ '_' + fsp
.Type
+ ext
)
669 hfsp
= open(filename
, 'wb')
670 print ("Ceate FSP component file '%s'" % filename
)
671 for fvidx
in fsp
.FvIdxList
:
672 fv
= fd
.FvList
[fvidx
]
673 hfsp
.write(fv
.FvData
)
676 def RebaseFspBin (FspBinary
, FspComponent
, FspBase
, OutputDir
, OutputFile
):
677 fd
= FirmwareDevice(0, FspBinary
)
681 numcomp
= len(FspComponent
)
683 if numcomp
!= len(baselist
):
684 print "ERROR: Required number of base does not match number of FSP component !"
687 newfspbin
= fd
.FdData
[:]
689 for idx
, fspcomp
in enumerate(FspComponent
):
692 for fsp
in fd
.FspList
:
693 ftype
= fsp
.Type
.lower()
699 print "ERROR: Could not find FSP_%c component to rebase !" % fspcomp
.upper()
702 fspbase
= baselist
[idx
]
703 if fspbase
.startswith('0x'):
704 newbase
= int(fspbase
, 16)
706 newbase
= int(fspbase
)
707 oldbase
= fsp
.Fih
.ImageBase
708 delta
= newbase
- oldbase
709 print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype
.upper(),oldbase
,newbase
)
712 for fvidx
in fsp
.FvIdxList
:
713 fv
= fd
.FvList
[fvidx
]
714 for ffs
in fv
.FfsList
:
715 for sec
in ffs
.SecList
:
716 if sec
.SecHdr
.Type
in [EFI_SECTION_TYPE
.TE
, EFI_SECTION_TYPE
.PE32
]: # TE or PE32
717 offset
= fd
.Offset
+ fv
.Offset
+ ffs
.Offset
+ sec
.Offset
+ sizeof(sec
.SecHdr
)
718 imglist
.append ((offset
, len(sec
.SecData
) - sizeof(sec
.SecHdr
)))
722 for (offset
, length
) in imglist
:
723 img
= PeTeImage(offset
, fd
.FdData
[offset
:offset
+ length
])
725 pcount
+= img
.Rebase(delta
, newfspbin
)
728 print " Patched %d entries in %d TE/PE32 images." % (pcount
, fcount
)
730 (count
, applied
) = fsp
.Patch(delta
, newfspbin
)
731 print " Patched %d entries using FSP patch table." % applied
733 print " %d invalid entries are ignored !" % (count
- applied
)
736 filename
= os
.path
.basename(FspBinary
)
737 base
, ext
= os
.path
.splitext(filename
)
738 OutputFile
= base
+ "_%08X" % newbase
+ ext
740 fspname
, ext
= os
.path
.splitext(os
.path
.basename(OutputFile
))
741 filename
= os
.path
.join(OutputDir
, fspname
+ ext
)
742 fd
= open(filename
, "wb")
747 parser
= argparse
.ArgumentParser()
748 subparsers
= parser
.add_subparsers(title
='commands')
750 parser_rebase
= subparsers
.add_parser('rebase', help='rebase a FSP into a new base address')
751 parser_rebase
.set_defaults(which
='rebase')
752 parser_rebase
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
753 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)
754 parser_rebase
.add_argument('-b', '--newbase', dest
='FspBase', nargs
='+', type=str, help='Rebased FSP binary file name', default
= '', required
= True)
755 parser_rebase
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
756 parser_rebase
.add_argument('-n', '--outfile', dest
='OutputFile', type=str, help='Rebased FSP binary file name', default
= '')
758 parser_split
= subparsers
.add_parser('split', help='split a FSP into multiple components')
759 parser_split
.set_defaults(which
='split')
760 parser_split
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
761 parser_split
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
762 parser_split
.add_argument('-n', '--nametpl', dest
='NameTemplate', type=str, help='Output name template', default
= '')
764 parser_genhdr
= subparsers
.add_parser('genhdr', help='generate a header file for FSP binary')
765 parser_genhdr
.set_defaults(which
='genhdr')
766 parser_genhdr
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
767 parser_genhdr
.add_argument('-o', '--outdir' , dest
='OutputDir', type=str, help='Output directory path', default
= '.')
768 parser_genhdr
.add_argument('-n', '--hfile', dest
='HFileName', type=str, help='Output header file name', default
= '')
770 parser_info
= subparsers
.add_parser('info', help='display FSP information')
771 parser_info
.set_defaults(which
='info')
772 parser_info
.add_argument('-f', '--fspbin' , dest
='FspBinary', type=str, help='FSP binary file path', required
= True)
774 args
= parser
.parse_args()
775 if args
.which
in ['rebase', 'split', 'genhdr', 'info']:
776 if not os
.path
.exists(args
.FspBinary
):
777 raise Exception ("ERROR: Could not locate FSP binary file '%s' !" % args
.FspBinary
)
778 if hasattr(args
, 'OutputDir') and not os
.path
.exists(args
.OutputDir
):
779 raise Exception ("ERROR: Invalid output directory '%s' !" % args
.OutputDir
)
781 if args
.which
== 'rebase':
782 RebaseFspBin (args
.FspBinary
, args
.FspComponent
, args
.FspBase
, args
.OutputDir
, args
.OutputFile
)
783 elif args
.which
== 'split':
784 SplitFspBin (args
.FspBinary
, args
.OutputDir
, args
.NameTemplate
)
785 elif args
.which
== 'genhdr':
786 GenFspHdr (args
.FspBinary
, args
.OutputDir
, args
.HFileName
)
787 elif args
.which
== 'info':
788 ShowFspInfo (args
.FspBinary
)
794 if __name__
== '__main__':