Signed-off-by: Patrick Georgi <pgeo...@google.com>
Contributed-under: TianoCore Contribution Agreement 1.1
---
 IntelFsp2Pkg/Tools/.gitattributes |    1 +
 IntelFsp2Pkg/Tools/SplitFspBin.py | 1708 ++++++++++++++---------------
 2 files changed, 855 insertions(+), 854 deletions(-)
 create mode 100644 IntelFsp2Pkg/Tools/.gitattributes

diff --git a/IntelFsp2Pkg/Tools/.gitattributes 
b/IntelFsp2Pkg/Tools/.gitattributes
new file mode 100644
index 0000000000..0f876007cd
--- /dev/null
+++ b/IntelFsp2Pkg/Tools/.gitattributes
@@ -0,0 +1 @@
+SplitFspBin.py text
diff --git a/IntelFsp2Pkg/Tools/SplitFspBin.py 
b/IntelFsp2Pkg/Tools/SplitFspBin.py
index ac864492e8..5f1fab071f 100755
--- a/IntelFsp2Pkg/Tools/SplitFspBin.py
+++ b/IntelFsp2Pkg/Tools/SplitFspBin.py
@@ -1,854 +1,854 @@
-#!/usr/bin/env python
-## @ FspTool.py
-#
-# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
-# This program and the accompanying materials are licensed and made available 
under
-# the terms and conditions of the BSD License that accompanies this 
distribution.
-# The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php.
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-##
-
-import os
-import sys
-import uuid
-import copy
-import struct
-import argparse
-from   ctypes import *
-
-"""
-This utility supports some operations for Intel FSP 2.0 image.
-It supports:
-    - Display FSP 2.0 information header
-    - Split FSP 2.0 image into individual FSP-T/M/S/O component
-    - Rebase FSP 2.0 components to a different base address
-    - Generate FSP mapping C header file
-"""
-
-CopyRightHeaderFile = """/*
- *
- * Automatically generated file; DO NOT EDIT.
- * FSP mapping file
- *
- */
-"""
-
-class c_uint24(Structure):
-    """Little-Endian 24-bit Unsigned Integer"""
-    _pack_   = 1
-    _fields_ = [('Data', (c_uint8 * 3))]
-
-    def __init__(self, val=0):
-        self.set_value(val)
-
-    def __str__(self, indent=0):
-        return '0x%.6x' % self.value
-
-    def __int__(self):
-        return self.get_value()
-
-    def set_value(self, val):
-        self.Data[0:3] = Val2Bytes(val, 3)
-
-    def get_value(self):
-        return Bytes2Val(self.Data[0:3])
-
-    value = property(get_value, set_value)
-
-class EFI_FIRMWARE_VOLUME_HEADER(Structure):
-    _fields_ = [
-        ('ZeroVector',           ARRAY(c_uint8, 16)),
-        ('FileSystemGuid',       ARRAY(c_uint8, 16)),
-        ('FvLength',             c_uint64),
-        ('Signature',            ARRAY(c_char, 4)),
-        ('Attributes',           c_uint32),
-        ('HeaderLength',         c_uint16),
-        ('Checksum',             c_uint16),
-        ('ExtHeaderOffset',      c_uint16),
-        ('Reserved',             c_uint8),
-        ('Revision',             c_uint8)
-        ]
-
-class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure):
-    _fields_ = [
-        ('FvName',               ARRAY(c_uint8, 16)),
-        ('ExtHeaderSize',        c_uint32)
-        ]
-
-class EFI_FFS_INTEGRITY_CHECK(Structure):
-    _fields_ = [
-        ('Header',               c_uint8),
-        ('File',                 c_uint8)
-        ]
-
-class EFI_FFS_FILE_HEADER(Structure):
-    _fields_ = [
-        ('Name',                 ARRAY(c_uint8, 16)),
-        ('IntegrityCheck',       EFI_FFS_INTEGRITY_CHECK),
-        ('Type',                 c_uint8),
-        ('Attributes',           c_uint8),
-        ('Size',                 c_uint24),
-        ('State',                c_uint8)
-        ]
-
-class EFI_COMMON_SECTION_HEADER(Structure):
-    _fields_ = [
-        ('Size',                 c_uint24),
-        ('Type',                 c_uint8)
-        ]
-
-class FSP_COMMON_HEADER(Structure):
-     _fields_ = [
-        ('Signature',            ARRAY(c_char, 4)),
-        ('HeaderLength',         c_uint32)
-        ]
-
-class FSP_INFORMATION_HEADER(Structure):
-     _fields_ = [
-        ('Signature',            ARRAY(c_char, 4)),
-        ('HeaderLength',         c_uint32),
-        ('Reserved1',            c_uint16),
-        ('SpecVersion',          c_uint8),
-        ('HeaderRevision',       c_uint8),
-        ('ImageRevision',        c_uint32),
-        ('ImageId',              ARRAY(c_char, 8)),
-        ('ImageSize',            c_uint32),
-        ('ImageBase',            c_uint32),
-        ('ImageAttribute',       c_uint16),
-        ('ComponentAttribute',   c_uint16),
-        ('CfgRegionOffset',      c_uint32),
-        ('CfgRegionSize',        c_uint32),
-        ('Reserved2',            c_uint32),
-        ('TempRamInitEntryOffset',     c_uint32),
-        ('Reserved3',                  c_uint32),
-        ('NotifyPhaseEntryOffset',     c_uint32),
-        ('FspMemoryInitEntryOffset',   c_uint32),
-        ('TempRamExitEntryOffset',     c_uint32),
-        ('FspSiliconInitEntryOffset',  c_uint32)
-    ]
-
-class FSP_PATCH_TABLE(Structure):
-    _fields_ = [
-        ('Signature',            ARRAY(c_char, 4)),
-        ('HeaderLength',         c_uint16),
-        ('HeaderRevision',       c_uint8),
-        ('Reserved',             c_uint8),
-        ('PatchEntryNum',        c_uint32)
-        ]
-
-class EFI_IMAGE_DATA_DIRECTORY(Structure):
-    _fields_ = [
-        ('VirtualAddress',       c_uint32),
-        ('Size',                 c_uint32)
-        ]
-
-class EFI_TE_IMAGE_HEADER(Structure):
-    _fields_ = [
-        ('Signature',            ARRAY(c_char, 2)),
-        ('Machine',              c_uint16),
-        ('NumberOfSections',     c_uint8),
-        ('Subsystem',            c_uint8),
-        ('StrippedSize',         c_uint16),
-        ('AddressOfEntryPoint',  c_uint32),
-        ('BaseOfCode',           c_uint32),
-        ('ImageBase',            c_uint64),
-        ('DataDirectoryBaseReloc',  EFI_IMAGE_DATA_DIRECTORY),
-        ('DataDirectoryDebug',      EFI_IMAGE_DATA_DIRECTORY)
-        ]
-
-class EFI_IMAGE_DOS_HEADER(Structure):
-    _fields_ = [
-        ('e_magic',              c_uint16),
-        ('e_cblp',               c_uint16),
-        ('e_cp',                 c_uint16),
-        ('e_crlc',               c_uint16),
-        ('e_cparhdr',            c_uint16),
-        ('e_minalloc',           c_uint16),
-        ('e_maxalloc',           c_uint16),
-        ('e_ss',                 c_uint16),
-        ('e_sp',                 c_uint16),
-        ('e_csum',               c_uint16),
-        ('e_ip',                 c_uint16),
-        ('e_cs',                 c_uint16),
-        ('e_lfarlc',             c_uint16),
-        ('e_ovno',               c_uint16),
-        ('e_res',                ARRAY(c_uint16, 4)),
-        ('e_oemid',              c_uint16),
-        ('e_oeminfo',            c_uint16),
-        ('e_res2',               ARRAY(c_uint16, 10)),
-        ('e_lfanew',             c_uint16)
-        ]
-
-class EFI_IMAGE_FILE_HEADER(Structure):
-    _fields_ = [
-        ('Machine',               c_uint16),
-        ('NumberOfSections',      c_uint16),
-        ('TimeDateStamp',         c_uint32),
-        ('PointerToSymbolTable',  c_uint32),
-        ('NumberOfSymbols',       c_uint32),
-        ('SizeOfOptionalHeader',  c_uint16),
-        ('Characteristics',       c_uint16)
-        ]
-
-class PE_RELOC_BLOCK_HEADER(Structure):
-    _fields_ = [
-        ('PageRVA',              c_uint32),
-        ('BlockSize',            c_uint32)
-        ]
-
-class EFI_IMAGE_OPTIONAL_HEADER32(Structure):
-    _fields_ = [
-        ('Magic',                         c_uint16),
-        ('MajorLinkerVersion',            c_uint8),
-        ('MinorLinkerVersion',            c_uint8),
-        ('SizeOfCode',                    c_uint32),
-        ('SizeOfInitializedData',         c_uint32),
-        ('SizeOfUninitializedData',       c_uint32),
-        ('AddressOfEntryPoint',           c_uint32),
-        ('BaseOfCode',                    c_uint32),
-        ('BaseOfData',                    c_uint32),
-        ('ImageBase',                     c_uint32),
-        ('SectionAlignment',              c_uint32),
-        ('FileAlignment',                 c_uint32),
-        ('MajorOperatingSystemVersion',   c_uint16),
-        ('MinorOperatingSystemVersion',   c_uint16),
-        ('MajorImageVersion',             c_uint16),
-        ('MinorImageVersion',             c_uint16),
-        ('MajorSubsystemVersion',         c_uint16),
-        ('MinorSubsystemVersion',         c_uint16),
-        ('Win32VersionValue',             c_uint32),
-        ('SizeOfImage',                   c_uint32),
-        ('SizeOfHeaders',                 c_uint32),
-        ('CheckSum'     ,                 c_uint32),
-        ('Subsystem',                     c_uint16),
-        ('DllCharacteristics',            c_uint16),
-        ('SizeOfStackReserve',            c_uint32),
-        ('SizeOfStackCommit' ,            c_uint32),
-        ('SizeOfHeapReserve',             c_uint32),
-        ('SizeOfHeapCommit' ,             c_uint32),
-        ('LoaderFlags'     ,              c_uint32),
-        ('NumberOfRvaAndSizes',           c_uint32),
-        ('DataDirectory',                 ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
-        ]
-
-class EFI_IMAGE_OPTIONAL_HEADER32_PLUS(Structure):
-    _fields_ = [
-        ('Magic',                         c_uint16),
-        ('MajorLinkerVersion',            c_uint8),
-        ('MinorLinkerVersion',            c_uint8),
-        ('SizeOfCode',                    c_uint32),
-        ('SizeOfInitializedData',         c_uint32),
-        ('SizeOfUninitializedData',       c_uint32),
-        ('AddressOfEntryPoint',           c_uint32),
-        ('BaseOfCode',                    c_uint32),
-        ('ImageBase',                     c_uint64),
-        ('SectionAlignment',              c_uint32),
-        ('FileAlignment',                 c_uint32),
-        ('MajorOperatingSystemVersion',   c_uint16),
-        ('MinorOperatingSystemVersion',   c_uint16),
-        ('MajorImageVersion',             c_uint16),
-        ('MinorImageVersion',             c_uint16),
-        ('MajorSubsystemVersion',         c_uint16),
-        ('MinorSubsystemVersion',         c_uint16),
-        ('Win32VersionValue',             c_uint32),
-        ('SizeOfImage',                   c_uint32),
-        ('SizeOfHeaders',                 c_uint32),
-        ('CheckSum'     ,                 c_uint32),
-        ('Subsystem',                     c_uint16),
-        ('DllCharacteristics',            c_uint16),
-        ('SizeOfStackReserve',            c_uint64),
-        ('SizeOfStackCommit' ,            c_uint64),
-        ('SizeOfHeapReserve',             c_uint64),
-        ('SizeOfHeapCommit' ,             c_uint64),
-        ('LoaderFlags'     ,              c_uint32),
-        ('NumberOfRvaAndSizes',           c_uint32),
-        ('DataDirectory',                 ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
-        ]
-
-class EFI_IMAGE_OPTIONAL_HEADER(Union):
-    _fields_ = [
-        ('PeOptHdr',             EFI_IMAGE_OPTIONAL_HEADER32),
-        ('PePlusOptHdr',         EFI_IMAGE_OPTIONAL_HEADER32_PLUS)
-        ]
-
-class EFI_IMAGE_NT_HEADERS32(Structure):
-    _fields_ = [
-        ('Signature',            c_uint32),
-        ('FileHeader',           EFI_IMAGE_FILE_HEADER),
-        ('OptionalHeader',       EFI_IMAGE_OPTIONAL_HEADER)
-        ]
-
-
-class EFI_IMAGE_DIRECTORY_ENTRY:
-    EXPORT                     = 0
-    IMPORT                     = 1
-    RESOURCE                   = 2
-    EXCEPTION                  = 3
-    SECURITY                   = 4
-    BASERELOC                  = 5
-    DEBUG                      = 6
-    COPYRIGHT                  = 7
-    GLOBALPTR                  = 8
-    TLS                        = 9
-    LOAD_CONFIG                = 10
-
-class EFI_FV_FILETYPE:
-    ALL                        = 0x00
-    RAW                        = 0x01
-    FREEFORM                   = 0x02
-    SECURITY_CORE              = 0x03
-    PEI_CORE                   = 0x04
-    DXE_CORE                   = 0x05
-    PEIM                       = 0x06
-    DRIVER                     = 0x07
-    COMBINED_PEIM_DRIVER       = 0x08
-    APPLICATION                = 0x09
-    SMM                        = 0x0a
-    FIRMWARE_VOLUME_IMAGE      = 0x0b
-    COMBINED_SMM_DXE           = 0x0c
-    SMM_CORE                   = 0x0d
-    OEM_MIN                    = 0xc0
-    OEM_MAX                    = 0xdf
-    DEBUG_MIN                  = 0xe0
-    DEBUG_MAX                  = 0xef
-    FFS_MIN                    = 0xf0
-    FFS_MAX                    = 0xff
-    FFS_PAD                    = 0xf0
-
-class EFI_SECTION_TYPE:
-    """Enumeration of all valid firmware file section types."""
-    ALL                        = 0x00
-    COMPRESSION                = 0x01
-    GUID_DEFINED               = 0x02
-    DISPOSABLE                 = 0x03
-    PE32                       = 0x10
-    PIC                        = 0x11
-    TE                         = 0x12
-    DXE_DEPEX                  = 0x13
-    VERSION                    = 0x14
-    USER_INTERFACE             = 0x15
-    COMPATIBILITY16            = 0x16
-    FIRMWARE_VOLUME_IMAGE      = 0x17
-    FREEFORM_SUBTYPE_GUID      = 0x18
-    RAW                        = 0x19
-    PEI_DEPEX                  = 0x1b
-    SMM_DEPEX                  = 0x1c
-
-def AlignPtr (offset, alignment = 8):
-    return (offset + alignment - 1) & ~(alignment - 1)
-
-def Bytes2Val (bytes):
-    return reduce(lambda x,y: (x<<8)|y,  bytes[::-1] )
-
-def Val2Bytes (value, blen):
-    return [(value>>(i*8) & 0xff) for i in range(blen)]
-
-def OutputStruct (obj, indent = 0, plen = 0):
-    if indent:
-        body = ''
-    else:
-        body = ('  ' * indent + '<%s>:\n') % obj.__class__.__name__
-
-    if plen == 0:
-        plen = sizeof(obj)
-
-    max_key_len = 26
-    pstr = ('  ' * (indent + 1) + '{0:<%d} = {1}\n') % max_key_len
-
-    for field in obj._fields_:
-        key = field[0]
-        val = getattr(obj, key)
-        rep = ''
-        if not isinstance(val, c_uint24) and isinstance(val, Structure):
-            body += pstr.format(key, val.__class__.__name__)
-            body += OutputStruct (val, indent + 1)
-            plen -= sizeof(val)
-        else:
-            if type(val) is str:
-                rep = "0x%X ('%s')" % (Bytes2Val(bytearray(val)), val)
-            elif type(val) in (int, long):
-                rep = '0x%X' % val
-            elif isinstance(val, c_uint24):
-                rep = '0x%X' % val.get_value()
-            elif 'c_ubyte_Array' in str(type(val)):
-                if sizeof(val) == 16:
-                    rep = str(uuid.UUID(bytes = str(bytearray(val)))).upper()
-                else:
-                    res = ['0x%02X'%i for i in bytearray(val)]
-                    rep = '[%s]' % (','.join(res))
-            else:
-                rep = str(val)
-            plen -= sizeof(field[1])
-            body += pstr.format(key, rep)
-        if plen <= 0:
-            break
-    return body
-
-class Section:
-    def __init__(self, offset, secdata):
-        self.SecHdr   = EFI_COMMON_SECTION_HEADER.from_buffer (secdata, 0)
-        self.SecData  = secdata[0:int(self.SecHdr.Size)]
-        self.Offset   = offset
-
-class FirmwareFile:
-    def __init__(self, offset, filedata):
-        self.FfsHdr   = EFI_FFS_FILE_HEADER.from_buffer (filedata, 0)
-        self.FfsData  = filedata[0:int(self.FfsHdr.Size)]
-        self.Offset   = offset
-        self.SecList  = []
-
-    def ParseFfs(self):
-        ffssize = len(self.FfsData)
-        offset  = sizeof(self.FfsHdr)
-        if self.FfsHdr.Name != '\xff' * 16:
-            while offset < ffssize:
-                sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, 
offset)
-                sec = Section (offset, self.FfsData[offset:offset + 
int(sechdr.Size)])
-                self.SecList.append(sec)
-                offset += int(sechdr.Size)
-                offset  = AlignPtr(offset, 4)
-
-class FirmwareVolume:
-    def __init__(self, offset, fvdata):
-        self.FvHdr    = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (fvdata, 0)
-        self.FvData   = fvdata[0 : self.FvHdr.FvLength]
-        self.Offset   = offset
-        if self.FvHdr.ExtHeaderOffset > 0:
-            self.FvExtHdr = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer 
(self.FvData, self.FvHdr.ExtHeaderOffset)
-        else:
-            self.FvExtHdr = None
-        self.FfsList  = []
-
-    def ParseFv(self):
-        fvsize = len(self.FvData)
-        if self.FvExtHdr:
-            offset = self.FvHdr.ExtHeaderOffset + self.FvExtHdr.ExtHeaderSize
-        else:
-            offset = self.FvHdr.HeaderLength
-        offset = AlignPtr(offset)
-        while offset < fvsize:
-            ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset)
-            if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF):
-                offset = fvsize
-            else:
-                ffs = FirmwareFile (offset, self.FvData[offset:offset + 
int(ffshdr.Size)])
-                ffs.ParseFfs()
-                self.FfsList.append(ffs)
-                offset += int(ffshdr.Size)
-                offset = AlignPtr(offset)
-
-class FspImage:
-    def __init__(self, offset, fih, fihoff, patch):
-        self.Fih       = fih
-        self.FihOffset = fihoff
-        self.Offset    = offset
-        self.FvIdxList = []
-        self.Type      = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 
0x0F]
-        self.PatchList = patch
-        self.PatchList.append(fihoff + 0x1C)
-
-    def AppendFv(self, FvIdx):
-        self.FvIdxList.append(FvIdx)
-
-    def Patch(self, delta, fdbin):
-        count   = 0
-        applied = 0
-        for idx, patch in enumerate(self.PatchList):
-            ptype = (patch>>24) & 0x0F
-            if ptype not in [0x00, 0x0F]:
-                raise Exception('ERROR: Invalid patch type %d !' % ptype)
-            if patch & 0x80000000:
-                patch = self.Fih.ImageSize - (0x1000000 - (patch & 0xFFFFFF))
-            else:
-                patch = patch & 0xFFFFFF
-            if (patch < self.Fih.ImageSize) and (patch + sizeof(c_uint32) <= 
self.Fih.ImageSize):
-                offset = patch + self.Offset
-                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
-                value += delta
-                fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, 
sizeof(c_uint32))
-                applied += 1
-            count += 1
-        # Don't count the FSP base address patch entry appended at the end
-        if count != 0:
-            count   -= 1
-            applied -= 1
-        return (count, applied)
-
-class FirmwareDevice:
-    def __init__(self, offset, fdfile):
-        self.FvList  = []
-        self.FspList = []
-        self.FdFile = fdfile
-        self.Offset = 0
-        hfsp = open (self.FdFile, 'rb')
-        self.FdData = bytearray(hfsp.read())
-        hfsp.close()
-
-    def ParseFd(self):
-        offset = 0
-        fdsize = len(self.FdData)
-        self.FvList  = []
-        while offset < fdsize:
-            fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset)
-            if '_FVH' != fvh.Signature:
-                raise Exception("ERROR: Invalid FV header !")
-            fv = FirmwareVolume (offset, self.FdData[offset:offset + 
fvh.FvLength])
-            fv.ParseFv ()
-            self.FvList.append(fv)
-            offset += fv.FvHdr.FvLength
-
-    def CheckFsp (self):
-        if len(self.FspList) == 0:
-            return
-
-        fih = None
-        for fsp in self.FspList:
-            if fsp.Fih.HeaderRevision < 3:
-                raise Exception("ERROR: FSP 1.x is not supported by this tool 
!")
-            if not fih:
-                fih = fsp.Fih
-            else:
-                newfih = fsp.Fih
-                if (newfih.ImageId != fih.ImageId) or (newfih.ImageRevision != 
fih.ImageRevision):
-                    raise Exception("ERROR: Inconsistent FSP ImageId or 
ImageRevision detected !")
-
-    def ParseFsp(self):
-        flen = 0
-        for idx, fv in enumerate(self.FvList):
-            # Check if this FV contains FSP header
-            if flen == 0:
-                if len(fv.FfsList) == 0:
-                    continue
-                ffs = fv.FfsList[0]
-                if len(ffs.SecList) == 0:
-                    continue
-                sec = ffs.SecList[0]
-                if sec.SecHdr.Type != EFI_SECTION_TYPE.RAW:
-                    continue
-                fihoffset = ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
-                fspoffset = fv.Offset
-                offset    = fspoffset + fihoffset
-                fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset)
-                if 'FSPH' != fih.Signature:
-                    continue
-
-                offset += fih.HeaderLength
-                offset = AlignPtr(offset, 4)
-                plist  = []
-                while True:
-                    fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset)
-                    if 'FSPP' != fch.Signature:
-                        offset += fch.HeaderLength
-                        offset = AlignPtr(offset, 4)
-                    else:
-                        fspp = FSP_PATCH_TABLE.from_buffer (self.FdData, 
offset)
-                        offset += sizeof(fspp)
-                        pdata  = (c_uint32 * 
fspp.PatchEntryNum).from_buffer(self.FdData, offset)
-                        plist  = list(pdata)
-                        break
-
-                fsp  = FspImage (fspoffset, fih, fihoffset, plist)
-                fsp.AppendFv (idx)
-                self.FspList.append(fsp)
-                flen = fsp.Fih.ImageSize - fv.FvHdr.FvLength
-            else:
-                fsp.AppendFv (idx)
-                flen -= fv.FvHdr.FvLength
-                if flen < 0:
-                    raise Exception("ERROR: Incorrect FV size in image !")
-        self.CheckFsp ()
-
-class PeTeImage:
-    def __init__(self, offset, data):
-        self.Offset    = offset
-        tehdr          = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)
-        if   tehdr.Signature == 'VZ': # TE image
-            self.TeHdr   = tehdr
-        elif tehdr.Signature == 'MZ': # PE image
-            self.TeHdr   = None
-            self.DosHdr  = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)
-            self.PeHdr   = EFI_IMAGE_NT_HEADERS32.from_buffer (data, 
self.DosHdr.e_lfanew)
-            if self.PeHdr.Signature != 0x4550:
-                raise Exception("ERROR: Invalid PE32 header !")
-            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image
-                if self.PeHdr.FileHeader.SizeOfOptionalHeader < 
EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:
-                    raise Exception("ERROR: Unsupported PE32 image !")
-                if self.PeHdr.OptionalHeader.PeOptHdr.NumberOfRvaAndSizes <= 
EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
-                    raise Exception("ERROR: No relocation information 
available !")
-            elif self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ 
image
-                if self.PeHdr.FileHeader.SizeOfOptionalHeader < 
EFI_IMAGE_OPTIONAL_HEADER32_PLUS.DataDirectory.offset:
-                    raise Exception("ERROR: Unsupported PE32+ image !")
-                if self.PeHdr.OptionalHeader.PePlusOptHdr.NumberOfRvaAndSizes 
<= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
-                    raise Exception("ERROR: No relocation information 
available !")
-            else:
-                raise Exception("ERROR: Invalid PE32 optional header !")
-        self.Offset    = offset
-        self.Data      = data
-        self.RelocList = []
-
-    def IsTeImage(self):
-        return  self.TeHdr is not None
-
-    def ParseReloc(self):
-        if self.IsTeImage():
-            rsize   = self.TeHdr.DataDirectoryBaseReloc.Size
-            roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + 
self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
-        else:
-            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image
-                rsize   = 
self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
-                roffset = 
self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
-            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ image
-                rsize   = 
self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
-                roffset = 
self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
-
-        alignment = 4
-        offset = roffset
-        while offset < roffset + rsize:
-            offset = AlignPtr(offset, 4)
-            blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, offset)
-            offset += sizeof(blkhdr)
-            # Read relocation type,offset pairs
-            rlen  = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
-            rnum  = rlen/sizeof(c_uint16)
-            rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)
-            for each in rdata:
-                roff  = each & 0xfff
-                rtype = each >> 12
-                if rtype == 0: # IMAGE_REL_BASED_ABSOLUTE:
-                    continue
-                if ((rtype != 3) and (rtype != 10)): # IMAGE_REL_BASED_HIGHLOW 
and IMAGE_REL_BASED_DIR64
-                    raise Exception("ERROR: Unsupported relocation type %d!" % 
rtype)
-                # Calculate the offset of the relocation
-                aoff  = blkhdr.PageRVA + roff
-                if self.IsTeImage():
-                    aoff += sizeof(self.TeHdr) - self.TeHdr.StrippedSize
-                self.RelocList.append((rtype, aoff))
-            offset += sizeof(rdata)
-
-    def Rebase(self, delta, fdbin):
-        count = 0
-        if delta == 0:
-            return count
-
-        for (rtype, roff) in self.RelocList:
-            if rtype == 3: # IMAGE_REL_BASED_HIGHLOW
-                offset = roff + self.Offset
-                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
-                value += delta
-                fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, 
sizeof(c_uint32))
-                count += 1
-            elif rtype == 10: # IMAGE_REL_BASED_DIR64
-                offset = roff + self.Offset
-                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint64)])
-                value += delta
-                fdbin[offset:offset+sizeof(c_uint64)] = Val2Bytes(value, 
sizeof(c_uint64))
-                count += 1
-            else:
-                raise Exception('ERROR: Unknown relocation type %d !' % rtype)
-
-        if self.IsTeImage():
-            offset  = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset
-            size    = EFI_TE_IMAGE_HEADER.ImageBase.size
-        else:
-            offset  = self.Offset + self.DosHdr.e_lfanew
-            offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
-            offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
-            size    = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
-
-        value  = Bytes2Val(fdbin[offset:offset+size]) + delta
-        fdbin[offset:offset+size] = Val2Bytes(value, size)
-
-        return count
-
-def ShowFspInfo (fspfile):
-    fd = FirmwareDevice(0, fspfile)
-    fd.ParseFd  ()
-    fd.ParseFsp ()
-
-    print ("\nFound the following %d Firmware Volumes in FSP binary:" % 
(len(fd.FvList)))
-    for idx, fv in enumerate(fd.FvList):
-        name = fv.FvExtHdr.FvName
-        if not name:
-            name = '\xff' * 16
-        else:
-            name = str(bytearray(name))
-        guid = uuid.UUID(bytes = name)
-        print ("FV%d:" % idx)
-        print ("  GUID   : %s" % str(guid).upper())
-        print ("  Offset : 0x%08X" %  fv.Offset)
-        print ("  Length : 0x%08X" % fv.FvHdr.FvLength)
-    print ("\n")
-
-    for fsp in fd.FspList:
-        fvlist = map(lambda x : 'FV%d' % x, fsp.FvIdxList)
-        print ("FSP_%s contains %s" % (fsp.Type, ','.join(fvlist)))
-        print ("%s" % (OutputStruct(fsp.Fih, 0, fsp.Fih.HeaderLength)))
-
-def GenFspHdr (fspfile, outdir, hfile):
-    fd = FirmwareDevice(0, fspfile)
-    fd.ParseFd  ()
-    fd.ParseFsp ()
-
-    if not hfile:
-        hfile = os.path.splitext(os.path.basename(fspfile))[0] + '.h'
-    fspname, ext = os.path.splitext(os.path.basename(hfile))
-    filename = os.path.join(outdir, fspname + ext)
-    hfsp   = open(filename, 'w')
-    hfsp.write ('%s\n\n' % CopyRightHeaderFile)
-
-    firstfv = True
-    for fsp in fd.FspList:
-        fih = fsp.Fih
-        if firstfv:
-            hfsp.write("#define  FSP_IMAGE_ID    0x%016X    /* '%s' */\n" % 
(Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))
-            hfsp.write("#define  FSP_IMAGE_REV   0x%08X \n\n" % 
fih.ImageRevision)
-            firstfv = False
-        fv = fd.FvList[fsp.FvIdxList[0]]
-        hfsp.write ('#define  FSP%s_BASE       0x%08X\n'   % (fsp.Type, 
fih.ImageBase))
-        hfsp.write ('#define  FSP%s_OFFSET     0x%08X\n'   % (fsp.Type, 
fv.Offset))
-        hfsp.write ('#define  FSP%s_LENGTH     0x%08X\n\n' % (fsp.Type, 
fih.ImageSize))
-
-    hfsp.close()
-
-def SplitFspBin (fspfile, outdir, nametemplate):
-    fd = FirmwareDevice(0, fspfile)
-    fd.ParseFd  ()
-    fd.ParseFsp ()
-
-    for fsp in fd.FspList:
-        ftype = fsp.Type
-        if not nametemplate:
-            nametemplate = fspfile
-        fspname, ext = os.path.splitext(os.path.basename(nametemplate))
-        filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext)
-        hfsp = open(filename, 'wb')
-        print ("Create FSP component file '%s'" % filename)
-        for fvidx in fsp.FvIdxList:
-            fv = fd.FvList[fvidx]
-            hfsp.write(fv.FvData)
-        hfsp.close()
-
-def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
-    fd = FirmwareDevice(0, FspBinary)
-    fd.ParseFd  ()
-    fd.ParseFsp ()
-
-    numcomp  = len(FspComponent)
-    baselist = FspBase
-    if numcomp != len(baselist):
-        print "ERROR: Required number of base does not match number of FSP 
component !"
-        return
-
-    newfspbin = fd.FdData[:]
-
-    for idx, fspcomp in enumerate(FspComponent):
-
-        found = False
-        for fsp in fd.FspList:
-            ftype = fsp.Type.lower()
-            if ftype == fspcomp:
-                found = True
-                break
-
-        if not found:
-            print "ERROR: Could not find FSP_%c component to rebase !" % 
fspcomp.upper()
-            return
-
-        fspbase = baselist[idx]
-        if fspbase.startswith('0x'):
-            newbase = int(fspbase, 16)
-        else:
-            newbase = int(fspbase)
-        oldbase = fsp.Fih.ImageBase
-        delta = newbase - oldbase
-        print "Rebase FSP-%c from 0x%08X to 0x%08X:" % 
(ftype.upper(),oldbase,newbase)
-
-        imglist = []
-        for fvidx in fsp.FvIdxList:
-            fv = fd.FvList[fvidx]
-            for ffs in fv.FfsList:
-                for sec in ffs.SecList:
-                    if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, 
EFI_SECTION_TYPE.PE32]:   # TE or PE32
-                        offset = fd.Offset + fv.Offset + ffs.Offset + 
sec.Offset + sizeof(sec.SecHdr)
-                        imglist.append ((offset, len(sec.SecData) - 
sizeof(sec.SecHdr)))
-
-        fcount  = 0
-        pcount  = 0
-        for (offset, length) in imglist:
-            img = PeTeImage(offset, fd.FdData[offset:offset + length])
-            img.ParseReloc()
-            pcount += img.Rebase(delta, newfspbin)
-            fcount += 1
-
-        print "  Patched %d entries in %d TE/PE32 images." % (pcount, fcount)
-
-        (count, applied) = fsp.Patch(delta, newfspbin)
-        print "  Patched %d entries using FSP patch table." % applied
-        if count != applied:
-            print "  %d invalid entries are ignored !" % (count - applied)
-
-    if OutputFile == '':
-        filename = os.path.basename(FspBinary)
-        base, ext  = os.path.splitext(filename)
-        OutputFile = base + "_%08X" % newbase + ext
-
-    fspname, ext = os.path.splitext(os.path.basename(OutputFile))
-    filename = os.path.join(OutputDir, fspname + ext)
-    fd = open(filename, "wb")
-    fd.write(newfspbin)
-    fd.close()
-
-def main ():
-    parser     = argparse.ArgumentParser()
-    subparsers = parser.add_subparsers(title='commands')
-
-    parser_rebase  = subparsers.add_parser('rebase',  help='rebase a FSP into 
a new base address')
-    parser_rebase.set_defaults(which='rebase')
-    parser_rebase.add_argument('-f',  '--fspbin' , dest='FspBinary',  
type=str, help='FSP binary file path', required = True)
-    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)
-    parser_rebase.add_argument('-b',  '--newbase', dest='FspBase', nargs='+', 
type=str, help='Rebased FSP binary file name', default = '', required = True)
-    parser_rebase.add_argument('-o',  '--outdir' , dest='OutputDir',  
type=str, help='Output directory path', default = '.')
-    parser_rebase.add_argument('-n',  '--outfile', dest='OutputFile', 
type=str, help='Rebased FSP binary file name', default = '')
-
-    parser_split  = subparsers.add_parser('split',  help='split a FSP into 
multiple components')
-    parser_split.set_defaults(which='split')
-    parser_split.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
-    parser_split.add_argument('-o',  '--outdir' , dest='OutputDir', type=str, 
help='Output directory path',   default = '.')
-    parser_split.add_argument('-n',  '--nametpl', dest='NameTemplate', 
type=str, help='Output name template', default = '')
-
-    parser_genhdr = subparsers.add_parser('genhdr',  help='generate a header 
file for FSP binary')
-    parser_genhdr.set_defaults(which='genhdr')
-    parser_genhdr.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
-    parser_genhdr.add_argument('-o',  '--outdir' , dest='OutputDir', type=str, 
help='Output directory path',   default = '.')
-    parser_genhdr.add_argument('-n',  '--hfile',   dest='HFileName', type=str, 
help='Output header file name', default = '')
-
-    parser_info = subparsers.add_parser('info',  help='display FSP 
information')
-    parser_info.set_defaults(which='info')
-    parser_info.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
-
-    args = parser.parse_args()
-    if args.which in ['rebase', 'split', 'genhdr', 'info']:
-        if not os.path.exists(args.FspBinary):
-            raise Exception ("ERROR: Could not locate FSP binary file '%s' !" 
% args.FspBinary)
-        if hasattr(args, 'OutputDir') and not os.path.exists(args.OutputDir):
-            raise Exception ("ERROR: Invalid output directory '%s' !" % 
args.OutputDir)
-
-    if args.which == 'rebase':
-        RebaseFspBin (args.FspBinary, args.FspComponent, args.FspBase, 
args.OutputDir, args.OutputFile)
-    elif args.which == 'split':
-        SplitFspBin (args.FspBinary, args.OutputDir, args.NameTemplate)
-    elif args.which == 'genhdr':
-        GenFspHdr (args.FspBinary, args.OutputDir, args.HFileName)
-    elif args.which == 'info':
-        ShowFspInfo (args.FspBinary)
-    else:
-        pass
-
-    return 0
-
-if __name__ == '__main__':
-    sys.exit(main())
+#!/usr/bin/env python
+## @ FspTool.py
+#
+# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials are licensed and made available 
under
+# the terms and conditions of the BSD License that accompanies this 
distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+import os
+import sys
+import uuid
+import copy
+import struct
+import argparse
+from   ctypes import *
+
+"""
+This utility supports some operations for Intel FSP 2.0 image.
+It supports:
+    - Display FSP 2.0 information header
+    - Split FSP 2.0 image into individual FSP-T/M/S/O component
+    - Rebase FSP 2.0 components to a different base address
+    - Generate FSP mapping C header file
+"""
+
+CopyRightHeaderFile = """/*
+ *
+ * Automatically generated file; DO NOT EDIT.
+ * FSP mapping file
+ *
+ */
+"""
+
+class c_uint24(Structure):
+    """Little-Endian 24-bit Unsigned Integer"""
+    _pack_   = 1
+    _fields_ = [('Data', (c_uint8 * 3))]
+
+    def __init__(self, val=0):
+        self.set_value(val)
+
+    def __str__(self, indent=0):
+        return '0x%.6x' % self.value
+
+    def __int__(self):
+        return self.get_value()
+
+    def set_value(self, val):
+        self.Data[0:3] = Val2Bytes(val, 3)
+
+    def get_value(self):
+        return Bytes2Val(self.Data[0:3])
+
+    value = property(get_value, set_value)
+
+class EFI_FIRMWARE_VOLUME_HEADER(Structure):
+    _fields_ = [
+        ('ZeroVector',           ARRAY(c_uint8, 16)),
+        ('FileSystemGuid',       ARRAY(c_uint8, 16)),
+        ('FvLength',             c_uint64),
+        ('Signature',            ARRAY(c_char, 4)),
+        ('Attributes',           c_uint32),
+        ('HeaderLength',         c_uint16),
+        ('Checksum',             c_uint16),
+        ('ExtHeaderOffset',      c_uint16),
+        ('Reserved',             c_uint8),
+        ('Revision',             c_uint8)
+        ]
+
+class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure):
+    _fields_ = [
+        ('FvName',               ARRAY(c_uint8, 16)),
+        ('ExtHeaderSize',        c_uint32)
+        ]
+
+class EFI_FFS_INTEGRITY_CHECK(Structure):
+    _fields_ = [
+        ('Header',               c_uint8),
+        ('File',                 c_uint8)
+        ]
+
+class EFI_FFS_FILE_HEADER(Structure):
+    _fields_ = [
+        ('Name',                 ARRAY(c_uint8, 16)),
+        ('IntegrityCheck',       EFI_FFS_INTEGRITY_CHECK),
+        ('Type',                 c_uint8),
+        ('Attributes',           c_uint8),
+        ('Size',                 c_uint24),
+        ('State',                c_uint8)
+        ]
+
+class EFI_COMMON_SECTION_HEADER(Structure):
+    _fields_ = [
+        ('Size',                 c_uint24),
+        ('Type',                 c_uint8)
+        ]
+
+class FSP_COMMON_HEADER(Structure):
+     _fields_ = [
+        ('Signature',            ARRAY(c_char, 4)),
+        ('HeaderLength',         c_uint32)
+        ]
+
+class FSP_INFORMATION_HEADER(Structure):
+     _fields_ = [
+        ('Signature',            ARRAY(c_char, 4)),
+        ('HeaderLength',         c_uint32),
+        ('Reserved1',            c_uint16),
+        ('SpecVersion',          c_uint8),
+        ('HeaderRevision',       c_uint8),
+        ('ImageRevision',        c_uint32),
+        ('ImageId',              ARRAY(c_char, 8)),
+        ('ImageSize',            c_uint32),
+        ('ImageBase',            c_uint32),
+        ('ImageAttribute',       c_uint16),
+        ('ComponentAttribute',   c_uint16),
+        ('CfgRegionOffset',      c_uint32),
+        ('CfgRegionSize',        c_uint32),
+        ('Reserved2',            c_uint32),
+        ('TempRamInitEntryOffset',     c_uint32),
+        ('Reserved3',                  c_uint32),
+        ('NotifyPhaseEntryOffset',     c_uint32),
+        ('FspMemoryInitEntryOffset',   c_uint32),
+        ('TempRamExitEntryOffset',     c_uint32),
+        ('FspSiliconInitEntryOffset',  c_uint32)
+    ]
+
+class FSP_PATCH_TABLE(Structure):
+    _fields_ = [
+        ('Signature',            ARRAY(c_char, 4)),
+        ('HeaderLength',         c_uint16),
+        ('HeaderRevision',       c_uint8),
+        ('Reserved',             c_uint8),
+        ('PatchEntryNum',        c_uint32)
+        ]
+
+class EFI_IMAGE_DATA_DIRECTORY(Structure):
+    _fields_ = [
+        ('VirtualAddress',       c_uint32),
+        ('Size',                 c_uint32)
+        ]
+
+class EFI_TE_IMAGE_HEADER(Structure):
+    _fields_ = [
+        ('Signature',            ARRAY(c_char, 2)),
+        ('Machine',              c_uint16),
+        ('NumberOfSections',     c_uint8),
+        ('Subsystem',            c_uint8),
+        ('StrippedSize',         c_uint16),
+        ('AddressOfEntryPoint',  c_uint32),
+        ('BaseOfCode',           c_uint32),
+        ('ImageBase',            c_uint64),
+        ('DataDirectoryBaseReloc',  EFI_IMAGE_DATA_DIRECTORY),
+        ('DataDirectoryDebug',      EFI_IMAGE_DATA_DIRECTORY)
+        ]
+
+class EFI_IMAGE_DOS_HEADER(Structure):
+    _fields_ = [
+        ('e_magic',              c_uint16),
+        ('e_cblp',               c_uint16),
+        ('e_cp',                 c_uint16),
+        ('e_crlc',               c_uint16),
+        ('e_cparhdr',            c_uint16),
+        ('e_minalloc',           c_uint16),
+        ('e_maxalloc',           c_uint16),
+        ('e_ss',                 c_uint16),
+        ('e_sp',                 c_uint16),
+        ('e_csum',               c_uint16),
+        ('e_ip',                 c_uint16),
+        ('e_cs',                 c_uint16),
+        ('e_lfarlc',             c_uint16),
+        ('e_ovno',               c_uint16),
+        ('e_res',                ARRAY(c_uint16, 4)),
+        ('e_oemid',              c_uint16),
+        ('e_oeminfo',            c_uint16),
+        ('e_res2',               ARRAY(c_uint16, 10)),
+        ('e_lfanew',             c_uint16)
+        ]
+
+class EFI_IMAGE_FILE_HEADER(Structure):
+    _fields_ = [
+        ('Machine',               c_uint16),
+        ('NumberOfSections',      c_uint16),
+        ('TimeDateStamp',         c_uint32),
+        ('PointerToSymbolTable',  c_uint32),
+        ('NumberOfSymbols',       c_uint32),
+        ('SizeOfOptionalHeader',  c_uint16),
+        ('Characteristics',       c_uint16)
+        ]
+
+class PE_RELOC_BLOCK_HEADER(Structure):
+    _fields_ = [
+        ('PageRVA',              c_uint32),
+        ('BlockSize',            c_uint32)
+        ]
+
+class EFI_IMAGE_OPTIONAL_HEADER32(Structure):
+    _fields_ = [
+        ('Magic',                         c_uint16),
+        ('MajorLinkerVersion',            c_uint8),
+        ('MinorLinkerVersion',            c_uint8),
+        ('SizeOfCode',                    c_uint32),
+        ('SizeOfInitializedData',         c_uint32),
+        ('SizeOfUninitializedData',       c_uint32),
+        ('AddressOfEntryPoint',           c_uint32),
+        ('BaseOfCode',                    c_uint32),
+        ('BaseOfData',                    c_uint32),
+        ('ImageBase',                     c_uint32),
+        ('SectionAlignment',              c_uint32),
+        ('FileAlignment',                 c_uint32),
+        ('MajorOperatingSystemVersion',   c_uint16),
+        ('MinorOperatingSystemVersion',   c_uint16),
+        ('MajorImageVersion',             c_uint16),
+        ('MinorImageVersion',             c_uint16),
+        ('MajorSubsystemVersion',         c_uint16),
+        ('MinorSubsystemVersion',         c_uint16),
+        ('Win32VersionValue',             c_uint32),
+        ('SizeOfImage',                   c_uint32),
+        ('SizeOfHeaders',                 c_uint32),
+        ('CheckSum'     ,                 c_uint32),
+        ('Subsystem',                     c_uint16),
+        ('DllCharacteristics',            c_uint16),
+        ('SizeOfStackReserve',            c_uint32),
+        ('SizeOfStackCommit' ,            c_uint32),
+        ('SizeOfHeapReserve',             c_uint32),
+        ('SizeOfHeapCommit' ,             c_uint32),
+        ('LoaderFlags'     ,              c_uint32),
+        ('NumberOfRvaAndSizes',           c_uint32),
+        ('DataDirectory',                 ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
+        ]
+
+class EFI_IMAGE_OPTIONAL_HEADER32_PLUS(Structure):
+    _fields_ = [
+        ('Magic',                         c_uint16),
+        ('MajorLinkerVersion',            c_uint8),
+        ('MinorLinkerVersion',            c_uint8),
+        ('SizeOfCode',                    c_uint32),
+        ('SizeOfInitializedData',         c_uint32),
+        ('SizeOfUninitializedData',       c_uint32),
+        ('AddressOfEntryPoint',           c_uint32),
+        ('BaseOfCode',                    c_uint32),
+        ('ImageBase',                     c_uint64),
+        ('SectionAlignment',              c_uint32),
+        ('FileAlignment',                 c_uint32),
+        ('MajorOperatingSystemVersion',   c_uint16),
+        ('MinorOperatingSystemVersion',   c_uint16),
+        ('MajorImageVersion',             c_uint16),
+        ('MinorImageVersion',             c_uint16),
+        ('MajorSubsystemVersion',         c_uint16),
+        ('MinorSubsystemVersion',         c_uint16),
+        ('Win32VersionValue',             c_uint32),
+        ('SizeOfImage',                   c_uint32),
+        ('SizeOfHeaders',                 c_uint32),
+        ('CheckSum'     ,                 c_uint32),
+        ('Subsystem',                     c_uint16),
+        ('DllCharacteristics',            c_uint16),
+        ('SizeOfStackReserve',            c_uint64),
+        ('SizeOfStackCommit' ,            c_uint64),
+        ('SizeOfHeapReserve',             c_uint64),
+        ('SizeOfHeapCommit' ,             c_uint64),
+        ('LoaderFlags'     ,              c_uint32),
+        ('NumberOfRvaAndSizes',           c_uint32),
+        ('DataDirectory',                 ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
+        ]
+
+class EFI_IMAGE_OPTIONAL_HEADER(Union):
+    _fields_ = [
+        ('PeOptHdr',             EFI_IMAGE_OPTIONAL_HEADER32),
+        ('PePlusOptHdr',         EFI_IMAGE_OPTIONAL_HEADER32_PLUS)
+        ]
+
+class EFI_IMAGE_NT_HEADERS32(Structure):
+    _fields_ = [
+        ('Signature',            c_uint32),
+        ('FileHeader',           EFI_IMAGE_FILE_HEADER),
+        ('OptionalHeader',       EFI_IMAGE_OPTIONAL_HEADER)
+        ]
+
+
+class EFI_IMAGE_DIRECTORY_ENTRY:
+    EXPORT                     = 0
+    IMPORT                     = 1
+    RESOURCE                   = 2
+    EXCEPTION                  = 3
+    SECURITY                   = 4
+    BASERELOC                  = 5
+    DEBUG                      = 6
+    COPYRIGHT                  = 7
+    GLOBALPTR                  = 8
+    TLS                        = 9
+    LOAD_CONFIG                = 10
+
+class EFI_FV_FILETYPE:
+    ALL                        = 0x00
+    RAW                        = 0x01
+    FREEFORM                   = 0x02
+    SECURITY_CORE              = 0x03
+    PEI_CORE                   = 0x04
+    DXE_CORE                   = 0x05
+    PEIM                       = 0x06
+    DRIVER                     = 0x07
+    COMBINED_PEIM_DRIVER       = 0x08
+    APPLICATION                = 0x09
+    SMM                        = 0x0a
+    FIRMWARE_VOLUME_IMAGE      = 0x0b
+    COMBINED_SMM_DXE           = 0x0c
+    SMM_CORE                   = 0x0d
+    OEM_MIN                    = 0xc0
+    OEM_MAX                    = 0xdf
+    DEBUG_MIN                  = 0xe0
+    DEBUG_MAX                  = 0xef
+    FFS_MIN                    = 0xf0
+    FFS_MAX                    = 0xff
+    FFS_PAD                    = 0xf0
+
+class EFI_SECTION_TYPE:
+    """Enumeration of all valid firmware file section types."""
+    ALL                        = 0x00
+    COMPRESSION                = 0x01
+    GUID_DEFINED               = 0x02
+    DISPOSABLE                 = 0x03
+    PE32                       = 0x10
+    PIC                        = 0x11
+    TE                         = 0x12
+    DXE_DEPEX                  = 0x13
+    VERSION                    = 0x14
+    USER_INTERFACE             = 0x15
+    COMPATIBILITY16            = 0x16
+    FIRMWARE_VOLUME_IMAGE      = 0x17
+    FREEFORM_SUBTYPE_GUID      = 0x18
+    RAW                        = 0x19
+    PEI_DEPEX                  = 0x1b
+    SMM_DEPEX                  = 0x1c
+
+def AlignPtr (offset, alignment = 8):
+    return (offset + alignment - 1) & ~(alignment - 1)
+
+def Bytes2Val (bytes):
+    return reduce(lambda x,y: (x<<8)|y,  bytes[::-1] )
+
+def Val2Bytes (value, blen):
+    return [(value>>(i*8) & 0xff) for i in range(blen)]
+
+def OutputStruct (obj, indent = 0, plen = 0):
+    if indent:
+        body = ''
+    else:
+        body = ('  ' * indent + '<%s>:\n') % obj.__class__.__name__
+
+    if plen == 0:
+        plen = sizeof(obj)
+
+    max_key_len = 26
+    pstr = ('  ' * (indent + 1) + '{0:<%d} = {1}\n') % max_key_len
+
+    for field in obj._fields_:
+        key = field[0]
+        val = getattr(obj, key)
+        rep = ''
+        if not isinstance(val, c_uint24) and isinstance(val, Structure):
+            body += pstr.format(key, val.__class__.__name__)
+            body += OutputStruct (val, indent + 1)
+            plen -= sizeof(val)
+        else:
+            if type(val) is str:
+                rep = "0x%X ('%s')" % (Bytes2Val(bytearray(val)), val)
+            elif type(val) in (int, long):
+                rep = '0x%X' % val
+            elif isinstance(val, c_uint24):
+                rep = '0x%X' % val.get_value()
+            elif 'c_ubyte_Array' in str(type(val)):
+                if sizeof(val) == 16:
+                    rep = str(uuid.UUID(bytes = str(bytearray(val)))).upper()
+                else:
+                    res = ['0x%02X'%i for i in bytearray(val)]
+                    rep = '[%s]' % (','.join(res))
+            else:
+                rep = str(val)
+            plen -= sizeof(field[1])
+            body += pstr.format(key, rep)
+        if plen <= 0:
+            break
+    return body
+
+class Section:
+    def __init__(self, offset, secdata):
+        self.SecHdr   = EFI_COMMON_SECTION_HEADER.from_buffer (secdata, 0)
+        self.SecData  = secdata[0:int(self.SecHdr.Size)]
+        self.Offset   = offset
+
+class FirmwareFile:
+    def __init__(self, offset, filedata):
+        self.FfsHdr   = EFI_FFS_FILE_HEADER.from_buffer (filedata, 0)
+        self.FfsData  = filedata[0:int(self.FfsHdr.Size)]
+        self.Offset   = offset
+        self.SecList  = []
+
+    def ParseFfs(self):
+        ffssize = len(self.FfsData)
+        offset  = sizeof(self.FfsHdr)
+        if self.FfsHdr.Name != '\xff' * 16:
+            while offset < ffssize:
+                sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, 
offset)
+                sec = Section (offset, self.FfsData[offset:offset + 
int(sechdr.Size)])
+                self.SecList.append(sec)
+                offset += int(sechdr.Size)
+                offset  = AlignPtr(offset, 4)
+
+class FirmwareVolume:
+    def __init__(self, offset, fvdata):
+        self.FvHdr    = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (fvdata, 0)
+        self.FvData   = fvdata[0 : self.FvHdr.FvLength]
+        self.Offset   = offset
+        if self.FvHdr.ExtHeaderOffset > 0:
+            self.FvExtHdr = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer 
(self.FvData, self.FvHdr.ExtHeaderOffset)
+        else:
+            self.FvExtHdr = None
+        self.FfsList  = []
+
+    def ParseFv(self):
+        fvsize = len(self.FvData)
+        if self.FvExtHdr:
+            offset = self.FvHdr.ExtHeaderOffset + self.FvExtHdr.ExtHeaderSize
+        else:
+            offset = self.FvHdr.HeaderLength
+        offset = AlignPtr(offset)
+        while offset < fvsize:
+            ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset)
+            if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF):
+                offset = fvsize
+            else:
+                ffs = FirmwareFile (offset, self.FvData[offset:offset + 
int(ffshdr.Size)])
+                ffs.ParseFfs()
+                self.FfsList.append(ffs)
+                offset += int(ffshdr.Size)
+                offset = AlignPtr(offset)
+
+class FspImage:
+    def __init__(self, offset, fih, fihoff, patch):
+        self.Fih       = fih
+        self.FihOffset = fihoff
+        self.Offset    = offset
+        self.FvIdxList = []
+        self.Type      = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 
0x0F]
+        self.PatchList = patch
+        self.PatchList.append(fihoff + 0x1C)
+
+    def AppendFv(self, FvIdx):
+        self.FvIdxList.append(FvIdx)
+
+    def Patch(self, delta, fdbin):
+        count   = 0
+        applied = 0
+        for idx, patch in enumerate(self.PatchList):
+            ptype = (patch>>24) & 0x0F
+            if ptype not in [0x00, 0x0F]:
+                raise Exception('ERROR: Invalid patch type %d !' % ptype)
+            if patch & 0x80000000:
+                patch = self.Fih.ImageSize - (0x1000000 - (patch & 0xFFFFFF))
+            else:
+                patch = patch & 0xFFFFFF
+            if (patch < self.Fih.ImageSize) and (patch + sizeof(c_uint32) <= 
self.Fih.ImageSize):
+                offset = patch + self.Offset
+                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
+                value += delta
+                fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, 
sizeof(c_uint32))
+                applied += 1
+            count += 1
+        # Don't count the FSP base address patch entry appended at the end
+        if count != 0:
+            count   -= 1
+            applied -= 1
+        return (count, applied)
+
+class FirmwareDevice:
+    def __init__(self, offset, fdfile):
+        self.FvList  = []
+        self.FspList = []
+        self.FdFile = fdfile
+        self.Offset = 0
+        hfsp = open (self.FdFile, 'rb')
+        self.FdData = bytearray(hfsp.read())
+        hfsp.close()
+
+    def ParseFd(self):
+        offset = 0
+        fdsize = len(self.FdData)
+        self.FvList  = []
+        while offset < fdsize:
+            fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset)
+            if '_FVH' != fvh.Signature:
+                raise Exception("ERROR: Invalid FV header !")
+            fv = FirmwareVolume (offset, self.FdData[offset:offset + 
fvh.FvLength])
+            fv.ParseFv ()
+            self.FvList.append(fv)
+            offset += fv.FvHdr.FvLength
+
+    def CheckFsp (self):
+        if len(self.FspList) == 0:
+            return
+
+        fih = None
+        for fsp in self.FspList:
+            if fsp.Fih.HeaderRevision < 3:
+                raise Exception("ERROR: FSP 1.x is not supported by this tool 
!")
+            if not fih:
+                fih = fsp.Fih
+            else:
+                newfih = fsp.Fih
+                if (newfih.ImageId != fih.ImageId) or (newfih.ImageRevision != 
fih.ImageRevision):
+                    raise Exception("ERROR: Inconsistent FSP ImageId or 
ImageRevision detected !")
+
+    def ParseFsp(self):
+        flen = 0
+        for idx, fv in enumerate(self.FvList):
+            # Check if this FV contains FSP header
+            if flen == 0:
+                if len(fv.FfsList) == 0:
+                    continue
+                ffs = fv.FfsList[0]
+                if len(ffs.SecList) == 0:
+                    continue
+                sec = ffs.SecList[0]
+                if sec.SecHdr.Type != EFI_SECTION_TYPE.RAW:
+                    continue
+                fihoffset = ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
+                fspoffset = fv.Offset
+                offset    = fspoffset + fihoffset
+                fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset)
+                if 'FSPH' != fih.Signature:
+                    continue
+
+                offset += fih.HeaderLength
+                offset = AlignPtr(offset, 4)
+                plist  = []
+                while True:
+                    fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset)
+                    if 'FSPP' != fch.Signature:
+                        offset += fch.HeaderLength
+                        offset = AlignPtr(offset, 4)
+                    else:
+                        fspp = FSP_PATCH_TABLE.from_buffer (self.FdData, 
offset)
+                        offset += sizeof(fspp)
+                        pdata  = (c_uint32 * 
fspp.PatchEntryNum).from_buffer(self.FdData, offset)
+                        plist  = list(pdata)
+                        break
+
+                fsp  = FspImage (fspoffset, fih, fihoffset, plist)
+                fsp.AppendFv (idx)
+                self.FspList.append(fsp)
+                flen = fsp.Fih.ImageSize - fv.FvHdr.FvLength
+            else:
+                fsp.AppendFv (idx)
+                flen -= fv.FvHdr.FvLength
+                if flen < 0:
+                    raise Exception("ERROR: Incorrect FV size in image !")
+        self.CheckFsp ()
+
+class PeTeImage:
+    def __init__(self, offset, data):
+        self.Offset    = offset
+        tehdr          = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)
+        if   tehdr.Signature == 'VZ': # TE image
+            self.TeHdr   = tehdr
+        elif tehdr.Signature == 'MZ': # PE image
+            self.TeHdr   = None
+            self.DosHdr  = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)
+            self.PeHdr   = EFI_IMAGE_NT_HEADERS32.from_buffer (data, 
self.DosHdr.e_lfanew)
+            if self.PeHdr.Signature != 0x4550:
+                raise Exception("ERROR: Invalid PE32 header !")
+            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image
+                if self.PeHdr.FileHeader.SizeOfOptionalHeader < 
EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:
+                    raise Exception("ERROR: Unsupported PE32 image !")
+                if self.PeHdr.OptionalHeader.PeOptHdr.NumberOfRvaAndSizes <= 
EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
+                    raise Exception("ERROR: No relocation information 
available !")
+            elif self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ 
image
+                if self.PeHdr.FileHeader.SizeOfOptionalHeader < 
EFI_IMAGE_OPTIONAL_HEADER32_PLUS.DataDirectory.offset:
+                    raise Exception("ERROR: Unsupported PE32+ image !")
+                if self.PeHdr.OptionalHeader.PePlusOptHdr.NumberOfRvaAndSizes 
<= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
+                    raise Exception("ERROR: No relocation information 
available !")
+            else:
+                raise Exception("ERROR: Invalid PE32 optional header !")
+        self.Offset    = offset
+        self.Data      = data
+        self.RelocList = []
+
+    def IsTeImage(self):
+        return  self.TeHdr is not None
+
+    def ParseReloc(self):
+        if self.IsTeImage():
+            rsize   = self.TeHdr.DataDirectoryBaseReloc.Size
+            roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + 
self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
+        else:
+            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image
+                rsize   = 
self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
+                roffset = 
self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
+            if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ image
+                rsize   = 
self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
+                roffset = 
self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
+
+        alignment = 4
+        offset = roffset
+        while offset < roffset + rsize:
+            offset = AlignPtr(offset, 4)
+            blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, offset)
+            offset += sizeof(blkhdr)
+            # Read relocation type,offset pairs
+            rlen  = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
+            rnum  = rlen/sizeof(c_uint16)
+            rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)
+            for each in rdata:
+                roff  = each & 0xfff
+                rtype = each >> 12
+                if rtype == 0: # IMAGE_REL_BASED_ABSOLUTE:
+                    continue
+                if ((rtype != 3) and (rtype != 10)): # IMAGE_REL_BASED_HIGHLOW 
and IMAGE_REL_BASED_DIR64
+                    raise Exception("ERROR: Unsupported relocation type %d!" % 
rtype)
+                # Calculate the offset of the relocation
+                aoff  = blkhdr.PageRVA + roff
+                if self.IsTeImage():
+                    aoff += sizeof(self.TeHdr) - self.TeHdr.StrippedSize
+                self.RelocList.append((rtype, aoff))
+            offset += sizeof(rdata)
+
+    def Rebase(self, delta, fdbin):
+        count = 0
+        if delta == 0:
+            return count
+
+        for (rtype, roff) in self.RelocList:
+            if rtype == 3: # IMAGE_REL_BASED_HIGHLOW
+                offset = roff + self.Offset
+                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
+                value += delta
+                fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, 
sizeof(c_uint32))
+                count += 1
+            elif rtype == 10: # IMAGE_REL_BASED_DIR64
+                offset = roff + self.Offset
+                value  = Bytes2Val(fdbin[offset:offset+sizeof(c_uint64)])
+                value += delta
+                fdbin[offset:offset+sizeof(c_uint64)] = Val2Bytes(value, 
sizeof(c_uint64))
+                count += 1
+            else:
+                raise Exception('ERROR: Unknown relocation type %d !' % rtype)
+
+        if self.IsTeImage():
+            offset  = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset
+            size    = EFI_TE_IMAGE_HEADER.ImageBase.size
+        else:
+            offset  = self.Offset + self.DosHdr.e_lfanew
+            offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
+            offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
+            size    = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
+
+        value  = Bytes2Val(fdbin[offset:offset+size]) + delta
+        fdbin[offset:offset+size] = Val2Bytes(value, size)
+
+        return count
+
+def ShowFspInfo (fspfile):
+    fd = FirmwareDevice(0, fspfile)
+    fd.ParseFd  ()
+    fd.ParseFsp ()
+
+    print ("\nFound the following %d Firmware Volumes in FSP binary:" % 
(len(fd.FvList)))
+    for idx, fv in enumerate(fd.FvList):
+        name = fv.FvExtHdr.FvName
+        if not name:
+            name = '\xff' * 16
+        else:
+            name = str(bytearray(name))
+        guid = uuid.UUID(bytes = name)
+        print ("FV%d:" % idx)
+        print ("  GUID   : %s" % str(guid).upper())
+        print ("  Offset : 0x%08X" %  fv.Offset)
+        print ("  Length : 0x%08X" % fv.FvHdr.FvLength)
+    print ("\n")
+
+    for fsp in fd.FspList:
+        fvlist = map(lambda x : 'FV%d' % x, fsp.FvIdxList)
+        print ("FSP_%s contains %s" % (fsp.Type, ','.join(fvlist)))
+        print ("%s" % (OutputStruct(fsp.Fih, 0, fsp.Fih.HeaderLength)))
+
+def GenFspHdr (fspfile, outdir, hfile):
+    fd = FirmwareDevice(0, fspfile)
+    fd.ParseFd  ()
+    fd.ParseFsp ()
+
+    if not hfile:
+        hfile = os.path.splitext(os.path.basename(fspfile))[0] + '.h'
+    fspname, ext = os.path.splitext(os.path.basename(hfile))
+    filename = os.path.join(outdir, fspname + ext)
+    hfsp   = open(filename, 'w')
+    hfsp.write ('%s\n\n' % CopyRightHeaderFile)
+
+    firstfv = True
+    for fsp in fd.FspList:
+        fih = fsp.Fih
+        if firstfv:
+            hfsp.write("#define  FSP_IMAGE_ID    0x%016X    /* '%s' */\n" % 
(Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))
+            hfsp.write("#define  FSP_IMAGE_REV   0x%08X \n\n" % 
fih.ImageRevision)
+            firstfv = False
+        fv = fd.FvList[fsp.FvIdxList[0]]
+        hfsp.write ('#define  FSP%s_BASE       0x%08X\n'   % (fsp.Type, 
fih.ImageBase))
+        hfsp.write ('#define  FSP%s_OFFSET     0x%08X\n'   % (fsp.Type, 
fv.Offset))
+        hfsp.write ('#define  FSP%s_LENGTH     0x%08X\n\n' % (fsp.Type, 
fih.ImageSize))
+
+    hfsp.close()
+
+def SplitFspBin (fspfile, outdir, nametemplate):
+    fd = FirmwareDevice(0, fspfile)
+    fd.ParseFd  ()
+    fd.ParseFsp ()
+
+    for fsp in fd.FspList:
+        ftype = fsp.Type
+        if not nametemplate:
+            nametemplate = fspfile
+        fspname, ext = os.path.splitext(os.path.basename(nametemplate))
+        filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext)
+        hfsp = open(filename, 'wb')
+        print ("Create FSP component file '%s'" % filename)
+        for fvidx in fsp.FvIdxList:
+            fv = fd.FvList[fvidx]
+            hfsp.write(fv.FvData)
+        hfsp.close()
+
+def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
+    fd = FirmwareDevice(0, FspBinary)
+    fd.ParseFd  ()
+    fd.ParseFsp ()
+
+    numcomp  = len(FspComponent)
+    baselist = FspBase
+    if numcomp != len(baselist):
+        print "ERROR: Required number of base does not match number of FSP 
component !"
+        return
+
+    newfspbin = fd.FdData[:]
+
+    for idx, fspcomp in enumerate(FspComponent):
+
+        found = False
+        for fsp in fd.FspList:
+            ftype = fsp.Type.lower()
+            if ftype == fspcomp:
+                found = True
+                break
+
+        if not found:
+            print "ERROR: Could not find FSP_%c component to rebase !" % 
fspcomp.upper()
+            return
+
+        fspbase = baselist[idx]
+        if fspbase.startswith('0x'):
+            newbase = int(fspbase, 16)
+        else:
+            newbase = int(fspbase)
+        oldbase = fsp.Fih.ImageBase
+        delta = newbase - oldbase
+        print "Rebase FSP-%c from 0x%08X to 0x%08X:" % 
(ftype.upper(),oldbase,newbase)
+
+        imglist = []
+        for fvidx in fsp.FvIdxList:
+            fv = fd.FvList[fvidx]
+            for ffs in fv.FfsList:
+                for sec in ffs.SecList:
+                    if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, 
EFI_SECTION_TYPE.PE32]:   # TE or PE32
+                        offset = fd.Offset + fv.Offset + ffs.Offset + 
sec.Offset + sizeof(sec.SecHdr)
+                        imglist.append ((offset, len(sec.SecData) - 
sizeof(sec.SecHdr)))
+
+        fcount  = 0
+        pcount  = 0
+        for (offset, length) in imglist:
+            img = PeTeImage(offset, fd.FdData[offset:offset + length])
+            img.ParseReloc()
+            pcount += img.Rebase(delta, newfspbin)
+            fcount += 1
+
+        print "  Patched %d entries in %d TE/PE32 images." % (pcount, fcount)
+
+        (count, applied) = fsp.Patch(delta, newfspbin)
+        print "  Patched %d entries using FSP patch table." % applied
+        if count != applied:
+            print "  %d invalid entries are ignored !" % (count - applied)
+
+    if OutputFile == '':
+        filename = os.path.basename(FspBinary)
+        base, ext  = os.path.splitext(filename)
+        OutputFile = base + "_%08X" % newbase + ext
+
+    fspname, ext = os.path.splitext(os.path.basename(OutputFile))
+    filename = os.path.join(OutputDir, fspname + ext)
+    fd = open(filename, "wb")
+    fd.write(newfspbin)
+    fd.close()
+
+def main ():
+    parser     = argparse.ArgumentParser()
+    subparsers = parser.add_subparsers(title='commands')
+
+    parser_rebase  = subparsers.add_parser('rebase',  help='rebase a FSP into 
a new base address')
+    parser_rebase.set_defaults(which='rebase')
+    parser_rebase.add_argument('-f',  '--fspbin' , dest='FspBinary',  
type=str, help='FSP binary file path', required = True)
+    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)
+    parser_rebase.add_argument('-b',  '--newbase', dest='FspBase', nargs='+', 
type=str, help='Rebased FSP binary file name', default = '', required = True)
+    parser_rebase.add_argument('-o',  '--outdir' , dest='OutputDir',  
type=str, help='Output directory path', default = '.')
+    parser_rebase.add_argument('-n',  '--outfile', dest='OutputFile', 
type=str, help='Rebased FSP binary file name', default = '')
+
+    parser_split  = subparsers.add_parser('split',  help='split a FSP into 
multiple components')
+    parser_split.set_defaults(which='split')
+    parser_split.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
+    parser_split.add_argument('-o',  '--outdir' , dest='OutputDir', type=str, 
help='Output directory path',   default = '.')
+    parser_split.add_argument('-n',  '--nametpl', dest='NameTemplate', 
type=str, help='Output name template', default = '')
+
+    parser_genhdr = subparsers.add_parser('genhdr',  help='generate a header 
file for FSP binary')
+    parser_genhdr.set_defaults(which='genhdr')
+    parser_genhdr.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
+    parser_genhdr.add_argument('-o',  '--outdir' , dest='OutputDir', type=str, 
help='Output directory path',   default = '.')
+    parser_genhdr.add_argument('-n',  '--hfile',   dest='HFileName', type=str, 
help='Output header file name', default = '')
+
+    parser_info = subparsers.add_parser('info',  help='display FSP 
information')
+    parser_info.set_defaults(which='info')
+    parser_info.add_argument('-f',  '--fspbin' , dest='FspBinary', type=str, 
help='FSP binary file path', required = True)
+
+    args = parser.parse_args()
+    if args.which in ['rebase', 'split', 'genhdr', 'info']:
+        if not os.path.exists(args.FspBinary):
+            raise Exception ("ERROR: Could not locate FSP binary file '%s' !" 
% args.FspBinary)
+        if hasattr(args, 'OutputDir') and not os.path.exists(args.OutputDir):
+            raise Exception ("ERROR: Invalid output directory '%s' !" % 
args.OutputDir)
+
+    if args.which == 'rebase':
+        RebaseFspBin (args.FspBinary, args.FspComponent, args.FspBase, 
args.OutputDir, args.OutputFile)
+    elif args.which == 'split':
+        SplitFspBin (args.FspBinary, args.OutputDir, args.NameTemplate)
+    elif args.which == 'genhdr':
+        GenFspHdr (args.FspBinary, args.OutputDir, args.HFileName)
+    elif args.which == 'info':
+        ShowFspInfo (args.FspBinary)
+    else:
+        pass
+
+    return 0
+
+if __name__ == '__main__':
+    sys.exit(main())
-- 
2.19.0.397.gdd90340f6a-goog

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to