[PATCH 3/3] binman: Add gzip bintool

Stefan Herbrechtsmeier stefan.herbrechtsmeier-oss at weidmueller.com
Tue Aug 2 14:27:58 CEST 2022


From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier at weidmueller.com>

Add gzip bintool to binman to support on-the-fly compression of Linux
kernel images and FPGA bitstreams. The SPL basic fitImage implementation
supports only gzip decompression.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier at weidmueller.com>
---

 tools/binman/btool/gzip.py | 94 ++++++++++++++++++++++++++++++++++++++
 tools/binman/comp_util.py  | 17 +++++--
 tools/binman/ftest.py      | 18 ++++++++
 3 files changed, 124 insertions(+), 5 deletions(-)
 create mode 100644 tools/binman/btool/gzip.py

diff --git a/tools/binman/btool/gzip.py b/tools/binman/btool/gzip.py
new file mode 100644
index 0000000000..27fb654ed5
--- /dev/null
+++ b/tools/binman/btool/gzip.py
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2022 Google LLC
+#
+"""Bintool implementation for gzip
+
+gzip allows compression and decompression of files.
+
+Documentation is available via::
+
+   man gzip
+"""
+
+import re
+import tempfile
+
+from binman import bintool
+from patman import tools
+
+# pylint: disable=C0103
+class Bintoolgzip(bintool.Bintool):
+    """Compression/decompression using the gzip algorithm
+
+    This bintool supports running `gzip` to compress and decompress data, as
+    used by binman.
+
+    It is also possible to fetch the tool, which uses `apt` to install it.
+
+    Documentation is available via::
+
+        man gzip
+    """
+    def __init__(self, name):
+        super().__init__(name, 'gzip compression')
+
+    def compress(self, indata):
+        """Compress data with gzip
+
+        Args:
+            indata (bytes): Data to compress
+
+        Returns:
+            bytes: Compressed data
+        """
+        with tempfile.NamedTemporaryFile(prefix='comp.tmp',
+                                         dir=tools.get_output_dir()) as tmp:
+            tools.write_file(tmp.name, indata)
+            args = ['-c', tmp.name]
+            return self.run_cmd(*args, binary=True)
+
+    def decompress(self, indata):
+        """Decompress data with gzip
+
+        Args:
+            indata (bytes): Data to decompress
+
+        Returns:
+            bytes: Decompressed data
+        """
+        with tempfile.NamedTemporaryFile(prefix='decomp.tmp',
+                                         dir=tools.get_output_dir()) as inf:
+            tools.write_file(inf.name, indata)
+            args = ['-cd', inf.name]
+            return self.run_cmd(*args, binary=True)
+
+    def fetch(self, method):
+        """Fetch handler for gzip
+
+        This installs the gzip package 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('gzip')
+
+    def version(self):
+        """Version handler
+
+        Returns:
+            str: Version number of gzip
+        """
+        out = self.run_cmd('-V').strip()
+        if not out:
+            return super().version()
+        m_version = re.match(r'.*gzip ([0-9.]*).*', out)
+        return m_version.group(1) if m_version else out
diff --git a/tools/binman/comp_util.py b/tools/binman/comp_util.py
index 269bbf7975..1d30f1613c 100644
--- a/tools/binman/comp_util.py
+++ b/tools/binman/comp_util.py
@@ -8,6 +8,9 @@ import tempfile
 from binman import bintool
 from patman import tools
 
+GZIP = bintool.Bintool.create('gzip')
+HAVE_GZIP = GZIP.is_present()
+
 LZ4 = bintool.Bintool.create('lz4')
 HAVE_LZ4 = LZ4.is_present()
 
@@ -21,19 +24,21 @@ def compress(indata, algo):
     Note that for lzma this uses an old version of the algorithm, not that
     provided by xz.
 
-    This requires 'lz4' and 'lzma_alone' tools. It also requires an output
+    This requires 'gzip', 'lz4' and 'lzma_alone' tools. It also requires an output
     directory to be previously set up, by calling PrepareOutputDir().
 
     Args:
         indata (bytes): Input data to compress
-        algo (str): Algorithm to use ('none', 'lz4' or 'lzma')
+        algo (str): Algorithm to use ('none', 'gzip', 'lz4' or 'lzma')
 
     Returns:
         bytes: Compressed data
     """
     if algo == 'none':
         return indata
-    if algo == 'lz4':
+    if algo == 'gzip':
+        data = GZIP.compress(indata)
+    elif algo == 'lz4':
         data = LZ4.compress(indata)
     # cbfstool uses a very old version of lzma
     elif algo == 'lzma':
@@ -48,12 +53,12 @@ def decompress(indata, algo):
     Note that for lzma this uses an old version of the algorithm, not that
     provided by xz.
 
-    This requires 'lz4' and 'lzma_alone' tools. It also requires an output
+    This requires 'gzip', 'lz4' and 'lzma_alone' tools. It also requires an output
     directory to be previously set up, by calling PrepareOutputDir().
 
     Args:
         indata (bytes): Input data to decompress
-        algo (str): Algorithm to use ('none', 'lz4' or 'lzma')
+        algo (str): Algorithm to use ('none', 'gzip', 'lz4' or 'lzma')
 
     Returns:
         (bytes) Compressed data
@@ -62,6 +67,8 @@ def decompress(indata, algo):
         return indata
     if algo == 'lz4':
         data = LZ4.decompress(indata)
+    elif algo == 'gzip':
+        data = GZIP.decompress(indata)
     elif algo == 'lzma':
         data = LZMA_ALONE.decompress(indata)
     else:
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index b1f564ed7d..5956ffa6e4 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -5226,6 +5226,24 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
             comp_util.decompress(b'1234', 'invalid')
         self.assertIn("Unknown algorithm 'invalid'", str(e.exception))
 
+    def testGzipCompress(self):
+        """Test gzip compress"""
+        if not comp_util.HAVE_GZIP:
+            self.skipTest('gzip not available')
+        data = comp_util.compress(COMPRESS_DATA, 'gzip')
+        gzip = bintool.Bintool.create('gzip')
+        orig = gzip.decompress(data)
+        self.assertEquals(COMPRESS_DATA, orig)
+
+    def testGzipDecompress(self):
+        """Test gzip decompress"""
+        if not comp_util.HAVE_GZIP:
+            self.skipTest('gzip not available')
+        gzip = bintool.Bintool.create('gzip')
+        data = gzip.compress(COMPRESS_DATA)
+        orig = comp_util.decompress(data, 'gzip')
+        self.assertEquals(COMPRESS_DATA, orig)
+
     def testBintoolDocs(self):
         """Test for creation of bintool documentation"""
         with test_util.capture_sys_output() as (stdout, stderr):
-- 
2.30.2



More information about the U-Boot mailing list