All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Tom Rini <trini@konsulko.com>, huang lin <hl@rock-chips.com>,
	Jeffy Chen <jeffy.chen@rock-chips.com>,
	Simon Glass <sjg@chromium.org>,
	Kever Yang <kever.yang@rock-chips.com>,
	Philipp Tomsich <philipp.tomsich@theobroma-systems.com>,
	Ivan Mikhaylov <ivan.mikhaylov@siemens.com>,
	Quentin Schulz <quentin.schulz@theobroma-systems.com>,
	Roger Quadros <rogerq@ti.com>,
	Philippe Reynes <philippe.reynes@softathome.com>,
	Alper Nebi Yasak <alpernebiyasak@gmail.com>,
	Jerome Forissier <jerome.forissier@linaro.org>,
	Peter Geis <pgwipeout@gmail.com>
Subject: [PATCH v8 07/13] binman: Support optional external blobs
Date: Wed, 21 Dec 2022 16:07:20 -0700	[thread overview]
Message-ID: <20221221230726.638740-8-sjg@chromium.org> (raw)
In-Reply-To: <20221221230726.638740-1-sjg@chromium.org>

Some blobs are actually not necessary for the board to work correctly. Add
a property to allow this to be indicated. Missing optional blobs do not
cause a build failure.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v8:
- Move support for optional external blobs into this series
- Support optional FIT images

 tools/binman/binman.rst                |  9 +++++++++
 tools/binman/control.py                | 11 +++++++++++
 tools/binman/entry.py                  | 25 +++++++++++++++++++++----
 tools/binman/etype/blob.py             |  2 +-
 tools/binman/etype/fit.py              | 11 ++++++-----
 tools/binman/etype/section.py          | 14 +++++++++++++-
 tools/binman/ftest.py                  | 10 ++++++++++
 tools/binman/test/266_blob_ext_opt.dts | 21 +++++++++++++++++++++
 8 files changed, 92 insertions(+), 11 deletions(-)
 create mode 100644 tools/binman/test/266_blob_ext_opt.dts

diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 1ab6d012b83..391494907ab 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -689,6 +689,15 @@ no-expanded:
     `no-expanded` property disables this just for a single entry. Put the
     `no-expanded` boolean property in the node to select this behaviour.
 
+optional:
+    External blobs are normally required to be present for the image to be
+    built (but see `External blobs`_). This properly allows an entry to be
+    optional, so that when it is cannot be found, this problem is ignored and
+    an empty file is used for this blob. This should be used only when the blob
+    is entirely optional and is not needed for correct operation of the image.
+    Note that missing, optional blobs do not produce a non-zero exit code from
+    binman, although it does show a warning about the missing external blob.
+
 The attributes supported for images and sections are described below. Several
 are similar to those for entries.
 
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 07225381146..e64740094f6 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -594,12 +594,14 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
     image.BuildImage()
     if write_map:
         image.WriteMap()
+
     missing_list = []
     image.CheckMissing(missing_list)
     if missing_list:
         tout.warning("Image '%s' is missing external blobs and is non-functional: %s" %
                      (image.name, ' '.join([e.name for e in missing_list])))
         _ShowHelpForMissingBlobs(missing_list)
+
     faked_list = []
     image.CheckFakedBlobs(faked_list)
     if faked_list:
@@ -607,6 +609,15 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
             "Image '%s' has faked external blobs and is non-functional: %s" %
             (image.name, ' '.join([os.path.basename(e.GetDefaultFilename())
                                    for e in faked_list])))
+
+    optional_list = []
+    image.CheckOptional(optional_list)
+    if optional_list:
+        tout.warning(
+            "Image '%s' is missing external blobs but is still functional: %s" %
+            (image.name, ' '.join([e.name for e in optional_list])))
+        _ShowHelpForMissingBlobs(optional_list)
+
     missing_bintool_list = []
     image.check_missing_bintools(missing_bintool_list)
     if missing_bintool_list:
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index de51d295891..d73f3013405 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -73,7 +73,9 @@ class Entry(object):
         compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
         orig_offset: Original offset value read from node
         orig_size: Original size value read from node
-        missing: True if this entry is missing its contents
+        missing: True if this entry is missing its contents. Note that if it is
+            optional, this entry will not appear in the list generated by
+            entry.CheckMissing() since it is considered OK for it to be missing.
         allow_missing: Allow children of this entry to be missing (used by
             subclasses such as Entry_section)
         allow_fake: Allow creating a dummy fake file if the blob file is not
@@ -95,6 +97,7 @@ class Entry(object):
             the entry itself, allowing it to vanish in certain circumstances.
             An absent entry is removed during processing so that it does not
             appear in the map
+        optional (bool): True if this entry contains an optional external blob
     """
     fake_dir = None
 
@@ -138,6 +141,7 @@ class Entry(object):
         self.elf_fname = None
         self.auto_write_symbols = auto_write_symbols
         self.absent = False
+        self.optional = False
 
     @staticmethod
     def FindEntryClass(etype, expanded):
@@ -289,6 +293,7 @@ class Entry(object):
         self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
         self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
         self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
+        self.optional = fdt_util.GetBool(self._node, 'optional')
 
         # This is only supported by blobs and sections at present
         self.compress = fdt_util.GetString(self._node, 'compress', 'none')
@@ -1039,14 +1044,15 @@ features to produce new behaviours.
         self.allow_fake = allow_fake
 
     def CheckMissing(self, missing_list):
-        """Check if any entries in this section have missing external blobs
+        """Check if the entry has missing external blobs
 
-        If there are missing blobs, the entries are added to the list
+        If there are missing (non-optional) blobs, the entries are added to the
+        list
 
         Args:
             missing_list: List of Entry objects to be added to
         """
-        if self.missing:
+        if self.missing and not self.optional:
             missing_list.append(self)
 
     def check_fake_fname(self, fname, size=0):
@@ -1085,6 +1091,17 @@ features to produce new behaviours.
         # This is meaningless for anything other than blobs
         pass
 
+    def CheckOptional(self, optional_list):
+        """Check if the entry has missing but optional external blobs
+
+        If there are missing (optional) blobs, the entries are added to the list
+
+        Args:
+            optional_list (list): List of Entry objects to be added to
+        """
+        if self.missing and self.optional:
+            optional_list.append(self)
+
     def GetAllowMissing(self):
         """Get whether a section allows missing external blobs
 
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index a50a8068901..70dea7158ee 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -39,7 +39,7 @@ class Entry_blob(Entry):
     def ObtainContents(self, fake_size=0):
         self._filename = self.GetDefaultFilename()
         self._pathname = tools.get_input_filename(self._filename,
-            self.external and self.section.GetAllowMissing())
+            self.external and (self.optional or self.section.GetAllowMissing()))
         # Allow the file to be missing
         if not self._pathname:
             self._pathname, faked = self.check_fake_fname(self._filename,
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index 21c769a1cbe..acd0466be5a 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -392,8 +392,8 @@ class Entry_fit(Entry_section):
 
         _add_entries(self._node, 0, self._node)
 
-        # Keep a copy of all entries, including generator entries, since these
-        # removed from self._entries later.
+        # Keep a copy of all entries, including generator entries, since those
+        # are removed from self._entries later.
         self._priv_entries = dict(self._entries)
 
     def BuildSectionData(self, required):
@@ -601,14 +601,15 @@ class Entry_fit(Entry_section):
                 # Entry_section.ObtainContents() either returns True or
                 # raises an exception.
                 data = None
-                missing_list = []
+                missing_opt_list = []
                 entry.ObtainContents()
                 entry.Pack(0)
-                entry.CheckMissing(missing_list)
+                entry.CheckMissing(missing_opt_list)
+                entry.CheckOptional(missing_opt_list)
 
                 # If any pieces are missing, skip this. The missing entries will
                 # show an error
-                if not missing_list:
+                if not missing_opt_list:
                     segs = entry.read_elf_segments()
                     if segs:
                         segments, entry_addr = segs
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 57bfee0b286..44dafaf7262 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -863,7 +863,8 @@ class Entry_section(Entry):
     def CheckMissing(self, missing_list):
         """Check if any entries in this section have missing external blobs
 
-        If there are missing blobs, the entries are added to the list
+        If there are missing (non-optional) blobs, the entries are added to the
+        list
 
         Args:
             missing_list: List of Entry objects to be added to
@@ -882,6 +883,17 @@ class Entry_section(Entry):
         for entry in self._entries.values():
             entry.CheckFakedBlobs(faked_blobs_list)
 
+    def CheckOptional(self, optional_list):
+        """Check the section for missing but optional external blobs
+
+        If there are missing (optional) blobs, the entries are added to the list
+
+        Args:
+            optional_list (list): List of Entry objects to be added to
+        """
+        for entry in self._entries.values():
+            entry.CheckOptional(optional_list)
+
     def check_missing_bintools(self, missing_list):
         """Check if any entries in this section have missing bintools
 
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index f893050e706..330e8e1ccb4 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6178,6 +6178,16 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
             "Node '/binman/fit/images/@tee-SEQ/tee-os': Invalid OP-TEE file: size mismatch (expected 0x4, have 0xe)",
             str(exc.exception))
 
+    def testExtblobOptional(self):
+        """Test an image with an external blob that is optional"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            data = self._DoReadFile('266_blob_ext_opt.dts')
+        self.assertEqual(REFCODE_DATA, data)
+        err = stderr.getvalue()
+        self.assertRegex(
+            err,
+            "Image '.*' is missing external blobs but is still functional: missing")
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/266_blob_ext_opt.dts b/tools/binman/test/266_blob_ext_opt.dts
new file mode 100644
index 00000000000..717153152ce
--- /dev/null
+++ b/tools/binman/test/266_blob_ext_opt.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		ok {
+			type = "blob-ext";
+			filename = "refcode.bin";
+		};
+
+		missing {
+			type = "blob-ext";
+			filename = "missing.bin";
+			optional;
+		};
+	};
+};
-- 
2.39.0.314.g84b9a713c41-goog


  parent reply	other threads:[~2022-12-21 23:09 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-21 23:07 [PATCH v8 00/13] binman: rockchip: Migrate from rockchip SPL_FIT_GENERATOR script Simon Glass
2022-12-21 23:07 ` [PATCH v8 01/13] binman: Allow writing section contents to a file Simon Glass
2022-12-21 23:07 ` [PATCH v8 02/13] binman: Tidy up comment in fit _gen_node Simon Glass
2022-12-21 23:07 ` [PATCH v8 03/13] binman: Update entry docs Simon Glass
2023-01-02 16:19   ` Quentin Schulz
2022-12-21 23:07 ` [PATCH v8 04/13] binman: Support optional entries Simon Glass
2022-12-21 23:07 ` [PATCH v8 05/13] binman: Add a way to check for a valid ELF file Simon Glass
2023-01-02 16:26   ` Quentin Schulz
2022-12-21 23:07 ` [PATCH v8 06/13] binman: Support new op-tee binary format Simon Glass
2022-12-22 15:36   ` Jerome Forissier
2022-12-22 20:18     ` Simon Glass
2022-12-22 20:23       ` Simon Glass
2022-12-22 22:20         ` Jerome Forissier
2023-01-07 18:55           ` Simon Glass
2023-01-07 21:58             ` Jerome Forissier
2023-01-02 17:53   ` Quentin Schulz
2023-01-07 18:55     ` Simon Glass
2023-01-07 21:51       ` Jerome Forissier
2022-12-21 23:07 ` Simon Glass [this message]
2022-12-21 23:07 ` [PATCH v8 08/13] rockchip: evb-rk3288: Drop raw-image support Simon Glass
2022-12-21 23:07 ` [PATCH v8 09/13] rockchip: Use multiple-images for rk3399 Simon Glass
2023-01-02 16:42   ` Quentin Schulz
2023-01-04 20:01     ` Simon Glass
2023-01-05  9:47       ` Quentin Schulz
2023-01-07  0:13         ` Simon Glass
2022-12-21 23:07 ` [PATCH v8 10/13] rockchip: Support building the all output files in binman Simon Glass
2022-12-21 23:07 ` [PATCH v8 11/13] rockchip: Convert all boards to use binman Simon Glass
2022-12-21 23:07 ` [PATCH v8 12/13] rockchip: Drop the FIT generator script Simon Glass
2022-12-21 23:07 ` [PATCH v8 13/13] treewide: Disable USE_SPL_FIT_GENERATOR by default Simon Glass
2022-12-21 23:11   ` Tom Rini
2022-12-22 17:41     ` Simon Glass
2022-12-22 17:57       ` Tom Rini
2022-12-22 19:25         ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221221230726.638740-8-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=alpernebiyasak@gmail.com \
    --cc=hl@rock-chips.com \
    --cc=ivan.mikhaylov@siemens.com \
    --cc=jeffy.chen@rock-chips.com \
    --cc=jerome.forissier@linaro.org \
    --cc=kever.yang@rock-chips.com \
    --cc=pgwipeout@gmail.com \
    --cc=philipp.tomsich@theobroma-systems.com \
    --cc=philippe.reynes@softathome.com \
    --cc=quentin.schulz@theobroma-systems.com \
    --cc=rogerq@ti.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.