[PATCH v9 05/14] binman: Support optional entries
Simon Glass
sjg at chromium.org
Sat Jan 7 22:07:12 CET 2023
Support entries which can be optional depending on their contents. This
allows special entry types which appear in the image only when needed.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
(no changes since v1)
tools/binman/binman.rst | 22 ++++++++++++++++++++++
tools/binman/control.py | 1 +
tools/binman/entry.py | 9 +++++++++
tools/binman/etype/_testing.py | 3 +++
tools/binman/etype/section.py | 7 +++++++
tools/binman/ftest.py | 5 +++++
tools/binman/test/262_absent.dts | 20 ++++++++++++++++++++
7 files changed, 67 insertions(+)
create mode 100644 tools/binman/test/262_absent.dts
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index ef3e5a6d19b..5e3961f2255 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -1013,6 +1013,28 @@ For the BSS case, a 'spl-bss-pad' entry arg controls whether it is present. All
entry args are provided by the U-Boot Makefile.
+Optional entries
+----------------
+
+Some entries need to exist only if certain conditions are met. For example, an
+entry may want to appear in the image only if a file has a particular format.
+Obviously the entry must exist in the image description for it to be processed
+at all, so a way needs to be found to have the entry remove itself.
+
+To handle this, when entry.ObtainContents() is called, the entry can call
+entry.mark_absent() to mark itself as absent, passing a suitable message as the
+reason.
+
+Any absent entries are dropped immediately after ObtainContents() has been
+called on all entries.
+
+It is not possible for an entry to mark itself absent at any other point in the
+processing. It must happen in the ObtainContents() method.
+
+The effect is as if the entry had never been present at all, since the image
+is packed without it and it disappears from the list of entries.
+
+
Compression
-----------
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 964c6984f9b..07225381146 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -552,6 +552,7 @@ def ProcessImage(image, update_fdt, write_map, get_contents=True,
image.SetAllowMissing(allow_missing)
image.SetAllowFakeBlob(allow_fake_blobs)
image.GetEntryContents()
+ image.drop_absent()
image.GetEntryOffsets()
# We need to pack the entries to figure out where everything
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 1be31a05e00..637aece3705 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -91,6 +91,10 @@ class Entry(object):
file, or is a binary file produced from an ELF file
auto_write_symbols (bool): True to write ELF symbols into this entry's
contents
+ absent (bool): True if this entry is absent. This can be controlled by
+ 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
"""
fake_dir = None
@@ -133,6 +137,7 @@ class Entry(object):
self.comp_bintool = None
self.elf_fname = None
self.auto_write_symbols = auto_write_symbols
+ self.absent = False
@staticmethod
def FindEntryClass(etype, expanded):
@@ -1281,3 +1286,7 @@ features to produce new behaviours.
not_present.append(prop)
if not_present:
self.Raise(f"'{self.etype}' entry is missing properties: {' '.join(not_present)}")
+
+ def mark_absent(self, msg):
+ tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
+ self.absent = True
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index 69600487814..1c1efb21a44 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -63,6 +63,7 @@ class Entry__testing(Entry):
'bad-update-contents-twice')
self.return_contents_later = fdt_util.GetBool(self._node,
'return-contents-later')
+ self.set_to_absent = fdt_util.GetBool(self._node, 'set-to-absent')
# Set to True when the entry is ready to process the FDT.
self.process_fdt_ready = False
@@ -119,6 +120,8 @@ class Entry__testing(Entry):
if self.require_bintool_for_contents:
if self.bintool_for_contents is None:
self.Raise("Required bintool unusable in ObtainContents()")
+ if self.set_to_absent:
+ self.mark_absent('for testing purposes')
return True
def GetOffsets(self):
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 305155c8461..dcb7a062047 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -672,6 +672,9 @@ class Entry_section(Entry):
def GetEntryContents(self, skip_entry=None):
"""Call ObtainContents() for each entry in the section
+
+ Note that this may set entry.absent to True if the entry is not
+ actually needed
"""
def _CheckDone(entry):
if entry != skip_entry:
@@ -716,6 +719,10 @@ class Entry_section(Entry):
todo)
return True
+ def drop_absent(self):
+ """Drop entries which are absent"""
+ self._entries = {n: e for n, e in self._entries.items() if not e.absent}
+
def _SetEntryOffsetSize(self, name, offset, size):
"""Set the offset and size of an entry
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index c3cb32dca26..f47a745f1e1 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6090,6 +6090,11 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
sect_data = tools.read_file(sect_fname)
self.assertEqual(U_BOOT_DATA, sect_data)
+ def testAbsent(self):
+ """Check handling of absent entries"""
+ data = self._DoReadFile('262_absent.dts')
+ self.assertEqual(U_BOOT_DATA + U_BOOT_IMG_DATA, data)
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/262_absent.dts b/tools/binman/test/262_absent.dts
new file mode 100644
index 00000000000..2ab8766c878
--- /dev/null
+++ b/tools/binman/test/262_absent.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ _testing {
+ set-to-absent;
+ };
+
+ u-boot-img {
+ };
+ };
+};
--
2.39.0.314.g84b9a713c41-goog
More information about the U-Boot
mailing list