BaseTools/Capsule: Add Capsule Generation Tools
authorKinney, Michael D <michael.d.kinney@intel.com>
Wed, 2 May 2018 03:54:46 +0000 (20:54 -0700)
committerKinney, Michael D <michael.d.kinney@intel.com>
Thu, 2 Aug 2018 21:35:20 +0000 (14:35 -0700)
https://bugzilla.tianocore.org/show_bug.cgi?id=945

Based on content from the following branch

https://github.com/Microsoft/MS_UEFI/tree/share/beta/CapsuleTools

* Convert C tools to Python
* Add common python modules to:
    BaseTools/Source/Python/Common/Uefi/Capsule
    BaseTools/Source/Python/Common/Edk2/Capsule
* Add GenerateCapsule.py to BaseTools/Source/Python/Capsule
* Add Windows and Posix wrappers for GenerateCapsule.py

usage: GenerateCapsule [-h] [-o OUTPUTFILE] (-e | -d | --dump-info)
                       [--capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset}]
                       [--capoemflag CAPSULEOEMFLAG] [--guid GUID]
                       [--hardware-instance HARDWAREINSTANCE]
                       [--monotonic-count MONOTONICCOUNT]
                       [--fw-version FWVERSION] [--lsv LOWESTSUPPORTEDVERSION]
                       [--pfx-file SIGNTOOLPFXFILE]
                       [--signer-private-cert OPENSSLSIGNERPRIVATECERTFILE]
                       [--other-public-cert OPENSSLOTHERPUBLICCERTFILE]
                       [--trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE]
                       [--signing-tool-path SIGNINGTOOLPATH] [--version] [-v]
                       [-q] [--debug [0-9]]
                       InputFile

Generate a capsule. Copyright (c) 2018, Intel Corporation. All rights
reserved.

positional arguments:
  InputFile             Input binary payload filename.

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUTFILE, --output OUTPUTFILE
                        Output filename.
  -e, --encode          Encode file
  -d, --decode          Decode file
  --dump-info           Display FMP Payload Header information
  --capflag {PersistAcrossReset,PopulateSystemTable,InitiateReset}
                        Capsule flag can be PersistAcrossReset, or
                        PopulateSystemTable or InitiateReset or not set
  --capoemflag CAPSULEOEMFLAG
                        Capsule OEM Flag is an integer between 0x0000 and
                        0xffff.
  --guid GUID           The FMP/ESRT GUID in registry format. Required for
                        encode operations.
  --hardware-instance HARDWAREINSTANCE
                        The 64-bit hardware instance. The default is
                        0x0000000000000000
  --monotonic-count MONOTONICCOUNT
                        64-bit monotonic count value in header. Default is
                        0x0000000000000000.
  --fw-version FWVERSION
                        The 32-bit version of the binary payload (e.g.
                        0x11223344 or 5678).
  --lsv LOWESTSUPPORTEDVERSION
                        The 32-bit lowest supported version of the binary
                        payload (e.g. 0x11223344 or 5678).
  --pfx-file SIGNTOOLPFXFILE
                        signtool PFX certificate filename.
  --signer-private-cert OPENSSLSIGNERPRIVATECERTFILE
                        OpenSSL signer private certificate filename.
  --other-public-cert OPENSSLOTHERPUBLICCERTFILE
                        OpenSSL other public certificate filename.
  --trusted-public-cert OPENSSLTRUSTEDPUBLICCERTFILE
                        OpenSSL trusted public certificate filename.
  --signing-tool-path SIGNINGTOOLPATH
                        Path to signtool or OpenSSL tool. Optional if path to
                        tools are already in PATH.
  --version             show program's version number and exit
  -v, --verbose         Turn on verbose output with informational messages
                        printed, including capsule headers and warning
                        messages.
  -q, --quiet           Disable all messages except fatal errors.
  --debug [0-9]         Set debug level

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
BaseTools/BinWrappers/PosixLike/GenerateCapsule [new file with mode: 0644]
BaseTools/BinWrappers/WindowsLike/GenerateCapsule.bat [new file with mode: 0644]
BaseTools/Source/Python/Capsule/GenerateCapsule.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Edk2/__init__.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py [new file with mode: 0644]
BaseTools/Source/Python/Common/Uefi/__init__.py [new file with mode: 0644]

diff --git a/BaseTools/BinWrappers/PosixLike/GenerateCapsule b/BaseTools/BinWrappers/PosixLike/GenerateCapsule
new file mode 100644 (file)
index 0000000..59a6c8b
--- /dev/null
@@ -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 (file)
index 0000000..ca442d1
--- /dev/null
@@ -0,0 +1 @@
+@%PYTHON_HOME%\python.exe %BASE_TOOLS_PATH%\Source\Python\Capsule\GenerateCapsule.py %*\r
diff --git a/BaseTools/Source/Python/Capsule/GenerateCapsule.py b/BaseTools/Source/Python/Capsule/GenerateCapsule.py
new file mode 100644 (file)
index 0000000..4018dc0
--- /dev/null
@@ -0,0 +1,522 @@
+## @file\r
+# Generate a capsule.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+GenerateCapsule\r
+'''\r
+\r
+import sys\r
+import argparse\r
+import uuid\r
+import struct\r
+import subprocess\r
+import os\r
+import tempfile\r
+import shutil\r
+import platform\r
+from Common.Uefi.Capsule.UefiCapsuleHeader import UefiCapsuleHeaderClass\r
+from Common.Uefi.Capsule.FmpCapsuleHeader  import FmpCapsuleHeaderClass\r
+from Common.Uefi.Capsule.FmpAuthHeader     import FmpAuthHeaderClass\r
+from Common.Edk2.Capsule.FmpPayloadHeader  import FmpPayloadHeaderClass\r
+\r
+#\r
+# Globals for help information\r
+#\r
+__prog__        = 'GenerateCapsule'\r
+__version__     = '0.9'\r
+__copyright__   = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r
+__description__ = 'Generate a capsule.\n'\r
+\r
+def SignPayloadSignTool (Payload, ToolPath, PfxFile):\r
+    #\r
+    # Create a temporary directory\r
+    #\r
+    TempDirectoryName = tempfile.mkdtemp()\r
+\r
+    #\r
+    # Generate temp file name for the payload contents\r
+    #\r
+    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r
+\r
+    #\r
+    # Create temporary payload file for signing\r
+    #\r
+    try:\r
+        File = open (TempFileName, mode='wb')\r
+        File.write (Payload)\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r
+\r
+    #\r
+    # Build signtool command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'signtool.exe'))\r
+    Command = Command + 'sign /fd sha256 /p7ce DetachedSignedData /p7co 1.2.840.113549.1.7.2 '\r
+    Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)\r
+    Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)\r
+    Command = Command + TempFileName\r
+\r
+    #\r
+    # Sign the input file using the specified private key\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate('')\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not run signtool.')\r
+\r
+    if Process.returncode != 0:\r
+        shutil.rmtree (TempDirectoryName)\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: signtool failed.')\r
+\r
+    #\r
+    # Read the signature from the generated output file\r
+    #\r
+    try:\r
+        File = open (TempFileName + '.p7', mode='rb')\r
+        Signature = File.read ()\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not read signature file.')\r
+\r
+    shutil.rmtree (TempDirectoryName)\r
+    return Signature\r
+\r
+def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):\r
+    print ('signtool verify is not supported.')\r
+    raise ValueError ('GenerateCapsule: error: signtool verify is not supported.')\r
+\r
+def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r
+    #\r
+    # Build openssl command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r
+    Command = Command + 'smime -sign -binary -outform DER -md sha256 '\r
+    Command = Command + '-signer "{Private}" -certfile "{Public}"'.format (Private = SignerPrivateCertFile, Public = OtherPublicCertFile)\r
+\r
+    #\r
+    # Sign the input file using the specified private key and capture signature from STDOUT\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate(input = Payload)\r
+        Signature = Result[0]\r
+    except:\r
+        raise ValueError ('GenerateCapsule: error: can not run openssl.')\r
+\r
+    if Process.returncode != 0:\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: openssl failed.')\r
+\r
+    return Signature\r
+\r
+def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile):\r
+    #\r
+    # Create a temporary directory\r
+    #\r
+    TempDirectoryName = tempfile.mkdtemp()\r
+\r
+    #\r
+    # Generate temp file name for the payload contents\r
+    #\r
+    TempFileName = os.path.join (TempDirectoryName, 'Payload.bin')\r
+\r
+    #\r
+    # Create temporary payload file for verification\r
+    #\r
+    try:\r
+        File = open (TempFileName, mode='wb')\r
+        File.write (Payload)\r
+        File.close ()\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r
+\r
+    #\r
+    # Build openssl command\r
+    #\r
+    if ToolPath is None:\r
+        ToolPath = ''\r
+    Command = ''\r
+    Command = Command + '"{Path}" '.format (Path = os.path.join (ToolPath, 'openssl'))\r
+    Command = Command + 'smime -verify -inform DER '\r
+    Command = Command + '-content {Content} -CAfile "{Public}"'.format (Content = TempFileName, Public = TrustedPublicCertFile)\r
+\r
+    #\r
+    # Verify signature\r
+    #\r
+    try:\r
+        Process = subprocess.Popen (Command, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)\r
+        Result = Process.communicate(input = CertData)\r
+    except:\r
+        shutil.rmtree (TempDirectoryName)\r
+        raise ValueError ('GenerateCapsule: error: can not run openssl.')\r
+\r
+    if Process.returncode != 0:\r
+        shutil.rmtree (TempDirectoryName)\r
+        print (Result[1].decode())\r
+        raise ValueError ('GenerateCapsule: error: openssl failed.')\r
+\r
+    shutil.rmtree (TempDirectoryName)\r
+    return Payload\r
+\r
+if __name__ == '__main__':\r
+    def convert_arg_line_to_args(arg_line):\r
+        for arg in arg_line.split():\r
+            if not arg.strip():\r
+                continue\r
+            yield arg\r
+\r
+    def ValidateUnsignedInteger (Argument):\r
+        try:\r
+            Value = int (Argument, 0)\r
+        except:\r
+            Message = '{Argument} is not a valid integer value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        if Value < 0:\r
+            Message = '{Argument} is a negative value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        return Value\r
+\r
+    def ValidateRegistryFormatGuid (Argument):\r
+        try:\r
+            Value = uuid.UUID (Argument)\r
+        except:\r
+            Message = '{Argument} is not a valid registry format GUID value.'.format (Argument = Argument)\r
+            raise argparse.ArgumentTypeError (Message)\r
+        return Value\r
+\r
+    #\r
+    # Create command line argument parser object\r
+    #\r
+    parser = argparse.ArgumentParser (\r
+                        prog = __prog__,\r
+                        description = __description__ + __copyright__,\r
+                        conflict_handler = 'resolve',\r
+                        fromfile_prefix_chars = '@'\r
+                        )\r
+    parser.convert_arg_line_to_args = convert_arg_line_to_args\r
+\r
+    #\r
+    # Add input and output file arguments\r
+    #\r
+    parser.add_argument("InputFile",  type = argparse.FileType('rb'),\r
+                        help = "Input binary payload filename.")\r
+    parser.add_argument("-o", "--output", dest = 'OutputFile', type = argparse.FileType('wb'),\r
+                        help = "Output filename.")\r
+    #\r
+    # Add group for -e and -d flags that are mutually exclusive and required\r
+    #\r
+    group = parser.add_mutually_exclusive_group (required = True)\r
+    group.add_argument ("-e", "--encode", dest = 'Encode', action = "store_true",\r
+                        help = "Encode file")\r
+    group.add_argument ("-d", "--decode", dest = 'Decode', action = "store_true",\r
+                        help = "Decode file")\r
+    group.add_argument ("--dump-info", dest = 'DumpInfo', action = "store_true",\r
+                        help = "Display FMP Payload Header information")\r
+    #\r
+    # Add optional arguments for this command\r
+    #\r
+    parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],\r
+                         choices=['PersistAcrossReset', 'PopulateSystemTable', 'InitiateReset'],\r
+                         help = "Capsule flag can be PersistAcrossReset, or PopulateSystemTable or InitiateReset or not set")\r
+    parser.add_argument ("--capoemflag", dest = 'CapsuleOemFlag', type = ValidateUnsignedInteger, default = 0x0000,\r
+                         help = "Capsule OEM Flag is an integer between 0x0000 and 0xffff.")\r
+\r
+    parser.add_argument ("--guid", dest = 'Guid', type = ValidateRegistryFormatGuid,\r
+                         help = "The FMP/ESRT GUID in registry format.  Required for encode operations.")\r
+    parser.add_argument ("--hardware-instance", dest = 'HardwareInstance', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r
+                         help = "The 64-bit hardware instance.  The default is 0x0000000000000000")\r
+\r
+\r
+    parser.add_argument ("--monotonic-count", dest = 'MonotonicCount', type = ValidateUnsignedInteger, default = 0x0000000000000000,\r
+                         help = "64-bit monotonic count value in header.  Default is 0x0000000000000000.")\r
+\r
+    parser.add_argument ("--fw-version", dest = 'FwVersion', type = ValidateUnsignedInteger,\r
+                         help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678).")\r
+    parser.add_argument ("--lsv", dest = 'LowestSupportedVersion', type = ValidateUnsignedInteger,\r
+                         help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678).")\r
+\r
+    parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),\r
+                         help="signtool PFX certificate filename.")\r
+\r
+    parser.add_argument ("--signer-private-cert", dest='OpenSslSignerPrivateCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL signer private certificate filename.")\r
+    parser.add_argument ("--other-public-cert", dest='OpenSslOtherPublicCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL other public certificate filename.")\r
+    parser.add_argument ("--trusted-public-cert", dest='OpenSslTrustedPublicCertFile', type=argparse.FileType('rb'),\r
+                         help="OpenSSL trusted public certificate filename.")\r
+\r
+    parser.add_argument ("--signing-tool-path", dest = 'SigningToolPath',\r
+                         help = "Path to signtool or OpenSSL tool.  Optional if path to tools are already in PATH.")\r
+\r
+    #\r
+    # Add optional arguments common to all operations\r
+    #\r
+    parser.add_argument ('--version', action='version', version='%(prog)s ' + __version__)\r
+    parser.add_argument ("-v", "--verbose", dest = 'Verbose', action = "store_true",\r
+                         help = "Turn on verbose output with informational messages printed, including capsule headers and warning messages.")\r
+    parser.add_argument ("-q", "--quiet", dest = 'Quiet', action = "store_true",\r
+                         help = "Disable all messages except fatal errors.")\r
+    parser.add_argument ("--debug", dest = 'Debug', type = int, metavar = '[0-9]', choices = range (0, 10), default = 0,\r
+                         help = "Set debug level")\r
+\r
+    #\r
+    # Parse command line arguments\r
+    #\r
+    args = parser.parse_args()\r
+\r
+    #\r
+    # Perform additional argument verification\r
+    #\r
+    if args.Encode:\r
+        if args.Guid is None:\r
+            parser.error ('the following option is required: --guid')\r
+        if 'PersistAcrossReset' not in args.CapsuleFlag:\r
+            if 'PopulateSystemTable' in args.CapsuleFlag:\r
+                parser.error ('--capflag PopulateSystemTable also requires --capflag PersistAcrossReset')\r
+            if 'InitiateReset' in args.CapsuleFlag:\r
+                parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r
+\r
+    UseSignTool = args.SignToolPfxFile is not None\r
+    UseOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None and\r
+                   args.OpenSslOtherPublicCertFile is not None and\r
+                   args.OpenSslTrustedPublicCertFile is not None)\r
+    AnyOpenSsl  = (args.OpenSslSignerPrivateCertFile is not None or\r
+                   args.OpenSslOtherPublicCertFile is not None or\r
+                   args.OpenSslTrustedPublicCertFile is not None)\r
+    if args.Encode or args.Decode:\r
+        if args.OutputFile is None:\r
+            parser.error ('the following option is required for all encode and decode operations: --output')\r
+\r
+        if UseSignTool and AnyOpenSsl:\r
+            parser.error ('Providing both signtool and OpenSSL options is not supported')\r
+        if not UseSignTool and not UseOpenSsl and AnyOpenSsl:\r
+            parser.error ('all the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')\r
+        if UseSignTool and platform.system() != 'Windows':\r
+            parser.error ('Use of signtool is not supported on this operating system.')\r
+        if args.Encode and (UseSignTool or UseOpenSsl):\r
+            if args.FwVersion is None or args.LowestSupportedVersion is None:\r
+                parser.error ('the following options are required: --fw-version, --lsv')\r
+\r
+        if UseSignTool:\r
+            args.SignToolPfxFile.close()\r
+            args.SignToolPfxFile = args.SignToolPfxFile.name\r
+        if UseOpenSsl:\r
+            args.OpenSslSignerPrivateCertFile.close()\r
+            args.OpenSslOtherPublicCertFile.close()\r
+            args.OpenSslTrustedPublicCertFile.close()\r
+            args.OpenSslSignerPrivateCertFile = args.OpenSslSignerPrivateCertFile.name\r
+            args.OpenSslOtherPublicCertFile   = args.OpenSslOtherPublicCertFile.name\r
+            args.OpenSslTrustedPublicCertFile = args.OpenSslTrustedPublicCertFile.name\r
+\r
+    #\r
+    # Read binary input file\r
+    #\r
+    try:\r
+        if args.Verbose:\r
+            print ('Read binary input file {File}'.format (File = args.InputFile.name))\r
+        Buffer = args.InputFile.read ()\r
+        args.InputFile.close ()\r
+    except:\r
+        print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = args.InputFile.name))\r
+        sys.exit (1)\r
+\r
+    #\r
+    # Create objects\r
+    #\r
+    UefiCapsuleHeader = UefiCapsuleHeaderClass ()\r
+    FmpCapsuleHeader  = FmpCapsuleHeaderClass ()\r
+    FmpAuthHeader     = FmpAuthHeaderClass ()\r
+    FmpPayloadHeader  = FmpPayloadHeaderClass ()\r
+\r
+    if args.Encode:\r
+        Result = Buffer\r
+        if UseSignTool or UseOpenSsl:\r
+            try:\r
+                FmpPayloadHeader.FwVersion              = args.FwVersion\r
+                FmpPayloadHeader.LowestSupportedVersion = args.LowestSupportedVersion\r
+                FmpPayloadHeader.Payload                = Result\r
+                Result = FmpPayloadHeader.Encode ()\r
+                if args.Verbose:\r
+                    FmpPayloadHeader.DumpInfo ()\r
+            except:\r
+                print ('GenerateCapsule: error: can not encode FMP Payload Header')\r
+                sys.exit (1)\r
+\r
+            #\r
+            # Sign image with 64-bit MonotonicCount appended to end of image\r
+            #\r
+            try:\r
+                if UseSignTool:\r
+                    CertData = SignPayloadSignTool (\r
+                                 Result + struct.pack ('<Q', args.MonotonicCount),\r
+                                 args.SigningToolPath,\r
+                                 args.SignToolPfxFile\r
+                                 )\r
+                else:\r
+                    CertData = SignPayloadOpenSsl (\r
+                                 Result + struct.pack ('<Q', args.MonotonicCount),\r
+                                 args.SigningToolPath,\r
+                                 args.OpenSslSignerPrivateCertFile,\r
+                                 args.OpenSslOtherPublicCertFile,\r
+                                 args.OpenSslTrustedPublicCertFile\r
+                                 )\r
+            except:\r
+                print ('GenerateCapsule: error: can not sign payload')\r
+                raise\r
+                sys.exit (1)\r
+\r
+            try:\r
+                FmpAuthHeader.MonotonicCount = args.MonotonicCount\r
+                FmpAuthHeader.CertData       = CertData\r
+                FmpAuthHeader.Payload        = Result\r
+                Result = FmpAuthHeader.Encode ()\r
+                if args.Verbose:\r
+                    FmpAuthHeader.DumpInfo ()\r
+            except:\r
+                print ('GenerateCapsule: error: can not encode FMP Auth Header')\r
+                sys.exit (1)\r
+\r
+        try:\r
+            FmpCapsuleHeader.AddPayload (args.Guid, Result, HardwareInstance = args.HardwareInstance)\r
+            Result = FmpCapsuleHeader.Encode ()\r
+            if args.Verbose:\r
+                FmpCapsuleHeader.DumpInfo ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not encode FMP Capsule Header')\r
+            sys.exit (1)\r
+\r
+        try:\r
+            UefiCapsuleHeader.OemFlags            = args.CapsuleOemFlag\r
+            UefiCapsuleHeader.PersistAcrossReset  = 'PersistAcrossReset'  in args.CapsuleFlag\r
+            UefiCapsuleHeader.PopulateSystemTable = 'PopulateSystemTable' in args.CapsuleFlag\r
+            UefiCapsuleHeader.InitiateReset       = 'InitiateReset'       in args.CapsuleFlag\r
+            UefiCapsuleHeader.Payload             = Result\r
+            Result = UefiCapsuleHeader.Encode ()\r
+            if args.Verbose:\r
+                UefiCapsuleHeader.DumpInfo ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not encode UEFI Capsule Header')\r
+            sys.exit (1)\r
+\r
+    elif args.Decode:\r
+        try:\r
+            Result = UefiCapsuleHeader.Decode (Buffer)\r
+            FmpCapsuleHeader.Decode (Result)\r
+            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+            if args.Verbose:\r
+                print ('========')\r
+                UefiCapsuleHeader.DumpInfo ()\r
+                print ('--------')\r
+                FmpCapsuleHeader.DumpInfo ()\r
+            if UseSignTool or UseOpenSsl:\r
+                Result = FmpAuthHeader.Decode (Result)\r
+\r
+                #\r
+                # Verify Image with 64-bit MonotonicCount appended to end of image\r
+                #\r
+                try:\r
+                  if UseSignTool:\r
+                      CertData = VerifyPayloadSignTool (\r
+                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+                                   FmpAuthHeader.CertData,\r
+                                   args.SigningToolPath,\r
+                                   args.SignToolPfxFile\r
+                                   )\r
+                  else:\r
+                      CertData = VerifyPayloadOpenSsl (\r
+                                   FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+                                   FmpAuthHeader.CertData,\r
+                                   args.SigningToolPath,\r
+                                   args.OpenSslSignerPrivateCertFile,\r
+                                   args.OpenSslOtherPublicCertFile,\r
+                                   args.OpenSslTrustedPublicCertFile\r
+                                   )\r
+                except ValueError:\r
+                    print ('GenerateCapsule: warning: can not verify payload.')\r
+\r
+                Result = FmpPayloadHeader.Decode (Result)\r
+                if args.Verbose:\r
+                    print ('--------')\r
+                    FmpAuthHeader.DumpInfo ()\r
+                    print ('--------')\r
+                    FmpPayloadHeader.DumpInfo ()\r
+            else:\r
+                if args.Verbose:\r
+                    print ('--------')\r
+                    print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+                    print ('--------')\r
+                    print ('No FMP_PAYLOAD_HEADER')\r
+            if args.Verbose:\r
+                print ('========')\r
+        except:\r
+            print ('GenerateCapsule: error: can not decode capsule')\r
+            raise\r
+            sys.exit (1)\r
+\r
+    elif args.DumpInfo:\r
+        try:\r
+            Result = UefiCapsuleHeader.Decode (Buffer)\r
+            FmpCapsuleHeader.Decode (Result)\r
+            Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+            print ('========')\r
+            UefiCapsuleHeader.DumpInfo ()\r
+            print ('--------')\r
+            FmpCapsuleHeader.DumpInfo ()\r
+            try:\r
+                Result = FmpAuthHeader.Decode (Result)\r
+                Result = FmpPayloadHeader.Decode (Result)\r
+                print ('--------')\r
+                FmpAuthHeader.DumpInfo ()\r
+                print ('--------')\r
+                FmpPayloadHeader.DumpInfo ()\r
+            except:\r
+                print ('--------')\r
+                print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+                print ('--------')\r
+                print ('No FMP_PAYLOAD_HEADER')\r
+            print ('========')\r
+        except:\r
+            print ('GenerateCapsule: error: can not decode capsule')\r
+            sys.exit (1)\r
+    else:\r
+        print('GenerateCapsule: error: invalid options')\r
+        sys.exit (1)\r
+\r
+    #\r
+    # Write binary output file\r
+    #\r
+    if args.OutputFile is not None:\r
+        try:\r
+            if args.Verbose:\r
+                print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r
+            args.OutputFile.write (Result)\r
+            args.OutputFile.close ()\r
+        except:\r
+            print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = args.OutputFile.name))\r
+            sys.exit (1)\r
+\r
+    if args.Verbose:\r
+        print('Success')\r
diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py b/BaseTools/Source/Python/Common/Edk2/Capsule/FmpPayloadHeader.py
new file mode 100644 (file)
index 0000000..0ed5175
--- /dev/null
@@ -0,0 +1,91 @@
+## @file\r
+# Module that encodes and decodes a FMP_PAYLOAD_HEADER with a payload.\r
+# The FMP_PAYLOAD_HEADER is processed by the FmpPayloadHeaderLib in the\r
+# FmpDevicePkg.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+FmpPayloadHeader\r
+'''\r
+\r
+import struct\r
+\r
+def _SIGNATURE_32 (A, B, C, D):\r
+    return struct.unpack ('=I',bytearray (A + B + C + D, 'ascii'))[0]\r
+\r
+def _SIGNATURE_32_TO_STRING (Signature):\r
+    return struct.pack ("<I", Signature).decode ()\r
+\r
+class FmpPayloadHeaderClass (object):\r
+    #\r
+    # typedef struct {\r
+    #   UINT32  Signature;\r
+    #   UINT32  HeaderSize;\r
+    #   UINT32  FwVersion;\r
+    #   UINT32  LowestSupportedVersion;\r
+    # } FMP_PAYLOAD_HEADER;\r
+    #\r
+    # #define FMP_PAYLOAD_HEADER_SIGNATURE SIGNATURE_32 ('M', 'S', 'S', '1')\r
+    #\r
+    _StructFormat = '<IIII'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    _FMP_PAYLOAD_HEADER_SIGNATURE = _SIGNATURE_32 ('M', 'S', 'S', '1')\r
+\r
+    def __init__ (self):\r
+        self._Valid                 = False\r
+        self.Signature              = self._FMP_PAYLOAD_HEADER_SIGNATURE\r
+        self.HeaderSize             = self._StructSize\r
+        self.FwVersion              = 0x00000000\r
+        self.LowestSupportedVersion = 0x00000000\r
+        self.Payload                = b''\r
+\r
+    def Encode (self):\r
+        FmpPayloadHeader = struct.pack (\r
+                                     self._StructFormat,\r
+                                     self.Signature,\r
+                                     self.HeaderSize,\r
+                                     self.FwVersion,\r
+                                     self.LowestSupportedVersion\r
+                                     )\r
+        self._Valid = True\r
+        return FmpPayloadHeader + self.Payload\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (Signature, HeaderSize, FwVersion, LowestSupportedVersion) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+        if Signature != self._FMP_PAYLOAD_HEADER_SIGNATURE:\r
+            raise ValueError\r
+        if HeaderSize < self._StructSize:\r
+            raise ValueError\r
+        self.Signature              = Signature\r
+        self.HeaderSize             = HeaderSize\r
+        self.FwVersion              = FwVersion\r
+        self.LowestSupportedVersion = LowestSupportedVersion\r
+        self.Payload                = Buffer[self.HeaderSize:]\r
+\r
+        self._Valid                 = True\r
+        return self.Payload\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('FMP_PAYLOAD_HEADER.Signature              = {Signature:08X} ({SignatureString})'.format (Signature = self.Signature, SignatureString = _SIGNATURE_32_TO_STRING (self.Signature)))\r
+        print ('FMP_PAYLOAD_HEADER.HeaderSize             = {HeaderSize:08X}'.format (HeaderSize = self.HeaderSize))\r
+        print ('FMP_PAYLOAD_HEADER.FwVersion              = {FwVersion:08X}'.format (FwVersion = self.FwVersion))\r
+        print ('FMP_PAYLOAD_HEADER.LowestSupportedVersion = {LowestSupportedVersion:08X}'.format (LowestSupportedVersion = self.LowestSupportedVersion))\r
+        print ('sizeof (Payload)                          = {Size:08X}'.format (Size = len (self.Payload)))\r
diff --git a/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py b/BaseTools/Source/Python/Common/Edk2/Capsule/__init__.py
new file mode 100644 (file)
index 0000000..71c6f06
--- /dev/null
@@ -0,0 +1,15 @@
+## @file\r
+# Python 'Common.Edk2.Capsule' package initialization file.\r
+#\r
+# This file is required to make Python interpreter treat the directory\r
+# as containing package.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
diff --git a/BaseTools/Source/Python/Common/Edk2/__init__.py b/BaseTools/Source/Python/Common/Edk2/__init__.py
new file mode 100644 (file)
index 0000000..97d925c
--- /dev/null
@@ -0,0 +1,15 @@
+## @file\r
+# Python 'Common.Edk2' package initialization file.\r
+#\r
+# This file is required to make Python interpreter treat the directory\r
+# as containing package.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpAuthHeader.py
new file mode 100644 (file)
index 0000000..aec52bf
--- /dev/null
@@ -0,0 +1,184 @@
+## @file\r
+# Module that encodes and decodes a EFI_FIRMWARE_IMAGE_AUTHENTICATION with\r
+# certificate data and payload data.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+FmpAuthHeader\r
+'''\r
+\r
+import struct\r
+import uuid\r
+\r
+class FmpAuthHeaderClass (object):\r
+    # ///\r
+    # /// Image Attribute -Authentication Required\r
+    # ///\r
+    # typedef struct {\r
+    #   ///\r
+    #   /// It is included in the signature of AuthInfo. It is used to ensure freshness/no replay.\r
+    #   /// It is incremented during each firmware image operation.\r
+    #   ///\r
+    #   UINT64                                  MonotonicCount;\r
+    #   ///\r
+    #   /// Provides the authorization for the firmware image operations. It is a signature across\r
+    #   /// the image data and the Monotonic Count value. Caller uses the private key that is\r
+    #   /// associated with a public key that has been provisioned via the key exchange.\r
+    #   /// Because this is defined as a signature, WIN_CERTIFICATE_UEFI_GUID.CertType must\r
+    #   /// be EFI_CERT_TYPE_PKCS7_GUID.\r
+    #   ///\r
+    #   WIN_CERTIFICATE_UEFI_GUID               AuthInfo;\r
+    # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;\r
+    #\r
+    # ///\r
+    # /// Certificate which encapsulates a GUID-specific digital signature\r
+    # ///\r
+    # typedef struct {\r
+    #   ///\r
+    #   /// This is the standard WIN_CERTIFICATE header, where\r
+    #   /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID.\r
+    #   ///\r
+    #   WIN_CERTIFICATE   Hdr;\r
+    #   ///\r
+    #   /// This is the unique id which determines the\r
+    #   /// format of the CertData. .\r
+    #   ///\r
+    #   EFI_GUID          CertType;\r
+    #   ///\r
+    #   /// The following is the certificate data. The format of\r
+    #   /// the data is determined by the CertType.\r
+    #   /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,\r
+    #   /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.\r
+    #   ///\r
+    #   UINT8            CertData[1];\r
+    # } WIN_CERTIFICATE_UEFI_GUID;\r
+    #\r
+    # ///\r
+    # /// The WIN_CERTIFICATE structure is part of the PE/COFF specification.\r
+    # ///\r
+    # typedef struct {\r
+    #   ///\r
+    #   /// The length of the entire certificate,\r
+    #   /// including the length of the header, in bytes.\r
+    #   ///\r
+    #   UINT32  dwLength;\r
+    #   ///\r
+    #   /// The revision level of the WIN_CERTIFICATE\r
+    #   /// structure. The current revision level is 0x0200.\r
+    #   ///\r
+    #   UINT16  wRevision;\r
+    #   ///\r
+    #   /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI\r
+    #   /// certificate types. The UEFI specification reserves the range of\r
+    #   /// certificate type values from 0x0EF0 to 0x0EFF.\r
+    #   ///\r
+    #   UINT16  wCertificateType;\r
+    #   ///\r
+    #   /// The following is the actual certificate. The format of\r
+    #   /// the certificate depends on wCertificateType.\r
+    #   ///\r
+    #   /// UINT8 bCertificate[ANYSIZE_ARRAY];\r
+    #   ///\r
+    # } WIN_CERTIFICATE;\r
+    #\r
+    # #define WIN_CERT_TYPE_EFI_GUID         0x0EF1\r
+    #\r
+    # ///\r
+    # /// This identifies a signature containing a DER-encoded PKCS #7 version 1.5 [RFC2315]\r
+    # /// SignedData value.\r
+    # ///\r
+    # #define EFI_CERT_TYPE_PKCS7_GUID \\r
+    #   { \\r
+    #     0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \\r
+    #   }\r
+\r
+    _StructFormat = '<QIHH16s'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    _MonotonicCountFormat = '<Q'\r
+    _MonotonicCountSize   = struct.calcsize (_MonotonicCountFormat)\r
+\r
+    _StructAuthInfoFormat = '<IHH16s'\r
+    _StructAuthInfoSize   = struct.calcsize (_StructAuthInfoFormat)\r
+\r
+    _WIN_CERT_REVISION        = 0x0200\r
+    _WIN_CERT_TYPE_EFI_GUID   = 0x0EF1\r
+    _EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID ('4aafd29d-68df-49ee-8aa9-347d375665a7')\r
+\r
+    def __init__ (self):\r
+        self._Valid              = False\r
+        self.MonotonicCount      = 0\r
+        self.dwLength            = self._StructAuthInfoSize\r
+        self.wRevision           = self._WIN_CERT_REVISION\r
+        self.wCertificateType    = self._WIN_CERT_TYPE_EFI_GUID\r
+        self.CertType            = self._EFI_CERT_TYPE_PKCS7_GUID\r
+        self.CertData            = b''\r
+        self.Payload             = b''\r
+\r
+\r
+    def Encode (self):\r
+        if self.wRevision != self._WIN_CERT_REVISION:\r
+            raise ValueError\r
+        if self.wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:\r
+            raise ValueError\r
+        if self.CertType != self._EFI_CERT_TYPE_PKCS7_GUID:\r
+            raise ValueError\r
+        self.dwLength = self._StructAuthInfoSize + len (self.CertData)\r
+\r
+        FmpAuthHeader = struct.pack (\r
+                                 self._StructFormat,\r
+                                 self.MonotonicCount,\r
+                                 self.dwLength,\r
+                                 self.wRevision,\r
+                                 self.wCertificateType,\r
+                                 self.CertType.bytes_le\r
+                                 )\r
+        self._Valid = True\r
+\r
+        return FmpAuthHeader + self.CertData + self.Payload\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (MonotonicCount, dwLength, wRevision, wCertificateType, CertType) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+        if dwLength < self._StructAuthInfoSize:\r
+            raise ValueError\r
+        if wRevision != self._WIN_CERT_REVISION:\r
+            raise ValueError\r
+        if wCertificateType != self._WIN_CERT_TYPE_EFI_GUID:\r
+            raise ValueError\r
+        if CertType != self._EFI_CERT_TYPE_PKCS7_GUID.bytes_le:\r
+            raise ValueError\r
+        self.MonotonicCount   = MonotonicCount\r
+        self.dwLength         = dwLength\r
+        self.wRevision        = wRevision\r
+        self.wCertificateType = wCertificateType\r
+        self.CertType         = uuid.UUID (bytes = CertType)\r
+        self.CertData         = Buffer[self._StructSize:self._MonotonicCountSize + self.dwLength]\r
+        self.Payload          = Buffer[self._MonotonicCountSize + self.dwLength:]\r
+        self._Valid           = True\r
+        return self.Payload\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.MonotonicCount                = {MonotonicCount:016X}'.format (MonotonicCount = self.MonotonicCount))\r
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.dwLength         = {dwLength:08X}'.format (dwLength = self.dwLength))\r
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wRevision        = {wRevision:04X}'.format (wRevision = self.wRevision))\r
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.Hdr.wCertificateType = {wCertificateType:04X}'.format (wCertificateType = self.wCertificateType))\r
+        print ('EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertType             = {Guid}'.format (Guid = str(self.CertType).upper()))\r
+        print ('sizeof (EFI_FIRMWARE_IMAGE_AUTHENTICATION.AuthInfo.CertData)    = {Size:08X}'.format (Size = len (self.CertData)))\r
+        print ('sizeof (Payload)                                                = {Size:08X}'.format (Size = len (self.Payload)))\r
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
new file mode 100644 (file)
index 0000000..2461fb5
--- /dev/null
@@ -0,0 +1,302 @@
+## @file\r
+# Module that encodes and decodes a EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER with\r
+# a payload.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+FmpCapsuleHeader\r
+'''\r
+\r
+import struct\r
+import uuid\r
+\r
+class FmpCapsuleImageHeaderClass (object):\r
+    # typedef struct {\r
+    #   UINT32   Version;\r
+    #\r
+    #   ///\r
+    #   /// Used to identify device firmware targeted by this update. This guid is matched by\r
+    #   /// system firmware against ImageTypeId field within a EFI_FIRMWARE_IMAGE_DESCRIPTOR\r
+    #   ///\r
+    #   EFI_GUID UpdateImageTypeId;\r
+    #\r
+    #   ///\r
+    #   /// Passed as ImageIndex in call to EFI_FIRMWARE_MANAGEMENT_PROTOCOL.SetImage ()\r
+    #   ///\r
+    #   UINT8    UpdateImageIndex;\r
+    #   UINT8    reserved_bytes[3];\r
+    #\r
+    #   ///\r
+    #   /// Size of the binary update image which immediately follows this structure\r
+    #   ///\r
+    #   UINT32   UpdateImageSize;\r
+    #\r
+    #   ///\r
+    #   /// Size of the VendorCode bytes which optionally immediately follow binary update image in the capsule\r
+    #   ///\r
+    #   UINT32   UpdateVendorCodeSize;\r
+    #\r
+    #   ///\r
+    #   /// The HardwareInstance to target with this update. If value is zero it means match all\r
+    #   /// HardwareInstances. This field allows update software to target only a single device in\r
+    #   /// cases where there are more than one device with the same ImageTypeId GUID.\r
+    #   /// This header is outside the signed data of the Authentication Info structure and\r
+    #   /// therefore can be modified without changing the Auth data.\r
+    #   ///\r
+    #   UINT64   UpdateHardwareInstance;\r
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;\r
+    #\r
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002\r
+\r
+    _StructFormat = '<I16sB3BIIQ'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002\r
+\r
+    def __init__ (self):\r
+        self._Valid                 = False\r
+        self.Version                = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION\r
+        self.UpdateImageTypeId      = uuid.UUID ('00000000-0000-0000-0000-000000000000')\r
+        self.UpdateImageIndex       = 0\r
+        self.UpdateImageSize        = 0\r
+        self.UpdateVendorCodeSize   = 0\r
+        self.UpdateHardwareInstance = 0x0000000000000000\r
+        self.Payload                = b''\r
+        self.VendorCodeBytes        = b''\r
+\r
+    def Encode (self):\r
+        self.UpdateImageSize      = len (self.Payload)\r
+        self.UpdateVendorCodeSize = len (self.VendorCodeBytes)\r
+        FmpCapsuleImageHeader = struct.pack (\r
+                                         self._StructFormat,\r
+                                         self.Version,\r
+                                         self.UpdateImageTypeId.bytes_le,\r
+                                         self.UpdateImageIndex,\r
+                                         0,0,0,\r
+                                         self.UpdateImageSize,\r
+                                         self.UpdateVendorCodeSize,\r
+                                         self.UpdateHardwareInstance\r
+                                         )\r
+        self._Valid = True\r
+        return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+\r
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION:\r
+            raise ValueError\r
+        if UpdateImageIndex < 1:\r
+            raise ValueError\r
+        if UpdateImageSize + UpdateVendorCodeSize != len (Buffer[self._StructSize:]):\r
+            raise ValueError\r
+\r
+        self.Version                = Version\r
+        self.UpdateImageTypeId      = uuid.UUID (bytes_le = UpdateImageTypeId)\r
+        self.UpdateImageIndex       = UpdateImageIndex\r
+        self.UpdateImageSize        = UpdateImageSize\r
+        self.UpdateVendorCodeSize   = UpdateVendorCodeSize\r
+        self.UpdateHardwareInstance = UpdateHardwareInstance\r
+        self.Payload                = Buffer[self._StructSize:self._StructSize + UpdateImageSize]\r
+        self.VendorCodeBytes        = Buffer[self._StructSize + UpdateImageSize:]\r
+        self._Valid                 = True\r
+        return Buffer[self._StructSize:]\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.Version                = {Version:08X}'.format (Version = self.Version))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageTypeId      = {UpdateImageTypeId}'.format (UpdateImageTypeId = str(self.UpdateImageTypeId).upper()))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageIndex       = {UpdateImageIndex:08X}'.format (UpdateImageIndex = self.UpdateImageIndex))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize        = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize   = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))\r
+        print ('sizeof (Payload)                                                    = {Size:08X}'.format (Size = len (self.Payload)))\r
+        print ('sizeof (VendorCodeBytes)                                            = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))\r
+\r
+class FmpCapsuleHeaderClass (object):\r
+    # typedef struct {\r
+    #   UINT32 Version;\r
+    #\r
+    #   ///\r
+    #   /// The number of drivers included in the capsule and the number of corresponding\r
+    #   /// offsets stored in ItemOffsetList array.\r
+    #   ///\r
+    #   UINT16 EmbeddedDriverCount;\r
+    #\r
+    #   ///\r
+    #   /// The number of payload items included in the capsule and the number of\r
+    #   /// corresponding offsets stored in the ItemOffsetList array.\r
+    #   ///\r
+    #   UINT16 PayloadItemCount;\r
+    #\r
+    #   ///\r
+    #   /// Variable length array of dimension [EmbeddedDriverCount + PayloadItemCount]\r
+    #   /// containing offsets of each of the drivers and payload items contained within the capsule\r
+    #   ///\r
+    #   // UINT64 ItemOffsetList[];\r
+    # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;\r
+    #\r
+    #  #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION       0x00000001\r
+    _StructFormat = '<IHH'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    _ItemOffsetFormat = '<Q'\r
+    _ItemOffsetSize   = struct.calcsize (_ItemOffsetFormat)\r
+\r
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001\r
+\r
+    def __init__ (self):\r
+        self._Valid                     = False\r
+        self.Version                    = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\r
+        self.EmbeddedDriverCount        = 0\r
+        self.PayloadItemCount           = 0\r
+        self._ItemOffsetList            = []\r
+        self._EmbeddedDriverList        = []\r
+        self._PayloadList               = []\r
+        self._FmpCapsuleImageHeaderList = []\r
+\r
+    def AddEmbeddedDriver (self, EmbeddedDriver):\r
+        self._EmbeddedDriverList.append (EmbeddedDriver)\r
+\r
+    def GetEmbeddedDriver (self, Index):\r
+        if Index > len (self._EmbeddedDriverList):\r
+            raise ValueError\r
+        return self._EmbeddedDriverList[Index]\r
+\r
+    def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0):\r
+        self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance))\r
+\r
+    def GetFmpCapsuleImageHeader (self, Index):\r
+        if Index >= len (self._FmpCapsuleImageHeaderList):\r
+            raise ValueError\r
+        return self._FmpCapsuleImageHeaderList[Index]\r
+\r
+    def Encode (self):\r
+        self.EmbeddedDriverCount = len (self._EmbeddedDriverList)\r
+        self.PayloadItemCount    = len (self._PayloadList)\r
+\r
+        FmpCapsuleHeader = struct.pack (\r
+                                    self._StructFormat,\r
+                                    self.Version,\r
+                                    self.EmbeddedDriverCount,\r
+                                    self.PayloadItemCount\r
+                                    )\r
+\r
+        FmpCapsuleData = b''\r
+        Offset = self._StructSize + (self.EmbeddedDriverCount + self.PayloadItemCount) * self._ItemOffsetSize\r
+        for EmbeddedDriver in self._EmbeddedDriverList:\r
+            FmpCapsuleData = FmpCapsuleData + EmbeddedDriver\r
+            self._ItemOffsetList.append (Offset)\r
+            Offset = Offset + len (EmbeddedDriver)\r
+        Index = 1\r
+        for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance) in self._PayloadList:\r
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()\r
+            FmpCapsuleImageHeader.UpdateImageTypeId      = UpdateImageTypeId\r
+            FmpCapsuleImageHeader.UpdateImageIndex       = Index\r
+            FmpCapsuleImageHeader.Payload                = Payload\r
+            FmpCapsuleImageHeader.VendorCodeBytes        = VendorCodeBytes\r
+            FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance\r
+            FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()\r
+            FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage\r
+\r
+            self._ItemOffsetList.append (Offset)\r
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)\r
+\r
+            Offset = Offset + len (FmpCapsuleImage)\r
+            Index = Index + 1\r
+\r
+        for Offset in self._ItemOffsetList:\r
+          FmpCapsuleHeader = FmpCapsuleHeader + struct.pack (self._ItemOffsetFormat, Offset)\r
+\r
+        self._Valid = True\r
+        return FmpCapsuleHeader + FmpCapsuleData\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (Version, EmbeddedDriverCount, PayloadItemCount) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+        if Version < self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION:\r
+            raise ValueError\r
+\r
+        self.Version                    = Version\r
+        self.EmbeddedDriverCount        = EmbeddedDriverCount\r
+        self.PayloadItemCount           = PayloadItemCount\r
+        self._ItemOffsetList            = []\r
+        self._EmbeddedDriverList        = []\r
+        self._PayloadList               = []\r
+        self._FmpCapsuleImageHeaderList = []\r
+\r
+        #\r
+        # Parse the ItemOffsetList values\r
+        #\r
+        Offset = self._StructSize\r
+        for Index in range (0, EmbeddedDriverCount + PayloadItemCount):\r
+            ItemOffset = struct.unpack (self._ItemOffsetFormat, Buffer[Offset:Offset + self._ItemOffsetSize])[0]\r
+            if ItemOffset >= len (Buffer):\r
+                raise ValueError\r
+            self._ItemOffsetList.append (ItemOffset)\r
+            Offset = Offset + self._ItemOffsetSize\r
+        Result = Buffer[Offset:]\r
+\r
+        #\r
+        # Parse the EmbeddedDrivers\r
+        #\r
+        for Index in range (0, EmbeddedDriverCount):\r
+            Offset = self._ItemOffsetList[Index]\r
+            if Index < (len (self._ItemOffsetList) - 1):\r
+                Length = self._ItemOffsetList[Index + 1] - Offset\r
+            else:\r
+                Length = len (Buffer) - Offset\r
+            self.AddEmbeddedDriver (Buffer[Offset:Offset + Length])\r
+\r
+        #\r
+        # Parse the Payloads that are FMP Capsule Images\r
+        #\r
+        for Index in range (EmbeddedDriverCount, EmbeddedDriverCount + PayloadItemCount):\r
+            Offset = self._ItemOffsetList[Index]\r
+            if Index < (len (self._ItemOffsetList) - 1):\r
+                Length = self._ItemOffsetList[Index + 1] - Offset\r
+            else:\r
+                Length = len (Buffer) - Offset\r
+            FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()\r
+            FmpCapsuleImageHeader.Decode (Buffer[Offset:Offset + Length])\r
+            self.AddPayload (\r
+                   FmpCapsuleImageHeader.UpdateImageTypeId,\r
+                   FmpCapsuleImageHeader.Payload,\r
+                   FmpCapsuleImageHeader.VendorCodeBytes\r
+                   )\r
+            self._FmpCapsuleImageHeaderList.append (FmpCapsuleImageHeader)\r
+\r
+        self._Valid = True\r
+        return Result\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.Version             = {Version:08X}'.format (Version = self.Version))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.EmbeddedDriverCount = {EmbeddedDriverCount:08X}'.format (EmbeddedDriverCount = self.EmbeddedDriverCount))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.PayloadItemCount    = {PayloadItemCount:08X}'.format (PayloadItemCount = self.PayloadItemCount))\r
+        print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER.ItemOffsetList      = ')\r
+        for Offset in self._ItemOffsetList:\r
+            print ('  {Offset:016X}'.format (Offset = Offset))\r
+        for FmpCapsuleImageHeader in self._FmpCapsuleImageHeaderList:\r
+            FmpCapsuleImageHeader.DumpInfo ()\r
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py b/BaseTools/Source/Python/Common/Uefi/Capsule/UefiCapsuleHeader.py
new file mode 100644 (file)
index 0000000..cfe1cb6
--- /dev/null
@@ -0,0 +1,136 @@
+## @file\r
+# Module that encodes and decodes a EFI_CAPSULE_HEADER with a payload\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+'''\r
+UefiCapsuleHeader\r
+'''\r
+\r
+import struct\r
+import uuid\r
+\r
+class UefiCapsuleHeaderClass (object):\r
+    # typedef struct {\r
+    #   ///\r
+    #   /// A GUID that defines the contents of a capsule.\r
+    #   ///\r
+    #   EFI_GUID          CapsuleGuid;\r
+    #   ///\r
+    #   /// The size of the capsule header. This may be larger than the size of\r
+    #   /// the EFI_CAPSULE_HEADER since CapsuleGuid may imply\r
+    #   /// extended header entries\r
+    #   ///\r
+    #   UINT32            HeaderSize;\r
+    #   ///\r
+    #   /// Bit-mapped list describing the capsule attributes. The Flag values\r
+    #   /// of 0x0000 - 0xFFFF are defined by CapsuleGuid. Flag values\r
+    #   /// of 0x10000 - 0xFFFFFFFF are defined by this specification\r
+    #   ///\r
+    #   UINT32            Flags;\r
+    #   ///\r
+    #   /// Size in bytes of the capsule.\r
+    #   ///\r
+    #   UINT32            CapsuleImageSize;\r
+    # } EFI_CAPSULE_HEADER;\r
+    #\r
+    # #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET          0x00010000\r
+    # #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE         0x00020000\r
+    # #define CAPSULE_FLAGS_INITIATE_RESET                0x00040000\r
+    #\r
+    _StructFormat = '<16sIIII'\r
+    _StructSize   = struct.calcsize (_StructFormat)\r
+\r
+    EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID = uuid.UUID ('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')\r
+\r
+    _CAPSULE_FLAGS_PERSIST_ACROSS_RESET  = 0x00010000\r
+    _CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE = 0x00020000\r
+    _CAPSULE_FLAGS_INITIATE_RESET        = 0x00040000\r
+\r
+    def __init__ (self):\r
+        self._Valid              = False\r
+        self.CapsuleGuid         = self.EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID\r
+        self.HeaderSize          = self._StructSize\r
+        self.OemFlags            = 0x0000\r
+        self.PersistAcrossReset  = False\r
+        self.PopulateSystemTable = False\r
+        self.InitiateReset       = False\r
+        self.CapsuleImageSize    = self.HeaderSize\r
+        self.Payload             = b''\r
+\r
+    def Encode (self):\r
+        Flags = self.OemFlags\r
+        if self.PersistAcrossReset:\r
+            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET\r
+        if self.PopulateSystemTable:\r
+            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE\r
+        if self.InitiateReset:\r
+            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET\r
+\r
+        self.CapsuleImageSize = self.HeaderSize + len (self.Payload)\r
+\r
+        UefiCapsuleHeader = struct.pack (\r
+                                     self._StructFormat,\r
+                                     self.CapsuleGuid.bytes_le,\r
+                                     self.HeaderSize,\r
+                                     Flags,\r
+                                     self.CapsuleImageSize,\r
+                                     0\r
+                                     )\r
+        self._Valid = True\r
+        return UefiCapsuleHeader + self.Payload\r
+\r
+    def Decode (self, Buffer):\r
+        if len (Buffer) < self._StructSize:\r
+            raise ValueError\r
+        (CapsuleGuid, HeaderSize, Flags, CapsuleImageSize, Reserved) = \\r
+            struct.unpack (\r
+                     self._StructFormat,\r
+                     Buffer[0:self._StructSize]\r
+                     )\r
+        if HeaderSize < self._StructSize:\r
+            raise ValueError\r
+        if CapsuleImageSize != len (Buffer):\r
+            raise ValueError\r
+        self.CapsuleGuid         = uuid.UUID (bytes_le = CapsuleGuid)\r
+        self.HeaderSize          = HeaderSize\r
+        self.OemFlags            = Flags & 0xffff\r
+        self.PersistAcrossReset  = (Flags & self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0\r
+        self.PopulateSystemTable = (Flags & self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0\r
+        self.InitiateReset       = (Flags & self._CAPSULE_FLAGS_INITIATE_RESET) != 0\r
+        self.CapsuleImageSize    = CapsuleImageSize\r
+        self.Payload             = Buffer[self.HeaderSize:]\r
+\r
+        self._Valid              = True\r
+        return self.Payload\r
+\r
+    def DumpInfo (self):\r
+        if not self._Valid:\r
+            raise ValueError\r
+        Flags = self.OemFlags\r
+        if self.PersistAcrossReset:\r
+            Flags = Flags | self._CAPSULE_FLAGS_PERSIST_ACROSS_RESET\r
+        if self.PopulateSystemTable:\r
+            Flags = Flags | self._CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE\r
+        if self.InitiateReset:\r
+            Flags = Flags | self._CAPSULE_FLAGS_INITIATE_RESET\r
+        print ('EFI_CAPSULE_HEADER.CapsuleGuid      = {Guid}'.format (Guid = str(self.CapsuleGuid).upper()))\r
+        print ('EFI_CAPSULE_HEADER.HeaderSize       = {Size:08X}'.format (Size = self.HeaderSize))\r
+        print ('EFI_CAPSULE_HEADER.Flags            = {Flags:08X}'.format (Flags = Flags))\r
+        print ('  OEM Flags                         = {Flags:04X}'.format (Flags = self.OemFlags))\r
+        if self.PersistAcrossReset:\r
+            print ('  CAPSULE_FLAGS_PERSIST_ACROSS_RESET')\r
+        if self.PopulateSystemTable:\r
+            print ('  CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE')\r
+        if self.InitiateReset:\r
+            print ('  CAPSULE_FLAGS_INITIATE_RESET')\r
+        print ('EFI_CAPSULE_HEADER.CapsuleImageSize = {Size:08X}'.format (Size = self.CapsuleImageSize))\r
+        print ('sizeof (Payload)                    = {Size:08X}'.format (Size = len (self.Payload)))\r
diff --git a/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py b/BaseTools/Source/Python/Common/Uefi/Capsule/__init__.py
new file mode 100644 (file)
index 0000000..d9db4aa
--- /dev/null
@@ -0,0 +1,15 @@
+## @file\r
+# Python 'Common.Uefi.Capsule' package initialization file.\r
+#\r
+# This file is required to make Python interpreter treat the directory\r
+# as containing package.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
diff --git a/BaseTools/Source/Python/Common/Uefi/__init__.py b/BaseTools/Source/Python/Common/Uefi/__init__.py
new file mode 100644 (file)
index 0000000..d80219d
--- /dev/null
@@ -0,0 +1,15 @@
+## @file\r
+# Python 'Common.Uefi' package initialization file.\r
+#\r
+# This file is required to make Python interpreter treat the directory\r
+# as containing package.\r
+#\r
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution.  The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r