[PATCH v3 06/11] binman: capsule: Add support for generating capsules

Sughosh Ganu sughosh.ganu at linaro.org
Sun Jul 9 15:33:21 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.

Signed-off-by: Sughosh Ganu <sughosh.ganu at linaro.org>
---
Changes since V2:
* New patch which generates capsules through binman replacing the
  earlier make target.

 tools/binman/btool/mkeficapsule.py |  91 +++++++++++++++++++++++++
 tools/binman/entries.rst           |  27 ++++++++
 tools/binman/etype/capsule.py      | 102 +++++++++++++++++++++++++++++
 3 files changed, 220 insertions(+)
 create mode 100644 tools/binman/btool/mkeficapsule.py
 create mode 100644 tools/binman/etype/capsule.py

diff --git a/tools/binman/btool/mkeficapsule.py b/tools/binman/btool/mkeficapsule.py
new file mode 100644
index 0000000000..9f656c12cf
--- /dev/null
+++ b/tools/binman/btool/mkeficapsule.py
@@ -0,0 +1,91 @@
+# 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
+	-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):
+
+        args = [
+            f'--cfg-file={cfg_file}'
+        ]
+        self.run_cmd(*args)
+
+    def cmdline_capsule(self, image_index, image_guid, hardware_instance,
+                        payload, output_fname):
+
+        args = [
+            f'--index={image_index}',
+            f'--guid={image_guid}',
+            f'--instance={hardware_instance}',
+            payload,
+            output_fname
+        ]
+        self.run_cmd(*args)
+
+    def cmdline_auth_capsule(self, image_index, image_guid, hardware_instance,
+                             monotonic_count, priv_key, pub_key,
+                             payload, output_fname):
+
+        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
+        ]
+        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
+        result = self.build_from_git(
+            'https://source.denx.de/u-boot/u-boot.git',
+            'tools',
+            'tools/mkeficapsule')
+        return result
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index b71af801fd..9a263e8691 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -283,6 +283,33 @@ 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.
+    - image-index: Unique number for identifying
+      corresponding payload image.
+    - image-type-id: Image GUID which will be used
+      for identifying the image.
+    - hardware-instance: Optional number for identifying
+      unique hardware instance of a device in the system.
+    - monotomic-count: Count used when signing an image.
+    - private-key: Path to private key file.
+    - pub-key-cert: Path to public key certificate file.
+    - filename: Path to the input(payload) file.
+    - capsule: Path to the output capsule file.
+
+
+
 .. _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..a5ada885a6
--- /dev/null
+++ b/tools/binman/etype/capsule.py
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Linaro Limited
+#
+# Entry-type module for producing a capsule
+#
+
+import os
+from u_boot_pylib import tools
+from dtoc import fdt_util
+from binman.entry import Entry
+
+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.
+        - image-index: Unique number for identifying
+          corresponding payload image.
+        - image-type-id: Image GUID which will be used
+          for identifying the image.
+        - hardware-instance: Optional number for identifying
+          unique hardware instance of a device in the system.
+        - monotomic-count: Count used when signing an image.
+        - private-key: Path to private key file.
+        - pub-key-cert: Path to public key certificate file.
+        - filename: Path to the input(payload) file.
+        - capsule: Path to the output capsule file.
+
+    """
+    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.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.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)')
+
+            self.capsule_fname = fdt_util.GetString(self._node, 'capsule')
+            if not self.capsule_fname:
+                self.capsule_fname = os.path.splitext(self.payload)[0] + '.capsule'
+
+    def ObtainContents(self):
+        if self.cfg_file:
+            self.mkeficapsule.capsule_cfg_file(self.cfg_file)
+        elif self.auth:
+            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)
+        else:
+            self.mkeficapsule.cmdline_capsule(self.image_index,
+                                              self.image_guid,
+                                              self.hardware_instance,
+                                              self.payload,
+                                              self.capsule_fname)
+
+    def AddBintools(self, btools):
+        self.mkeficapsule = self.AddBintool(btools, 'mkeficapsule')
-- 
2.34.1



More information about the U-Boot mailing list