public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC 0/1] Add Capsule Generation Tools
@ 2018-05-29 22:56 Michael D Kinney
  2018-05-29 22:56 ` [RFC 1/1] BaseTools/Capsule: " Michael D Kinney
  0 siblings, 1 reply; 4+ messages in thread
From: Michael D Kinney @ 2018-05-29 22:56 UTC (permalink / raw)
  To: edk2-devel; +Cc: Sean Brogan, Jiewen Yao, Yonghong Zhu, Liming Gao

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

Command line unit tests for python modules available from following branch:

https://github.com/mdkinney/edk2/tree/Bug_945_StandAloneCapsuleTools_V2

https://github.com/mdkinney/edk2/tree/Bug_945_StandAloneCapsuleTools_V2/BaseToolsUnitTest

* 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]
                       [--version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION]
                       [--pfx-file SIGNTOOLPFXFILE]
                       [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE]
                       [--other-public-cert OPENSSLOTHERPUBLICCERTFILE]
                       [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE]
                       [--signing-tool-path SIGNINGTOOLPATH] [-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.
  --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 Open SLL tool. Optional if path to
                        tools are already in PATH.
  -v, --verbose         Increase output messages
  -q, --quiet           Reduce output messages
  --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>

Kinney, Michael D (1):
  BaseTools/Capsule: Add Capsule Generation Tools

 BaseTools/BinWrappers/PosixLike/GenerateCapsule    |  14 +
 .../BinWrappers/WindowsLike/GenerateCapsule.bat    |   1 +
 BaseTools/Source/Python/Capsule/GenerateCapsule.py | 500 +++++++++++++++++++++
 .../Python/Common/Edk2/Capsule/FmpPayloadHeader.py |  91 ++++
 .../Source/Python/Common/Edk2/Capsule/__init__.py  |  15 +
 BaseTools/Source/Python/Common/Edk2/__init__.py    |  15 +
 .../Python/Common/Uefi/Capsule/FmpAuthHeader.py    | 184 ++++++++
 .../Python/Common/Uefi/Capsule/FmpCapsuleHeader.py | 302 +++++++++++++
 .../Common/Uefi/Capsule/UefiCapsuleHeader.py       | 136 ++++++
 .../Source/Python/Common/Uefi/Capsule/__init__.py  |  15 +
 BaseTools/Source/Python/Common/Uefi/__init__.py    |  15 +
 11 files changed, 1288 insertions(+)
 create mode 100644 BaseTools/BinWrappers/PosixLike/GenerateCapsule
 create mode 100644 BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
 create mode 100644 BaseTools/Source/Python/Capsule/GenerateCapsule.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/__init__.py

-- 
2.14.2.windows.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 1/1] BaseTools/Capsule: Add Capsule Generation Tools
  2018-05-29 22:56 [RFC 0/1] Add Capsule Generation Tools Michael D Kinney
@ 2018-05-29 22:56 ` Michael D Kinney
  2018-05-31 14:25   ` Gao, Liming
  0 siblings, 1 reply; 4+ messages in thread
From: Michael D Kinney @ 2018-05-29 22:56 UTC (permalink / raw)
  To: edk2-devel
  Cc: Kinney, Michael D, Sean Brogan, Jiewen Yao, Yonghong Zhu,
	Liming Gao

From: "Kinney, Michael D" <michael.d.kinney@intel.com>

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]
                       [--version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION]
                       [--pfx-file SIGNTOOLPFXFILE]
                       [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE]
                       [--other-public-cert OPENSSLOTHERPUBLICCERTFILE]
                       [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE]
                       [--signing-tool-path SIGNINGTOOLPATH] [-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.
  --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 Open SLL tool. Optional if path to
                        tools are already in PATH.
  -v, --verbose         Increase output messages
  -q, --quiet           Reduce output messages
  --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>
---
 BaseTools/BinWrappers/PosixLike/GenerateCapsule    |  14 +
 .../BinWrappers/WindowsLike/GenerateCapsule.bat    |   1 +
 BaseTools/Source/Python/Capsule/GenerateCapsule.py | 500 +++++++++++++++++++++
 .../Python/Common/Edk2/Capsule/FmpPayloadHeader.py |  91 ++++
 .../Source/Python/Common/Edk2/Capsule/__init__.py  |  15 +
 BaseTools/Source/Python/Common/Edk2/__init__.py    |  15 +
 .../Python/Common/Uefi/Capsule/FmpAuthHeader.py    | 184 ++++++++
 .../Python/Common/Uefi/Capsule/FmpCapsuleHeader.py | 302 +++++++++++++
 .../Common/Uefi/Capsule/UefiCapsuleHeader.py       | 136 ++++++
 .../Source/Python/Common/Uefi/Capsule/__init__.py  |  15 +
 BaseTools/Source/Python/Common/Uefi/__init__.py    |  15 +
 11 files changed, 1288 insertions(+)
 create mode 100644 BaseTools/BinWrappers/PosixLike/GenerateCapsule
 create mode 100644 BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
 create mode 100644 BaseTools/Source/Python/Capsule/GenerateCapsule.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Edk2/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
 create mode 100644 BaseTools/Source/Python/Common/Uefi/__init__.py

diff --git a/BaseTools/BinWrappers/PosixLike/GenerateCapsule b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
new file mode 100644
index 0000000000..59a6c8ba43
--- /dev/null
+++ b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a python2 command is available, use it in preference to python
+if command -v python2 >/dev/null 2>&1; then
+    python_exe=python2
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+dir=$(dirname "$full_cmd")
+cmd=${full_cmd##*/}
+
+export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
+exec "${python_exe:-python}" "$dir/../../Source/Python/Capsule/$cmd.py" "$@"
diff --git a/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
new file mode 100644
index 0000000000..ca442d181b
--- /dev/null
+++ b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
@@ -0,0 +1 @@
+@%PYTHON_HOME%\python.exe %BASE_TOOLS_PATH%\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
index 0000000000..32ab95c3e0
--- /dev/null
+++ b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
@@ -0,0 +1,500 @@
+## @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
+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'
+__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 ("--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 Open SLL tool.  Optional if path to tools are already in PATH.")
+
+    #
+    # Add optional arguments common to all commands
+    #
+    parser.add_argument("-v", "--verbose", dest = 'Verbose', action = "store_true",
+                        help = "Increase output messages")
+    parser.add_argument("-q", "--quiet", dest = 'Quiet', action = "store_true",
+                        help = "Reduce output messages")
+    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 not args.DumpInfo and args.OutputFile is None:
+        parser.error ('the following arguments are required for all commands except --dump-info: --output')
+
+    if args.Encode and (args.Guid is None or args.FwVersion is None or args.LowestSupportedVersion is None):
+        parser.error ('the following arguments are required: --version, --lsv, --guid')
+
+    if not args.DumpInfo and not args.OutputFile:
+        parser.error ('the following arguments are required: --output')
+
+    if not args.DumpInfo:
+        if args.SignToolPfxFile is None and args.OpenSslSignerPrivateCertFile is None and args.OpenSslOtherPublicCertFile is None and args.OpenSslTrustedPublicCertFile is None:
+            parser.error ('certificate file arguments are required: --pfx-file | [--signer-private-cert --other-public-cert --trusted-public-cert]')
+
+    if args.SignToolPfxFile is not None:
+        if args.OpenSslSignerPrivateCertFile is not None:
+            parser.error ('Providing both signtool and OpenSSL options is not supported')
+        if args.OpenSslOtherPublicCertFile is not None:
+            parser.error ('Providing both signtool and OpenSSL options is not supported')
+        if args.OpenSslTrustedPublicCertFile is not None:
+            parser.error ('Providing both signtool and OpenSSL options is not supported')
+        args.SignToolPfxFile.close()
+        args.SignToolPfxFile = args.SignToolPfxFile.name
+
+    if not args.DumpInfo:
+        if args.SignToolPfxFile is None:
+            if args.OpenSslSignerPrivateCertFile is None:
+                parser.error ('the following arguments are required: --signer-private-cert')
+            if args.OpenSslOtherPublicCertFile is None:
+                parser.error ('the following arguments are required: --other-public-cert')
+            if args.OpenSslTrustedPublicCertFile is None:
+                parser.error ('the following arguments are required: --trusted-public-cert')
+            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:
+        try:
+            FmpPayloadHeader.FwVersion              = args.FwVersion
+            FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion
+            FmpPayloadHeader.Payload                = Buffer
+            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 args.SignToolPfxFile is not None:
+              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
+            Result = FmpAuthHeader.Decode (Result)
+
+            #
+            # Verify Image with 64-bit MonotonicCount appended to end of image
+            #
+            try:
+              if args.SignToolPfxFile is not None:
+                  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 ('========')
+                UefiCapsuleHeader.DumpInfo ()
+                print ('--------')
+                FmpCapsuleHeader.DumpInfo ()
+                print ('--------')
+                FmpAuthHeader.DumpInfo ()
+                print ('--------')
+                FmpPayloadHeader.DumpInfo ()
+                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
+            Result = FmpAuthHeader.Decode (Result)
+            Result = FmpPayloadHeader.Decode (Result)
+
+            print ('========')
+            UefiCapsuleHeader.DumpInfo ()
+            print ('--------')
+            FmpCapsuleHeader.DumpInfo ()
+            print ('--------')
+            FmpAuthHeader.DumpInfo ()
+            print ('--------')
+            FmpPayloadHeader.DumpInfo ()
+            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')
diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
new file mode 100644
index 0000000000..0ed51752d3
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
@@ -0,0 +1,91 @@
+## @file
+# Module that encodes and decodes a FMP_PAYLOAD_HEADER with a payload.
+# The FMP_PAYLOAD_HEADER is processed by the FmpPayloadHeaderLib in the
+# FmpDevicePkg.
+#
+# 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.
+#
+
+'''
+FmpPayloadHeader
+'''
+
+import struct
+
+def _SIGNATURE_32 (A, B, C, D):
+    return struct.unpack ('=I',bytearray (A + B + C + D, 'ascii'))[0]
+
+def _SIGNATURE_32_TO_STRING (Signature):
+    return struct.pack ("<I", Signature).decode ()
+
+class FmpPayloadHeaderClass (object):
+    #
+    # typedef struct {
+    #   UINT32  Signature;
+    #   UINT32  HeaderSize;
+    #   UINT32  FwVersion;
+    #   UINT32  LowestSupportedVersion;
+    # } FMP_PAYLOAD_HEADER;
+    #
+    # #define FMP_PAYLOAD_HEADER_SIGNATURE SIGNATURE_32 ('M', 'S', 'S', '1')
+    #
+    _StructFormat = '<IIII'
+    _StructSize   = struct.calcsize (_StructFormat)
+
+    _FMP_PAYLOAD_HEADER_SIGNATURE = _SIGNATURE_32 ('M', 'S', 'S', '1')
+
+    def __init__ (self):
+        self._Valid                 = False
+        self.Signature              = self._FMP_PAYLOAD_HEADER_SIGNATURE
+        self.HeaderSize             = self._StructSize
+        self.FwVersion              = 0x00000000
+        self.LowestSupportedVersion = 0x00000000
+        self.Payload                = b''
+
+    def Encode (self):
+        FmpPayloadHeader = struct.pack (
+                                     self._StructFormat,
+                                     self.Signature,
+                                     self.HeaderSize,
+                                     self.FwVersion,
+                                     self.LowestSupportedVersion
+                                     )
+        self._Valid = True
+        return FmpPayloadHeader + self.Payload
+
+    def Decode (self, Buffer):
+        if len (Buffer) < self._StructSize:
+            raise ValueError
+        (Signature, HeaderSize, FwVersion, LowestSupportedVersion) = \
+            struct.unpack (
+                     self._StructFormat,
+                     Buffer[0:self._StructSize]
+                     )
+        if Signature != self._FMP_PAYLOAD_HEADER_SIGNATURE:
+            raise ValueError
+        if HeaderSize < self._StructSize:
+            raise ValueError
+        self.Signature              = Signature
+        self.HeaderSize             = HeaderSize
+        self.FwVersion              = FwVersion
+        self.LowestSupportedVersion = LowestSupportedVersion
+        self.Payload                = Buffer[self.HeaderSize:]
+
+        self._Valid                 = True
+        return self.Payload
+
+    def DumpInfo (self):
+        if not self._Valid:
+            raise ValueError
+        print ('FMP_PAYLOAD_HEADER.Signature              = {Signature:08X} ({SignatureString})'.format (Signature = self.Signature, SignatureString = _SIGNATURE_32_TO_STRING (self.Signature)))
+        print ('FMP_PAYLOAD_HEADER.HeaderSize             = {HeaderSize:08X}'.format (HeaderSize = self.HeaderSize))
+        print ('FMP_PAYLOAD_HEADER.FwVersion              = {FwVersion:08X}'.format (FwVersion = self.FwVersion))
+        print ('FMP_PAYLOAD_HEADER.LowestSupportedVersion = {LowestSupportedVersion:08X}'.format (LowestSupportedVersion = self.LowestSupportedVersion))
+        print ('sizeof (Payload)                          = {Size:08X}'.format (Size = len (self.Payload)))
diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
new file mode 100644
index 0000000000..71c6f06838
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
@@ -0,0 +1,15 @@
+## @file
+# Python 'Common.Edk2.Capsule' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# 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.
+#
diff --git a/BaseTools/Source/Python/Common/Edk2/__init__.py b/BaseTools/Source/Python/Common/Edk2/__init__.py
new file mode 100644
index 0000000000..97d925cbf8
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Edk2/__init__.py
@@ -0,0 +1,15 @@
+## @file
+# Python 'Common.Edk2' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# 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.
+#
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
new file mode 100644
index 0000000000..aec52bf772
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
@@ -0,0 +1,184 @@
+## @file
+# Module that encodes and decodes a EFI_FIRMWARE_IMAGE_AUTHENTICATION with
+# certificate data and payload data.
+#
+# 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.
+#
+
+'''
+FmpAuthHeader
+'''
+
+import struct
+import uuid
+
+class FmpAuthHeaderClass (object):
+    # ///
+    # /// Image Attribute -Authentication Required
+    # ///
+    # typedef struct {
+    #   ///
+    #   /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay.
+    #   /// It is incremented during each firmware image operation.
+    #   ///
+    #   UINT64                                  MonotonicCount;
+    #   ///
+    #   /// Provides the authorization for the firmware image operations. It is a signature across
+    #   /// the image data and the Monotonic Count value. Caller uses the private key that is
+    #   /// associated with a public key that has been provisioned via the key exchange.
+    #   /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must
+    #   /// be EFI_CERT_TYPE_PKCS7_GUID.
+    #   ///
+    #   WIN_CERTIFICATE_UEFI_GUID               AuthInfo;
+    # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
+    #
+    # ///
+    # /// Certificate which encapsulates a GUID-specific digital signature
+    # ///
+    # typedef struct {
+    #   ///
+    #   /// This is the standard WIN_CERTIFICATE header, where
+    #   /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.
+    #   ///
+    #   WIN_CERTIFICATE   Hdr;
+    #   ///
+    #   /// This is the unique id which determines the
+    #   /// format of the CertData. .
+    #   ///
+    #   EFI_GUID          CertType;
+    #   ///
+    #   /// The following is the certificate data. The format of
+    #   /// the data is determined by the CertType.
+    #   /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
+    #   /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
+    #   ///
+    #   UINT8            CertData[1];
+    # } WIN_CERTIFICATE_UEFI_GUID;
+    #
+    # ///
+    # /// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
+    # ///
+    # typedef struct {
+    #   ///
+    #   /// The length of the entire certificate,
+    #   /// including the length of the header, in bytes.
+    #   ///
+    #   UINT32  dwLength;
+    #   ///
+    #   /// The revision level of the WIN_CERTIFICATE
+    #   /// structure. The current revision level is 0x0200.
+    #   ///
+    #   UINT16  wRevision;
+    #   ///
+    #   /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
+    #   /// certificate types. The UEFI specification reserves the range of
+    #   /// certificate type values from 0x0EF0 to 0x0EFF.
+    #   ///
+    #   UINT16  wCertificateType;
+    #   ///
+    #   /// The following is the actual certificate. The format of
+    #   /// the certificate depends on wCertificateType.
+    #   ///
+    #   /// UINT8 bCertificate[ANYSIZE_ARRAY];
+    #   ///
+    # } WIN_CERTIFICATE;
+    #
+    # #define WIN_CERT_TYPE_EFI_GUID         0x0EF1
+    #
+    # ///
+    # /// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]
+    # /// SignedData value.
+    # ///
+    # #define EFI_CERT_TYPE_PKCS7_GUID \
+    #   { \
+    #     0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
+    #   }
+
+    _StructFormat = '<QIHH16s'
+    _StructSize   = struct.calcsize (_StructFormat)
+
+    _MonotonicCountFormat = '<Q'
+    _MonotonicCountSize   = struct.calcsize (_MonotonicCountFormat)
+
+    _StructAuthInfoFormat = '<IHH16s'
+    _StructAuthInfoSize   = struct.calcsize (_StructAuthInfoFormat)
+
+    _WIN_CERT_REVISION        = 0x0200
+    _WIN_CERT_TYPE_EFI_GUID   = 0x0EF1
+    _EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-68df-49ee-8aa9-347d375665a7')
+
+    def __init__ (self):
+        self._Valid              = False
+        self.MonotonicCount      = 0
+        self.dwLength            = self._StructAuthInfoSize
+        self.wRevision           = self._WIN_CERT_REVISION
+        self.wCertificateType    = self._WIN_CERT_TYPE_EFI_GUID
+        self.CertType            = self._EFI_CERT_TYPE_PKCS7_GUID
+        self.CertData            = b''
+        self.Payload             = b''
+
+
+    def Encode (self):
+        if self.wRevision != self._WIN_CERT_REVISION:
+            raise ValueError
+        if self.wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
+            raise ValueError
+        if self.CertType != self._EFI_CERT_TYPE_PKCS7_GUID:
+            raise ValueError
+        self.dwLength = self._StructAuthInfoSize + len (self.CertData)
+
+        FmpAuthHeader = struct.pack (
+                                 self._StructFormat,
+                                 self.MonotonicCount,
+                                 self.dwLength,
+                                 self.wRevision,
+                                 self.wCertificateType,
+                                 self.CertType.bytes_le
+                                 )
+        self._Valid = True
+
+        return FmpAuthHeader + self.CertData + self.Payload
+
+    def Decode (self, Buffer):
+        if len (Buffer) < self._StructSize:
+            raise ValueError
+        (MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \
+            struct.unpack (
+                     self._StructFormat,
+                     Buffer[0:self._StructSize]
+                     )
+        if dwLength < self._StructAuthInfoSize:
+            raise ValueError
+        if wRevision != self._WIN_CERT_REVISION:
+            raise ValueError
+        if wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
+            raise ValueError
+        if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le:
+            raise ValueError
+        self.MonotonicCount   = MonotonicCount
+        self.dwLength         = dwLength
+        self.wRevision        = wRevision
+        self.wCertificateType = wCertificateType
+        self.CertType         = uuid.UUID (bytes = CertType)
+        self.CertData         = Buffer[self._StructSize:self._MonotonicCountSize + self.dwLength]
+        self.Payload          = Buffer[self._MonotonicCountSize + self.dwLength:]
+        self._Valid           = True
+        return self.Payload
+
+    def DumpInfo (self):
+        if not self._Valid:
+            raise ValueError
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount                = {MonotonicCount:016X}'.format (MonotonicCount = self.MonotonicCount))
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength         = {dwLength:08X}'.format (dwLength = self.dwLength))
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision        = {wRevision:04X}'.format (wRevision = self.wRevision))
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType = {wCertificateType:04X}'.format (wCertificateType = self.wCertificateType))
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType             = {Guid}'.format (Guid = str(self.CertType).upper()))
+        print ('sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData)    = {Size:08X}'.format (Size = len (self.CertData)))
+        print ('sizeof (Payload)                                                = {Size:08X}'.format (Size = len (self.Payload)))
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
new file mode 100644
index 0000000000..2461fb5068
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
@@ -0,0 +1,302 @@
+## @file
+# Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
+# a payload.
+#
+# 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.
+#
+
+'''
+FmpCapsuleHeader
+'''
+
+import struct
+import uuid
+
+class FmpCapsuleImageHeaderClass (object):
+    # typedef struct {
+    #   UINT32   Version;
+    #
+    #   ///
+    #   /// Used to identify device firmware targeted by this update. This guid is matched by
+    #   /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR
+    #   ///
+    #   EFI_GUID UpdateImageTypeId;
+    #
+    #   ///
+    #   /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()
+    #   ///
+    #   UINT8    UpdateImageIndex;
+    #   UINT8    reserved_bytes[3];
+    #
+    #   ///
+    #   /// Size of the binary update image which immediately follows this structure
+    #   ///
+    #   UINT32   UpdateImageSize;
+    #
+    #   ///
+    #   /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule
+    #   ///
+    #   UINT32   UpdateVendorCodeSize;
+    #
+    #   ///
+    #   /// The HardwareInstance to target with this update. If value is zero it means match all
+    #   /// HardwareInstances. This field allows update software to target only a single device in
+    #   /// cases where there are more than one device with the same ImageTypeId GUID.
+    #   /// This header is outside the signed data of the Authentication Info structure and
+    #   /// therefore can be modified without changing the Auth data.
+    #   ///
+    #   UINT64   UpdateHardwareInstance;
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
+    #
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
+
+    _StructFormat = '<I16sB3BIIQ'
+    _StructSize   = struct.calcsize (_StructFormat)
+
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
+
+    def __init__ (self):
+        self._Valid                 = False
+        self.Version                = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
+        self.UpdateImageTypeId      = uuid.UUID ('00000000-0000-0000-0000-000000000000')
+        self.UpdateImageIndex       = 0
+        self.UpdateImageSize        = 0
+        self.UpdateVendorCodeSize   = 0
+        self.UpdateHardwareInstance = 0x0000000000000000
+        self.Payload                = b''
+        self.VendorCodeBytes        = b''
+
+    def Encode (self):
+        self.UpdateImageSize      = len (self.Payload)
+        self.UpdateVendorCodeSize = len (self.VendorCodeBytes)
+        FmpCapsuleImageHeader = struct.pack (
+                                         self._StructFormat,
+                                         self.Version,
+                                         self.UpdateImageTypeId.bytes_le,
+                                         self.UpdateImageIndex,
+                                         0,0,0,
+                                         self.UpdateImageSize,
+                                         self.UpdateVendorCodeSize,
+                                         self.UpdateHardwareInstance
+                                         )
+        self._Valid = True
+        return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
+
+    def Decode (self, Buffer):
+        if len (Buffer) < self._StructSize:
+            raise ValueError
+        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \
+            struct.unpack (
+                     self._StructFormat,
+                     Buffer[0:self._StructSize]
+                     )
+
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:
+            raise ValueError
+        if UpdateImageIndex < 1:
+            raise ValueError
+        if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):
+            raise ValueError
+
+        self.Version                = Version
+        self.UpdateImageTypeId      = uuid.UUID (bytes_le = UpdateImageTypeId)
+        self.UpdateImageIndex       = UpdateImageIndex
+        self.UpdateImageSize        = UpdateImageSize
+        self.UpdateVendorCodeSize   = UpdateVendorCodeSize
+        self.UpdateHardwareInstance = UpdateHardwareInstance
+        self.Payload                = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
+        self.VendorCodeBytes        = Buffer[self._StructSize + UpdateImageSize:]
+        self._Valid                 = True
+        return Buffer[self._StructSize:]
+
+    def DumpInfo (self):
+        if not self._Valid:
+            raise ValueError
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version                = {Version:08X}'.format (Version = self.Version))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId      = {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex       = {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize        = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize   = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
+        print ('sizeof (Payload)                                                    = {Size:08X}'.format (Size = len (self.Payload)))
+        print ('sizeof (VendorCodeBytes)                                            = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))
+
+class FmpCapsuleHeaderClass (object):
+    # typedef struct {
+    #   UINT32 Version;
+    #
+    #   ///
+    #   /// The number of drivers included in the capsule and the number of corresponding
+    #   /// offsets stored in ItemOffsetList array.
+    #   ///
+    #   UINT16 EmbeddedDriverCount;
+    #
+    #   ///
+    #   /// The number of payload items included in the capsule and the number of
+    #   /// corresponding offsets stored in the ItemOffsetList array.
+    #   ///
+    #   UINT16 PayloadItemCount;
+    #
+    #   ///
+    #   /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]
+    #   /// containing offsets of each of the drivers and payload items contained within the capsule
+    #   ///
+    #   // UINT64 ItemOffsetList[];
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
+    #
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION       0x00000001
+    _StructFormat = '<IHH'
+    _StructSize   = struct.calcsize (_StructFormat)
+
+    _ItemOffsetFormat = '<Q'
+    _ItemOffsetSize   = struct.calcsize (_ItemOffsetFormat)
+
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
+
+    def __init__ (self):
+        self._Valid                     = False
+        self.Version                    = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
+        self.EmbeddedDriverCount        = 0
+        self.PayloadItemCount           = 0
+        self._ItemOffsetList            = []
+        self._EmbeddedDriverList        = []
+        self._PayloadList               = []
+        self._FmpCapsuleImageHeaderList = []
+
+    def AddEmbeddedDriver (self, EmbeddedDriver):
+        self._EmbeddedDriverList.append (EmbeddedDriver)
+
+    def GetEmbeddedDriver (self, Index):
+        if Index > len (self._EmbeddedDriverList):
+            raise ValueError
+        return self._EmbeddedDriverList[Index]
+
+    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):
+        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))
+
+    def GetFmpCapsuleImageHeader (self, Index):
+        if Index >= len (self._FmpCapsuleImageHeaderList):
+            raise ValueError
+        return self._FmpCapsuleImageHeaderList[Index]
+
+    def Encode (self):
+        self.EmbeddedDriverCount = len (self._EmbeddedDriverList)
+        self.PayloadItemCount    = len (self._PayloadList)
+
+        FmpCapsuleHeader = struct.pack (
+                                    self._StructFormat,
+                                    self.Version,
+                                    self.EmbeddedDriverCount,
+                                    self.PayloadItemCount
+                                    )
+
+        FmpCapsuleData = b''
+        Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize
+        for EmbeddedDriver in self._EmbeddedDriverList:
+            FmpCapsuleData = FmpCapsuleData + EmbeddedDriver
+            self._ItemOffsetList.append (Offset)
+            Offset = Offset + len (EmbeddedDriver)
+        Index = 1
+        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
+            FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId
+            FmpCapsuleImageHeader.UpdateImageIndex       = Index
+            FmpCapsuleImageHeader.Payload                = Payload
+            FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes
+            FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
+            FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
+            FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
+
+            self._ItemOffsetList.append (Offset)
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
+
+            Offset = Offset + len (FmpCapsuleImage)
+            Index = Index + 1
+
+        for Offset in self._ItemOffsetList:
+          FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)
+
+        self._Valid = True
+        return FmpCapsuleHeader + FmpCapsuleData
+
+    def Decode (self, Buffer):
+        if len (Buffer) < self._StructSize:
+            raise ValueError
+        (Version, EmbeddedDriverCount, PayloadItemCount) = \
+            struct.unpack (
+                     self._StructFormat,
+                     Buffer[0:self._StructSize]
+                     )
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:
+            raise ValueError
+
+        self.Version                    = Version
+        self.EmbeddedDriverCount        = EmbeddedDriverCount
+        self.PayloadItemCount           = PayloadItemCount
+        self._ItemOffsetList            = []
+        self._EmbeddedDriverList        = []
+        self._PayloadList               = []
+        self._FmpCapsuleImageHeaderList = []
+
+        #
+        # Parse the ItemOffsetList values
+        #
+        Offset = self._StructSize
+        for Index in range (0, EmbeddedDriverCount + PayloadItemCount):
+            ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]
+            if ItemOffset >= len (Buffer):
+                raise ValueError
+            self._ItemOffsetList.append (ItemOffset)
+            Offset = Offset + self._ItemOffsetSize
+        Result = Buffer[Offset:]
+
+        #
+        # Parse the EmbeddedDrivers
+        #
+        for Index in range (0, EmbeddedDriverCount):
+            Offset = self._ItemOffsetList[Index]
+            if Index < (len (self._ItemOffsetList) - 1):
+                Length = self._ItemOffsetList[Index + 1] - Offset
+            else:
+                Length = len (Buffer) - Offset
+            self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])
+
+        #
+        # Parse the Payloads that are FMP Capsule Images
+        #
+        for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):
+            Offset = self._ItemOffsetList[Index]
+            if Index < (len (self._ItemOffsetList) - 1):
+                Length = self._ItemOffsetList[Index + 1] - Offset
+            else:
+                Length = len (Buffer) - Offset
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
+            FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])
+            self.AddPayload (
+                   FmpCapsuleImageHeader.UpdateImageTypeId,
+                   FmpCapsuleImageHeader.Payload,
+                   FmpCapsuleImageHeader.VendorCodeBytes
+                   )
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
+
+        self._Valid = True
+        return Result
+
+    def DumpInfo (self):
+        if not self._Valid:
+            raise ValueError
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version             = {Version:08X}'.format (Version = self.Version))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount    = {PayloadItemCount:08X}'.format (PayloadItemCount = self.PayloadItemCount))
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList      = ')
+        for Offset in self._ItemOffsetList:
+            print ('  {Offset:016X}'.format (Offset = Offset))
+        for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:
+            FmpCapsuleImageHeader.DumpInfo ()
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
new file mode 100644
index 0000000000..cfe1cb6c46
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
@@ -0,0 +1,136 @@
+## @file
+# Module that encodes and decodes a EFI_CAPSULE_HEADER with a payload
+#
+# 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.
+#
+
+'''
+UefiCapsuleHeader
+'''
+
+import struct
+import uuid
+
+class UefiCapsuleHeaderClass (object):
+    # typedef struct {
+    #   ///
+    #   /// A GUID that defines the contents of a capsule.
+    #   ///
+    #   EFI_GUID          CapsuleGuid;
+    #   ///
+    #   /// The size of the capsule header. This may be larger than the size of
+    #   /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply
+    #   /// extended header entries
+    #   ///
+    #   UINT32            HeaderSize;
+    #   ///
+    #   /// Bit-mapped list describing the capsule attributes. The Flag values
+    #   /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values
+    #   /// of 0x10000 - 0xFFFFFFFF are defined by this specification
+    #   ///
+    #   UINT32            Flags;
+    #   ///
+    #   /// Size in bytes of the capsule.
+    #   ///
+    #   UINT32            CapsuleImageSize;
+    # } EFI_CAPSULE_HEADER;
+    #
+    # #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET          0x00010000
+    # #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE         0x00020000
+    # #define CAPSULE_FLAGS_INITIATE_RESET                0x00040000
+    #
+    _StructFormat = '<16sIIII'
+    _StructSize   = struct.calcsize (_StructFormat)
+
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID = uuid.UUID ('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')
+
+    _CAPSULE_FLAGS_PERSIST_ACROSS_RESET  = 0x00010000
+    _CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000
+    _CAPSULE_FLAGS_INITIATE_RESET        = 0x00040000
+
+    def __init__ (self):
+        self._Valid              = False
+        self.CapsuleGuid         = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
+        self.HeaderSize          = self._StructSize
+        self.OemFlags            = 0x0000
+        self.PersistAcrossReset  = False
+        self.PopulateSystemTable = False
+        self.InitiateReset       = False
+        self.CapsuleImageSize    = self.HeaderSize
+        self.Payload             = b''
+
+    def Encode (self):
+        Flags = self.OemFlags
+        if self.PersistAcrossReset:
+            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+        if self.PopulateSystemTable:
+            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
+        if self.InitiateReset:
+            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
+
+        self.CapsuleImageSize = self.HeaderSize + len (self.Payload)
+
+        UefiCapsuleHeader = struct.pack (
+                                     self._StructFormat,
+                                     self.CapsuleGuid.bytes_le,
+                                     self.HeaderSize,
+                                     Flags,
+                                     self.CapsuleImageSize,
+                                     0
+                                     )
+        self._Valid = True
+        return UefiCapsuleHeader + self.Payload
+
+    def Decode (self, Buffer):
+        if len (Buffer) < self._StructSize:
+            raise ValueError
+        (CapsuleGuid, HeaderSize, Flags, CapsuleImageSize, Reserved) = \
+            struct.unpack (
+                     self._StructFormat,
+                     Buffer[0:self._StructSize]
+                     )
+        if HeaderSize < self._StructSize:
+            raise ValueError
+        if CapsuleImageSize != len (Buffer):
+            raise ValueError
+        self.CapsuleGuid         = uuid.UUID (bytes_le = CapsuleGuid)
+        self.HeaderSize          = HeaderSize
+        self.OemFlags            = Flags & 0xffff
+        self.PersistAcrossReset  = (Flags & self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0
+        self.PopulateSystemTable = (Flags & self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0
+        self.InitiateReset       = (Flags & self._CAPSULE_FLAGS_INITIATE_RESET) != 0
+        self.CapsuleImageSize    = CapsuleImageSize
+        self.Payload             = Buffer[self.HeaderSize:]
+
+        self._Valid              = True
+        return self.Payload
+
+    def DumpInfo (self):
+        if not self._Valid:
+            raise ValueError
+        Flags = self.OemFlags
+        if self.PersistAcrossReset:
+            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+        if self.PopulateSystemTable:
+            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
+        if self.InitiateReset:
+            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
+        print ('EFI_CAPSULE_HEADER.CapsuleGuid      = {Guid}'.format (Guid = str(self.CapsuleGuid).upper()))
+        print ('EFI_CAPSULE_HEADER.HeaderSize       = {Size:08X}'.format (Size = self.HeaderSize))
+        print ('EFI_CAPSULE_HEADER.Flags            = {Flags:08X}'.format (Flags = Flags))
+        print ('  OEM Flags                         = {Flags:04X}'.format (Flags = self.OemFlags))
+        if self.PersistAcrossReset:
+            print ('  CAPSULE_FLAGS_PERSIST_ACROSS_RESET')
+        if self.PopulateSystemTable:
+            print ('  CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE')
+        if self.InitiateReset:
+            print ('  CAPSULE_FLAGS_INITIATE_RESET')
+        print ('EFI_CAPSULE_HEADER.CapsuleImageSize = {Size:08X}'.format (Size = self.CapsuleImageSize))
+        print ('sizeof (Payload)                    = {Size:08X}'.format (Size = len (self.Payload)))
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
new file mode 100644
index 0000000000..d9db4aa919
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
@@ -0,0 +1,15 @@
+## @file
+# Python 'Common.Uefi.Capsule' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# 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.
+#
diff --git a/BaseTools/Source/Python/Common/Uefi/__init__.py b/BaseTools/Source/Python/Common/Uefi/__init__.py
new file mode 100644
index 0000000000..d80219dcb3
--- /dev/null
+++ b/BaseTools/Source/Python/Common/Uefi/__init__.py
@@ -0,0 +1,15 @@
+## @file
+# Python 'Common.Uefi' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# 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.
+#
-- 
2.14.2.windows.3



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC 1/1] BaseTools/Capsule: Add Capsule Generation Tools
  2018-05-29 22:56 ` [RFC 1/1] BaseTools/Capsule: " Michael D Kinney
@ 2018-05-31 14:25   ` Gao, Liming
  2018-05-31 16:36     ` Kinney, Michael D
  0 siblings, 1 reply; 4+ messages in thread
From: Gao, Liming @ 2018-05-31 14:25 UTC (permalink / raw)
  To: Kinney, Michael D, edk2-devel@lists.01.org
  Cc: Sean Brogan, Yao, Jiewen, Zhu, Yonghong

Mike:
  Which C tool is converted? Does it support all capsule generation functionality in GenFv tool? 
  
  And, GenFds has the logic to generate FMP capsule. Can they share same logic? 

Thanks
Liming
> -----Original Message-----
> From: Kinney, Michael D
> Sent: Wednesday, May 30, 2018 6:57 AM
> To: edk2-devel@lists.01.org
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Sean Brogan <sean.brogan@microsoft.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Zhu, Yonghong <yonghong.zhu@intel.com>; Gao, Liming <liming.gao@intel.com>
> Subject: [RFC 1/1] BaseTools/Capsule: Add Capsule Generation Tools
> 
> From: "Kinney, Michael D" <michael.d.kinney@intel.com>
> 
> 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]
>                        [--version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION]
>                        [--pfx-file SIGNTOOLPFXFILE]
>                        [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE]
>                        [--other-public-cert OPENSSLOTHERPUBLICCERTFILE]
>                        [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE]
>                        [--signing-tool-path SIGNINGTOOLPATH] [-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.
>   --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 Open SLL tool. Optional if path to
>                         tools are already in PATH.
>   -v, --verbose         Increase output messages
>   -q, --quiet           Reduce output messages
>   --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>
> ---
>  BaseTools/BinWrappers/PosixLike/GenerateCapsule    |  14 +
>  .../BinWrappers/WindowsLike/GenerateCapsule.bat    |   1 +
>  BaseTools/Source/Python/Capsule/GenerateCapsule.py | 500 +++++++++++++++++++++
>  .../Python/Common/Edk2/Capsule/FmpPayloadHeader.py |  91 ++++
>  .../Source/Python/Common/Edk2/Capsule/__init__.py  |  15 +
>  BaseTools/Source/Python/Common/Edk2/__init__.py    |  15 +
>  .../Python/Common/Uefi/Capsule/FmpAuthHeader.py    | 184 ++++++++
>  .../Python/Common/Uefi/Capsule/FmpCapsuleHeader.py | 302 +++++++++++++
>  .../Common/Uefi/Capsule/UefiCapsuleHeader.py       | 136 ++++++
>  .../Source/Python/Common/Uefi/Capsule/__init__.py  |  15 +
>  BaseTools/Source/Python/Common/Uefi/__init__.py    |  15 +
>  11 files changed, 1288 insertions(+)
>  create mode 100644 BaseTools/BinWrappers/PosixLike/GenerateCapsule
>  create mode 100644 BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
>  create mode 100644 BaseTools/Source/Python/Capsule/GenerateCapsule.py
>  create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
>  create mode 100644 BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
>  create mode 100644 BaseTools/Source/Python/Common/Edk2/__init__.py
>  create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
>  create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
>  create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
>  create mode 100644 BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
>  create mode 100644 BaseTools/Source/Python/Common/Uefi/__init__.py
> 
> diff --git a/BaseTools/BinWrappers/PosixLike/GenerateCapsule b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
> new file mode 100644
> index 0000000000..59a6c8ba43
> --- /dev/null
> +++ b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
> @@ -0,0 +1,14 @@
> +#!/usr/bin/env bash
> +#python `dirname $0`/RunToolFromSource.py `basename $0` $*
> +
> +# If a python2 command is available, use it in preference to python
> +if command -v python2 >/dev/null 2>&1; then
> +    python_exe=python2
> +fi
> +
> +full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
> +dir=$(dirname "$full_cmd")
> +cmd=${full_cmd##*/}
> +
> +export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
> +exec "${python_exe:-python}" "$dir/../../Source/Python/Capsule/$cmd.py" "$@"
> diff --git a/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> new file mode 100644
> index 0000000000..ca442d181b
> --- /dev/null
> +++ b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> @@ -0,0 +1 @@
> +@%PYTHON_HOME%\python.exe %BASE_TOOLS_PATH%\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
> index 0000000000..32ab95c3e0
> --- /dev/null
> +++ b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
> @@ -0,0 +1,500 @@
> +## @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
> +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'
> +__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 ("--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 Open SLL tool.  Optional if path to tools are already in PATH.")
> +
> +    #
> +    # Add optional arguments common to all commands
> +    #
> +    parser.add_argument("-v", "--verbose", dest = 'Verbose', action = "store_true",
> +                        help = "Increase output messages")
> +    parser.add_argument("-q", "--quiet", dest = 'Quiet', action = "store_true",
> +                        help = "Reduce output messages")
> +    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 not args.DumpInfo and args.OutputFile is None:
> +        parser.error ('the following arguments are required for all commands except --dump-info: --output')
> +
> +    if args.Encode and (args.Guid is None or args.FwVersion is None or args.LowestSupportedVersion is None):
> +        parser.error ('the following arguments are required: --version, --lsv, --guid')
> +
> +    if not args.DumpInfo and not args.OutputFile:
> +        parser.error ('the following arguments are required: --output')
> +
> +    if not args.DumpInfo:
> +        if args.SignToolPfxFile is None and args.OpenSslSignerPrivateCertFile is None and args.OpenSslOtherPublicCertFile is None
> and args.OpenSslTrustedPublicCertFile is None:
> +            parser.error ('certificate file arguments are required: --pfx-file | [--signer-private-cert --other-public-cert
> --trusted-public-cert]')
> +
> +    if args.SignToolPfxFile is not None:
> +        if args.OpenSslSignerPrivateCertFile is not None:
> +            parser.error ('Providing both signtool and OpenSSL options is not supported')
> +        if args.OpenSslOtherPublicCertFile is not None:
> +            parser.error ('Providing both signtool and OpenSSL options is not supported')
> +        if args.OpenSslTrustedPublicCertFile is not None:
> +            parser.error ('Providing both signtool and OpenSSL options is not supported')
> +        args.SignToolPfxFile.close()
> +        args.SignToolPfxFile = args.SignToolPfxFile.name
> +
> +    if not args.DumpInfo:
> +        if args.SignToolPfxFile is None:
> +            if args.OpenSslSignerPrivateCertFile is None:
> +                parser.error ('the following arguments are required: --signer-private-cert')
> +            if args.OpenSslOtherPublicCertFile is None:
> +                parser.error ('the following arguments are required: --other-public-cert')
> +            if args.OpenSslTrustedPublicCertFile is None:
> +                parser.error ('the following arguments are required: --trusted-public-cert')
> +            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:
> +        try:
> +            FmpPayloadHeader.FwVersion              = args.FwVersion
> +            FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion
> +            FmpPayloadHeader.Payload                = Buffer
> +            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 args.SignToolPfxFile is not None:
> +              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
> +            Result = FmpAuthHeader.Decode (Result)
> +
> +            #
> +            # Verify Image with 64-bit MonotonicCount appended to end of image
> +            #
> +            try:
> +              if args.SignToolPfxFile is not None:
> +                  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 ('========')
> +                UefiCapsuleHeader.DumpInfo ()
> +                print ('--------')
> +                FmpCapsuleHeader.DumpInfo ()
> +                print ('--------')
> +                FmpAuthHeader.DumpInfo ()
> +                print ('--------')
> +                FmpPayloadHeader.DumpInfo ()
> +                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
> +            Result = FmpAuthHeader.Decode (Result)
> +            Result = FmpPayloadHeader.Decode (Result)
> +
> +            print ('========')
> +            UefiCapsuleHeader.DumpInfo ()
> +            print ('--------')
> +            FmpCapsuleHeader.DumpInfo ()
> +            print ('--------')
> +            FmpAuthHeader.DumpInfo ()
> +            print ('--------')
> +            FmpPayloadHeader.DumpInfo ()
> +            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')
> diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
> b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
> new file mode 100644
> index 0000000000..0ed51752d3
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
> @@ -0,0 +1,91 @@
> +## @file
> +# Module that encodes and decodes a FMP_PAYLOAD_HEADER with a payload.
> +# The FMP_PAYLOAD_HEADER is processed by the FmpPayloadHeaderLib in the
> +# FmpDevicePkg.
> +#
> +# 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.
> +#
> +
> +'''
> +FmpPayloadHeader
> +'''
> +
> +import struct
> +
> +def _SIGNATURE_32 (A, B, C, D):
> +    return struct.unpack ('=I',bytearray (A + B + C + D, 'ascii'))[0]
> +
> +def _SIGNATURE_32_TO_STRING (Signature):
> +    return struct.pack ("<I", Signature).decode ()
> +
> +class FmpPayloadHeaderClass (object):
> +    #
> +    # typedef struct {
> +    #   UINT32  Signature;
> +    #   UINT32  HeaderSize;
> +    #   UINT32  FwVersion;
> +    #   UINT32  LowestSupportedVersion;
> +    # } FMP_PAYLOAD_HEADER;
> +    #
> +    # #define FMP_PAYLOAD_HEADER_SIGNATURE SIGNATURE_32 ('M', 'S', 'S', '1')
> +    #
> +    _StructFormat = '<IIII'
> +    _StructSize   = struct.calcsize (_StructFormat)
> +
> +    _FMP_PAYLOAD_HEADER_SIGNATURE = _SIGNATURE_32 ('M', 'S', 'S', '1')
> +
> +    def __init__ (self):
> +        self._Valid                 = False
> +        self.Signature              = self._FMP_PAYLOAD_HEADER_SIGNATURE
> +        self.HeaderSize             = self._StructSize
> +        self.FwVersion              = 0x00000000
> +        self.LowestSupportedVersion = 0x00000000
> +        self.Payload                = b''
> +
> +    def Encode (self):
> +        FmpPayloadHeader = struct.pack (
> +                                     self._StructFormat,
> +                                     self.Signature,
> +                                     self.HeaderSize,
> +                                     self.FwVersion,
> +                                     self.LowestSupportedVersion
> +                                     )
> +        self._Valid = True
> +        return FmpPayloadHeader + self.Payload
> +
> +    def Decode (self, Buffer):
> +        if len (Buffer) < self._StructSize:
> +            raise ValueError
> +        (Signature, HeaderSize, FwVersion, LowestSupportedVersion) = \
> +            struct.unpack (
> +                     self._StructFormat,
> +                     Buffer[0:self._StructSize]
> +                     )
> +        if Signature != self._FMP_PAYLOAD_HEADER_SIGNATURE:
> +            raise ValueError
> +        if HeaderSize < self._StructSize:
> +            raise ValueError
> +        self.Signature              = Signature
> +        self.HeaderSize             = HeaderSize
> +        self.FwVersion              = FwVersion
> +        self.LowestSupportedVersion = LowestSupportedVersion
> +        self.Payload                = Buffer[self.HeaderSize:]
> +
> +        self._Valid                 = True
> +        return self.Payload
> +
> +    def DumpInfo (self):
> +        if not self._Valid:
> +            raise ValueError
> +        print ('FMP_PAYLOAD_HEADER.Signature              = {Signature:08X} ({SignatureString})'.format (Signature =
> self.Signature, SignatureString = _SIGNATURE_32_TO_STRING (self.Signature)))
> +        print ('FMP_PAYLOAD_HEADER.HeaderSize             = {HeaderSize:08X}'.format (HeaderSize = self.HeaderSize))
> +        print ('FMP_PAYLOAD_HEADER.FwVersion              = {FwVersion:08X}'.format (FwVersion = self.FwVersion))
> +        print ('FMP_PAYLOAD_HEADER.LowestSupportedVersion = {LowestSupportedVersion:08X}'.format
> (LowestSupportedVersion = self.LowestSupportedVersion))
> +        print ('sizeof (Payload)                          = {Size:08X}'.format (Size = len (self.Payload)))
> diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
> b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
> new file mode 100644
> index 0000000000..71c6f06838
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
> @@ -0,0 +1,15 @@
> +## @file
> +# Python 'Common.Edk2.Capsule' package initialization file.
> +#
> +# This file is required to make Python interpreter treat the directory
> +# as containing package.
> +#
> +# 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.
> +#
> diff --git a/BaseTools/Source/Python/Common/Edk2/__init__.py b/BaseTools/Source/Python/Common/Edk2/__init__.py
> new file mode 100644
> index 0000000000..97d925cbf8
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Edk2/__init__.py
> @@ -0,0 +1,15 @@
> +## @file
> +# Python 'Common.Edk2' package initialization file.
> +#
> +# This file is required to make Python interpreter treat the directory
> +# as containing package.
> +#
> +# 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.
> +#
> diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
> new file mode 100644
> index 0000000000..aec52bf772
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
> @@ -0,0 +1,184 @@
> +## @file
> +# Module that encodes and decodes a EFI_FIRMWARE_IMAGE_AUTHENTICATION with
> +# certificate data and payload data.
> +#
> +# 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.
> +#
> +
> +'''
> +FmpAuthHeader
> +'''
> +
> +import struct
> +import uuid
> +
> +class FmpAuthHeaderClass (object):
> +    # ///
> +    # /// Image Attribute -Authentication Required
> +    # ///
> +    # typedef struct {
> +    #   ///
> +    #   /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay.
> +    #   /// It is incremented during each firmware image operation.
> +    #   ///
> +    #   UINT64                                  MonotonicCount;
> +    #   ///
> +    #   /// Provides the authorization for the firmware image operations. It is a signature across
> +    #   /// the image data and the Monotonic Count value. Caller uses the private key that is
> +    #   /// associated with a public key that has been provisioned via the key exchange.
> +    #   /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must
> +    #   /// be EFI_CERT_TYPE_PKCS7_GUID.
> +    #   ///
> +    #   WIN_CERTIFICATE_UEFI_GUID               AuthInfo;
> +    # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
> +    #
> +    # ///
> +    # /// Certificate which encapsulates a GUID-specific digital signature
> +    # ///
> +    # typedef struct {
> +    #   ///
> +    #   /// This is the standard WIN_CERTIFICATE header, where
> +    #   /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.
> +    #   ///
> +    #   WIN_CERTIFICATE   Hdr;
> +    #   ///
> +    #   /// This is the unique id which determines the
> +    #   /// format of the CertData. .
> +    #   ///
> +    #   EFI_GUID          CertType;
> +    #   ///
> +    #   /// The following is the certificate data. The format of
> +    #   /// the data is determined by the CertType.
> +    #   /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
> +    #   /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
> +    #   ///
> +    #   UINT8            CertData[1];
> +    # } WIN_CERTIFICATE_UEFI_GUID;
> +    #
> +    # ///
> +    # /// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
> +    # ///
> +    # typedef struct {
> +    #   ///
> +    #   /// The length of the entire certificate,
> +    #   /// including the length of the header, in bytes.
> +    #   ///
> +    #   UINT32  dwLength;
> +    #   ///
> +    #   /// The revision level of the WIN_CERTIFICATE
> +    #   /// structure. The current revision level is 0x0200.
> +    #   ///
> +    #   UINT16  wRevision;
> +    #   ///
> +    #   /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
> +    #   /// certificate types. The UEFI specification reserves the range of
> +    #   /// certificate type values from 0x0EF0 to 0x0EFF.
> +    #   ///
> +    #   UINT16  wCertificateType;
> +    #   ///
> +    #   /// The following is the actual certificate. The format of
> +    #   /// the certificate depends on wCertificateType.
> +    #   ///
> +    #   /// UINT8 bCertificate[ANYSIZE_ARRAY];
> +    #   ///
> +    # } WIN_CERTIFICATE;
> +    #
> +    # #define WIN_CERT_TYPE_EFI_GUID         0x0EF1
> +    #
> +    # ///
> +    # /// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]
> +    # /// SignedData value.
> +    # ///
> +    # #define EFI_CERT_TYPE_PKCS7_GUID \
> +    #   { \
> +    #     0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
> +    #   }
> +
> +    _StructFormat = '<QIHH16s'
> +    _StructSize   = struct.calcsize (_StructFormat)
> +
> +    _MonotonicCountFormat = '<Q'
> +    _MonotonicCountSize   = struct.calcsize (_MonotonicCountFormat)
> +
> +    _StructAuthInfoFormat = '<IHH16s'
> +    _StructAuthInfoSize   = struct.calcsize (_StructAuthInfoFormat)
> +
> +    _WIN_CERT_REVISION        = 0x0200
> +    _WIN_CERT_TYPE_EFI_GUID   = 0x0EF1
> +    _EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-68df-49ee-8aa9-347d375665a7')
> +
> +    def __init__ (self):
> +        self._Valid              = False
> +        self.MonotonicCount      = 0
> +        self.dwLength            = self._StructAuthInfoSize
> +        self.wRevision           = self._WIN_CERT_REVISION
> +        self.wCertificateType    = self._WIN_CERT_TYPE_EFI_GUID
> +        self.CertType            = self._EFI_CERT_TYPE_PKCS7_GUID
> +        self.CertData            = b''
> +        self.Payload             = b''
> +
> +
> +    def Encode (self):
> +        if self.wRevision != self._WIN_CERT_REVISION:
> +            raise ValueError
> +        if self.wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
> +            raise ValueError
> +        if self.CertType != self._EFI_CERT_TYPE_PKCS7_GUID:
> +            raise ValueError
> +        self.dwLength = self._StructAuthInfoSize + len (self.CertData)
> +
> +        FmpAuthHeader = struct.pack (
> +                                 self._StructFormat,
> +                                 self.MonotonicCount,
> +                                 self.dwLength,
> +                                 self.wRevision,
> +                                 self.wCertificateType,
> +                                 self.CertType.bytes_le
> +                                 )
> +        self._Valid = True
> +
> +        return FmpAuthHeader + self.CertData + self.Payload
> +
> +    def Decode (self, Buffer):
> +        if len (Buffer) < self._StructSize:
> +            raise ValueError
> +        (MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \
> +            struct.unpack (
> +                     self._StructFormat,
> +                     Buffer[0:self._StructSize]
> +                     )
> +        if dwLength < self._StructAuthInfoSize:
> +            raise ValueError
> +        if wRevision != self._WIN_CERT_REVISION:
> +            raise ValueError
> +        if wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:
> +            raise ValueError
> +        if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le:
> +            raise ValueError
> +        self.MonotonicCount   = MonotonicCount
> +        self.dwLength         = dwLength
> +        self.wRevision        = wRevision
> +        self.wCertificateType = wCertificateType
> +        self.CertType         = uuid.UUID (bytes = CertType)
> +        self.CertData         = Buffer[self._StructSize:self._MonotonicCountSize + self.dwLength]
> +        self.Payload          = Buffer[self._MonotonicCountSize + self.dwLength:]
> +        self._Valid           = True
> +        return self.Payload
> +
> +    def DumpInfo (self):
> +        if not self._Valid:
> +            raise ValueError
> +        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount                = {MonotonicCount:016X}'.format
> (MonotonicCount = self.MonotonicCount))
> +        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength         = {dwLength:08X}'.format (dwLength =
> self.dwLength))
> +        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision        = {wRevision:04X}'.format (wRevision =
> self.wRevision))
> +        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType = {wCertificateType:04X}'.format
> (wCertificateType = self.wCertificateType))
> +        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType             = {Guid}'.format (Guid =
> str(self.CertType).upper()))
> +        print ('sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData)    = {Size:08X}'.format (Size = len
> (self.CertData)))
> +        print ('sizeof (Payload)                                                = {Size:08X}'.format (Size = len
> (self.Payload)))
> diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> new file mode 100644
> index 0000000000..2461fb5068
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
> @@ -0,0 +1,302 @@
> +## @file
> +# Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
> +# a payload.
> +#
> +# 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.
> +#
> +
> +'''
> +FmpCapsuleHeader
> +'''
> +
> +import struct
> +import uuid
> +
> +class FmpCapsuleImageHeaderClass (object):
> +    # typedef struct {
> +    #   UINT32   Version;
> +    #
> +    #   ///
> +    #   /// Used to identify device firmware targeted by this update. This guid is matched by
> +    #   /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR
> +    #   ///
> +    #   EFI_GUID UpdateImageTypeId;
> +    #
> +    #   ///
> +    #   /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()
> +    #   ///
> +    #   UINT8    UpdateImageIndex;
> +    #   UINT8    reserved_bytes[3];
> +    #
> +    #   ///
> +    #   /// Size of the binary update image which immediately follows this structure
> +    #   ///
> +    #   UINT32   UpdateImageSize;
> +    #
> +    #   ///
> +    #   /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule
> +    #   ///
> +    #   UINT32   UpdateVendorCodeSize;
> +    #
> +    #   ///
> +    #   /// The HardwareInstance to target with this update. If value is zero it means match all
> +    #   /// HardwareInstances. This field allows update software to target only a single device in
> +    #   /// cases where there are more than one device with the same ImageTypeId GUID.
> +    #   /// This header is outside the signed data of the Authentication Info structure and
> +    #   /// therefore can be modified without changing the Auth data.
> +    #   ///
> +    #   UINT64   UpdateHardwareInstance;
> +    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
> +    #
> +    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
> +
> +    _StructFormat = '<I16sB3BIIQ'
> +    _StructSize   = struct.calcsize (_StructFormat)
> +
> +    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
> +
> +    def __init__ (self):
> +        self._Valid                 = False
> +        self.Version                = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION
> +        self.UpdateImageTypeId      = uuid.UUID ('00000000-0000-0000-0000-000000000000')
> +        self.UpdateImageIndex       = 0
> +        self.UpdateImageSize        = 0
> +        self.UpdateVendorCodeSize   = 0
> +        self.UpdateHardwareInstance = 0x0000000000000000
> +        self.Payload                = b''
> +        self.VendorCodeBytes        = b''
> +
> +    def Encode (self):
> +        self.UpdateImageSize      = len (self.Payload)
> +        self.UpdateVendorCodeSize = len (self.VendorCodeBytes)
> +        FmpCapsuleImageHeader = struct.pack (
> +                                         self._StructFormat,
> +                                         self.Version,
> +                                         self.UpdateImageTypeId.bytes_le,
> +                                         self.UpdateImageIndex,
> +                                         0,0,0,
> +                                         self.UpdateImageSize,
> +                                         self.UpdateVendorCodeSize,
> +                                         self.UpdateHardwareInstance
> +                                         )
> +        self._Valid = True
> +        return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
> +
> +    def Decode (self, Buffer):
> +        if len (Buffer) < self._StructSize:
> +            raise ValueError
> +        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize,
> UpdateHardwareInstance) = \
> +            struct.unpack (
> +                     self._StructFormat,
> +                     Buffer[0:self._StructSize]
> +                     )
> +
> +        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:
> +            raise ValueError
> +        if UpdateImageIndex < 1:
> +            raise ValueError
> +        if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):
> +            raise ValueError
> +
> +        self.Version                = Version
> +        self.UpdateImageTypeId      = uuid.UUID (bytes_le = UpdateImageTypeId)
> +        self.UpdateImageIndex       = UpdateImageIndex
> +        self.UpdateImageSize        = UpdateImageSize
> +        self.UpdateVendorCodeSize   = UpdateVendorCodeSize
> +        self.UpdateHardwareInstance = UpdateHardwareInstance
> +        self.Payload                = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
> +        self.VendorCodeBytes        = Buffer[self._StructSize + UpdateImageSize:]
> +        self._Valid                 = True
> +        return Buffer[self._StructSize:]
> +
> +    def DumpInfo (self):
> +        if not self._Valid:
> +            raise ValueError
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version                = {Version:08X}'.format
> (Version = self.Version))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId      =
> {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex       =
> {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize        =
> {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize   =
> {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance =
> {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
> +        print ('sizeof (Payload)                                                    = {Size:08X}'.format (Size = len
> (self.Payload)))
> +        print ('sizeof (VendorCodeBytes)                                            = {Size:08X}'.format (Size = len
> (self.VendorCodeBytes)))
> +
> +class FmpCapsuleHeaderClass (object):
> +    # typedef struct {
> +    #   UINT32 Version;
> +    #
> +    #   ///
> +    #   /// The number of drivers included in the capsule and the number of corresponding
> +    #   /// offsets stored in ItemOffsetList array.
> +    #   ///
> +    #   UINT16 EmbeddedDriverCount;
> +    #
> +    #   ///
> +    #   /// The number of payload items included in the capsule and the number of
> +    #   /// corresponding offsets stored in the ItemOffsetList array.
> +    #   ///
> +    #   UINT16 PayloadItemCount;
> +    #
> +    #   ///
> +    #   /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]
> +    #   /// containing offsets of each of the drivers and payload items contained within the capsule
> +    #   ///
> +    #   // UINT64 ItemOffsetList[];
> +    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
> +    #
> +    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION       0x00000001
> +    _StructFormat = '<IHH'
> +    _StructSize   = struct.calcsize (_StructFormat)
> +
> +    _ItemOffsetFormat = '<Q'
> +    _ItemOffsetSize   = struct.calcsize (_ItemOffsetFormat)
> +
> +    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
> +
> +    def __init__ (self):
> +        self._Valid                     = False
> +        self.Version                    = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
> +        self.EmbeddedDriverCount        = 0
> +        self.PayloadItemCount           = 0
> +        self._ItemOffsetList            = []
> +        self._EmbeddedDriverList        = []
> +        self._PayloadList               = []
> +        self._FmpCapsuleImageHeaderList = []
> +
> +    def AddEmbeddedDriver (self, EmbeddedDriver):
> +        self._EmbeddedDriverList.append (EmbeddedDriver)
> +
> +    def GetEmbeddedDriver (self, Index):
> +        if Index > len (self._EmbeddedDriverList):
> +            raise ValueError
> +        return self._EmbeddedDriverList[Index]
> +
> +    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):
> +        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))
> +
> +    def GetFmpCapsuleImageHeader (self, Index):
> +        if Index >= len (self._FmpCapsuleImageHeaderList):
> +            raise ValueError
> +        return self._FmpCapsuleImageHeaderList[Index]
> +
> +    def Encode (self):
> +        self.EmbeddedDriverCount = len (self._EmbeddedDriverList)
> +        self.PayloadItemCount    = len (self._PayloadList)
> +
> +        FmpCapsuleHeader = struct.pack (
> +                                    self._StructFormat,
> +                                    self.Version,
> +                                    self.EmbeddedDriverCount,
> +                                    self.PayloadItemCount
> +                                    )
> +
> +        FmpCapsuleData = b''
> +        Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize
> +        for EmbeddedDriver in self._EmbeddedDriverList:
> +            FmpCapsuleData = FmpCapsuleData + EmbeddedDriver
> +            self._ItemOffsetList.append (Offset)
> +            Offset = Offset + len (EmbeddedDriver)
> +        Index = 1
> +        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:
> +            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
> +            FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId
> +            FmpCapsuleImageHeader.UpdateImageIndex       = Index
> +            FmpCapsuleImageHeader.Payload                = Payload
> +            FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes
> +            FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
> +            FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
> +            FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
> +
> +            self._ItemOffsetList.append (Offset)
> +            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
> +
> +            Offset = Offset + len (FmpCapsuleImage)
> +            Index = Index + 1
> +
> +        for Offset in self._ItemOffsetList:
> +          FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)
> +
> +        self._Valid = True
> +        return FmpCapsuleHeader + FmpCapsuleData
> +
> +    def Decode (self, Buffer):
> +        if len (Buffer) < self._StructSize:
> +            raise ValueError
> +        (Version, EmbeddedDriverCount, PayloadItemCount) = \
> +            struct.unpack (
> +                     self._StructFormat,
> +                     Buffer[0:self._StructSize]
> +                     )
> +        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:
> +            raise ValueError
> +
> +        self.Version                    = Version
> +        self.EmbeddedDriverCount        = EmbeddedDriverCount
> +        self.PayloadItemCount           = PayloadItemCount
> +        self._ItemOffsetList            = []
> +        self._EmbeddedDriverList        = []
> +        self._PayloadList               = []
> +        self._FmpCapsuleImageHeaderList = []
> +
> +        #
> +        # Parse the ItemOffsetList values
> +        #
> +        Offset = self._StructSize
> +        for Index in range (0, EmbeddedDriverCount + PayloadItemCount):
> +            ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]
> +            if ItemOffset >= len (Buffer):
> +                raise ValueError
> +            self._ItemOffsetList.append (ItemOffset)
> +            Offset = Offset + self._ItemOffsetSize
> +        Result = Buffer[Offset:]
> +
> +        #
> +        # Parse the EmbeddedDrivers
> +        #
> +        for Index in range (0, EmbeddedDriverCount):
> +            Offset = self._ItemOffsetList[Index]
> +            if Index < (len (self._ItemOffsetList) - 1):
> +                Length = self._ItemOffsetList[Index + 1] - Offset
> +            else:
> +                Length = len (Buffer) - Offset
> +            self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])
> +
> +        #
> +        # Parse the Payloads that are FMP Capsule Images
> +        #
> +        for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):
> +            Offset = self._ItemOffsetList[Index]
> +            if Index < (len (self._ItemOffsetList) - 1):
> +                Length = self._ItemOffsetList[Index + 1] - Offset
> +            else:
> +                Length = len (Buffer) - Offset
> +            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
> +            FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])
> +            self.AddPayload (
> +                   FmpCapsuleImageHeader.UpdateImageTypeId,
> +                   FmpCapsuleImageHeader.Payload,
> +                   FmpCapsuleImageHeader.VendorCodeBytes
> +                   )
> +            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)
> +
> +        self._Valid = True
> +        return Result
> +
> +    def DumpInfo (self):
> +        if not self._Valid:
> +            raise ValueError
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version             = {Version:08X}'.format (Version =
> self.Version))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format
> (EmbeddedDriverCount = self.EmbeddedDriverCount))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount    = {PayloadItemCount:08X}'.format
> (PayloadItemCount = self.PayloadItemCount))
> +        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList      = ')
> +        for Offset in self._ItemOffsetList:
> +            print ('  {Offset:016X}'.format (Offset = Offset))
> +        for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:
> +            FmpCapsuleImageHeader.DumpInfo ()
> diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
> b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
> new file mode 100644
> index 0000000000..cfe1cb6c46
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
> @@ -0,0 +1,136 @@
> +## @file
> +# Module that encodes and decodes a EFI_CAPSULE_HEADER with a payload
> +#
> +# 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.
> +#
> +
> +'''
> +UefiCapsuleHeader
> +'''
> +
> +import struct
> +import uuid
> +
> +class UefiCapsuleHeaderClass (object):
> +    # typedef struct {
> +    #   ///
> +    #   /// A GUID that defines the contents of a capsule.
> +    #   ///
> +    #   EFI_GUID          CapsuleGuid;
> +    #   ///
> +    #   /// The size of the capsule header. This may be larger than the size of
> +    #   /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply
> +    #   /// extended header entries
> +    #   ///
> +    #   UINT32            HeaderSize;
> +    #   ///
> +    #   /// Bit-mapped list describing the capsule attributes. The Flag values
> +    #   /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values
> +    #   /// of 0x10000 - 0xFFFFFFFF are defined by this specification
> +    #   ///
> +    #   UINT32            Flags;
> +    #   ///
> +    #   /// Size in bytes of the capsule.
> +    #   ///
> +    #   UINT32            CapsuleImageSize;
> +    # } EFI_CAPSULE_HEADER;
> +    #
> +    # #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET          0x00010000
> +    # #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE         0x00020000
> +    # #define CAPSULE_FLAGS_INITIATE_RESET                0x00040000
> +    #
> +    _StructFormat = '<16sIIII'
> +    _StructSize   = struct.calcsize (_StructFormat)
> +
> +    EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID = uuid.UUID ('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')
> +
> +    _CAPSULE_FLAGS_PERSIST_ACROSS_RESET  = 0x00010000
> +    _CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000
> +    _CAPSULE_FLAGS_INITIATE_RESET        = 0x00040000
> +
> +    def __init__ (self):
> +        self._Valid              = False
> +        self.CapsuleGuid         = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
> +        self.HeaderSize          = self._StructSize
> +        self.OemFlags            = 0x0000
> +        self.PersistAcrossReset  = False
> +        self.PopulateSystemTable = False
> +        self.InitiateReset       = False
> +        self.CapsuleImageSize    = self.HeaderSize
> +        self.Payload             = b''
> +
> +    def Encode (self):
> +        Flags = self.OemFlags
> +        if self.PersistAcrossReset:
> +            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
> +        if self.PopulateSystemTable:
> +            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> +        if self.InitiateReset:
> +            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
> +
> +        self.CapsuleImageSize = self.HeaderSize + len (self.Payload)
> +
> +        UefiCapsuleHeader = struct.pack (
> +                                     self._StructFormat,
> +                                     self.CapsuleGuid.bytes_le,
> +                                     self.HeaderSize,
> +                                     Flags,
> +                                     self.CapsuleImageSize,
> +                                     0
> +                                     )
> +        self._Valid = True
> +        return UefiCapsuleHeader + self.Payload
> +
> +    def Decode (self, Buffer):
> +        if len (Buffer) < self._StructSize:
> +            raise ValueError
> +        (CapsuleGuid, HeaderSize, Flags, CapsuleImageSize, Reserved) = \
> +            struct.unpack (
> +                     self._StructFormat,
> +                     Buffer[0:self._StructSize]
> +                     )
> +        if HeaderSize < self._StructSize:
> +            raise ValueError
> +        if CapsuleImageSize != len (Buffer):
> +            raise ValueError
> +        self.CapsuleGuid         = uuid.UUID (bytes_le = CapsuleGuid)
> +        self.HeaderSize          = HeaderSize
> +        self.OemFlags            = Flags & 0xffff
> +        self.PersistAcrossReset  = (Flags & self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0
> +        self.PopulateSystemTable = (Flags & self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0
> +        self.InitiateReset       = (Flags & self._CAPSULE_FLAGS_INITIATE_RESET) != 0
> +        self.CapsuleImageSize    = CapsuleImageSize
> +        self.Payload             = Buffer[self.HeaderSize:]
> +
> +        self._Valid              = True
> +        return self.Payload
> +
> +    def DumpInfo (self):
> +        if not self._Valid:
> +            raise ValueError
> +        Flags = self.OemFlags
> +        if self.PersistAcrossReset:
> +            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
> +        if self.PopulateSystemTable:
> +            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> +        if self.InitiateReset:
> +            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET
> +        print ('EFI_CAPSULE_HEADER.CapsuleGuid      = {Guid}'.format (Guid = str(self.CapsuleGuid).upper()))
> +        print ('EFI_CAPSULE_HEADER.HeaderSize       = {Size:08X}'.format (Size = self.HeaderSize))
> +        print ('EFI_CAPSULE_HEADER.Flags            = {Flags:08X}'.format (Flags = Flags))
> +        print ('  OEM Flags                         = {Flags:04X}'.format (Flags = self.OemFlags))
> +        if self.PersistAcrossReset:
> +            print ('  CAPSULE_FLAGS_PERSIST_ACROSS_RESET')
> +        if self.PopulateSystemTable:
> +            print ('  CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE')
> +        if self.InitiateReset:
> +            print ('  CAPSULE_FLAGS_INITIATE_RESET')
> +        print ('EFI_CAPSULE_HEADER.CapsuleImageSize = {Size:08X}'.format (Size = self.CapsuleImageSize))
> +        print ('sizeof (Payload)                    = {Size:08X}'.format (Size = len (self.Payload)))
> diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
> b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
> new file mode 100644
> index 0000000000..d9db4aa919
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
> @@ -0,0 +1,15 @@
> +## @file
> +# Python 'Common.Uefi.Capsule' package initialization file.
> +#
> +# This file is required to make Python interpreter treat the directory
> +# as containing package.
> +#
> +# 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.
> +#
> diff --git a/BaseTools/Source/Python/Common/Uefi/__init__.py b/BaseTools/Source/Python/Common/Uefi/__init__.py
> new file mode 100644
> index 0000000000..d80219dcb3
> --- /dev/null
> +++ b/BaseTools/Source/Python/Common/Uefi/__init__.py
> @@ -0,0 +1,15 @@
> +## @file
> +# Python 'Common.Uefi' package initialization file.
> +#
> +# This file is required to make Python interpreter treat the directory
> +# as containing package.
> +#
> +# 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.
> +#
> --
> 2.14.2.windows.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 1/1] BaseTools/Capsule: Add Capsule Generation Tools
  2018-05-31 14:25   ` Gao, Liming
@ 2018-05-31 16:36     ` Kinney, Michael D
  0 siblings, 0 replies; 4+ messages in thread
From: Kinney, Michael D @ 2018-05-31 16:36 UTC (permalink / raw)
  To: Gao, Liming, edk2-devel@lists.01.org, Kinney, Michael D
  Cc: Sean Brogan, Yao, Jiewen, Zhu, Yonghong

Liming,

The C code was in the original content from MS_UEFI.

It may be possible to update GenFds to use the new
python modules.  I have not investigated this yet.

Mike

> -----Original Message-----
> From: Gao, Liming
> Sent: Thursday, May 31, 2018 7:26 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>;
> edk2-devel@lists.01.org
> Cc: Sean Brogan <sean.brogan@microsoft.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Zhu, Yonghong
> <yonghong.zhu@intel.com>
> Subject: RE: [RFC 1/1] BaseTools/Capsule: Add Capsule
> Generation Tools
> 
> Mike:
>   Which C tool is converted? Does it support all capsule
> generation functionality in GenFv tool?
> 
>   And, GenFds has the logic to generate FMP capsule. Can
> they share same logic?
> 
> Thanks
> Liming
> > -----Original Message-----
> > From: Kinney, Michael D
> > Sent: Wednesday, May 30, 2018 6:57 AM
> > To: edk2-devel@lists.01.org
> > Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
> Sean Brogan <sean.brogan@microsoft.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>; Zhu, Yonghong
> <yonghong.zhu@intel.com>; Gao, Liming
> <liming.gao@intel.com>
> > Subject: [RFC 1/1] BaseTools/Capsule: Add Capsule
> Generation Tools
> >
> > From: "Kinney, Michael D" <michael.d.kinney@intel.com>
> >
> > 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/Cap
> suleTools
> >
> > * 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]
> >                        [--version FWVERSION] [--lsv
> LOWESTSUPPORTEDVERSION]
> >                        [--pfx-file SIGNTOOLPFXFILE]
> >                        [--signer-private-cert
> OPENSSLSIGNERPRIVATECERTFILE]
> >                        [--other-public-cert
> OPENSSLOTHERPUBLICCERTFILE]
> >                        [--trusted-public-cert
> OPENSSLTRUSTEDPUBLICCERTFILE]
> >                        [--signing-tool-path
> SIGNINGTOOLPATH] [-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.
> >   --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 Open SLL
> tool. Optional if path to
> >                         tools are already in PATH.
> >   -v, --verbose         Increase output messages
> >   -q, --quiet           Reduce output messages
> >   --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>
> > ---
> >  BaseTools/BinWrappers/PosixLike/GenerateCapsule    |
> 14 +
> >  .../BinWrappers/WindowsLike/GenerateCapsule.bat    |
> 1 +
> >  BaseTools/Source/Python/Capsule/GenerateCapsule.py |
> 500 +++++++++++++++++++++
> >  .../Python/Common/Edk2/Capsule/FmpPayloadHeader.py |
> 91 ++++
> >  .../Source/Python/Common/Edk2/Capsule/__init__.py  |
> 15 +
> >  BaseTools/Source/Python/Common/Edk2/__init__.py    |
> 15 +
> >  .../Python/Common/Uefi/Capsule/FmpAuthHeader.py    |
> 184 ++++++++
> >  .../Python/Common/Uefi/Capsule/FmpCapsuleHeader.py |
> 302 +++++++++++++
> >  .../Common/Uefi/Capsule/UefiCapsuleHeader.py       |
> 136 ++++++
> >  .../Source/Python/Common/Uefi/Capsule/__init__.py  |
> 15 +
> >  BaseTools/Source/Python/Common/Uefi/__init__.py    |
> 15 +
> >  11 files changed, 1288 insertions(+)
> >  create mode 100644
> BaseTools/BinWrappers/PosixLike/GenerateCapsule
> >  create mode 100644
> BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> >  create mode 100644
> BaseTools/Source/Python/Capsule/GenerateCapsule.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHe
> ader.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Edk2/__init__.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeade
> r.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHe
> ader.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleH
> eader.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
> >  create mode 100644
> BaseTools/Source/Python/Common/Uefi/__init__.py
> >
> > diff --git
> a/BaseTools/BinWrappers/PosixLike/GenerateCapsule
> b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
> > new file mode 100644
> > index 0000000000..59a6c8ba43
> > --- /dev/null
> > +++ b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
> > @@ -0,0 +1,14 @@
> > +#!/usr/bin/env bash
> > +#python `dirname $0`/RunToolFromSource.py `basename
> $0` $*
> > +
> > +# If a python2 command is available, use it in
> preference to python
> > +if command -v python2 >/dev/null 2>&1; then
> > +    python_exe=python2
> > +fi
> > +
> > +full_cmd=${BASH_SOURCE:-$0} # see
> http://mywiki.wooledge.org/BashFAQ/028 for a discussion
> of why $0 is not a good choice here
> > +dir=$(dirname "$full_cmd")
> > +cmd=${full_cmd##*/}
> > +
> > +export
> PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYT
> HONPATH"}"
> > +exec "${python_exe:-python}"
> "$dir/../../Source/Python/Capsule/$cmd.py" "$@"
> > diff --git
> a/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> > new file mode 100644
> > index 0000000000..ca442d181b
> > --- /dev/null
> > +++
> b/BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat
> > @@ -0,0 +1 @@
> > +@%PYTHON_HOME%\python.exe
> %BASE_TOOLS_PATH%\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
> > index 0000000000..32ab95c3e0
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
> > @@ -0,0 +1,500 @@
> > +## @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
> > +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'
> > +__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 ("--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
> Open SLL tool.  Optional if path to tools are already in
> PATH.")
> > +
> > +    #
> > +    # Add optional arguments common to all commands
> > +    #
> > +    parser.add_argument("-v", "--verbose", dest =
> 'Verbose', action = "store_true",
> > +                        help = "Increase output
> messages")
> > +    parser.add_argument("-q", "--quiet", dest =
> 'Quiet', action = "store_true",
> > +                        help = "Reduce output
> messages")
> > +    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 not args.DumpInfo and args.OutputFile is None:
> > +        parser.error ('the following arguments are
> required for all commands except --dump-info: --output')
> > +
> > +    if args.Encode and (args.Guid is None or
> args.FwVersion is None or args.LowestSupportedVersion is
> None):
> > +        parser.error ('the following arguments are
> required: --version, --lsv, --guid')
> > +
> > +    if not args.DumpInfo and not args.OutputFile:
> > +        parser.error ('the following arguments are
> required: --output')
> > +
> > +    if not args.DumpInfo:
> > +        if args.SignToolPfxFile is None and
> args.OpenSslSignerPrivateCertFile is None and
> args.OpenSslOtherPublicCertFile is None
> > and args.OpenSslTrustedPublicCertFile is None:
> > +            parser.error ('certificate file arguments
> are required: --pfx-file | [--signer-private-cert --
> other-public-cert
> > --trusted-public-cert]')
> > +
> > +    if args.SignToolPfxFile is not None:
> > +        if args.OpenSslSignerPrivateCertFile is not
> None:
> > +            parser.error ('Providing both signtool
> and OpenSSL options is not supported')
> > +        if args.OpenSslOtherPublicCertFile is not
> None:
> > +            parser.error ('Providing both signtool
> and OpenSSL options is not supported')
> > +        if args.OpenSslTrustedPublicCertFile is not
> None:
> > +            parser.error ('Providing both signtool
> and OpenSSL options is not supported')
> > +        args.SignToolPfxFile.close()
> > +        args.SignToolPfxFile =
> args.SignToolPfxFile.name
> > +
> > +    if not args.DumpInfo:
> > +        if args.SignToolPfxFile is None:
> > +            if args.OpenSslSignerPrivateCertFile is
> None:
> > +                parser.error ('the following
> arguments are required: --signer-private-cert')
> > +            if args.OpenSslOtherPublicCertFile is
> None:
> > +                parser.error ('the following
> arguments are required: --other-public-cert')
> > +            if args.OpenSslTrustedPublicCertFile is
> None:
> > +                parser.error ('the following
> arguments are required: --trusted-public-cert')
> > +            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:
> > +        try:
> > +            FmpPayloadHeader.FwVersion              =
> args.FwVersion
> > +            FmpPayloadHeader.LowestSupportedVersion =
> args.LowestSupportedVersion
> > +            FmpPayloadHeader.Payload                =
> Buffer
> > +            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 args.SignToolPfxFile is not None:
> > +              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
> > +            Result = FmpAuthHeader.Decode (Result)
> > +
> > +            #
> > +            # Verify Image with 64-bit MonotonicCount
> appended to end of image
> > +            #
> > +            try:
> > +              if args.SignToolPfxFile is not None:
> > +                  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 ('========')
> > +                UefiCapsuleHeader.DumpInfo ()
> > +                print ('--------')
> > +                FmpCapsuleHeader.DumpInfo ()
> > +                print ('--------')
> > +                FmpAuthHeader.DumpInfo ()
> > +                print ('--------')
> > +                FmpPayloadHeader.DumpInfo ()
> > +                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
> > +            Result = FmpAuthHeader.Decode (Result)
> > +            Result = FmpPayloadHeader.Decode (Result)
> > +
> > +            print ('========')
> > +            UefiCapsuleHeader.DumpInfo ()
> > +            print ('--------')
> > +            FmpCapsuleHeader.DumpInfo ()
> > +            print ('--------')
> > +            FmpAuthHeader.DumpInfo ()
> > +            print ('--------')
> > +            FmpPayloadHeader.DumpInfo ()
> > +            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')
> > diff --git
> a/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayload
> Header.py
> >
> b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayload
> Header.py
> > new file mode 100644
> > index 0000000000..0ed51752d3
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayload
> Header.py
> > @@ -0,0 +1,91 @@
> > +## @file
> > +# Module that encodes and decodes a
> FMP_PAYLOAD_HEADER with a payload.
> > +# The FMP_PAYLOAD_HEADER is processed by the
> FmpPayloadHeaderLib in the
> > +# FmpDevicePkg.
> > +#
> > +# 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.
> > +#
> > +
> > +'''
> > +FmpPayloadHeader
> > +'''
> > +
> > +import struct
> > +
> > +def _SIGNATURE_32 (A, B, C, D):
> > +    return struct.unpack ('=I',bytearray (A + B + C +
> D, 'ascii'))[0]
> > +
> > +def _SIGNATURE_32_TO_STRING (Signature):
> > +    return struct.pack ("<I", Signature).decode ()
> > +
> > +class FmpPayloadHeaderClass (object):
> > +    #
> > +    # typedef struct {
> > +    #   UINT32  Signature;
> > +    #   UINT32  HeaderSize;
> > +    #   UINT32  FwVersion;
> > +    #   UINT32  LowestSupportedVersion;
> > +    # } FMP_PAYLOAD_HEADER;
> > +    #
> > +    # #define FMP_PAYLOAD_HEADER_SIGNATURE
> SIGNATURE_32 ('M', 'S', 'S', '1')
> > +    #
> > +    _StructFormat = '<IIII'
> > +    _StructSize   = struct.calcsize (_StructFormat)
> > +
> > +    _FMP_PAYLOAD_HEADER_SIGNATURE = _SIGNATURE_32
> ('M', 'S', 'S', '1')
> > +
> > +    def __init__ (self):
> > +        self._Valid                 = False
> > +        self.Signature              =
> self._FMP_PAYLOAD_HEADER_SIGNATURE
> > +        self.HeaderSize             =
> self._StructSize
> > +        self.FwVersion              = 0x00000000
> > +        self.LowestSupportedVersion = 0x00000000
> > +        self.Payload                = b''
> > +
> > +    def Encode (self):
> > +        FmpPayloadHeader = struct.pack (
> > +
> self._StructFormat,
> > +                                     self.Signature,
> > +                                     self.HeaderSize,
> > +                                     self.FwVersion,
> > +
> self.LowestSupportedVersion
> > +                                     )
> > +        self._Valid = True
> > +        return FmpPayloadHeader + self.Payload
> > +
> > +    def Decode (self, Buffer):
> > +        if len (Buffer) < self._StructSize:
> > +            raise ValueError
> > +        (Signature, HeaderSize, FwVersion,
> LowestSupportedVersion) = \
> > +            struct.unpack (
> > +                     self._StructFormat,
> > +                     Buffer[0:self._StructSize]
> > +                     )
> > +        if Signature !=
> self._FMP_PAYLOAD_HEADER_SIGNATURE:
> > +            raise ValueError
> > +        if HeaderSize < self._StructSize:
> > +            raise ValueError
> > +        self.Signature              = Signature
> > +        self.HeaderSize             = HeaderSize
> > +        self.FwVersion              = FwVersion
> > +        self.LowestSupportedVersion =
> LowestSupportedVersion
> > +        self.Payload                =
> Buffer[self.HeaderSize:]
> > +
> > +        self._Valid                 = True
> > +        return self.Payload
> > +
> > +    def DumpInfo (self):
> > +        if not self._Valid:
> > +            raise ValueError
> > +        print ('FMP_PAYLOAD_HEADER.Signature
> = {Signature:08X} ({SignatureString})'.format (Signature
> =
> > self.Signature, SignatureString =
> _SIGNATURE_32_TO_STRING (self.Signature)))
> > +        print ('FMP_PAYLOAD_HEADER.HeaderSize
> = {HeaderSize:08X}'.format (HeaderSize =
> self.HeaderSize))
> > +        print ('FMP_PAYLOAD_HEADER.FwVersion
> = {FwVersion:08X}'.format (FwVersion = self.FwVersion))
> > +        print
> ('FMP_PAYLOAD_HEADER.LowestSupportedVersion =
> {LowestSupportedVersion:08X}'.format
> > (LowestSupportedVersion =
> self.LowestSupportedVersion))
> > +        print ('sizeof (Payload)
> = {Size:08X}'.format (Size = len (self.Payload)))
> > diff --git
> a/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.p
> y
> >
> b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.p
> y
> > new file mode 100644
> > index 0000000000..71c6f06838
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.p
> y
> > @@ -0,0 +1,15 @@
> > +## @file
> > +# Python 'Common.Edk2.Capsule' package initialization
> file.
> > +#
> > +# This file is required to make Python interpreter
> treat the directory
> > +# as containing package.
> > +#
> > +# 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.
> > +#
> > diff --git
> a/BaseTools/Source/Python/Common/Edk2/__init__.py
> b/BaseTools/Source/Python/Common/Edk2/__init__.py
> > new file mode 100644
> > index 0000000000..97d925cbf8
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/Common/Edk2/__init__.py
> > @@ -0,0 +1,15 @@
> > +## @file
> > +# Python 'Common.Edk2' package initialization file.
> > +#
> > +# This file is required to make Python interpreter
> treat the directory
> > +# as containing package.
> > +#
> > +# 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.
> > +#
> > diff --git
> a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHea
> der.py
> >
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHea
> der.py
> > new file mode 100644
> > index 0000000000..aec52bf772
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHea
> der.py
> > @@ -0,0 +1,184 @@
> > +## @file
> > +# Module that encodes and decodes a
> EFI_FIRMWARE_IMAGE_AUTHENTICATION with
> > +# certificate data and payload data.
> > +#
> > +# 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.
> > +#
> > +
> > +'''
> > +FmpAuthHeader
> > +'''
> > +
> > +import struct
> > +import uuid
> > +
> > +class FmpAuthHeaderClass (object):
> > +    # ///
> > +    # /// Image Attribute -Authentication Required
> > +    # ///
> > +    # typedef struct {
> > +    #   ///
> > +    #   /// It is included in the signature of
> AuthInfo. It is used to ensure freshness/no replay.
> > +    #   /// It is incremented during each firmware
> image operation.
> > +    #   ///
> > +    #   UINT64
> MonotonicCount;
> > +    #   ///
> > +    #   /// Provides the authorization for the
> firmware image operations. It is a signature across
> > +    #   /// the image data and the Monotonic Count
> value. Caller uses the private key that is
> > +    #   /// associated with a public key that has
> been provisioned via the key exchange.
> > +    #   /// Because this is defined as a signature,
> WIN_CERTIFICATE_UEFI_GUID.CertType must
> > +    #   /// be EFI_CERT_TYPE_PKCS7_GUID.
> > +    #   ///
> > +    #   WIN_CERTIFICATE_UEFI_GUID
> AuthInfo;
> > +    # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
> > +    #
> > +    # ///
> > +    # /// Certificate which encapsulates a GUID-
> specific digital signature
> > +    # ///
> > +    # typedef struct {
> > +    #   ///
> > +    #   /// This is the standard WIN_CERTIFICATE
> header, where
> > +    #   /// wCertificateType is set to
> WIN_CERT_TYPE_EFI_GUID.
> > +    #   ///
> > +    #   WIN_CERTIFICATE   Hdr;
> > +    #   ///
> > +    #   /// This is the unique id which determines
> the
> > +    #   /// format of the CertData. .
> > +    #   ///
> > +    #   EFI_GUID          CertType;
> > +    #   ///
> > +    #   /// The following is the certificate data.
> The format of
> > +    #   /// the data is determined by the CertType.
> > +    #   /// If CertType is
> EFI_CERT_TYPE_RSA2048_SHA256_GUID,
> > +    #   /// the CertData will be
> EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
> > +    #   ///
> > +    #   UINT8            CertData[1];
> > +    # } WIN_CERTIFICATE_UEFI_GUID;
> > +    #
> > +    # ///
> > +    # /// The WIN_CERTIFICATE structure is part of
> the PE/COFF specification.
> > +    # ///
> > +    # typedef struct {
> > +    #   ///
> > +    #   /// The length of the entire certificate,
> > +    #   /// including the length of the header, in
> bytes.
> > +    #   ///
> > +    #   UINT32  dwLength;
> > +    #   ///
> > +    #   /// The revision level of the WIN_CERTIFICATE
> > +    #   /// structure. The current revision level is
> 0x0200.
> > +    #   ///
> > +    #   UINT16  wRevision;
> > +    #   ///
> > +    #   /// The certificate type. See
> WIN_CERT_TYPE_xxx for the UEFI
> > +    #   /// certificate types. The UEFI specification
> reserves the range of
> > +    #   /// certificate type values from 0x0EF0 to
> 0x0EFF.
> > +    #   ///
> > +    #   UINT16  wCertificateType;
> > +    #   ///
> > +    #   /// The following is the actual certificate.
> The format of
> > +    #   /// the certificate depends on
> wCertificateType.
> > +    #   ///
> > +    #   /// UINT8 bCertificate[ANYSIZE_ARRAY];
> > +    #   ///
> > +    # } WIN_CERTIFICATE;
> > +    #
> > +    # #define WIN_CERT_TYPE_EFI_GUID         0x0EF1
> > +    #
> > +    # ///
> > +    # /// This identifies a signature containing a
> DER-encoded PKCS #7 version 1.5 [RFC2315]
> > +    # /// SignedData value.
> > +    # ///
> > +    # #define EFI_CERT_TYPE_PKCS7_GUID \
> > +    #   { \
> > +    #     0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9,
> 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
> > +    #   }
> > +
> > +    _StructFormat = '<QIHH16s'
> > +    _StructSize   = struct.calcsize (_StructFormat)
> > +
> > +    _MonotonicCountFormat = '<Q'
> > +    _MonotonicCountSize   = struct.calcsize
> (_MonotonicCountFormat)
> > +
> > +    _StructAuthInfoFormat = '<IHH16s'
> > +    _StructAuthInfoSize   = struct.calcsize
> (_StructAuthInfoFormat)
> > +
> > +    _WIN_CERT_REVISION        = 0x0200
> > +    _WIN_CERT_TYPE_EFI_GUID   = 0x0EF1
> > +    _EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-
> 68df-49ee-8aa9-347d375665a7')
> > +
> > +    def __init__ (self):
> > +        self._Valid              = False
> > +        self.MonotonicCount      = 0
> > +        self.dwLength            =
> self._StructAuthInfoSize
> > +        self.wRevision           =
> self._WIN_CERT_REVISION
> > +        self.wCertificateType    =
> self._WIN_CERT_TYPE_EFI_GUID
> > +        self.CertType            =
> self._EFI_CERT_TYPE_PKCS7_GUID
> > +        self.CertData            = b''
> > +        self.Payload             = b''
> > +
> > +
> > +    def Encode (self):
> > +        if self.wRevision != self._WIN_CERT_REVISION:
> > +            raise ValueError
> > +        if self.wCertificateType !=
> self._WIN_CERT_TYPE_EFI_GUID:
> > +            raise ValueError
> > +        if self.CertType !=
> self._EFI_CERT_TYPE_PKCS7_GUID:
> > +            raise ValueError
> > +        self.dwLength = self._StructAuthInfoSize +
> len (self.CertData)
> > +
> > +        FmpAuthHeader = struct.pack (
> > +                                 self._StructFormat,
> > +                                 self.MonotonicCount,
> > +                                 self.dwLength,
> > +                                 self.wRevision,
> > +
> self.wCertificateType,
> > +
> self.CertType.bytes_le
> > +                                 )
> > +        self._Valid = True
> > +
> > +        return FmpAuthHeader + self.CertData +
> self.Payload
> > +
> > +    def Decode (self, Buffer):
> > +        if len (Buffer) < self._StructSize:
> > +            raise ValueError
> > +        (MonotonicCount, dwLength, wRevision,
> wCertificateType, CertType) = \
> > +            struct.unpack (
> > +                     self._StructFormat,
> > +                     Buffer[0:self._StructSize]
> > +                     )
> > +        if dwLength < self._StructAuthInfoSize:
> > +            raise ValueError
> > +        if wRevision != self._WIN_CERT_REVISION:
> > +            raise ValueError
> > +        if wCertificateType !=
> self._WIN_CERT_TYPE_EFI_GUID:
> > +            raise ValueError
> > +        if CertType !=
> self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le:
> > +            raise ValueError
> > +        self.MonotonicCount   = MonotonicCount
> > +        self.dwLength         = dwLength
> > +        self.wRevision        = wRevision
> > +        self.wCertificateType = wCertificateType
> > +        self.CertType         = uuid.UUID (bytes =
> CertType)
> > +        self.CertData         =
> Buffer[self._StructSize:self._MonotonicCountSize +
> self.dwLength]
> > +        self.Payload          =
> Buffer[self._MonotonicCountSize + self.dwLength:]
> > +        self._Valid           = True
> > +        return self.Payload
> > +
> > +    def DumpInfo (self):
> > +        if not self._Valid:
> > +            raise ValueError
> > +        print
> ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount
> = {MonotonicCount:016X}'.format
> > (MonotonicCount = self.MonotonicCount))
> > +        print
> ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLengt
> h         = {dwLength:08X}'.format (dwLength =
> > self.dwLength))
> > +        print
> ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevisi
> on        = {wRevision:04X}'.format (wRevision =
> > self.wRevision))
> > +        print
> ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertif
> icateType = {wCertificateType:04X}'.format
> > (wCertificateType = self.wCertificateType))
> > +        print
> ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType
> = {Guid}'.format (Guid =
> > str(self.CertType).upper()))
> > +        print ('sizeof
> (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData)
> = {Size:08X}'.format (Size = len
> > (self.CertData)))
> > +        print ('sizeof (Payload)
> = {Size:08X}'.format (Size = len
> > (self.Payload)))
> > diff --git
> a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsule
> Header.py
> >
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsule
> Header.py
> > new file mode 100644
> > index 0000000000..2461fb5068
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsule
> Header.py
> > @@ -0,0 +1,302 @@
> > +## @file
> > +# Module that encodes and decodes a
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with
> > +# a payload.
> > +#
> > +# 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.
> > +#
> > +
> > +'''
> > +FmpCapsuleHeader
> > +'''
> > +
> > +import struct
> > +import uuid
> > +
> > +class FmpCapsuleImageHeaderClass (object):
> > +    # typedef struct {
> > +    #   UINT32   Version;
> > +    #
> > +    #   ///
> > +    #   /// Used to identify device firmware targeted
> by this update. This guid is matched by
> > +    #   /// system firmware against ImageTypeId field
> within a EFI_FIRMWARE_IMAGE_DESCRIPTOR
> > +    #   ///
> > +    #   EFI_GUID UpdateImageTypeId;
> > +    #
> > +    #   ///
> > +    #   /// Passed as ImageIndex in call to
> EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()
> > +    #   ///
> > +    #   UINT8    UpdateImageIndex;
> > +    #   UINT8    reserved_bytes[3];
> > +    #
> > +    #   ///
> > +    #   /// Size of the binary update image which
> immediately follows this structure
> > +    #   ///
> > +    #   UINT32   UpdateImageSize;
> > +    #
> > +    #   ///
> > +    #   /// Size of the VendorCode bytes which
> optionally immediately follow binary update image in the
> capsule
> > +    #   ///
> > +    #   UINT32   UpdateVendorCodeSize;
> > +    #
> > +    #   ///
> > +    #   /// The HardwareInstance to target with this
> update. If value is zero it means match all
> > +    #   /// HardwareInstances. This field allows
> update software to target only a single device in
> > +    #   /// cases where there are more than one
> device with the same ImageTypeId GUID.
> > +    #   /// This header is outside the signed data of
> the Authentication Info structure and
> > +    #   /// therefore can be modified without
> changing the Auth data.
> > +    #   ///
> > +    #   UINT64   UpdateHardwareInstance;
> > +    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
> > +    #
> > +    #  #define
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSIO
> N 0x00000002
> > +
> > +    _StructFormat = '<I16sB3BIIQ'
> > +    _StructSize   = struct.calcsize (_StructFormat)
> > +
> > +
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSIO
> N = 0x00000002
> > +
> > +    def __init__ (self):
> > +        self._Valid                 = False
> > +        self.Version                =
> self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_V
> ERSION
> > +        self.UpdateImageTypeId      = uuid.UUID
> ('00000000-0000-0000-0000-000000000000')
> > +        self.UpdateImageIndex       = 0
> > +        self.UpdateImageSize        = 0
> > +        self.UpdateVendorCodeSize   = 0
> > +        self.UpdateHardwareInstance =
> 0x0000000000000000
> > +        self.Payload                = b''
> > +        self.VendorCodeBytes        = b''
> > +
> > +    def Encode (self):
> > +        self.UpdateImageSize      = len
> (self.Payload)
> > +        self.UpdateVendorCodeSize = len
> (self.VendorCodeBytes)
> > +        FmpCapsuleImageHeader = struct.pack (
> > +
> self._StructFormat,
> > +
> self.Version,
> > +
> self.UpdateImageTypeId.bytes_le,
> > +
> self.UpdateImageIndex,
> > +                                         0,0,0,
> > +
> self.UpdateImageSize,
> > +
> self.UpdateVendorCodeSize,
> > +
> self.UpdateHardwareInstance
> > +                                         )
> > +        self._Valid = True
> > +        return FmpCapsuleImageHeader + self.Payload +
> self.VendorCodeBytes
> > +
> > +    def Decode (self, Buffer):
> > +        if len (Buffer) < self._StructSize:
> > +            raise ValueError
> > +        (Version, UpdateImageTypeId,
> UpdateImageIndex, r0, r1, r2, UpdateImageSize,
> UpdateVendorCodeSize,
> > UpdateHardwareInstance) = \
> > +            struct.unpack (
> > +                     self._StructFormat,
> > +                     Buffer[0:self._StructSize]
> > +                     )
> > +
> > +        if Version <
> self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_V
> ERSION:
> > +            raise ValueError
> > +        if UpdateImageIndex < 1:
> > +            raise ValueError
> > +        if UpdateImageSize + UpdateVendorCodeSize !=
> len (Buffer[self._StructSize:]):
> > +            raise ValueError
> > +
> > +        self.Version                = Version
> > +        self.UpdateImageTypeId      = uuid.UUID
> (bytes_le = UpdateImageTypeId)
> > +        self.UpdateImageIndex       =
> UpdateImageIndex
> > +        self.UpdateImageSize        = UpdateImageSize
> > +        self.UpdateVendorCodeSize   =
> UpdateVendorCodeSize
> > +        self.UpdateHardwareInstance =
> UpdateHardwareInstance
> > +        self.Payload                =
> Buffer[self._StructSize:self._StructSize +
> UpdateImageSize]
> > +        self.VendorCodeBytes        =
> Buffer[self._StructSize + UpdateImageSize:]
> > +        self._Valid                 = True
> > +        return Buffer[self._StructSize:]
> > +
> > +    def DumpInfo (self):
> > +        if not self._Valid:
> > +            raise ValueError
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version
> = {Version:08X}'.format
> > (Version = self.Version))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateIma
> geTypeId      =
> > {UpdateImageTypeId}'.format (UpdateImageTypeId =
> str(self.UpdateImageTypeId).upper()))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateIma
> geIndex       =
> > {UpdateImageIndex:08X}'.format (UpdateImageIndex =
> self.UpdateImageIndex))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateIma
> geSize        =
> > {UpdateImageSize:08X}'.format (UpdateImageSize =
> self.UpdateImageSize))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVen
> dorCodeSize   =
> > {UpdateVendorCodeSize:08X}'.format
> (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHar
> dwareInstance =
> > {UpdateHardwareInstance:016X}'.format
> (UpdateHardwareInstance = self.UpdateHardwareInstance))
> > +        print ('sizeof (Payload)
> = {Size:08X}'.format (Size = len
> > (self.Payload)))
> > +        print ('sizeof (VendorCodeBytes)
> = {Size:08X}'.format (Size = len
> > (self.VendorCodeBytes)))
> > +
> > +class FmpCapsuleHeaderClass (object):
> > +    # typedef struct {
> > +    #   UINT32 Version;
> > +    #
> > +    #   ///
> > +    #   /// The number of drivers included in the
> capsule and the number of corresponding
> > +    #   /// offsets stored in ItemOffsetList array.
> > +    #   ///
> > +    #   UINT16 EmbeddedDriverCount;
> > +    #
> > +    #   ///
> > +    #   /// The number of payload items included in
> the capsule and the number of
> > +    #   /// corresponding offsets stored in the
> ItemOffsetList array.
> > +    #   ///
> > +    #   UINT16 PayloadItemCount;
> > +    #
> > +    #   ///
> > +    #   /// Variable length array of dimension
> [EmbeddedDriverCount + PayloadItemCount]
> > +    #   /// containing offsets of each of the drivers
> and payload items contained within the capsule
> > +    #   ///
> > +    #   // UINT64 ItemOffsetList[];
> > +    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
> > +    #
> > +    #  #define
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
> 0x00000001
> > +    _StructFormat = '<IHH'
> > +    _StructSize   = struct.calcsize (_StructFormat)
> > +
> > +    _ItemOffsetFormat = '<Q'
> > +    _ItemOffsetSize   = struct.calcsize
> (_ItemOffsetFormat)
> > +
> > +
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION =
> 0x00000001
> > +
> > +    def __init__ (self):
> > +        self._Valid                     = False
> > +        self.Version                    =
> self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
> > +        self.EmbeddedDriverCount        = 0
> > +        self.PayloadItemCount           = 0
> > +        self._ItemOffsetList            = []
> > +        self._EmbeddedDriverList        = []
> > +        self._PayloadList               = []
> > +        self._FmpCapsuleImageHeaderList = []
> > +
> > +    def AddEmbeddedDriver (self, EmbeddedDriver):
> > +        self._EmbeddedDriverList.append
> (EmbeddedDriver)
> > +
> > +    def GetEmbeddedDriver (self, Index):
> > +        if Index > len (self._EmbeddedDriverList):
> > +            raise ValueError
> > +        return self._EmbeddedDriverList[Index]
> > +
> > +    def AddPayload (self, UpdateImageTypeId, Payload
> = b'', VendorCodeBytes = b'', HardwareInstance = 0):
> > +        self._PayloadList.append ((UpdateImageTypeId,
> Payload, VendorCodeBytes, HardwareInstance))
> > +
> > +    def GetFmpCapsuleImageHeader (self, Index):
> > +        if Index >= len
> (self._FmpCapsuleImageHeaderList):
> > +            raise ValueError
> > +        return self._FmpCapsuleImageHeaderList[Index]
> > +
> > +    def Encode (self):
> > +        self.EmbeddedDriverCount = len
> (self._EmbeddedDriverList)
> > +        self.PayloadItemCount    = len
> (self._PayloadList)
> > +
> > +        FmpCapsuleHeader = struct.pack (
> > +
> self._StructFormat,
> > +                                    self.Version,
> > +
> self.EmbeddedDriverCount,
> > +
> self.PayloadItemCount
> > +                                    )
> > +
> > +        FmpCapsuleData = b''
> > +        Offset = self._StructSize +
> (self.EmbeddedDriverCount + self.PayloadItemCount) *
> self._ItemOffsetSize
> > +        for EmbeddedDriver in
> self._EmbeddedDriverList:
> > +            FmpCapsuleData = FmpCapsuleData +
> EmbeddedDriver
> > +            self._ItemOffsetList.append (Offset)
> > +            Offset = Offset + len (EmbeddedDriver)
> > +        Index = 1
> > +        for (UpdateImageTypeId, Payload,
> VendorCodeBytes, HardwareInstance) in self._PayloadList:
> > +            FmpCapsuleImageHeader =
> FmpCapsuleImageHeaderClass ()
> > +            FmpCapsuleImageHeader.UpdateImageTypeId
> = UpdateImageTypeId
> > +            FmpCapsuleImageHeader.UpdateImageIndex
> = Index
> > +            FmpCapsuleImageHeader.Payload
> = Payload
> > +            FmpCapsuleImageHeader.VendorCodeBytes
> = VendorCodeBytes
> > +
> FmpCapsuleImageHeader.UpdateHardwareInstance =
> HardwareInstance
> > +            FmpCapsuleImage =
> FmpCapsuleImageHeader.Encode ()
> > +            FmpCapsuleData = FmpCapsuleData +
> FmpCapsuleImage
> > +
> > +            self._ItemOffsetList.append (Offset)
> > +            self._FmpCapsuleImageHeaderList.append
> (FmpCapsuleImageHeader)
> > +
> > +            Offset = Offset + len (FmpCapsuleImage)
> > +            Index = Index + 1
> > +
> > +        for Offset in self._ItemOffsetList:
> > +          FmpCapsuleHeader = FmpCapsuleHeader +
> struct.pack (self._ItemOffsetFormat, Offset)
> > +
> > +        self._Valid = True
> > +        return FmpCapsuleHeader + FmpCapsuleData
> > +
> > +    def Decode (self, Buffer):
> > +        if len (Buffer) < self._StructSize:
> > +            raise ValueError
> > +        (Version, EmbeddedDriverCount,
> PayloadItemCount) = \
> > +            struct.unpack (
> > +                     self._StructFormat,
> > +                     Buffer[0:self._StructSize]
> > +                     )
> > +        if Version <
> self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION
> :
> > +            raise ValueError
> > +
> > +        self.Version                    = Version
> > +        self.EmbeddedDriverCount        =
> EmbeddedDriverCount
> > +        self.PayloadItemCount           =
> PayloadItemCount
> > +        self._ItemOffsetList            = []
> > +        self._EmbeddedDriverList        = []
> > +        self._PayloadList               = []
> > +        self._FmpCapsuleImageHeaderList = []
> > +
> > +        #
> > +        # Parse the ItemOffsetList values
> > +        #
> > +        Offset = self._StructSize
> > +        for Index in range (0, EmbeddedDriverCount +
> PayloadItemCount):
> > +            ItemOffset = struct.unpack
> (self._ItemOffsetFormat, Buffer[Offset:Offset +
> self._ItemOffsetSize])[0]
> > +            if ItemOffset >= len (Buffer):
> > +                raise ValueError
> > +            self._ItemOffsetList.append (ItemOffset)
> > +            Offset = Offset + self._ItemOffsetSize
> > +        Result = Buffer[Offset:]
> > +
> > +        #
> > +        # Parse the EmbeddedDrivers
> > +        #
> > +        for Index in range (0, EmbeddedDriverCount):
> > +            Offset = self._ItemOffsetList[Index]
> > +            if Index < (len (self._ItemOffsetList) -
> 1):
> > +                Length = self._ItemOffsetList[Index +
> 1] - Offset
> > +            else:
> > +                Length = len (Buffer) - Offset
> > +            self.AddEmbeddedDriver
> (Buffer[Offset:Offset + Length])
> > +
> > +        #
> > +        # Parse the Payloads that are FMP Capsule
> Images
> > +        #
> > +        for Index in range (EmbeddedDriverCount,
> EmbeddedDriverCount + PayloadItemCount):
> > +            Offset = self._ItemOffsetList[Index]
> > +            if Index < (len (self._ItemOffsetList) -
> 1):
> > +                Length = self._ItemOffsetList[Index +
> 1] - Offset
> > +            else:
> > +                Length = len (Buffer) - Offset
> > +            FmpCapsuleImageHeader =
> FmpCapsuleImageHeaderClass ()
> > +            FmpCapsuleImageHeader.Decode
> (Buffer[Offset:Offset + Length])
> > +            self.AddPayload (
> > +
> FmpCapsuleImageHeader.UpdateImageTypeId,
> > +                   FmpCapsuleImageHeader.Payload,
> > +
> FmpCapsuleImageHeader.VendorCodeBytes
> > +                   )
> > +            self._FmpCapsuleImageHeaderList.append
> (FmpCapsuleImageHeader)
> > +
> > +        self._Valid = True
> > +        return Result
> > +
> > +    def DumpInfo (self):
> > +        if not self._Valid:
> > +            raise ValueError
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version
> = {Version:08X}'.format (Version =
> > self.Version))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverC
> ount = {EmbeddedDriverCount:08X}'.format
> > (EmbeddedDriverCount = self.EmbeddedDriverCount))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCoun
> t    = {PayloadItemCount:08X}'.format
> > (PayloadItemCount = self.PayloadItemCount))
> > +        print
> ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList
> = ')
> > +        for Offset in self._ItemOffsetList:
> > +            print ('  {Offset:016X}'.format (Offset =
> Offset))
> > +        for FmpCapsuleImageHeader in
> self._FmpCapsuleImageHeaderList:
> > +            FmpCapsuleImageHeader.DumpInfo ()
> > diff --git
> a/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsul
> eHeader.py
> >
> b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsul
> eHeader.py
> > new file mode 100644
> > index 0000000000..cfe1cb6c46
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsul
> eHeader.py
> > @@ -0,0 +1,136 @@
> > +## @file
> > +# Module that encodes and decodes a
> EFI_CAPSULE_HEADER with a payload
> > +#
> > +# 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.
> > +#
> > +
> > +'''
> > +UefiCapsuleHeader
> > +'''
> > +
> > +import struct
> > +import uuid
> > +
> > +class UefiCapsuleHeaderClass (object):
> > +    # typedef struct {
> > +    #   ///
> > +    #   /// A GUID that defines the contents of a
> capsule.
> > +    #   ///
> > +    #   EFI_GUID          CapsuleGuid;
> > +    #   ///
> > +    #   /// The size of the capsule header. This may
> be larger than the size of
> > +    #   /// the EFI_CAPSULE_HEADER since CapsuleGuid
> may imply
> > +    #   /// extended header entries
> > +    #   ///
> > +    #   UINT32            HeaderSize;
> > +    #   ///
> > +    #   /// Bit-mapped list describing the capsule
> attributes. The Flag values
> > +    #   /// of 0x0000 - 0xFFFF are defined by
> CapsuleGuid. Flag values
> > +    #   /// of 0x10000 - 0xFFFFFFFF are defined by
> this specification
> > +    #   ///
> > +    #   UINT32            Flags;
> > +    #   ///
> > +    #   /// Size in bytes of the capsule.
> > +    #   ///
> > +    #   UINT32            CapsuleImageSize;
> > +    # } EFI_CAPSULE_HEADER;
> > +    #
> > +    # #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET
> 0x00010000
> > +    # #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> 0x00020000
> > +    # #define CAPSULE_FLAGS_INITIATE_RESET
> 0x00040000
> > +    #
> > +    _StructFormat = '<16sIIII'
> > +    _StructSize   = struct.calcsize (_StructFormat)
> > +
> > +    EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID =
> uuid.UUID ('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')
> > +
> > +    _CAPSULE_FLAGS_PERSIST_ACROSS_RESET  = 0x00010000
> > +    _CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000
> > +    _CAPSULE_FLAGS_INITIATE_RESET        = 0x00040000
> > +
> > +    def __init__ (self):
> > +        self._Valid              = False
> > +        self.CapsuleGuid         =
> self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
> > +        self.HeaderSize          = self._StructSize
> > +        self.OemFlags            = 0x0000
> > +        self.PersistAcrossReset  = False
> > +        self.PopulateSystemTable = False
> > +        self.InitiateReset       = False
> > +        self.CapsuleImageSize    = self.HeaderSize
> > +        self.Payload             = b''
> > +
> > +    def Encode (self):
> > +        Flags = self.OemFlags
> > +        if self.PersistAcrossReset:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
> > +        if self.PopulateSystemTable:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> > +        if self.InitiateReset:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_INITIATE_RESET
> > +
> > +        self.CapsuleImageSize = self.HeaderSize + len
> (self.Payload)
> > +
> > +        UefiCapsuleHeader = struct.pack (
> > +
> self._StructFormat,
> > +
> self.CapsuleGuid.bytes_le,
> > +                                     self.HeaderSize,
> > +                                     Flags,
> > +
> self.CapsuleImageSize,
> > +                                     0
> > +                                     )
> > +        self._Valid = True
> > +        return UefiCapsuleHeader + self.Payload
> > +
> > +    def Decode (self, Buffer):
> > +        if len (Buffer) < self._StructSize:
> > +            raise ValueError
> > +        (CapsuleGuid, HeaderSize, Flags,
> CapsuleImageSize, Reserved) = \
> > +            struct.unpack (
> > +                     self._StructFormat,
> > +                     Buffer[0:self._StructSize]
> > +                     )
> > +        if HeaderSize < self._StructSize:
> > +            raise ValueError
> > +        if CapsuleImageSize != len (Buffer):
> > +            raise ValueError
> > +        self.CapsuleGuid         = uuid.UUID
> (bytes_le = CapsuleGuid)
> > +        self.HeaderSize          = HeaderSize
> > +        self.OemFlags            = Flags & 0xffff
> > +        self.PersistAcrossReset  = (Flags &
> self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0
> > +        self.PopulateSystemTable = (Flags &
> self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0
> > +        self.InitiateReset       = (Flags &
> self._CAPSULE_FLAGS_INITIATE_RESET) != 0
> > +        self.CapsuleImageSize    = CapsuleImageSize
> > +        self.Payload             =
> Buffer[self.HeaderSize:]
> > +
> > +        self._Valid              = True
> > +        return self.Payload
> > +
> > +    def DumpInfo (self):
> > +        if not self._Valid:
> > +            raise ValueError
> > +        Flags = self.OemFlags
> > +        if self.PersistAcrossReset:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET
> > +        if self.PopulateSystemTable:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
> > +        if self.InitiateReset:
> > +            Flags = Flags |
> self._CAPSULE_FLAGS_INITIATE_RESET
> > +        print ('EFI_CAPSULE_HEADER.CapsuleGuid      =
> {Guid}'.format (Guid = str(self.CapsuleGuid).upper()))
> > +        print ('EFI_CAPSULE_HEADER.HeaderSize       =
> {Size:08X}'.format (Size = self.HeaderSize))
> > +        print ('EFI_CAPSULE_HEADER.Flags            =
> {Flags:08X}'.format (Flags = Flags))
> > +        print ('  OEM Flags                         =
> {Flags:04X}'.format (Flags = self.OemFlags))
> > +        if self.PersistAcrossReset:
> > +            print ('
> CAPSULE_FLAGS_PERSIST_ACROSS_RESET')
> > +        if self.PopulateSystemTable:
> > +            print ('
> CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE')
> > +        if self.InitiateReset:
> > +            print ('  CAPSULE_FLAGS_INITIATE_RESET')
> > +        print ('EFI_CAPSULE_HEADER.CapsuleImageSize =
> {Size:08X}'.format (Size = self.CapsuleImageSize))
> > +        print ('sizeof (Payload)                    =
> {Size:08X}'.format (Size = len (self.Payload)))
> > diff --git
> a/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.p
> y
> >
> b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.p
> y
> > new file mode 100644
> > index 0000000000..d9db4aa919
> > --- /dev/null
> > +++
> b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.p
> y
> > @@ -0,0 +1,15 @@
> > +## @file
> > +# Python 'Common.Uefi.Capsule' package initialization
> file.
> > +#
> > +# This file is required to make Python interpreter
> treat the directory
> > +# as containing package.
> > +#
> > +# 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.
> > +#
> > diff --git
> a/BaseTools/Source/Python/Common/Uefi/__init__.py
> b/BaseTools/Source/Python/Common/Uefi/__init__.py
> > new file mode 100644
> > index 0000000000..d80219dcb3
> > --- /dev/null
> > +++ b/BaseTools/Source/Python/Common/Uefi/__init__.py
> > @@ -0,0 +1,15 @@
> > +## @file
> > +# Python 'Common.Uefi' package initialization file.
> > +#
> > +# This file is required to make Python interpreter
> treat the directory
> > +# as containing package.
> > +#
> > +# 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.
> > +#
> > --
> > 2.14.2.windows.3



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-05-31 16:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-29 22:56 [RFC 0/1] Add Capsule Generation Tools Michael D Kinney
2018-05-29 22:56 ` [RFC 1/1] BaseTools/Capsule: " Michael D Kinney
2018-05-31 14:25   ` Gao, Liming
2018-05-31 16:36     ` Kinney, Michael D

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox