--- /dev/null
+#!/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" "$@"
--- /dev/null
+@%PYTHON_HOME%\python.exe %BASE_TOOLS_PATH%\Source\Python\Capsule\GenerateCapsule.py %*\r
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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
--- /dev/null
+## @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