binman: Support lists of external blobs
authorSimon Glass <sjg@chromium.org>
Wed, 24 Nov 2021 04:09:52 +0000 (21:09 -0700)
committerSimon Glass <sjg@chromium.org>
Sun, 5 Dec 2021 16:23:15 +0000 (09:23 -0700)
Sometimes it is useful to have a list of related external blobs in a
single entry. An example is the DDR binaries used by meson. There are
9 files in total. Add support for this, so we don't have to have a
separate entry for each.

Signed-off-by: Simon Glass <sjg@chromium.org>
tools/binman/entries.rst
tools/binman/etype/blob.py
tools/binman/etype/blob_ext_list.py [new file with mode: 0644]
tools/binman/ftest.py
tools/binman/test/215_blob_ext_list.dts [new file with mode: 0644]
tools/binman/test/216_blob_ext_list_missing.dts [new file with mode: 0644]

index 2ebac51..d5aa3b0 100644 (file)
@@ -69,6 +69,20 @@ See 'blob' for Properties / Entry arguments.
 
 
 
+Entry: blob-ext-list: List of externally built binary blobs
+-----------------------------------------------------------
+
+This is like blob-ext except that a number of blobs can be provided,
+typically with some sort of relationship, e.g. all are DDC parameters.
+
+If any of the external files needed by this llist is missing, binman can
+optionally ignore it and produce a broken image with a warning.
+
+Args:
+    filenames: List of filenames to read and include
+
+
+
 Entry: blob-named-by-arg: A blob entry which gets its filename property from its subclass
 -----------------------------------------------------------------------------------------
 
index fae86ca..8c1b809 100644 (file)
@@ -48,10 +48,10 @@ class Entry_blob(Entry):
         self.ReadBlobContents()
         return True
 
-    def ReadBlobContents(self):
+    def ReadFileContents(self, pathname):
         """Read blob contents into memory
 
-        This function compresses the data before storing if needed.
+        This function compresses the data before returning if needed.
 
         We assume the data is small enough to fit into memory. If this
         is used for large filesystem image that might not be true.
@@ -59,13 +59,23 @@ class Entry_blob(Entry):
         new Entry method which can read in chunks. Then we could copy
         the data in chunks and avoid reading it all at once. For now
         this seems like an unnecessary complication.
+
+        Args:
+            pathname (str): Pathname to read from
+
+        Returns:
+            bytes: Data read
         """
         state.TimingStart('read')
-        indata = tools.ReadFile(self._pathname)
+        indata = tools.ReadFile(pathname)
         state.TimingAccum('read')
         state.TimingStart('compress')
         data = self.CompressData(indata)
         state.TimingAccum('compress')
+        return data
+
+    def ReadBlobContents(self):
+        data = self.ReadFileContents(self._pathname)
         self.SetContents(data)
         return True
 
diff --git a/tools/binman/etype/blob_ext_list.py b/tools/binman/etype/blob_ext_list.py
new file mode 100644 (file)
index 0000000..136ae81
--- /dev/null
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for a list of external blobs, not built by U-Boot
+#
+
+import os
+
+from binman.etype.blob import Entry_blob
+from dtoc import fdt_util
+from patman import tools
+from patman import tout
+
+class Entry_blob_ext_list(Entry_blob):
+    """List of externally built binary blobs
+
+    This is like blob-ext except that a number of blobs can be provided,
+    typically with some sort of relationship, e.g. all are DDC parameters.
+
+    If any of the external files needed by this llist is missing, binman can
+    optionally ignore it and produce a broken image with a warning.
+
+    Args:
+        filenames: List of filenames to read and include
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+        self.external = True
+
+    def ReadNode(self):
+        super().ReadNode()
+        self._filenames = fdt_util.GetStringList(self._node, 'filenames')
+        self._pathnames = []
+
+    def ObtainContents(self):
+        missing = False
+        pathnames = []
+        for fname in self._filenames:
+            pathname = tools.GetInputFilename(
+                fname, self.external and self.section.GetAllowMissing())
+            # Allow the file to be missing
+            if not pathname:
+                missing = True
+            pathnames.append(pathname)
+        self._pathnames = pathnames
+
+        if missing:
+            self.SetContents(b'')
+            self.missing = True
+            return True
+
+        data = bytearray()
+        for pathname in pathnames:
+            data += self.ReadFileContents(pathname)
+
+        self.SetContents(data)
+        return True
index d3a6cbf..f5ceb9f 100644 (file)
@@ -4715,6 +4715,26 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         finally:
             shutil.rmtree(tmpdir)
 
+    def testExtblobList(self):
+        """Test an image with an external blob list"""
+        data = self._DoReadFile('215_blob_ext_list.dts')
+        self.assertEqual(REFCODE_DATA + FSP_M_DATA, data)
+
+    def testExtblobListMissing(self):
+        """Test an image with a missing external blob"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('216_blob_ext_list_missing.dts')
+        self.assertIn("Filename 'missing-file' not found in input path",
+                      str(e.exception))
+
+    def testExtblobListMissingOk(self):
+        """Test an image with an missing external blob that is allowed"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            self._DoTestFile('216_blob_ext_list_missing.dts',
+                             allow_missing=True)
+        err = stderr.getvalue()
+        self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/215_blob_ext_list.dts b/tools/binman/test/215_blob_ext_list.dts
new file mode 100644 (file)
index 0000000..aad2f03
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               blob-ext-list {
+                       filenames = "refcode.bin", "fsp_m.bin";
+               };
+       };
+};
diff --git a/tools/binman/test/216_blob_ext_list_missing.dts b/tools/binman/test/216_blob_ext_list_missing.dts
new file mode 100644 (file)
index 0000000..c02c335
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       binman {
+               blob-ext-list {
+                       filenames = "refcode.bin", "missing-file";
+               };
+       };
+};