From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <3bf6gWwcKCtAB20AD242AA270.yA80z6O-z0H0774EFE.MN.AD2@flex--pgeorgi.bounces.google.com> Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::c4a; helo=mail-yw1-xc4a.google.com; envelope-from=3bf6gwwckctab20ad242aa270.ya80z6o-z0h0774efe.mn.ad2@flex--pgeorgi.bounces.google.com; receiver=edk2-devel@lists.01.org Received: from mail-yw1-xc4a.google.com (mail-yw1-xc4a.google.com [IPv6:2607:f8b0:4864:20::c4a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A5D092114082F for ; Tue, 18 Sep 2018 06:32:30 -0700 (PDT) Received: by mail-yw1-xc4a.google.com with SMTP id p127-v6so839591ywg.1 for ; Tue, 18 Sep 2018 06:32:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=daCAnt8W8rsVON68K6IAss46Gq3A8aAbqpbmTXoneyM=; b=idPRXHvT0UYGazGsG/CrBRqKl8WFy+5zB/7kPUDd6IPORl8QZeJcbyQEIf1vg3+oFH 7M2JPWsowIfnAcg5j3YFmZZUs0zB1J5QZmpD5WT46FbDarIlXs2O5rpJtgmqz2B/5szu GCgsszNk5ObqOUuV5yUrEG/5vMMII+jDRfYxVYvz/MHqmdzLY0JZRSw9AGFceNSlC0VY cICCUoAFGGpuzioWoJJBDhC4KlitBEs2WlBk7gFzfsxEOS5WkfaladhiF68aUJ2OvHO9 /zl2J1E5kWeuhiOi/RKaMuaFKc11LRoy646avJdH345DDEcklsuPcJOA797rL7xHjjxv Q6Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=daCAnt8W8rsVON68K6IAss46Gq3A8aAbqpbmTXoneyM=; b=csTFIDrIQP4LE+S+yB3rnDPdHQBPN1k3ZBL3i7XUeCQbBkDSKCgFdlEc3Z713HFVjd uqVktWfeL8ojdJbMEqKbbWOuUM1CNo10CA5dn/LYsIh1UU8S4sM6O1M/d+LwD42AHtBI Z+/5XMH9ZhkIzsmLNbRmASsOw+epqw1NN6sDxr3zvyY8fVcOVWllZdFkxHFybJwfLaeY 0Uz8NSL2HD5lqY+t6lmhlwcsMYNeE3snHiEmMXdQBlTDZYZHWqI2bUxpVSOD4+ezTxZj XdLsYXn3Guo+rB6KQK/3VuUd56im4l1rAmem2BDUvFHz6wVpvkTmnp1ijNkvBci/NQe1 nk/Q== X-Gm-Message-State: APzg51BFzZ2u392ZMNhJjq+0wWjbErMgmc6NmU0qpZ0Atocw9ZzeHdFU ElZFWmtcCx+Bj04IGXrppRlpHv17rOUv/lf1cxtXRCeAGHjnsoASnCI36T0yGJXhAViFQhZ5jE3 UOfyrApmPBaU3ex1+Chqg2/2bCdWYNwYmKyNZ9KE+UTuA1jRO0/UF4DsBcjsx6abr6Q== X-Google-Smtp-Source: ANB0VdaP3v/CcY9RylBIjWZ23E5Mo4PvMvtANnSDsjYDkUXuOByHZ2i+qCfL1ZWVbH2xfhOughoHuQ85Wonk X-Received: by 2002:a0d:ff02:: with SMTP id p2-v6mr3002284ywf.16.1537277549136; Tue, 18 Sep 2018 06:32:29 -0700 (PDT) Date: Tue, 18 Sep 2018 09:32:03 -0400 In-Reply-To: <20180918133203.192779-1-pgeorgi@google.com> Message-Id: <20180918133203.192779-3-pgeorgi@google.com> Mime-Version: 1.0 References: <20180918133203.192779-1-pgeorgi@google.com> X-Mailer: git-send-email 2.19.0.397.gdd90340f6a-goog From: Patrick Georgi To: edk2-devel@lists.01.org Cc: Patrick Georgi Subject: [PATCH 3/3] IntelFsp2Pkg: Tell git to format SplitFspBin.py with native newlines X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Sep 2018 13:32:31 -0000 Content-Type: text/plain; charset="UTF-8" Signed-off-by: Patrick Georgi 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.
-# 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.
+# 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