From c8c9f3108a7b8c3ff391f60b184fa372ae4f32f2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 7 Jan 2023 14:07:12 -0700 Subject: [PATCH] binman: Support optional entries 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 --- 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 ef3e5a6d19..5e3961f225 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 964c6984f9..0722538114 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 1be31a05e0..637aece370 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 6960048781..1c1efb21a4 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 305155c846..dcb7a06204 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 c3cb32dca2..f47a745f1e 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 0000000000..2ab8766c87 --- /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.5