## @file\r
# Generate a capsule.\r
#\r
-# This tool generates a UEFI Capsule around an FMP Capsule. The capsule payload\r
+# This tool generates a UEFI Capsule around an FMP Capsule. The capsule payload\r
# be signed using signtool or OpenSSL and if it is signed the signed content\r
# includes an FMP Payload Header.\r
#\r
# This tool is intended to be used to generate UEFI Capsules to update the\r
-# system firmware or device firmware for integrated devices. In order to\r
+# system firmware or device firmware for integrated devices. In order to\r
# keep the tool as simple as possible, it has the following limitations:\r
-# * Do not support multiple payloads in a capsule.\r
-# * Do not support optional drivers in a capsule.\r
# * Do not support vendor code bytes in a capsule.\r
#\r
-# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
# SPDX-License-Identifier: BSD-2-Clause-Patent\r
#\r
\r
import tempfile\r
import shutil\r
import platform\r
+import json\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
__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.'\r
__description__ = 'Generate a capsule.\n'\r
\r
-def SignPayloadSignTool (Payload, ToolPath, PfxFile):\r
+def SignPayloadSignTool (Payload, ToolPath, PfxFile, Verbose = False):\r
#\r
# Create a temporary directory\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
+ with open (TempFileName, 'wb') as File:\r
+ File.write (Payload)\r
except:\r
shutil.rmtree (TempDirectoryName)\r
raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\r
Command = Command + '/p7 {TempDir} '.format (TempDir = TempDirectoryName)\r
Command = Command + '/f {PfxFile} '.format (PfxFile = PfxFile)\r
Command = Command + TempFileName\r
+ if Verbose:\r
+ print (Command)\r
\r
#\r
# Sign the input file using the specified private key\r
\r
if Process.returncode != 0:\r
shutil.rmtree (TempDirectoryName)\r
- print (Result[1].decode(encoding='utf-8', errors='ignore'))\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
+ with open (TempFileName + '.p7', 'rb') as File:\r
+ Signature = File.read ()\r
except:\r
shutil.rmtree (TempDirectoryName)\r
raise ValueError ('GenerateCapsule: error: can not read signature file.')\r
shutil.rmtree (TempDirectoryName)\r
return Signature\r
\r
-def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile):\r
+def VerifyPayloadSignTool (Payload, CertData, ToolPath, PfxFile, Verbose = False):\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
+def SignPayloadOpenSsl (Payload, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile, Verbose = False):\r
#\r
# Build openssl command\r
#\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
+ if Verbose:\r
+ print (Command)\r
\r
#\r
# Sign the input file using the specified private key and capture signature from STDOUT\r
raise ValueError ('GenerateCapsule: error: can not run openssl.')\r
\r
if Process.returncode != 0:\r
- print (Result[1].decode(encoding='utf-8', errors='ignore'))\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
+def VerifyPayloadOpenSsl (Payload, CertData, ToolPath, SignerPrivateCertFile, OtherPublicCertFile, TrustedPublicCertFile, Verbose = False):\r
#\r
# Create a temporary directory\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
+ with open (TempFileName, 'wb') as File:\r
+ File.write (Payload)\r
except:\r
shutil.rmtree (TempDirectoryName)\r
raise ValueError ('GenerateCapsule: error: can not write temporary payload file.')\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
+ if Verbose:\r
+ print (Command)\r
\r
#\r
# Verify signature\r
\r
if Process.returncode != 0:\r
shutil.rmtree (TempDirectoryName)\r
- print (Result[1].decode(encoding='utf-8', errors='ignore'))\r
+ print (Result[1].decode())\r
raise ValueError ('GenerateCapsule: error: openssl failed.')\r
\r
shutil.rmtree (TempDirectoryName)\r
raise argparse.ArgumentTypeError (Message)\r
return Value\r
\r
+ def ConvertJsonValue (Config, FieldName, Convert, Required = True, Default = None, Open = False):\r
+ if FieldName not in Config:\r
+ if Required:\r
+ print ('GenerateCapsule: error: Payload descriptor invalid syntax. Could not find {Key} in payload descriptor.'.format(Key = FieldName))\r
+ sys.exit (1)\r
+ return Default\r
+ try:\r
+ Value = Convert (Config[FieldName])\r
+ except:\r
+ print ('GenerateCapsule: error: {Key} in payload descriptor has invalid syntax.'.format (Key = FieldName))\r
+ sys.exit (1)\r
+ if Open:\r
+ try:\r
+ Value = open (Value, "rb")\r
+ except:\r
+ print ('GenerateCapsule: error: can not open file {File}'.format (File = FieldName))\r
+ sys.exit (1)\r
+ return Value\r
+\r
+ def DecodeJsonFileParse (Json):\r
+ if 'Payloads' not in Json:\r
+ print ('GenerateCapsule: error "Payloads" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ sys.exit (1)\r
+ for Config in Json['Payloads']:\r
+ #\r
+ # Parse fields from JSON\r
+ #\r
+ PayloadFile = ConvertJsonValue (Config, 'Payload', os.path.expandvars, Required = False)\r
+ Guid = ConvertJsonValue (Config, 'Guid', ValidateRegistryFormatGuid, Required = False)\r
+ FwVersion = ConvertJsonValue (Config, 'FwVersion', ValidateUnsignedInteger, Required = False)\r
+ LowestSupportedVersion = ConvertJsonValue (Config, 'LowestSupportedVersion', ValidateUnsignedInteger, Required = False)\r
+ HardwareInstance = ConvertJsonValue (Config, 'HardwareInstance', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ MonotonicCount = ConvertJsonValue (Config, 'MonotonicCount', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ SignToolPfxFile = ConvertJsonValue (Config, 'SignToolPfxFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslSignerPrivateCertFile = ConvertJsonValue (Config, 'OpenSslSignerPrivateCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslOtherPublicCertFile = ConvertJsonValue (Config, 'OpenSslOtherPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslTrustedPublicCertFile = ConvertJsonValue (Config, 'OpenSslTrustedPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ SigningToolPath = ConvertJsonValue (Config, 'SigningToolPath', os.path.expandvars, Required = False, Default = None)\r
+ UpdateImageIndex = ConvertJsonValue (Config, 'UpdateImageIndex', ValidateUnsignedInteger, Required = False, Default = 1)\r
+\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ PayloadFile,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ SignToolPfxFile,\r
+ OpenSslSignerPrivateCertFile,\r
+ OpenSslOtherPublicCertFile,\r
+ OpenSslTrustedPublicCertFile,\r
+ SigningToolPath\r
+ ))\r
+\r
+ def EncodeJsonFileParse (Json):\r
+ if 'EmbeddedDrivers' not in Json:\r
+ print ('GenerateCapsule: warning "EmbeddedDrivers" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ else:\r
+ for Config in Json['EmbeddedDrivers']:\r
+ EmbeddedDriverFile = ConvertJsonValue(Config, 'Driver', os.path.expandvars, Open = True)\r
+ #\r
+ #Read EmbeddedDriver file\r
+ #\r
+ try:\r
+ if args.Verbose:\r
+ print ('Read EmbeddedDriver file {File}'.format (File = EmbeddedDriverFile.name))\r
+ Driver = EmbeddedDriverFile.read()\r
+ except:\r
+ print ('GenerateCapsule: error: can not read EmbeddedDriver file {File}'.format (File = EmbeddedDriverFile.name))\r
+ sys.exit (1)\r
+ EmbeddedDriverDescriptorList.append (Driver)\r
+\r
+ if 'Payloads' not in Json:\r
+ print ('GenerateCapsule: error: "Payloads" section not found in JSON file {File}'.format (File = args.JsonFile.name))\r
+ sys.exit (1)\r
+ for Config in Json['Payloads']:\r
+ #\r
+ # Parse fields from JSON\r
+ #\r
+ PayloadFile = ConvertJsonValue (Config, 'Payload', os.path.expandvars, Open = True)\r
+ Guid = ConvertJsonValue (Config, 'Guid', ValidateRegistryFormatGuid)\r
+ FwVersion = ConvertJsonValue (Config, 'FwVersion', ValidateUnsignedInteger)\r
+ LowestSupportedVersion = ConvertJsonValue (Config, 'LowestSupportedVersion', ValidateUnsignedInteger)\r
+ HardwareInstance = ConvertJsonValue (Config, 'HardwareInstance', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ UpdateImageIndex = ConvertJsonValue (Config, 'UpdateImageIndex', ValidateUnsignedInteger, Required = False, Default = 1)\r
+ MonotonicCount = ConvertJsonValue (Config, 'MonotonicCount', ValidateUnsignedInteger, Required = False, Default = 0)\r
+ SignToolPfxFile = ConvertJsonValue (Config, 'SignToolPfxFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslSignerPrivateCertFile = ConvertJsonValue (Config, 'OpenSslSignerPrivateCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslOtherPublicCertFile = ConvertJsonValue (Config, 'OpenSslOtherPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ OpenSslTrustedPublicCertFile = ConvertJsonValue (Config, 'OpenSslTrustedPublicCertFile', os.path.expandvars, Required = False, Default = None, Open = True)\r
+ SigningToolPath = ConvertJsonValue (Config, 'SigningToolPath', os.path.expandvars, Required = False, Default = None)\r
+\r
+ #\r
+ # Read binary input file\r
+ #\r
+ try:\r
+ if args.Verbose:\r
+ print ('Read binary input file {File}'.format (File = PayloadFile.name))\r
+ Payload = PayloadFile.read()\r
+ PayloadFile.close ()\r
+ except:\r
+ print ('GenerateCapsule: error: can not read binary input file {File}'.format (File = PayloadFile.name))\r
+ sys.exit (1)\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Payload,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ SignToolPfxFile,\r
+ OpenSslSignerPrivateCertFile,\r
+ OpenSslOtherPublicCertFile,\r
+ OpenSslTrustedPublicCertFile,\r
+ SigningToolPath\r
+ ))\r
+\r
+ def GenerateOutputJson (PayloadJsonDescriptorList):\r
+ PayloadJson = {\r
+ "Payloads" : [\r
+ {\r
+ "Guid": str(PayloadDescriptor.Guid).upper(),\r
+ "FwVersion": str(PayloadDescriptor.FwVersion),\r
+ "LowestSupportedVersion": str(PayloadDescriptor.LowestSupportedVersion),\r
+ "MonotonicCount": str(PayloadDescriptor.MonotonicCount),\r
+ "Payload": PayloadDescriptor.Payload,\r
+ "HardwareInstance": str(PayloadDescriptor.HardwareInstance),\r
+ "UpdateImageIndex": str(PayloadDescriptor.UpdateImageIndex),\r
+ "SignToolPfxFile": str(PayloadDescriptor.SignToolPfxFile),\r
+ "OpenSslSignerPrivateCertFile": str(PayloadDescriptor.OpenSslSignerPrivateCertFile),\r
+ "OpenSslOtherPublicCertFile": str(PayloadDescriptor.OpenSslOtherPublicCertFile),\r
+ "OpenSslTrustedPublicCertFile": str(PayloadDescriptor.OpenSslTrustedPublicCertFile),\r
+ "SigningToolPath": str(PayloadDescriptor.SigningToolPath)\r
+ }for PayloadDescriptor in PayloadJsonDescriptorList\r
+ ]\r
+ }\r
+ OutputJsonFile = args.OutputFile.name + '.json'\r
+ if 'Payloads' in PayloadJson:\r
+ PayloadSection = PayloadJson ['Payloads']\r
+ Index = 0\r
+ for PayloadField in PayloadSection:\r
+ if PayloadJsonDescriptorList[Index].SignToolPfxFile is None:\r
+ del PayloadField ['SignToolPfxFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslSignerPrivateCertFile is None:\r
+ del PayloadField ['OpenSslSignerPrivateCertFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslOtherPublicCertFile is None:\r
+ del PayloadField ['OpenSslOtherPublicCertFile']\r
+ if PayloadJsonDescriptorList[Index].OpenSslTrustedPublicCertFile is None:\r
+ del PayloadField ['OpenSslTrustedPublicCertFile']\r
+ if PayloadJsonDescriptorList[Index].SigningToolPath is None:\r
+ del PayloadField ['SigningToolPath']\r
+ Index = Index + 1\r
+ Result = json.dumps (PayloadJson, indent=4, sort_keys=True, separators=(',', ': '))\r
+ with open (OutputJsonFile, 'w') as OutputFile:\r
+ OutputFile.write (Result)\r
+\r
+ def CheckArgumentConflict (args):\r
+ if args.Encode:\r
+ if args.InputFile:\r
+ print ('GenerateCapsule: error: Argument InputFile conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.EmbeddedDriver:\r
+ print ('GenerateCapsule: error: Argument --embedded-driver conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.Guid:\r
+ print ('GenerateCapsule: error: Argument --guid conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.FwVersion:\r
+ print ('GenerateCapsule: error: Argument --fw-version conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.LowestSupportedVersion:\r
+ print ('GenerateCapsule: error: Argument --lsv conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.MonotonicCount:\r
+ print ('GenerateCapsule: error: Argument --monotonic-count conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.HardwareInstance:\r
+ print ('GenerateCapsule: error: Argument --hardware-instance conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.SignToolPfxFile:\r
+ print ('GenerateCapsule: error: Argument --pfx-file conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslSignerPrivateCertFile:\r
+ print ('GenerateCapsule: error: Argument --signer-private-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslOtherPublicCertFile:\r
+ print ('GenerateCapsule: error: Argument --other-public-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.OpenSslTrustedPublicCertFile:\r
+ print ('GenerateCapsule: error: Argument --trusted-public-cert conflicts with Argument -j')\r
+ sys.exit (1)\r
+ if args.SigningToolPath:\r
+ print ('GenerateCapsule: error: Argument --signing-tool-path conflicts with Argument -j')\r
+ sys.exit (1)\r
+\r
+ class PayloadDescriptor (object):\r
+ def __init__(self,\r
+ Payload,\r
+ Guid,\r
+ FwVersion,\r
+ LowestSupportedVersion,\r
+ MonotonicCount = 0,\r
+ HardwareInstance = 0,\r
+ UpdateImageIndex = 1,\r
+ SignToolPfxFile = None,\r
+ OpenSslSignerPrivateCertFile = None,\r
+ OpenSslOtherPublicCertFile = None,\r
+ OpenSslTrustedPublicCertFile = None,\r
+ SigningToolPath = None\r
+ ):\r
+ self.Payload = Payload\r
+ self.Guid = Guid\r
+ self.FwVersion = FwVersion\r
+ self.LowestSupportedVersion = LowestSupportedVersion\r
+ self.MonotonicCount = MonotonicCount\r
+ self.HardwareInstance = HardwareInstance\r
+ self.UpdateImageIndex = UpdateImageIndex\r
+ self.SignToolPfxFile = SignToolPfxFile\r
+ self.OpenSslSignerPrivateCertFile = OpenSslSignerPrivateCertFile\r
+ self.OpenSslOtherPublicCertFile = OpenSslOtherPublicCertFile\r
+ self.OpenSslTrustedPublicCertFile = OpenSslTrustedPublicCertFile\r
+ self.SigningToolPath = SigningToolPath\r
+\r
+ self.UseSignTool = self.SignToolPfxFile is not None\r
+ self.UseOpenSsl = (self.OpenSslSignerPrivateCertFile is not None and\r
+ self.OpenSslOtherPublicCertFile is not None and\r
+ self.OpenSslTrustedPublicCertFile is not None)\r
+ self.AnyOpenSsl = (self.OpenSslSignerPrivateCertFile is not None or\r
+ self.OpenSslOtherPublicCertFile is not None or\r
+ self.OpenSslTrustedPublicCertFile is not None)\r
+\r
+ def Validate(self, args):\r
+ if self.UseSignTool and self.AnyOpenSsl:\r
+ raise argparse.ArgumentTypeError ('Providing both signtool and OpenSSL options is not supported')\r
+ if not self.UseSignTool and not self.UseOpenSsl and self.AnyOpenSsl:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON fields are required for OpenSSL: OpenSslSignerPrivateCertFile, OpenSslOtherPublicCertFile, OpenSslTrustedPublicCertFile')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following options are required for OpenSSL: --signer-private-cert, --other-public-cert, --trusted-public-cert')\r
+ if self.UseSignTool and platform.system() != 'Windows':\r
+ raise argparse.ArgumentTypeError ('Use of signtool is not supported on this operating system.')\r
+ if args.Encode:\r
+ if self.FwVersion is None or self.LowestSupportedVersion is None:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON fields are required: FwVersion, LowestSupportedVersion')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following options are required: --fw-version, --lsv')\r
+ if self.FwVersion > 0xFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field FwVersion must be an integer in range 0x0..0xffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--fw-version must be an integer in range 0x0..0xffffffff')\r
+ if self.LowestSupportedVersion > 0xFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field LowestSupportedVersion must be an integer in range 0x0..0xffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--lsv must be an integer in range 0x0..0xffffffff')\r
+\r
+ if args.Encode:\r
+ if self.Guid is None:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('the following JSON field is required: Guid')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('the following option is required: --guid')\r
+ if self.HardwareInstance > 0xFFFFFFFFFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field HardwareInstance must be an integer in range 0x0..0xffffffffffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--hardware-instance must be an integer in range 0x0..0xffffffffffffffff')\r
+ if self.MonotonicCount > 0xFFFFFFFFFFFFFFFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field MonotonicCount must be an integer in range 0x0..0xffffffffffffffff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--monotonic-count must be an integer in range 0x0..0xffffffffffffffff')\r
+ if self.UpdateImageIndex >0xFF:\r
+ if args.JsonFile:\r
+ raise argparse.ArgumentTypeError ('JSON field UpdateImageIndex must be an integer in range 0x0..0xff')\r
+ else:\r
+ raise argparse.ArgumentTypeError ('--update-image-index must be an integer in range 0x0..0xff')\r
+\r
+ if self.UseSignTool:\r
+ self.SignToolPfxFile.close()\r
+ self.SignToolPfxFile = self.SignToolPfxFile.name\r
+ if self.UseOpenSsl:\r
+ self.OpenSslSignerPrivateCertFile.close()\r
+ self.OpenSslOtherPublicCertFile.close()\r
+ self.OpenSslTrustedPublicCertFile.close()\r
+ self.OpenSslSignerPrivateCertFile = self.OpenSslSignerPrivateCertFile.name\r
+ self.OpenSslOtherPublicCertFile = self.OpenSslOtherPublicCertFile.name\r
+ self.OpenSslTrustedPublicCertFile = self.OpenSslTrustedPublicCertFile.name\r
+\r
+ #\r
+ # Perform additional argument verification\r
+ #\r
+ if args.Encode:\r
+ if 'PersistAcrossReset' not in args.CapsuleFlag:\r
+ if 'InitiateReset' in args.CapsuleFlag:\r
+ raise argparse.ArgumentTypeError ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r
+ if args.CapsuleOemFlag > 0xFFFF:\r
+ raise argparse.ArgumentTypeError ('--capoemflag must be an integer between 0x0000 and 0xffff')\r
+\r
+ return True\r
+\r
+\r
+ def Encode (PayloadDescriptorList, EmbeddedDriverDescriptorList, Buffer):\r
+ if args.JsonFile:\r
+ CheckArgumentConflict(args)\r
+ try:\r
+ Json = json.loads (args.JsonFile.read ())\r
+ except:\r
+ print ('GenerateCapsule: error: {JSONFile} loads failure. '.format (JSONFile = args.JsonFile))\r
+ sys.exit (1)\r
+ EncodeJsonFileParse(Json)\r
+ else:\r
+ for Driver in args.EmbeddedDriver:\r
+ EmbeddedDriverDescriptorList.append (Driver.read())\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Buffer,\r
+ args.Guid,\r
+ args.FwVersion,\r
+ args.LowestSupportedVersion,\r
+ args.MonotonicCount,\r
+ args.HardwareInstance,\r
+ args.UpdateImageIndex,\r
+ args.SignToolPfxFile,\r
+ args.OpenSslSignerPrivateCertFile,\r
+ args.OpenSslOtherPublicCertFile,\r
+ args.OpenSslTrustedPublicCertFile,\r
+ args.SigningToolPath\r
+ ))\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ try:\r
+ SinglePayloadDescriptor.Validate (args)\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error:' + str(Msg))\r
+ sys.exit (1)\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ Result = SinglePayloadDescriptor.Payload\r
+ try:\r
+ FmpPayloadHeader.FwVersion = SinglePayloadDescriptor.FwVersion\r
+ FmpPayloadHeader.LowestSupportedVersion = SinglePayloadDescriptor.LowestSupportedVersion\r
+ FmpPayloadHeader.Payload = SinglePayloadDescriptor.Payload\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
+ if SinglePayloadDescriptor.UseOpenSsl or SinglePayloadDescriptor.UseSignTool:\r
+ #\r
+ # Sign image with 64-bit MonotonicCount appended to end of image\r
+ #\r
+ try:\r
+ if SinglePayloadDescriptor.UseSignTool:\r
+ CertData = SignPayloadSignTool (\r
+ Result + struct.pack ('<Q', SinglePayloadDescriptor.MonotonicCount),\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.SignToolPfxFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ else:\r
+ CertData = SignPayloadOpenSsl (\r
+ Result + struct.pack ('<Q', SinglePayloadDescriptor.MonotonicCount),\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.OpenSslSignerPrivateCertFile,\r
+ SinglePayloadDescriptor.OpenSslOtherPublicCertFile,\r
+ SinglePayloadDescriptor.OpenSslTrustedPublicCertFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error: can not sign payload \n' + str(Msg))\r
+ sys.exit (1)\r
+\r
+ try:\r
+ FmpAuthHeader.MonotonicCount = SinglePayloadDescriptor.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
+ FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance = SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex)\r
+ try:\r
+ for EmbeddedDriver in EmbeddedDriverDescriptorList:\r
+ FmpCapsuleHeader.AddEmbeddedDriver(EmbeddedDriver)\r
+\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 = False\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
+ 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
+ def Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer):\r
+ if args.JsonFile:\r
+ CheckArgumentConflict(args)\r
+ #\r
+ # Parse payload descriptors from JSON\r
+ #\r
+ try:\r
+ Json = json.loads (args.JsonFile.read())\r
+ except:\r
+ print ('GenerateCapsule: error: {JSONFile} loads failure. '.format (JSONFile = args.JsonFile))\r
+ sys.exit (1)\r
+ DecodeJsonFileParse (Json)\r
+ else:\r
+ PayloadDescriptorList.append (PayloadDescriptor (\r
+ Buffer,\r
+ args.Guid,\r
+ args.FwVersion,\r
+ args.LowestSupportedVersion,\r
+ args.MonotonicCount,\r
+ args.HardwareInstance,\r
+ args.UpdateImageIndex,\r
+ args.SignToolPfxFile,\r
+ args.OpenSslSignerPrivateCertFile,\r
+ args.OpenSslOtherPublicCertFile,\r
+ args.OpenSslTrustedPublicCertFile,\r
+ args.SigningToolPath\r
+ ))\r
+ #\r
+ # Perform additional verification on payload descriptors\r
+ #\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ try:\r
+ SinglePayloadDescriptor.Validate (args)\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: error:' + str(Msg))\r
+ sys.exit (1)\r
+ try:\r
+ Result = UefiCapsuleHeader.Decode (Buffer)\r
+ if len (Result) > 0:\r
+ Result = FmpCapsuleHeader.Decode (Result)\r
+ if args.JsonFile:\r
+ if FmpCapsuleHeader.PayloadItemCount != len (PayloadDescriptorList):\r
+ CapsulePayloadNum = FmpCapsuleHeader.PayloadItemCount\r
+ JsonPayloadNum = len (PayloadDescriptorList)\r
+ print ('GenerateCapsule: Decode error: {JsonPayloadNumber} payloads in JSON file {File} and {CapsulePayloadNumber} payloads in Capsule {CapsuleName}'.format (JsonPayloadNumber = JsonPayloadNum, File = args.JsonFile.name, CapsulePayloadNumber = CapsulePayloadNum, CapsuleName = args.InputFile.name))\r
+ sys.exit (1)\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ if Index < len (PayloadDescriptorList):\r
+ GUID = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageTypeId\r
+ HardwareInstance = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateHardwareInstance\r
+ UpdateImageIndex = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageIndex\r
+ if PayloadDescriptorList[Index].Guid != GUID or PayloadDescriptorList[Index].HardwareInstance != HardwareInstance:\r
+ print ('GenerateCapsule: Decode error: Guid or HardwareInstance pair in input JSON file {File} does not match the payload {PayloadIndex} in Capsule {InputCapsule}'.format (File = args.JsonFile.name, PayloadIndex = Index + 1, InputCapsule = args.InputFile.name))\r
+ sys.exit (1)\r
+ PayloadDescriptorList[Index].Payload = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ DecodeJsonOutput = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = Index + 1)\r
+ PayloadJsonDescriptorList.append (PayloadDescriptor (\r
+ DecodeJsonOutput,\r
+ GUID,\r
+ None,\r
+ None,\r
+ None,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ PayloadDescriptorList[Index].SignToolPfxFile,\r
+ PayloadDescriptorList[Index].OpenSslSignerPrivateCertFile,\r
+ PayloadDescriptorList[Index].OpenSslOtherPublicCertFile,\r
+ PayloadDescriptorList[Index].OpenSslTrustedPublicCertFile,\r
+ PayloadDescriptorList[Index].SigningToolPath\r
+ ))\r
+ else:\r
+ PayloadDescriptorList[0].Payload = FmpCapsuleHeader.GetFmpCapsuleImageHeader (0).Payload\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ if Index > 0:\r
+ PayloadDecodeFile = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ PayloadDescriptorList.append (PayloadDescriptor (PayloadDecodeFile,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None,\r
+ None\r
+ ))\r
+ GUID = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageTypeId\r
+ HardwareInstance = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateHardwareInstance\r
+ UpdateImageIndex = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).UpdateImageIndex\r
+ DecodeJsonOutput = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = Index + 1)\r
+ PayloadJsonDescriptorList.append (PayloadDescriptor (\r
+ DecodeJsonOutput,\r
+ GUID,\r
+ None,\r
+ None,\r
+ None,\r
+ HardwareInstance,\r
+ UpdateImageIndex,\r
+ PayloadDescriptorList[Index].SignToolPfxFile,\r
+ PayloadDescriptorList[Index].OpenSslSignerPrivateCertFile,\r
+ PayloadDescriptorList[Index].OpenSslOtherPublicCertFile,\r
+ PayloadDescriptorList[Index].OpenSslTrustedPublicCertFile,\r
+ PayloadDescriptorList[Index].SigningToolPath\r
+ ))\r
+ JsonIndex = 0\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ if args.Verbose:\r
+ print ('========')\r
+ UefiCapsuleHeader.DumpInfo ()\r
+ print ('--------')\r
+ FmpCapsuleHeader.DumpInfo ()\r
+ if FmpAuthHeader.IsSigned(SinglePayloadDescriptor.Payload):\r
+ if not SinglePayloadDescriptor.UseOpenSsl and not SinglePayloadDescriptor.UseSignTool:\r
+ print ('GenerateCapsule: decode warning: can not verify singed payload without cert or pfx file. Index = {Index}'.format (Index = JsonIndex + 1))\r
+ SinglePayloadDescriptor.Payload = FmpAuthHeader.Decode (SinglePayloadDescriptor.Payload)\r
+ PayloadJsonDescriptorList[JsonIndex].MonotonicCount = FmpAuthHeader.MonotonicCount\r
+ if args.Verbose:\r
+ print ('--------')\r
+ FmpAuthHeader.DumpInfo ()\r
+\r
+ #\r
+ # Verify Image with 64-bit MonotonicCount appended to end of image\r
+ #\r
+ try:\r
+ if SinglePayloadDescriptor.UseSignTool:\r
+ CertData = VerifyPayloadSignTool (\r
+ FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+ FmpAuthHeader.CertData,\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.SignToolPfxFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ else:\r
+ CertData = VerifyPayloadOpenSsl (\r
+ FmpAuthHeader.Payload + struct.pack ('<Q', FmpAuthHeader.MonotonicCount),\r
+ FmpAuthHeader.CertData,\r
+ SinglePayloadDescriptor.SigningToolPath,\r
+ SinglePayloadDescriptor.OpenSslSignerPrivateCertFile,\r
+ SinglePayloadDescriptor.OpenSslOtherPublicCertFile,\r
+ SinglePayloadDescriptor.OpenSslTrustedPublicCertFile,\r
+ Verbose = args.Verbose\r
+ )\r
+ except Exception as Msg:\r
+ print ('GenerateCapsule: warning: payload verification failed Index = {Index} \n'.format (Index = JsonIndex + 1) + str(Msg))\r
+ else:\r
+ if args.Verbose:\r
+ print ('--------')\r
+ print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+ try:\r
+ SinglePayloadDescriptor.Payload = FmpPayloadHeader.Decode (SinglePayloadDescriptor.Payload)\r
+ PayloadJsonDescriptorList[JsonIndex].FwVersion = FmpPayloadHeader.FwVersion\r
+ PayloadJsonDescriptorList[JsonIndex].LowestSupportedVersion = FmpPayloadHeader.LowestSupportedVersion\r
+ JsonIndex = JsonIndex + 1\r
+ if args.Verbose:\r
+ print ('--------')\r
+ FmpPayloadHeader.DumpInfo ()\r
+ print ('========')\r
+ except:\r
+ if args.Verbose:\r
+ print ('--------')\r
+ print ('No FMP_PAYLOAD_HEADER')\r
+ print ('========')\r
+ sys.exit (1)\r
+ #\r
+ # Write embedded driver file(s)\r
+ #\r
+ for Index in range (0, FmpCapsuleHeader.EmbeddedDriverCount):\r
+ EmbeddedDriverBuffer = FmpCapsuleHeader.GetEmbeddedDriver (Index)\r
+ EmbeddedDriverPath = args.OutputFile.name + '.EmbeddedDriver.{Index:d}.efi'.format (Index = Index + 1)\r
+ try:\r
+ if args.Verbose:\r
+ print ('Write embedded driver file {File}'.format (File = EmbeddedDriverPath))\r
+ with open (EmbeddedDriverPath, 'wb') as EmbeddedDriverFile:\r
+ EmbeddedDriverFile.write (EmbeddedDriverBuffer)\r
+ except:\r
+ print ('GenerateCapsule: error: can not write embedded driver file {File}'.format (File = EmbeddedDriverPath))\r
+ sys.exit (1)\r
+\r
+ except:\r
+ print ('GenerateCapsule: error: can not decode capsule')\r
+ sys.exit (1)\r
+ GenerateOutputJson(PayloadJsonDescriptorList)\r
+ PayloadIndex = 0\r
+ for SinglePayloadDescriptor in PayloadDescriptorList:\r
+ if args.OutputFile is None:\r
+ print ('GenerateCapsule: Decode error: OutputFile is needed for decode output')\r
+ sys.exit (1)\r
+ try:\r
+ if args.Verbose:\r
+ print ('Write binary output file {File}'.format (File = args.OutputFile.name))\r
+ PayloadDecodePath = args.OutputFile.name + '.Payload.{Index:d}.bin'.format (Index = PayloadIndex + 1)\r
+ with open (PayloadDecodePath, 'wb') as PayloadDecodeFile:\r
+ PayloadDecodeFile.write (SinglePayloadDescriptor.Payload)\r
+ PayloadIndex = PayloadIndex + 1\r
+ except:\r
+ print ('GenerateCapsule: error: can not write binary output file {File}'.format (File = SinglePayloadDescriptor.OutputFile.name))\r
+ sys.exit (1)\r
+\r
+ def DumpInfo (Buffer, args):\r
+ if args.OutputFile is not None:\r
+ raise argparse.ArgumentTypeError ('the following option is not supported for dumpinfo operations: --output')\r
+ try:\r
+ Result = UefiCapsuleHeader.Decode (Buffer)\r
+ print ('========')\r
+ UefiCapsuleHeader.DumpInfo ()\r
+ if len (Result) > 0:\r
+ FmpCapsuleHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpCapsuleHeader.DumpInfo ()\r
+ for Index in range (0, FmpCapsuleHeader.PayloadItemCount):\r
+ Result = FmpCapsuleHeader.GetFmpCapsuleImageHeader (Index).Payload\r
+ try:\r
+ Result = FmpAuthHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpAuthHeader.DumpInfo ()\r
+ except:\r
+ print ('--------')\r
+ print ('No EFI_FIRMWARE_IMAGE_AUTHENTICATION')\r
+ try:\r
+ Result = FmpPayloadHeader.Decode (Result)\r
+ print ('--------')\r
+ FmpPayloadHeader.DumpInfo ()\r
+ except:\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
#\r
# Create command line argument parser object\r
#\r
#\r
# Add input and output file arguments\r
#\r
- parser.add_argument("InputFile", type = argparse.FileType('rb'),\r
+ parser.add_argument("InputFile", type = argparse.FileType('rb'), nargs='?',\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 optional arguments for this command\r
#\r
+ parser.add_argument ("-j", "--json-file", dest = 'JsonFile', type=argparse.FileType('r'),\r
+ help = "JSON configuration file for multiple payloads and embedded drivers.")\r
parser.add_argument ("--capflag", dest = 'CapsuleFlag', action='append', default = [],\r
choices=['PersistAcrossReset', 'InitiateReset'],\r
help = "Capsule flag can be PersistAcrossReset or InitiateReset or not set")\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
+ help = "The FMP/ESRT GUID in registry format. Required for single payload 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
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). Required for encode operations that sign a payload.")\r
+ help = "The 32-bit version of the binary payload (e.g. 0x11223344 or 5678). Required for encode operations.")\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). Required for encode operations that sign a payload.")\r
+ help = "The 32-bit lowest supported version of the binary payload (e.g. 0x11223344 or 5678). Required for encode operations.")\r
\r
parser.add_argument ("--pfx-file", dest='SignToolPfxFile', type=argparse.FileType('rb'),\r
help="signtool PFX certificate filename.")\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
+ parser.add_argument ("--embedded-driver", dest = 'EmbeddedDriver', type = argparse.FileType('rb'), action='append', default = [],\r
+ help = "Path to embedded UEFI driver to add to capsule.")\r
+\r
#\r
# Add optional arguments common to all operations\r
#\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
+ parser.add_argument ("--update-image-index", dest = 'UpdateImageIndex', type = ValidateUnsignedInteger, default = 0x01, help = "unique number identifying the firmware image within the device ")\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 'InitiateReset' in args.CapsuleFlag:\r
- parser.error ('--capflag InitiateReset also requires --capflag PersistAcrossReset')\r
- if args.CapsuleOemFlag > 0xFFFF:\r
- parser.error ('--capoemflag must be an integer between 0x0000 and 0xffff')\r
- if args.HardwareInstance > 0xFFFFFFFFFFFFFFFF:\r
- parser.error ('--hardware-instance must be an integer in range 0x0..0xffffffffffffffff')\r
- if args.MonotonicCount > 0xFFFFFFFFFFFFFFFF:\r
- parser.error ('--monotonic-count must be an integer in range 0x0..0xffffffffffffffff')\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
- if args.FwVersion > 0xFFFFFFFF:\r
- parser.error ('--fw-version must be an integer in range 0x0..0xffffffff')\r
- if args.LowestSupportedVersion > 0xFFFFFFFF:\r
- parser.error ('--lsv must be an integer in range 0x0..0xffffffff')\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
- if args.DumpInfo:\r
- if args.OutputFile is not None:\r
- parser.error ('the following option is not supported for dumpinfo operations: --output')\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
+ Buffer = ''\r
+ if args.InputFile:\r
+ if os.path.getsize (args.InputFile.name) == 0:\r
+ print ('GenerateCapsule: error: InputFile {File} is empty'.format (File = args.InputFile.name))\r
+ sys.exit (1)\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
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
- 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 = False\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
- if args.Verbose:\r
- print ('--------')\r
- FmpAuthHeader.DumpInfo ()\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
+ EmbeddedDriverDescriptorList = []\r
+ PayloadDescriptorList = []\r
+ PayloadJsonDescriptorList = []\r
\r
- try:\r
- Result = FmpPayloadHeader.Decode (Result)\r
- if args.Verbose:\r
- print ('--------')\r
- FmpPayloadHeader.DumpInfo ()\r
- print ('========')\r
- except:\r
- if args.Verbose:\r
- print ('--------')\r
- print ('No FMP_PAYLOAD_HEADER')\r
- print ('========')\r
- raise\r
- else:\r
- if args.Verbose:\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
+ #\r
+ #Encode Operation\r
+ #\r
+ if args.Encode:\r
+ Encode (PayloadDescriptorList, EmbeddedDriverDescriptorList, Buffer)\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
- print ('--------')\r
- FmpAuthHeader.DumpInfo ()\r
- try:\r
- Result = FmpPayloadHeader.Decode (Result)\r
- print ('--------')\r
- FmpPayloadHeader.DumpInfo ()\r
- except:\r
- print ('--------')\r
- print ('No FMP_PAYLOAD_HEADER')\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
+ #Decode Operation\r
+ #\r
+ if args.Decode:\r
+ Decode (PayloadDescriptorList, PayloadJsonDescriptorList, Buffer)\r
\r
#\r
- # Write binary output file\r
+ #Dump Info Operation\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
+ if args.DumpInfo:\r
+ DumpInfo (Buffer, args)\r
\r
if args.Verbose:\r
print('Success')\r