https://bugzilla.tianocore.org/show_bug.cgi?id=945 Based on content from the following branch https://github.com/Microsoft/MS_UEFI/tree/share/beta/CapsuleTools * Convert C tools to Python * Add common python modules to: BaseTools/Source/Python/Common/Uefi/Capsule BaseTools/Source/Python/Common/Edk2/Capsule * Add GenerateCapsule.py to BaseTools/Source/Python/Capsule * Add Windows and Posix wrappers for GenerateCapsule.py usage: GenerateCapsule [-h] [-o OUTPUTFILE] (-e | -d | --dump-info) [--capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset}] [--capoemflag CAPSULEOEMFLAG] [--guid GUID] [--hardware-instance HARDWAREINSTANCE] [--monotonic-count MONOTONICCOUNT] [--fw-version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION] [--pfx-file SIGNTOOLPFXFILE] [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE] [--other-public-cert OPENSSLOTHERPUBLICCERTFILE] [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE] [--signing-tool-path SIGNINGTOOLPATH] [--version] [-v] [-q] [--debug [0-9]] InputFile Generate a capsule. Copyright (c) 2018, Intel Corporation. All rights reserved. positional arguments: InputFile Input binary payload filename. optional arguments: -h, --help show this help message and exit -o OUTPUTFILE, --output OUTPUTFILE Output filename. -e, --encode Encode file -d, --decode Decode file --dump-info Display FMP Payload Header information --capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset} Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set --capoemflag CAPSULEOEMFLAG Capsule OEM Flag is an integer between 0x0000 and 0xffff. --guid GUID The FMP/ESRT GUID in registry format. Required for encode operations. --hardware-instance HARDWAREINSTANCE The 64-bit hardware instance. The default is 0x0000000000000000 --monotonic-count MONOTONICCOUNT 64-bit monotonic count value in header. Default is 0x0000000000000000. --fw-version FWVERSION The 32-bit version of the binary payload (e.g. 0x11223344 or 5678). --lsv LOWESTSUPPORTEDVERSION The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678). --pfx-file SIGNTOOLPFXFILE signtool PFX certificate filename. --signer-private-cert OPENSSLSIGNERPRIVATECERTFILE OpenSSL signer private certificate filename. --other-public-cert OPENSSLOTHERPUBLICCERTFILE OpenSSL other public certificate filename. --trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE OpenSSL trusted public certificate filename. --signing-tool-path SIGNINGTOOLPATH Path to signtool or OpenSSL tool. Optional if path to tools are already in PATH. --version show program's version number and exit -v, --verbose Turn on verbose output with informational messages printed, including capsule headers and warning messages. -q, --quiet Disable all messages except fatal errors. --debug [0-9] Set debug level Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Yonghong Zhu <yonghong.zhu@intel.com> Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
		
			
				
	
	
		
			523 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			523 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
## @file
 | 
						|
# Generate a capsule.
 | 
						|
#
 | 
						|
# Copyright (c) 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
 | 
						|
# which 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.
 | 
						|
#
 | 
						|
 | 
						|
'''
 | 
						|
GenerateCapsule
 | 
						|
'''
 | 
						|
 | 
						|
import sys
 | 
						|
import argparse
 | 
						|
import uuid
 | 
						|
import struct
 | 
						|
import subprocess
 | 
						|
import os
 | 
						|
import tempfile
 | 
						|
import shutil
 | 
						|
import platform
 | 
						|
from Common.Uefi.Capsule.UefiCapsuleHeader import UefiCapsuleHeaderClass
 | 
						|
from Common.Uefi.Capsule.FmpCapsuleHeader  import FmpCapsuleHeaderClass
 | 
						|
from Common.Uefi.Capsule.FmpAuthHeader     import FmpAuthHeaderClass
 | 
						|
from Common.Edk2.Capsule.FmpPayloadHeader  import FmpPayloadHeaderClass
 | 
						|
 | 
						|
#
 | 
						|
# Globals for help information
 | 
						|
#
 | 
						|
__prog__        = 'GenerateCapsule'
 | 
						|
__version__     = '0.9'
 | 
						|
__copyright__   = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'
 | 
						|
__description__ = 'Generate a capsule.\n'
 | 
						|
 | 
						|
def SignPayloadSignTool (Payload, ToolPath, PfxFile):
 | 
						|
    #
 | 
						|
    # Create a temporary directory
 | 
						|
    #
 | 
						|
    TempDirectoryName = tempfile.mkdtemp()
 | 
						|
 | 
						|
    #
 | 
						|
    # Generate temp file name for the payload contents
 | 
						|
    #
 | 
						|
    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')
 | 
						|
 | 
						|
    #
 | 
						|
    # Create temporary payload file for signing
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        File = open (TempFileName, mode='wb')
 | 
						|
        File.write (Payload)
 | 
						|
        File.close ()
 | 
						|
    except:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')
 | 
						|
 | 
						|
    #
 | 
						|
    # Build signtool command
 | 
						|
    #
 | 
						|
    if ToolPath is None:
 | 
						|
        ToolPath = ''
 | 
						|
    Command = ''
 | 
						|
    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'signtool.exe'))
 | 
						|
    Command = Command + 'sign /fd sha256 /p7ce DetachedSignedData /p7co 1.2.840.113549.1.7.2 '
 | 
						|
    Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)
 | 
						|
    Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)
 | 
						|
    Command = Command + TempFileName
 | 
						|
 | 
						|
    #
 | 
						|
    # Sign the input file using the specified private key
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
 | 
						|
        Result = Process.communicate('')
 | 
						|
    except:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not run signtool.')
 | 
						|
 | 
						|
    if Process.returncode != 0:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        print (Result[1].decode())
 | 
						|
        raise ValueError ('GenerateCapsule: error: signtool failed.')
 | 
						|
 | 
						|
    #
 | 
						|
    # Read the signature from the generated output file
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        File = open (TempFileName + '.p7', mode='rb')
 | 
						|
        Signature = File.read ()
 | 
						|
        File.close ()
 | 
						|
    except:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not read signature file.')
 | 
						|
 | 
						|
    shutil.rmtree (TempDirectoryName)
 | 
						|
    return Signature
 | 
						|
 | 
						|
def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):
 | 
						|
    print ('signtool verify is not supported.')
 | 
						|
    raise ValueError ('GenerateCapsule: error: signtool verify is not supported.')
 | 
						|
 | 
						|
def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):
 | 
						|
    #
 | 
						|
    # Build openssl command
 | 
						|
    #
 | 
						|
    if ToolPath is None:
 | 
						|
        ToolPath = ''
 | 
						|
    Command = ''
 | 
						|
    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))
 | 
						|
    Command = Command + 'smime -sign -binary -outform DER -md sha256 '
 | 
						|
    Command = Command + '-signer "{Private}" -certfile "{Public}"'.format (Private = SignerPrivateCertFile, Public = OtherPublicCertFile)
 | 
						|
 | 
						|
    #
 | 
						|
    # Sign the input file using the specified private key and capture signature from STDOUT
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
 | 
						|
        Result = Process.communicate(input = Payload)
 | 
						|
        Signature = Result[0]
 | 
						|
    except:
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not run openssl.')
 | 
						|
 | 
						|
    if Process.returncode != 0:
 | 
						|
        print (Result[1].decode())
 | 
						|
        raise ValueError ('GenerateCapsule: error: openssl failed.')
 | 
						|
 | 
						|
    return Signature
 | 
						|
 | 
						|
def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):
 | 
						|
    #
 | 
						|
    # Create a temporary directory
 | 
						|
    #
 | 
						|
    TempDirectoryName = tempfile.mkdtemp()
 | 
						|
 | 
						|
    #
 | 
						|
    # Generate temp file name for the payload contents
 | 
						|
    #
 | 
						|
    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')
 | 
						|
 | 
						|
    #
 | 
						|
    # Create temporary payload file for verification
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        File = open (TempFileName, mode='wb')
 | 
						|
        File.write (Payload)
 | 
						|
        File.close ()
 | 
						|
    except:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')
 | 
						|
 | 
						|
    #
 | 
						|
    # Build openssl command
 | 
						|
    #
 | 
						|
    if ToolPath is None:
 | 
						|
        ToolPath = ''
 | 
						|
    Command = ''
 | 
						|
    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))
 | 
						|
    Command = Command + 'smime -verify -inform DER '
 | 
						|
    Command = Command + '-content {Content} -CAfile "{Public}"'.format (Content = TempFileName, Public = TrustedPublicCertFile)
 | 
						|
 | 
						|
    #
 | 
						|
    # Verify signature
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
 | 
						|
        Result = Process.communicate(input = CertData)
 | 
						|
    except:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        raise ValueError ('GenerateCapsule: error: can not run openssl.')
 | 
						|
 | 
						|
    if Process.returncode != 0:
 | 
						|
        shutil.rmtree (TempDirectoryName)
 | 
						|
        print (Result[1].decode())
 | 
						|
        raise ValueError ('GenerateCapsule: error: openssl failed.')
 | 
						|
 | 
						|
    shutil.rmtree (TempDirectoryName)
 | 
						|
    return Payload
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    def convert_arg_line_to_args(arg_line):
 | 
						|
        for arg in arg_line.split():
 | 
						|
            if not arg.strip():
 | 
						|
                continue
 | 
						|
            yield arg
 | 
						|
 | 
						|
    def ValidateUnsignedInteger (Argument):
 | 
						|
        try:
 | 
						|
            Value = int (Argument, 0)
 | 
						|
        except:
 | 
						|
            Message = '{Argument} is not a valid integer value.'.format (Argument = Argument)
 | 
						|
            raise argparse.ArgumentTypeError (Message)
 | 
						|
        if Value < 0:
 | 
						|
            Message = '{Argument} is a negative value.'.format (Argument = Argument)
 | 
						|
            raise argparse.ArgumentTypeError (Message)
 | 
						|
        return Value
 | 
						|
 | 
						|
    def ValidateRegistryFormatGuid (Argument):
 | 
						|
        try:
 | 
						|
            Value = uuid.UUID (Argument)
 | 
						|
        except:
 | 
						|
            Message = '{Argument} is not a valid registry format GUID value.'.format (Argument = Argument)
 | 
						|
            raise argparse.ArgumentTypeError (Message)
 | 
						|
        return Value
 | 
						|
 | 
						|
    #
 | 
						|
    # Create command line argument parser object
 | 
						|
    #
 | 
						|
    parser = argparse.ArgumentParser (
 | 
						|
                        prog = __prog__,
 | 
						|
                        description = __description__ + __copyright__,
 | 
						|
                        conflict_handler = 'resolve',
 | 
						|
                        fromfile_prefix_chars = '@'
 | 
						|
                        )
 | 
						|
    parser.convert_arg_line_to_args = convert_arg_line_to_args
 | 
						|
 | 
						|
    #
 | 
						|
    # Add input and output file arguments
 | 
						|
    #
 | 
						|
    parser.add_argument("InputFile",  type = argparse.FileType('rb'),
 | 
						|
                        help = "Input binary payload filename.")
 | 
						|
    parser.add_argument("-o", "--output", dest = 'OutputFile', type = argparse.FileType('wb'),
 | 
						|
                        help = "Output filename.")
 | 
						|
    #
 | 
						|
    # Add group for -e and -d flags that are mutually exclusive and required
 | 
						|
    #
 | 
						|
    group = parser.add_mutually_exclusive_group (required = True)
 | 
						|
    group.add_argument ("-e", "--encode", dest = 'Encode', action = "store_true",
 | 
						|
                        help = "Encode file")
 | 
						|
    group.add_argument ("-d", "--decode", dest = 'Decode', action = "store_true",
 | 
						|
                        help = "Decode file")
 | 
						|
    group.add_argument ("--dump-info", dest = 'DumpInfo', action = "store_true",
 | 
						|
                        help = "Display FMP Payload Header information")
 | 
						|
    #
 | 
						|
    # Add optional arguments for this command
 | 
						|
    #
 | 
						|
    parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],
 | 
						|
                         choices=['PersistAcrossReset', 'PopulateSystemTable', 'InitiateReset'],
 | 
						|
                         help = "Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set")
 | 
						|
    parser.add_argument ("--capoemflag", dest = 'CapsuleOemFlag', type = ValidateUnsignedInteger, default = 0x0000,
 | 
						|
                         help = "Capsule OEM Flag is an integer between 0x0000 and 0xffff.")
 | 
						|
 | 
						|
    parser.add_argument ("--guid", dest = 'Guid', type = ValidateRegistryFormatGuid,
 | 
						|
                         help = "The FMP/ESRT GUID in registry format.  Required for encode operations.")
 | 
						|
    parser.add_argument ("--hardware-instance", dest = 'HardwareInstance', type = ValidateUnsignedInteger, default = 0x0000000000000000,
 | 
						|
                         help = "The 64-bit hardware instance.  The default is 0x0000000000000000")
 | 
						|
 | 
						|
 | 
						|
    parser.add_argument ("--monotonic-count", dest = 'MonotonicCount', type = ValidateUnsignedInteger, default = 0x0000000000000000,
 | 
						|
                         help = "64-bit monotonic count value in header.  Default is 0x0000000000000000.")
 | 
						|
 | 
						|
    parser.add_argument ("--fw-version", dest = 'FwVersion', type = ValidateUnsignedInteger,
 | 
						|
                         help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678).")
 | 
						|
    parser.add_argument ("--lsv", dest = 'LowestSupportedVersion', type = ValidateUnsignedInteger,
 | 
						|
                         help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678).")
 | 
						|
 | 
						|
    parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),
 | 
						|
                         help="signtool PFX certificate filename.")
 | 
						|
 | 
						|
    parser.add_argument ("--signer-private-cert", dest='OpenSslSignerPrivateCertFile', type=argparse.FileType('rb'),
 | 
						|
                         help="OpenSSL signer private certificate filename.")
 | 
						|
    parser.add_argument ("--other-public-cert", dest='OpenSslOtherPublicCertFile', type=argparse.FileType('rb'),
 | 
						|
                         help="OpenSSL other public certificate filename.")
 | 
						|
    parser.add_argument ("--trusted-public-cert", dest='OpenSslTrustedPublicCertFile', type=argparse.FileType('rb'),
 | 
						|
                         help="OpenSSL trusted public certificate filename.")
 | 
						|
 | 
						|
    parser.add_argument ("--signing-tool-path", dest = 'SigningToolPath',
 | 
						|
                         help = "Path to signtool or OpenSSL tool.  Optional if path to tools are already in PATH.")
 | 
						|
 | 
						|
    #
 | 
						|
    # Add optional arguments common to all operations
 | 
						|
    #
 | 
						|
    parser.add_argument ('--version', action='version', version='%(prog)s ' + __version__)
 | 
						|
    parser.add_argument ("-v", "--verbose", dest = 'Verbose', action = "store_true",
 | 
						|
                         help = "Turn on verbose output with informational messages printed, including capsule headers and warning messages.")
 | 
						|
    parser.add_argument ("-q", "--quiet", dest = 'Quiet', action = "store_true",
 | 
						|
                         help = "Disable all messages except fatal errors.")
 | 
						|
    parser.add_argument ("--debug", dest = 'Debug', type = int, metavar = '[0-9]', choices = range (0, 10), default = 0,
 | 
						|
                         help = "Set debug level")
 | 
						|
 | 
						|
    #
 | 
						|
    # Parse command line arguments
 | 
						|
    #
 | 
						|
    args = parser.parse_args()
 | 
						|
 | 
						|
    #
 | 
						|
    # Perform additional argument verification
 | 
						|
    #
 | 
						|
    if args.Encode:
 | 
						|
        if args.Guid is None:
 | 
						|
            parser.error ('the following option is required: --guid')
 | 
						|
        if 'PersistAcrossReset' not in args.CapsuleFlag:
 | 
						|
            if 'PopulateSystemTable' in args.CapsuleFlag:
 | 
						|
                parser.error ('--capflag PopulateSystemTable also requires --capflag PersistAcrossReset')
 | 
						|
            if 'InitiateReset' in args.CapsuleFlag:
 | 
						|
                parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')
 | 
						|
 | 
						|
    UseSignTool = args.SignToolPfxFile is not None
 | 
						|
    UseOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None and
 | 
						|
                   args.OpenSslOtherPublicCertFile is not None and
 | 
						|
                   args.OpenSslTrustedPublicCertFile is not None)
 | 
						|
    AnyOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None or
 | 
						|
                   args.OpenSslOtherPublicCertFile is not None or
 | 
						|
                   args.OpenSslTrustedPublicCertFile is not None)
 | 
						|
    if args.Encode or args.Decode:
 | 
						|
        if args.OutputFile is None:
 | 
						|
            parser.error ('the following option is required for all encode and decode operations: --output')
 | 
						|
 | 
						|
        if UseSignTool and AnyOpenSsl:
 | 
						|
            parser.error ('Providing both signtool and OpenSSL options is not supported')
 | 
						|
        if not UseSignTool and not UseOpenSsl and AnyOpenSsl:
 | 
						|
            parser.error ('all the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')
 | 
						|
        if UseSignTool and platform.system() != 'Windows':
 | 
						|
            parser.error ('Use of signtool is not supported on this operating system.')
 | 
						|
        if args.Encode and (UseSignTool or UseOpenSsl):
 | 
						|
            if args.FwVersion is None or args.LowestSupportedVersion is None:
 | 
						|
                parser.error ('the following options are required: --fw-version, --lsv')
 | 
						|
 | 
						|
        if UseSignTool:
 | 
						|
            args.SignToolPfxFile.close()
 | 
						|
            args.SignToolPfxFile = args.SignToolPfxFile.name
 | 
						|
        if UseOpenSsl:
 | 
						|
            args.OpenSslSignerPrivateCertFile.close()
 | 
						|
            args.OpenSslOtherPublicCertFile.close()
 | 
						|
            args.OpenSslTrustedPublicCertFile.close()
 | 
						|
            args.OpenSslSignerPrivateCertFile = args.OpenSslSignerPrivateCertFile.name
 | 
						|
            args.OpenSslOtherPublicCertFile   = args.OpenSslOtherPublicCertFile.name
 | 
						|
            args.OpenSslTrustedPublicCertFile = args.OpenSslTrustedPublicCertFile.name
 | 
						|
 | 
						|
    #
 | 
						|
    # Read binary input file
 | 
						|
    #
 | 
						|
    try:
 | 
						|
        if args.Verbose:
 | 
						|
            print ('Read binary input file {File}'.format (File = args.InputFile.name))
 | 
						|
        Buffer = args.InputFile.read ()
 | 
						|
        args.InputFile.close ()
 | 
						|
    except:
 | 
						|
        print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = args.InputFile.name))
 | 
						|
        sys.exit (1)
 | 
						|
 | 
						|
    #
 | 
						|
    # Create objects
 | 
						|
    #
 | 
						|
    UefiCapsuleHeader = UefiCapsuleHeaderClass ()
 | 
						|
    FmpCapsuleHeader  = FmpCapsuleHeaderClass ()
 | 
						|
    FmpAuthHeader     = FmpAuthHeaderClass ()
 | 
						|
    FmpPayloadHeader  = FmpPayloadHeaderClass ()
 | 
						|
 | 
						|
    if args.Encode:
 | 
						|
        Result = Buffer
 | 
						|
        if UseSignTool or UseOpenSsl:
 | 
						|
            try:
 | 
						|
                FmpPayloadHeader.FwVersion              = args.FwVersion
 | 
						|
                FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion
 | 
						|
                FmpPayloadHeader.Payload                = Result
 | 
						|
                Result = FmpPayloadHeader.Encode ()
 | 
						|
                if args.Verbose:
 | 
						|
                    FmpPayloadHeader.DumpInfo ()
 | 
						|
            except:
 | 
						|
                print ('GenerateCapsule: error: can not encode FMP Payload Header')
 | 
						|
                sys.exit (1)
 | 
						|
 | 
						|
            #
 | 
						|
            # Sign image with 64-bit MonotonicCount appended to end of image
 | 
						|
            #
 | 
						|
            try:
 | 
						|
                if UseSignTool:
 | 
						|
                    CertData = SignPayloadSignTool (
 | 
						|
                                 Result + struct.pack ('<Q', args.MonotonicCount),
 | 
						|
                                 args.SigningToolPath,
 | 
						|
                                 args.SignToolPfxFile
 | 
						|
                                 )
 | 
						|
                else:
 | 
						|
                    CertData = SignPayloadOpenSsl (
 | 
						|
                                 Result + struct.pack ('<Q', args.MonotonicCount),
 | 
						|
                                 args.SigningToolPath,
 | 
						|
                                 args.OpenSslSignerPrivateCertFile,
 | 
						|
                                 args.OpenSslOtherPublicCertFile,
 | 
						|
                                 args.OpenSslTrustedPublicCertFile
 | 
						|
                                 )
 | 
						|
            except:
 | 
						|
                print ('GenerateCapsule: error: can not sign payload')
 | 
						|
                raise
 | 
						|
                sys.exit (1)
 | 
						|
 | 
						|
            try:
 | 
						|
                FmpAuthHeader.MonotonicCount = args.MonotonicCount
 | 
						|
                FmpAuthHeader.CertData       = CertData
 | 
						|
                FmpAuthHeader.Payload        = Result
 | 
						|
                Result = FmpAuthHeader.Encode ()
 | 
						|
                if args.Verbose:
 | 
						|
                    FmpAuthHeader.DumpInfo ()
 | 
						|
            except:
 | 
						|
                print ('GenerateCapsule: error: can not encode FMP Auth Header')
 | 
						|
                sys.exit (1)
 | 
						|
 | 
						|
        try:
 | 
						|
            FmpCapsuleHeader.AddPayload (args.Guid, Result, HardwareInstance = args.HardwareInstance)
 | 
						|
            Result = FmpCapsuleHeader.Encode ()
 | 
						|
            if args.Verbose:
 | 
						|
                FmpCapsuleHeader.DumpInfo ()
 | 
						|
        except:
 | 
						|
            print ('GenerateCapsule: error: can not encode FMP Capsule Header')
 | 
						|
            sys.exit (1)
 | 
						|
 | 
						|
        try:
 | 
						|
            UefiCapsuleHeader.OemFlags            = args.CapsuleOemFlag
 | 
						|
            UefiCapsuleHeader.PersistAcrossReset  = 'PersistAcrossReset'  in args.CapsuleFlag
 | 
						|
            UefiCapsuleHeader.PopulateSystemTable = 'PopulateSystemTable' in args.CapsuleFlag
 | 
						|
            UefiCapsuleHeader.InitiateReset       = 'InitiateReset'       in args.CapsuleFlag
 | 
						|
            UefiCapsuleHeader.Payload             = Result
 | 
						|
            Result = UefiCapsuleHeader.Encode ()
 | 
						|
            if args.Verbose:
 | 
						|
                UefiCapsuleHeader.DumpInfo ()
 | 
						|
        except:
 | 
						|
            print ('GenerateCapsule: error: can not encode UEFI Capsule Header')
 | 
						|
            sys.exit (1)
 | 
						|
 | 
						|
    elif args.Decode:
 | 
						|
        try:
 | 
						|
            Result = UefiCapsuleHeader.Decode (Buffer)
 | 
						|
            FmpCapsuleHeader.Decode (Result)
 | 
						|
            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload
 | 
						|
            if args.Verbose:
 | 
						|
                print ('========')
 | 
						|
                UefiCapsuleHeader.DumpInfo ()
 | 
						|
                print ('--------')
 | 
						|
                FmpCapsuleHeader.DumpInfo ()
 | 
						|
            if UseSignTool or UseOpenSsl:
 | 
						|
                Result = FmpAuthHeader.Decode (Result)
 | 
						|
 | 
						|
                #
 | 
						|
                # Verify Image with 64-bit MonotonicCount appended to end of image
 | 
						|
                #
 | 
						|
                try:
 | 
						|
                  if UseSignTool:
 | 
						|
                      CertData = VerifyPayloadSignTool (
 | 
						|
                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),
 | 
						|
                                   FmpAuthHeader.CertData,
 | 
						|
                                   args.SigningToolPath,
 | 
						|
                                   args.SignToolPfxFile
 | 
						|
                                   )
 | 
						|
                  else:
 | 
						|
                      CertData = VerifyPayloadOpenSsl (
 | 
						|
                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),
 | 
						|
                                   FmpAuthHeader.CertData,
 | 
						|
                                   args.SigningToolPath,
 | 
						|
                                   args.OpenSslSignerPrivateCertFile,
 | 
						|
                                   args.OpenSslOtherPublicCertFile,
 | 
						|
                                   args.OpenSslTrustedPublicCertFile
 | 
						|
                                   )
 | 
						|
                except ValueError:
 | 
						|
                    print ('GenerateCapsule: warning: can not verify payload.')
 | 
						|
 | 
						|
                Result = FmpPayloadHeader.Decode (Result)
 | 
						|
                if args.Verbose:
 | 
						|
                    print ('--------')
 | 
						|
                    FmpAuthHeader.DumpInfo ()
 | 
						|
                    print ('--------')
 | 
						|
                    FmpPayloadHeader.DumpInfo ()
 | 
						|
            else:
 | 
						|
                if args.Verbose:
 | 
						|
                    print ('--------')
 | 
						|
                    print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')
 | 
						|
                    print ('--------')
 | 
						|
                    print ('No FMP_PAYLOAD_HEADER')
 | 
						|
            if args.Verbose:
 | 
						|
                print ('========')
 | 
						|
        except:
 | 
						|
            print ('GenerateCapsule: error: can not decode capsule')
 | 
						|
            raise
 | 
						|
            sys.exit (1)
 | 
						|
 | 
						|
    elif args.DumpInfo:
 | 
						|
        try:
 | 
						|
            Result = UefiCapsuleHeader.Decode (Buffer)
 | 
						|
            FmpCapsuleHeader.Decode (Result)
 | 
						|
            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload
 | 
						|
            print ('========')
 | 
						|
            UefiCapsuleHeader.DumpInfo ()
 | 
						|
            print ('--------')
 | 
						|
            FmpCapsuleHeader.DumpInfo ()
 | 
						|
            try:
 | 
						|
                Result = FmpAuthHeader.Decode (Result)
 | 
						|
                Result = FmpPayloadHeader.Decode (Result)
 | 
						|
                print ('--------')
 | 
						|
                FmpAuthHeader.DumpInfo ()
 | 
						|
                print ('--------')
 | 
						|
                FmpPayloadHeader.DumpInfo ()
 | 
						|
            except:
 | 
						|
                print ('--------')
 | 
						|
                print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')
 | 
						|
                print ('--------')
 | 
						|
                print ('No FMP_PAYLOAD_HEADER')
 | 
						|
            print ('========')
 | 
						|
        except:
 | 
						|
            print ('GenerateCapsule: error: can not decode capsule')
 | 
						|
            sys.exit (1)
 | 
						|
    else:
 | 
						|
        print('GenerateCapsule: error: invalid options')
 | 
						|
        sys.exit (1)
 | 
						|
 | 
						|
    #
 | 
						|
    # Write binary output file
 | 
						|
    #
 | 
						|
    if args.OutputFile is not None:
 | 
						|
        try:
 | 
						|
            if args.Verbose:
 | 
						|
                print ('Write binary output file {File}'.format (File = args.OutputFile.name))
 | 
						|
            args.OutputFile.write (Result)
 | 
						|
            args.OutputFile.close ()
 | 
						|
        except:
 | 
						|
            print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))
 | 
						|
            sys.exit (1)
 | 
						|
 | 
						|
    if args.Verbose:
 | 
						|
        print('Success')
 |