binman: Add a bintool implementation for mkimage

Add a Bintool for this, which is used to build images for use by U-Boot.
It supports the features needed by binman as well as installing via the
u-boot-tools packages. Although this is built in the U-Boot tree, it is
still useful to install a binary on the system.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/btool/mkimage.py b/tools/binman/btool/mkimage.py
new file mode 100644
index 0000000..c85bfe0
--- /dev/null
+++ b/tools/binman/btool/mkimage.py
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2022 Google LLC
+#
+"""Bintool implementation for mkimage"""
+
+import re
+
+from binman import bintool
+
+class Bintoolmkimage(bintool.Bintool):
+    """Image generation for U-Boot
+
+    This bintool supports running `mkimage` with some basic parameters as
+    neeed by binman.
+
+    Normally binman uses the mkimage built by U-Boot. But when run outside the
+    U-Boot build system, binman can use the version installed in your system.
+    Support is provided for fetching this on Debian-like systems, using apt.
+    """
+    def __init__(self, name):
+        super().__init__(name, 'Generate image for U-Boot')
+
+    # pylint: disable=R0913
+    def run(self, reset_timestamp=False, output_fname=None, external=False,
+            pad=None, version=False):
+        """Run mkimage
+
+        Args:
+            reset_timestamp: True to update the timestamp in the FIT
+            output_fname: Output filename to write to
+            external: True to create an 'external' FIT, where the binaries are
+                located outside the main data structure
+            pad: Bytes to use for padding the FIT devicetree output. This allows
+                other things to be easily added later, if required, such as
+                signatures
+            version: True to get the mkimage version
+        """
+        args = []
+        if external:
+            args.append('-E')
+        if pad:
+            args += ['-p', f'{pad:x}']
+        if reset_timestamp:
+            args.append('-t')
+        if output_fname:
+            args += ['-F', output_fname]
+        if version:
+            args.append('-V')
+        return self.run_cmd(*args)
+
+    def fetch(self, method):
+        """Fetch handler for mkimage
+
+        This installs mkimage using the apt utility.
+
+        Args:
+            method (FETCH_...): Method to use
+
+        Returns:
+            True if the file was fetched and now installed, None if a method
+            other than FETCH_BIN was requested
+
+        Raises:
+            Valuerror: Fetching could not be completed
+        """
+        if method != bintool.FETCH_BIN:
+            return None
+        return self.apt_install('u-boot-tools')
+
+    def version(self):
+        """Version handler for mkimage
+
+        Returns:
+            str: Version string for mkimage
+        """
+        out = self.run(version=True).strip()
+        if not out:
+            return super().version()
+        m_version = re.match(r'mkimage version (.*)', out)
+        return m_version.group(1) if m_version else out