]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Capsule/GenerateCapsule.py
BaseTools/Capsule: Add Capsule Generation Tools
[mirror_edk2.git] / BaseTools / Source / Python / Capsule / GenerateCapsule.py
diff --git a/BaseTools/Source/Python/Capsule/GenerateCapsule.py b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
new file mode 100644 (file)
index 0000000..4018dc0
--- /dev/null
@@ -0,0 +1,522 @@
+## @file\r
+# Generate a capsule.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+GenerateCapsule\r
+'''\r
+\r
+import sys\r
+import argparse\r
+import uuid\r
+import struct\r
+import subprocess\r
+import os\r
+import tempfile\r
+import shutil\r
+import platform\r
+from Common.Uefi.Capsule.UefiCapsuleHeader import UefiCapsuleHeaderClass\r
+from Common.Uefi.Capsule.FmpCapsuleHeader  import FmpCapsuleHeaderClass\r
+from Common.Uefi.Capsule.FmpAuthHeader     import FmpAuthHeaderClass\r
+from Common.Edk2.Capsule.FmpPayloadHeader  import FmpPayloadHeaderClass\r
+\r
+#\r
+# Globals for help information\r
+#\r
+__prog__        = 'GenerateCapsule'\r
+__version__     = '0.9'\r
+__copyright__   = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r
+__description__ = 'Generate a capsule.\n'\r
+\r
+def SignPayloadSignTool (Payload, ToolPath, PfxFile):\r
+    #\r
+    # Create a temporary directory\r
+    #\r
+    TempDirectoryName = tempfile.mkdtemp()\r
+\r
+    #\r
+    # Generate temp file name for the payload contents\r
+    #\r
+    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r
+\r
+    #\r
+    # Create temporary payload file for signing\r
+    #\r
+    try:\r
+        File = open (TempFileName, mode='wb')\r
+        File.write (Payload)\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r
+\r
+    #\r
+    # Build signtool command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'signtool.exe'))\r
+    Command = Command + 'sign /fd sha256 /p7ce DetachedSignedData /p7co 1.2.840.113549.1.7.2 '\r
+    Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)\r
+    Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)\r
+    Command = Command + TempFileName\r
+\r
+    #\r
+    # Sign the input file using the specified private key\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate('')\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not run signtool.')\r
+\r
+    if Process.returncode != 0:\r
+        shutil.rmtree (TempDirectoryName)\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: signtool failed.')\r
+\r
+    #\r
+    # Read the signature from the generated output file\r
+    #\r
+    try:\r
+        File = open (TempFileName + '.p7', mode='rb')\r
+        Signature = File.read ()\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not read signature file.')\r
+\r
+    shutil.rmtree (TempDirectoryName)\r
+    return Signature\r
+\r
+def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):\r
+    print ('signtool verify is not supported.')\r
+    raise ValueError ('GenerateCapsule: error: signtool verify is not supported.')\r
+\r
+def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r
+    #\r
+    # Build openssl command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r
+    Command = Command + 'smime -sign -binary -outform DER -md sha256 '\r
+    Command = Command + '-signer "{Private}" -certfile "{Public}"'.format (Private = SignerPrivateCertFile, Public = OtherPublicCertFile)\r
+\r
+    #\r
+    # Sign the input file using the specified private key and capture signature from STDOUT\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate(input = Payload)\r
+        Signature = Result[0]\r
+    except:\r
+        raise ValueError ('GenerateCapsule: error: can not run openssl.')\r
+\r
+    if Process.returncode != 0:\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: openssl failed.')\r
+\r
+    return Signature\r
+\r
+def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r
+    #\r
+    # Create a temporary directory\r
+    #\r
+    TempDirectoryName = tempfile.mkdtemp()\r
+\r
+    #\r
+    # Generate temp file name for the payload contents\r
+    #\r
+    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r
+\r
+    #\r
+    # Create temporary payload file for verification\r
+    #\r
+    try:\r
+        File = open (TempFileName, mode='wb')\r
+        File.write (Payload)\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r
+\r
+    #\r
+    # Build openssl command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r
+    Command = Command + 'smime -verify -inform DER '\r
+    Command = Command + '-content {Content} -CAfile "{Public}"'.format (Content = TempFileName, Public = TrustedPublicCertFile)\r
+\r
+    #\r
+    # Verify signature\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate(input = CertData)\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not run openssl.')\r
+\r
+    if Process.returncode != 0:\r
+        shutil.rmtree (TempDirectoryName)\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: openssl failed.')\r
+\r
+    shutil.rmtree (TempDirectoryName)\r
+    return Payload\r
+\r
+if __name__ == '__main__':\r
+    def convert_arg_line_to_args(arg_line):\r
+        for arg in arg_line.split():\r
+            if not arg.strip():\r
+                continue\r
+            yield arg\r
+\r
+    def ValidateUnsignedInteger (Argument):\r
+        try:\r
+            Value = int (Argument, 0)\r
+        except:\r
+            Message = '{Argument} is not a valid integer value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        if Value < 0:\r
+            Message = '{Argument} is a negative value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        return Value\r
+\r
+    def ValidateRegistryFormatGuid (Argument):\r
+        try:\r
+            Value = uuid.UUID (Argument)\r
+        except:\r
+            Message = '{Argument} is not a valid registry format GUID value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        return Value\r
+\r
+    #\r
+    # Create command line argument parser object\r
+    #\r
+    parser = argparse.ArgumentParser (\r
+                        prog = __prog__,\r
+                        description = __description__ + __copyright__,\r
+                        conflict_handler = 'resolve',\r
+                        fromfile_prefix_chars = '@'\r
+                        )\r
+    parser.convert_arg_line_to_args = convert_arg_line_to_args\r
+\r
+    #\r
+    # Add input and output file arguments\r
+    #\r
+    parser.add_argument("InputFile",  type = argparse.FileType('rb'),\r
+                        help = "Input binary payload filename.")\r
+    parser.add_argument("-o", "--output", dest = 'OutputFile', type = argparse.FileType('wb'),\r
+                        help = "Output filename.")\r
+    #\r
+    # Add group for -e and -d flags that are mutually exclusive and required\r
+    #\r
+    group = parser.add_mutually_exclusive_group (required = True)\r
+    group.add_argument ("-e", "--encode", dest = 'Encode', action = "store_true",\r
+                        help = "Encode file")\r
+    group.add_argument ("-d", "--decode", dest = 'Decode', action = "store_true",\r
+                        help = "Decode file")\r
+    group.add_argument ("--dump-info", dest = 'DumpInfo', action = "store_true",\r
+                        help = "Display FMP Payload Header information")\r
+    #\r
+    # Add optional arguments for this command\r
+    #\r
+    parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],\r
+                         choices=['PersistAcrossReset', 'PopulateSystemTable', 'InitiateReset'],\r
+                         help = "Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set")\r
+    parser.add_argument ("--capoemflag", dest = 'CapsuleOemFlag', type = ValidateUnsignedInteger, default = 0x0000,\r
+                         help = "Capsule OEM Flag is an integer between 0x0000 and 0xffff.")\r
+\r
+    parser.add_argument ("--guid", dest = 'Guid', type = ValidateRegistryFormatGuid,\r
+                         help = "The FMP/ESRT GUID in registry format.  Required for encode operations.")\r
+    parser.add_argument ("--hardware-instance", dest = 'HardwareInstance', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r
+                         help = "The 64-bit hardware instance.  The default is 0x0000000000000000")\r
+\r
+\r
+    parser.add_argument ("--monotonic-count", dest = 'MonotonicCount', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r
+                         help = "64-bit monotonic count value in header.  Default is 0x0000000000000000.")\r
+\r
+    parser.add_argument ("--fw-version", dest = 'FwVersion', type = ValidateUnsignedInteger,\r
+                         help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678).")\r
+    parser.add_argument ("--lsv", dest = 'LowestSupportedVersion', type = ValidateUnsignedInteger,\r
+                         help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678).")\r
+\r
+    parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),\r
+                         help="signtool PFX certificate filename.")\r
+\r
+    parser.add_argument ("--signer-private-cert", dest='OpenSslSignerPrivateCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL signer private certificate filename.")\r
+    parser.add_argument ("--other-public-cert", dest='OpenSslOtherPublicCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL other public certificate filename.")\r
+    parser.add_argument ("--trusted-public-cert", dest='OpenSslTrustedPublicCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL trusted public certificate filename.")\r
+\r
+    parser.add_argument ("--signing-tool-path", dest = 'SigningToolPath',\r
+                         help = "Path to signtool or OpenSSL tool.  Optional if path to tools are already in PATH.")\r
+\r
+    #\r
+    # Add optional arguments common to all operations\r
+    #\r
+    parser.add_argument ('--version', action='version', version='%(prog)s ' + __version__)\r
+    parser.add_argument ("-v", "--verbose", dest = 'Verbose', action = "store_true",\r
+                         help = "Turn on verbose output with informational messages printed, including capsule headers and warning messages.")\r
+    parser.add_argument ("-q", "--quiet", dest = 'Quiet', action = "store_true",\r
+                         help = "Disable all messages except fatal errors.")\r
+    parser.add_argument ("--debug", dest = 'Debug', type = int, metavar = '[0-9]', choices = range (0, 10), default = 0,\r
+                         help = "Set debug level")\r
+\r
+    #\r
+    # Parse command line arguments\r
+    #\r
+    args = parser.parse_args()\r
+\r
+    #\r
+    # Perform additional argument verification\r
+    #\r
+    if args.Encode:\r
+        if args.Guid is None:\r
+            parser.error ('the following option is required: --guid')\r
+        if 'PersistAcrossReset' not in args.CapsuleFlag:\r
+            if 'PopulateSystemTable' in args.CapsuleFlag:\r
+                parser.error ('--capflag PopulateSystemTable also requires --capflag PersistAcrossReset')\r
+            if 'InitiateReset' in args.CapsuleFlag:\r
+                parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r
+\r
+    UseSignTool = args.SignToolPfxFile is not None\r
+    UseOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None and\r
+                   args.OpenSslOtherPublicCertFile is not None and\r
+                   args.OpenSslTrustedPublicCertFile is not None)\r
+    AnyOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None or\r
+                   args.OpenSslOtherPublicCertFile is not None or\r
+                   args.OpenSslTrustedPublicCertFile is not None)\r
+    if args.Encode or args.Decode:\r
+        if args.OutputFile is None:\r
+            parser.error ('the following option is required for all encode and decode operations: --output')\r
+\r
+        if UseSignTool and AnyOpenSsl:\r
+            parser.error ('Providing both signtool and OpenSSL options is not supported')\r
+        if not UseSignTool and not UseOpenSsl and AnyOpenSsl:\r
+            parser.error ('all the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')\r
+        if UseSignTool and platform.system() != 'Windows':\r
+            parser.error ('Use of signtool is not supported on this operating system.')\r
+        if args.Encode and (UseSignTool or UseOpenSsl):\r
+            if args.FwVersion is None or args.LowestSupportedVersion is None:\r
+                parser.error ('the following options are required: --fw-version, --lsv')\r
+\r
+        if UseSignTool:\r
+            args.SignToolPfxFile.close()\r
+            args.SignToolPfxFile = args.SignToolPfxFile.name\r
+        if UseOpenSsl:\r
+            args.OpenSslSignerPrivateCertFile.close()\r
+            args.OpenSslOtherPublicCertFile.close()\r
+            args.OpenSslTrustedPublicCertFile.close()\r
+            args.OpenSslSignerPrivateCertFile = args.OpenSslSignerPrivateCertFile.name\r
+            args.OpenSslOtherPublicCertFile   = args.OpenSslOtherPublicCertFile.name\r
+            args.OpenSslTrustedPublicCertFile = args.OpenSslTrustedPublicCertFile.name\r
+\r
+    #\r
+    # Read binary input file\r
+    #\r
+    try:\r
+        if args.Verbose:\r
+            print ('Read binary input file {File}'.format (File = args.InputFile.name))\r
+        Buffer = args.InputFile.read ()\r
+        args.InputFile.close ()\r
+    except:\r
+        print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = args.InputFile.name))\r
+        sys.exit (1)\r
+\r
+    #\r
+    # Create objects\r
+    #\r
+    UefiCapsuleHeader = UefiCapsuleHeaderClass ()\r
+    FmpCapsuleHeader  = FmpCapsuleHeaderClass ()\r
+    FmpAuthHeader     = FmpAuthHeaderClass ()\r
+    FmpPayloadHeader  = FmpPayloadHeaderClass ()\r
+\r
+    if args.Encode:\r
+        Result = Buffer\r
+        if UseSignTool or UseOpenSsl:\r
+            try:\r
+                FmpPayloadHeader.FwVersion              = args.FwVersion\r
+                FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion\r
+                FmpPayloadHeader.Payload                = Result\r
+                Result = FmpPayloadHeader.Encode ()\r
+                if args.Verbose:\r
+                    FmpPayloadHeader.DumpInfo ()\r
+            except:\r
+                print ('GenerateCapsule: error: can not encode FMP Payload Header')\r
+                sys.exit (1)\r
+\r
+            #\r
+            # Sign image with 64-bit MonotonicCount appended to end of image\r
+            #\r
+            try:\r
+                if UseSignTool:\r
+                    CertData = SignPayloadSignTool (\r
+                                 Result + struct.pack ('<Q', args.MonotonicCount),\r
+                                 args.SigningToolPath,\r
+                                 args.SignToolPfxFile\r
+                                 )\r
+                else:\r
+                    CertData = SignPayloadOpenSsl (\r
+                                 Result + struct.pack ('<Q', args.MonotonicCount),\r
+                                 args.SigningToolPath,\r
+                                 args.OpenSslSignerPrivateCertFile,\r
+                                 args.OpenSslOtherPublicCertFile,\r
+                                 args.OpenSslTrustedPublicCertFile\r
+                                 )\r
+            except:\r
+                print ('GenerateCapsule: error: can not sign payload')\r
+                raise\r
+                sys.exit (1)\r
+\r
+            try:\r
+                FmpAuthHeader.MonotonicCount = args.MonotonicCount\r
+                FmpAuthHeader.CertData       = CertData\r
+                FmpAuthHeader.Payload        = Result\r
+                Result = FmpAuthHeader.Encode ()\r
+                if args.Verbose:\r
+                    FmpAuthHeader.DumpInfo ()\r
+            except:\r
+                print ('GenerateCapsule: error: can not encode FMP Auth Header')\r
+                sys.exit (1)\r
+\r
+        try:\r
+            FmpCapsuleHeader.AddPayload (args.Guid, Result, HardwareInstance = args.HardwareInstance)\r
+            Result = FmpCapsuleHeader.Encode ()\r
+            if args.Verbose:\r
+                FmpCapsuleHeader.DumpInfo ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not encode FMP Capsule Header')\r
+            sys.exit (1)\r
+\r
+        try:\r
+            UefiCapsuleHeader.OemFlags            = args.CapsuleOemFlag\r
+            UefiCapsuleHeader.PersistAcrossReset  = 'PersistAcrossReset'  in args.CapsuleFlag\r
+            UefiCapsuleHeader.PopulateSystemTable = 'PopulateSystemTable' in args.CapsuleFlag\r
+            UefiCapsuleHeader.InitiateReset       = 'InitiateReset'       in args.CapsuleFlag\r
+            UefiCapsuleHeader.Payload             = Result\r
+            Result = UefiCapsuleHeader.Encode ()\r
+            if args.Verbose:\r
+                UefiCapsuleHeader.DumpInfo ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not encode UEFI Capsule Header')\r
+            sys.exit (1)\r
+\r
+    elif args.Decode:\r
+        try:\r
+            Result = UefiCapsuleHeader.Decode (Buffer)\r
+            FmpCapsuleHeader.Decode (Result)\r
+            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+            if args.Verbose:\r
+                print ('========')\r
+                UefiCapsuleHeader.DumpInfo ()\r
+                print ('--------')\r
+                FmpCapsuleHeader.DumpInfo ()\r
+            if UseSignTool or UseOpenSsl:\r
+                Result = FmpAuthHeader.Decode (Result)\r
+\r
+                #\r
+                # Verify Image with 64-bit MonotonicCount appended to end of image\r
+                #\r
+                try:\r
+                  if UseSignTool:\r
+                      CertData = VerifyPayloadSignTool (\r
+                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+                                   FmpAuthHeader.CertData,\r
+                                   args.SigningToolPath,\r
+                                   args.SignToolPfxFile\r
+                                   )\r
+                  else:\r
+                      CertData = VerifyPayloadOpenSsl (\r
+                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+                                   FmpAuthHeader.CertData,\r
+                                   args.SigningToolPath,\r
+                                   args.OpenSslSignerPrivateCertFile,\r
+                                   args.OpenSslOtherPublicCertFile,\r
+                                   args.OpenSslTrustedPublicCertFile\r
+                                   )\r
+                except ValueError:\r
+                    print ('GenerateCapsule: warning: can not verify payload.')\r
+\r
+                Result = FmpPayloadHeader.Decode (Result)\r
+                if args.Verbose:\r
+                    print ('--------')\r
+                    FmpAuthHeader.DumpInfo ()\r
+                    print ('--------')\r
+                    FmpPayloadHeader.DumpInfo ()\r
+            else:\r
+                if args.Verbose:\r
+                    print ('--------')\r
+                    print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+                    print ('--------')\r
+                    print ('No FMP_PAYLOAD_HEADER')\r
+            if args.Verbose:\r
+                print ('========')\r
+        except:\r
+            print ('GenerateCapsule: error: can not decode capsule')\r
+            raise\r
+            sys.exit (1)\r
+\r
+    elif args.DumpInfo:\r
+        try:\r
+            Result = UefiCapsuleHeader.Decode (Buffer)\r
+            FmpCapsuleHeader.Decode (Result)\r
+            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+            print ('========')\r
+            UefiCapsuleHeader.DumpInfo ()\r
+            print ('--------')\r
+            FmpCapsuleHeader.DumpInfo ()\r
+            try:\r
+                Result = FmpAuthHeader.Decode (Result)\r
+                Result = FmpPayloadHeader.Decode (Result)\r
+                print ('--------')\r
+                FmpAuthHeader.DumpInfo ()\r
+                print ('--------')\r
+                FmpPayloadHeader.DumpInfo ()\r
+            except:\r
+                print ('--------')\r
+                print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+                print ('--------')\r
+                print ('No FMP_PAYLOAD_HEADER')\r
+            print ('========')\r
+        except:\r
+            print ('GenerateCapsule: error: can not decode capsule')\r
+            sys.exit (1)\r
+    else:\r
+        print('GenerateCapsule: error: invalid options')\r
+        sys.exit (1)\r
+\r
+    #\r
+    # Write binary output file\r
+    #\r
+    if args.OutputFile is not None:\r
+        try:\r
+            if args.Verbose:\r
+                print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r
+            args.OutputFile.write (Result)\r
+            args.OutputFile.close ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))\r
+            sys.exit (1)\r
+\r
+    if args.Verbose:\r
+        print('Success')\r