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 <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-01-07 14:07:12 -07:00
parent 23ab4e0054
commit c8c9f3108a
7 changed files with 67 additions and 0 deletions

View File

@ -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
-----------

View File

@ -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

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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()

View File

@ -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 {
};
};
};