[PATCH v4 06/12] binman: capsule: Add support for generating capsules

Sughosh Ganu sughosh.ganu at linaro.org
Sat Jul 15 15:45:27 CEST 2023


Add support in binman for generating capsules. The capsule parameters
can be specified either through a config file or through the capsule
binman entry. Also add test cases in binman for capsule generation,
and enable this testing on the sandbox_spl variant.

Signed-off-by: Sughosh Ganu <sughosh.ganu at linaro.org>
---
Changes since V3:
* Add test cases for covering the various capsule generation
  scenarios.
* Add function comments in the mkeficapsule bintool.
* Fix the fetch method of the mkeficapsule bintool to enable building
  the tool.
* Add more details about the capsule parameters in the documentation
  as well as the code.
* Fix order of module imports, and addition of blank lines in the
  capsule.py file.
* Use SetContents in the ObtainContents method.  

 configs/sandbox_spl_defconfig                 |   1 +
 tools/binman/btool/mkeficapsule.py            | 158 ++++++++++++++++++
 tools/binman/entries.rst                      |  37 ++++
 tools/binman/etype/capsule.py                 | 132 +++++++++++++++
 tools/binman/ftest.py                         | 127 ++++++++++++++
 tools/binman/test/282_capsule.dts             |  18 ++
 tools/binman/test/283_capsule_signed.dts      |  20 +++
 tools/binman/test/284_capsule_conf.dts        |  14 ++
 tools/binman/test/285_capsule_missing_key.dts |  19 +++
 .../binman/test/286_capsule_missing_index.dts |  17 ++
 .../binman/test/287_capsule_missing_guid.dts  |  17 ++
 .../test/288_capsule_missing_payload.dts      |  17 ++
 tools/binman/test/289_capsule_missing.dts     |  17 ++
 tools/binman/test/290_capsule_version.dts     |  19 +++
 tools/binman/test/capsule_cfg.txt             |   6 +
 15 files changed, 619 insertions(+)
 create mode 100644 tools/binman/btool/mkeficapsule.py
 create mode 100644 tools/binman/etype/capsule.py
 create mode 100644 tools/binman/test/282_capsule.dts
 create mode 100644 tools/binman/test/283_capsule_signed.dts
 create mode 100644 tools/binman/test/284_capsule_conf.dts
 create mode 100644 tools/binman/test/285_capsule_missing_key.dts
 create mode 100644 tools/binman/test/286_capsule_missing_index.dts
 create mode 100644 tools/binman/test/287_capsule_missing_guid.dts
 create mode 100644 tools/binman/test/288_capsule_missing_payload.dts
 create mode 100644 tools/binman/test/289_capsule_missing.dts
 create mode 100644 tools/binman/test/290_capsule_version.dts
 create mode 100644 tools/binman/test/capsule_cfg.txt

diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index dd848c57c6..2fcc789347 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -248,3 +248,4 @@ CONFIG_UNIT_TEST=y
 CONFIG_SPL_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
+CONFIG_TOOLS_MKEFICAPSULE=y
diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py
new file mode 100644
index 0000000000..ba6b666714
--- /dev/null
+++ b/tools/binman/btool/mkeficapsule.py
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2023 Linaro Limited
+#
+"""Bintool implementation for mkeficapsule tool
+
+mkeficapsule is a tool used for generating EFI capsules.
+
+The following are the command-line options to be provided
+to the tool
+Usage: mkeficapsule [options] <image blob> <output file>
+Options:
+	-g, --guid <guid string>    guid for image blob type
+	-i, --index <index>         update image index
+	-I, --instance <instance>   update hardware instance
+	-v, --fw-version <version>  firmware version
+	-p, --private-key <privkey file>  private key file
+	-c, --certificate <cert file>     signer's certificate file
+	-m, --monotonic-count <count>     monotonic count
+	-d, --dump_sig              dump signature (*.p7)
+	-A, --fw-accept  firmware accept capsule, requires GUID, no image blob
+	-R, --fw-revert  firmware revert capsule, takes no GUID, no image blob
+	-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff
+	-f, --cfg-file <config file> config file with capsule parameters
+	-h, --help                  print a help message
+
+"""
+
+from binman import bintool
+
+class Bintoolmkeficapsule(bintool.Bintool):
+    """Handles the 'mkeficapsule' tool
+
+    This bintool is used for generating the EFI capsules. The
+    capsule generation parameters can either be specified through
+    command-line, or through a config file.
+
+    """
+    def __init__(self, name):
+        super().__init__(name, 'mkeficapsule tool for generating capsules')
+
+    def capsule_cfg_file(self, cfg_file):
+        """Generate a capsule reading parameters from config file
+
+        Args:
+            cfg_file (str): Path to the config file
+
+        Returns:
+            str: Tool output
+        """
+
+        args = [
+            f'--cfg-file={cfg_file}'
+        ]
+        return self.run_cmd(*args)
+
+    def cmdline_capsule(self, image_index, image_guid, hardware_instance,
+                        payload, output_fname, version=0):
+        """Generate a capsule through commandline provided parameters
+
+        Args:
+            image_index (int): Unique number for identifying payload image
+            image_guid (str): GUID used for identifying the image
+            hardware_instance (int): Optional unique hardware instance of
+            a device in the system. 0 if not being used
+            payload (str): Path to the input payload image
+            output_fname (str): Path to the output capsule file
+            version (int): Image version (Optional)
+
+        Returns:
+            str: Tool output
+        """
+
+        if version:
+            args = [
+                f'--index={image_index}',
+                f'--fw-version={version}',
+                f'--guid={image_guid}',
+                f'--instance={hardware_instance}',
+                payload,
+                output_fname
+            ]
+        else:
+            args = [
+                f'--index={image_index}',
+                f'--guid={image_guid}',
+                f'--instance={hardware_instance}',
+                payload,
+                output_fname
+            ]
+
+        return self.run_cmd(*args)
+
+    def cmdline_auth_capsule(self, image_index, image_guid, hardware_instance,
+                             monotonic_count, priv_key, pub_key,
+                             payload, output_fname, version=0):
+        """Generate a signed capsule through commandline provided parameters
+
+        Args:
+            image_index (int): Unique number for identifying payload image
+            image_guid (str): GUID used for identifying the image
+            hardware_instance (int): Optional unique hardware instance of
+            a device in the system. 0 if not being used
+            monotonic_count (int): Count used when signing an image
+            priv_key (str): Path to the private key
+            pub_key(str): Path to the public key
+            payload (str): Path to the input payload image
+            output_fname (str): Path to the output capsule file
+            version (int): Image version (Optional)
+
+        Returns:
+            str: Tool output
+        """
+
+        if version:
+            args = [
+                f'--index={image_index}',
+                f'--guid={image_guid}',
+                f'--instance={hardware_instance}',
+                f'--monotonic-count={monotonic_count}',
+                f'--private-key={priv_key}',
+                f'--certificate={pub_key}',
+                f'--fw-version={version}',
+                payload,
+                output_fname
+            ]
+        else:
+            args = [
+                f'--index={image_index}',
+                f'--guid={image_guid}',
+                f'--instance={hardware_instance}',
+                f'--monotonic-count={monotonic_count}',
+                f'--private-key={priv_key}',
+                f'--certificate={pub_key}',
+                payload,
+                output_fname
+            ]
+
+        return self.run_cmd(*args)
+
+    def fetch(self, method):
+        """Fetch handler for mkeficapsule
+
+        This builds the tool from source
+
+        Returns:
+            tuple:
+                str: Filename of fetched file to copy to a suitable directory
+                str: Name of temp directory to remove, or None
+        """
+        if method != bintool.FETCH_BUILD:
+            return None
+
+        cmd = ['tools-only_defconfig', 'tools']
+        result = self.build_from_git(
+            'https://source.denx.de/u-boot/u-boot.git',
+            cmd,
+            'tools/mkeficapsule')
+        return result
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index b71af801fd..523c8222f5 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -283,6 +283,43 @@ entry; similarly for SPL.
 
 
 
+.. _etype_capsule:
+
+Entry: capsule: Entry for generating EFI Capsule files
+------------------------------------------------------
+
+This is an entry for generating EFI capsules.
+
+The parameters needed for generation of the capsules can either be
+provided separately, or through a config file.
+
+Properties / Entry arguments:
+    - cfg-file: Config file for providing capsule
+      parameters. These are parameters needed for generating the
+      capsules. The parameters can be listed by running the
+      './tools/mkeficapsule -h' command.
+    - image-index: Unique number for identifying corresponding
+      payload image. Number between 1 and descriptor count, i.e.
+      the total number of firmware images that can be updated.
+    - image-type-id: Image GUID which will be used for identifying the
+      updatable image on the board.
+    - hardware-instance: Optional number for identifying unique
+      hardware instance of a device in the system. Default value of 0
+      for images where value is not to be used.
+    - fw-version: Optional value of image version that can be put on
+      the capsule through the Firmware Management Protocol(FMP) header.
+    - monotomic-count: Count used when signing an image.
+    - private-key: Path to PEM formatted .key private key file.
+    - pub-key-cert: Path to PEM formatted .crt public key certificate
+      file.
+    - filename: Path to the input(payload) file. File can be any
+      format, a binary or an elf, platform specific.
+    - capsule: Path to the output capsule file. A capsule is a
+      continous set of data as defined by the EFI specification. Refer
+      to the specification for more details.
+
+
+
 .. _etype_cbfs:
 
 Entry: cbfs: Coreboot Filesystem (CBFS)
diff --git a/tools/binman/etype/capsule.py b/tools/binman/etype/capsule.py
new file mode 100644
index 0000000000..46e5507704
--- /dev/null
+++ b/tools/binman/etype/capsule.py
@@ -0,0 +1,132 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Linaro Limited
+#
+# Entry-type module for producing a capsule
+#
+
+import os
+
+from binman.entry import Entry
+from dtoc import fdt_util
+from u_boot_pylib import tools
+
+class Entry_capsule(Entry):
+    """Entry for generating EFI capsules
+
+    This is an entry for generating EFI capsules.
+
+    The parameters needed for generation of the capsules can
+    either be provided separately, or through a config file.
+
+    Properties / Entry arguments:
+    - cfg-file: Config file for providing capsule
+      parameters. These are parameters needed for generating the
+      capsules. The parameters can be listed by running the
+      './tools/mkeficapsule -h' command.
+    - image-index: Unique number for identifying corresponding
+      payload image. Number between 1 and descriptor count, i.e.
+      the total number of firmware images that can be updated.
+    - image-type-id: Image GUID which will be used for identifying the
+      updatable image on the board.
+    - hardware-instance: Optional number for identifying unique
+      hardware instance of a device in the system. Default value of 0
+      for images where value is not to be used.
+    - fw-version: Optional value of image version that can be put on
+      the capsule through the Firmware Management Protocol(FMP) header.
+    - monotomic-count: Count used when signing an image.
+    - private-key: Path to PEM formatted .key private key file.
+    - pub-key-cert: Path to PEM formatted .crt public key certificate
+      file.
+    - filename: Path to the input(payload) file. File can be any
+      format, a binary or an elf, platform specific.
+    - capsule: Path to the output capsule file. A capsule is a
+      continous set of data as defined by the EFI specification. Refer
+      to the specification for more details.
+
+    """
+    def __init__(self, section, etype, node):
+        super().__init__(section, etype, node)
+        self.image_index = 0
+        self.image_guid = ""
+        self.hardware_instance = 0
+        self.monotonic_count = 0
+        self.fw_version = 0
+        self.private_key = ""
+        self.pub_key_cert = ""
+        self.auth = 0
+        self.payload = ""
+        self.capsule_fname = ""
+
+    def ReadNode(self):
+        super().ReadNode()
+
+        self.cfg_file = fdt_util.GetString(self._node, 'cfg-file')
+        if not self.cfg_file:
+            self.image_index = fdt_util.GetInt(self._node, 'image-index')
+            if not self.image_index:
+                self.Raise('mkeficapsule must be provided an Image Index')
+
+            self.image_guid = fdt_util.GetString(self._node, 'image-type-id')
+            if not self.image_guid:
+                self.Raise('mkeficapsule must be provided an Image GUID')
+
+            self.fw_version = fdt_util.GetInt(self._node, 'fw-version')
+            self.hardware_instance = fdt_util.GetInt(self._node, 'hardware-instance')
+            self.monotonic_count = fdt_util.GetInt(self._node, 'monotonic-count')
+
+            self.private_key = fdt_util.GetString(self._node, 'private-key')
+            self.pub_key_cert = fdt_util.GetString(self._node, 'pub-key-cert')
+
+            if ((self.private_key and not self.pub_key_cert) or (self.pub_key_cert and not self.private_key)):
+                self.Raise('Both private-key and public key Certificate need to be provided')
+            elif not (self.private_key and self.pub_key_cert):
+                self.auth = 0
+            else:
+                self.auth = 1
+
+            self.payload = fdt_util.GetString(self._node, 'filename')
+            if not self.payload:
+                self.Raise('mkeficapsule must be provided an input filename(payload)')
+
+            if not os.path.isabs(self.payload):
+                self.payload_path = tools.get_input_filename(self.payload)
+                if not os.path.exists(self.payload_path):
+                    self.Raise('Cannot resolve path to the input filename(payload)')
+                else:
+                    self.payload = self.payload_path
+
+            self.capsule_fname = fdt_util.GetString(self._node, 'capsule')
+            if not self.capsule_fname:
+                self.Raise('Specify the output capsule file')
+
+            if not os.path.isabs(self.capsule_fname):
+                self.capsule_path = tools.get_output_filename(self.capsule_fname)
+                self.capsule_fname = self.capsule_path
+
+    def _GenCapsule(self):
+        if self.cfg_file:
+            return self.mkeficapsule.capsule_cfg_file(self.cfg_file)
+        elif self.auth:
+            return self.mkeficapsule.cmdline_auth_capsule(self.image_index,
+                                                          self.image_guid,
+                                                          self.hardware_instance,
+                                                          self.monotonic_count,
+                                                          self.private_key,
+                                                          self.pub_key_cert,
+                                                          self.payload,
+                                                          self.capsule_fname,
+                                                          self.fw_version)
+        else:
+            return self.mkeficapsule.cmdline_capsule(self.image_index,
+                                                     self.image_guid,
+                                                     self.hardware_instance,
+                                                     self.payload,
+                                                     self.capsule_fname,
+                                                     self.fw_version)
+
+    def ObtainContents(self):
+        self.SetContents(tools.to_bytes(self._GenCapsule()))
+        return True
+
+    def AddBintools(self, btools):
+        self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 43b4f850a6..f5dd62d028 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6676,6 +6676,133 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
                                 ['fit'])
         self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
+    def _CheckCapsule(self, signed_capsule=False, version_check=False):
+        # Firmware Management Protocol GUID used in capsule header
+        self.capsule_guid = "edd5cb6d2de8444cbda17194199ad92a"
+        # Image GUID specified in the DTS
+        self.image_guid = "52cfd7092007104791d108469b7fe9c8"
+        self.fmp_signature = "4d535331"
+        self.fmp_size = "10"
+        self.fmp_fw_version = "02"
+
+        self.capsule_data = tools.read_file(self.capsule_fname)
+
+        self.assertEqual(self.capsule_guid, self.capsule_data.hex()[:32])
+        self.assertEqual(self.image_guid, self.capsule_data.hex()[96:128])
+
+        if version_check:
+            self.assertEqual(self.fmp_signature, self.capsule_data.hex()[184:192])
+            self.assertEqual(self.fmp_size, self.capsule_data.hex()[192:194])
+            self.assertEqual(self.fmp_fw_version, self.capsule_data.hex()[200:202])
+
+        if signed_capsule:
+            self.assertEqual(self.payload_data.hex(), self.capsule_data.hex()[4770:4778])
+        elif version_check:
+            self.assertEqual(self.payload_data.hex(), self.capsule_data.hex()[216:224])
+        else:
+            self.assertEqual(self.payload_data.hex(), self.capsule_data.hex()[184:192])
+
+    def _GenCapsuleCfgPayload(self, fname, contents):
+        capsule_dir = '/tmp/capsules/'
+        pathname = os.path.join(capsule_dir, fname)
+        dirname = os.path.dirname(pathname)
+        if dirname and not os.path.exists(dirname):
+            os.makedirs(dirname)
+
+        with open(pathname, 'wb') as fd:
+            fd.write(contents)
+
+    def testCapsuleGen(self):
+        """Test generation of EFI capsule"""
+        self.payload_data = tools.to_bytes(TEXT_DATA)
+
+        TestFunctional._MakeInputFile('payload.txt', self.payload_data)
+
+        self._DoReadFile('282_capsule.dts')
+
+        self.capsule_fname = tools.get_output_filename('test.capsule')
+        self.assertTrue(os.path.exists(self.capsule_fname))
+
+        self._CheckCapsule()
+
+    def testSignedCapsuleGen(self):
+        """Test generation of EFI capsule"""
+        self.payload_data = tools.to_bytes(TEXT_DATA)
+
+        TestFunctional._MakeInputFile('payload.txt', self.payload_data)
+
+        self._DoReadFile('283_capsule_signed.dts')
+
+        self.capsule_fname = tools.get_output_filename('test.capsule')
+        self.assertTrue(os.path.exists(self.capsule_fname))
+
+        self._CheckCapsule(signed_capsule=True)
+
+    def testCapsuleGenCfgFile(self):
+        """Test generation of EFI capsule through config file"""
+        self.payload_data = tools.to_bytes(TEXT_DATA)
+
+        self._GenCapsuleCfgPayload('payload.txt', self.payload_data)
+
+        self._DoReadFile('284_capsule_conf.dts')
+
+        self.capsule_fname = '/tmp/capsules/test.capsule'
+        self.assertTrue(os.path.exists(self.capsule_fname))
+
+        self._CheckCapsule()
+
+    def testCapsuleGenVersionSupport(self):
+        """Test generation of EFI capsule with version support"""
+        self.payload_data = tools.to_bytes(TEXT_DATA)
 
+        TestFunctional._MakeInputFile('payload.txt', self.payload_data)
+
+        self._DoReadFile('290_capsule_version.dts')
+
+        self.capsule_fname = tools.get_output_filename('test.capsule')
+        self.assertTrue(os.path.exists(self.capsule_fname))
+
+        self._CheckCapsule(version_check=True)
+
+    def testCapsuleGenKeyMissing(self):
+        """Test that binman errors out on missing key"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('285_capsule_missing_key.dts')
+
+        self.assertIn("Both private-key and public key Certificate need to be provided",
+                      str(e.exception))
+
+    def testCapsuleGenIndexMissing(self):
+        """Test that binman errors out on missing image index"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('286_capsule_missing_index.dts')
+
+        self.assertIn("mkeficapsule must be provided an Image Index",
+                      str(e.exception))
+
+    def testCapsuleGenGuidMissing(self):
+        """Test that binman errors out on missing image GUID"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('287_capsule_missing_guid.dts')
+
+        self.assertIn("mkeficapsule must be provided an Image GUID",
+                      str(e.exception))
+
+    def testCapsuleGenPayloadMissing(self):
+        """Test that binman errors out on missing input(payload)image"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('288_capsule_missing_payload.dts')
+
+        self.assertIn("mkeficapsule must be provided an input filename(payload)",
+                      str(e.exception))
+
+    def testCapsuleGenCapsuleFileMissing(self):
+        """Test that binman errors out on missing output capsule file"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('289_capsule_missing.dts')
+
+        self.assertIn("Specify the output capsule file",
+                      str(e.exception))
+        
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/282_capsule.dts b/tools/binman/test/282_capsule.dts
new file mode 100644
index 0000000000..0e7fcdf8ab
--- /dev/null
+++ b/tools/binman/test/282_capsule.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/283_capsule_signed.dts b/tools/binman/test/283_capsule_signed.dts
new file mode 100644
index 0000000000..70a6690eef
--- /dev/null
+++ b/tools/binman/test/283_capsule_signed.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			private-key = "tools/binman/test/key.key";
+			pub-key-cert = "tools/binman/test/key.pem";
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/284_capsule_conf.dts b/tools/binman/test/284_capsule_conf.dts
new file mode 100644
index 0000000000..5d458a1a5a
--- /dev/null
+++ b/tools/binman/test/284_capsule_conf.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			cfg-file = "tools/binman/test/capsule_cfg.txt";
+		};
+	};
+};
diff --git a/tools/binman/test/285_capsule_missing_key.dts b/tools/binman/test/285_capsule_missing_key.dts
new file mode 100644
index 0000000000..7a09bbbf7b
--- /dev/null
+++ b/tools/binman/test/285_capsule_missing_key.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			private-key = "tools/binman/test/key.key";
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/286_capsule_missing_index.dts b/tools/binman/test/286_capsule_missing_index.dts
new file mode 100644
index 0000000000..dad521c0b5
--- /dev/null
+++ b/tools/binman/test/286_capsule_missing_index.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/287_capsule_missing_guid.dts b/tools/binman/test/287_capsule_missing_guid.dts
new file mode 100644
index 0000000000..b81aa3ecd2
--- /dev/null
+++ b/tools/binman/test/287_capsule_missing_guid.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			hardware-instance = <0x0>;
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/288_capsule_missing_payload.dts b/tools/binman/test/288_capsule_missing_payload.dts
new file mode 100644
index 0000000000..e702ac1a1d
--- /dev/null
+++ b/tools/binman/test/288_capsule_missing_payload.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/289_capsule_missing.dts b/tools/binman/test/289_capsule_missing.dts
new file mode 100644
index 0000000000..63b3d83370
--- /dev/null
+++ b/tools/binman/test/289_capsule_missing.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			filename = "payload.txt";
+		};
+	};
+};
diff --git a/tools/binman/test/290_capsule_version.dts b/tools/binman/test/290_capsule_version.dts
new file mode 100644
index 0000000000..b829d730f1
--- /dev/null
+++ b/tools/binman/test/290_capsule_version.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		capsule {
+			image-index = <0x1>;
+			fw-version = <0x2>;
+			image-type-id = "09D7CF52-0720-4710-91D1-08469B7FE9C8";
+			hardware-instance = <0x0>;
+			filename = "payload.txt";
+			capsule = "test.capsule";
+		};
+	};
+};
diff --git a/tools/binman/test/capsule_cfg.txt b/tools/binman/test/capsule_cfg.txt
new file mode 100644
index 0000000000..bf44a431b9
--- /dev/null
+++ b/tools/binman/test/capsule_cfg.txt
@@ -0,0 +1,6 @@
+{
+	image-index: 1
+	image-guid: 09D7CF52-0720-4710-91D1-08469B7FE9C8
+	payload: /tmp/capsules/payload.txt
+	capsule: /tmp/capsules/test.capsule
+}
-- 
2.34.1



More information about the U-Boot mailing list