[PATCH 5/8] binman: Support overlapping entries
Simon Glass
sjg at chromium.org
Thu Jan 12 00:10:16 CET 2023
In some cases it is useful to have an entry overlap with another in a
section, either to update the contents within a blob, or to add an entry
to the fdtmap that covers only part of the blob.
Add support for this.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
tools/binman/binman.rst | 9 +++-
tools/binman/entry.py | 5 ++
tools/binman/etype/section.py | 31 +++++++----
tools/binman/ftest.py | 63 +++++++++++++++++++++++
tools/binman/test/269_overlap.dts | 21 ++++++++
tools/binman/test/270_overlap_null.dts | 24 +++++++++
tools/binman/test/271_overlap_bad.dts | 21 ++++++++
tools/binman/test/272_overlap_no_size.dts | 19 +++++++
8 files changed, 183 insertions(+), 10 deletions(-)
create mode 100644 tools/binman/test/269_overlap.dts
create mode 100644 tools/binman/test/270_overlap_null.dts
create mode 100644 tools/binman/test/271_overlap_bad.dts
create mode 100644 tools/binman/test/272_overlap_no_size.dts
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index bfe300a39c1..97e2d4e55d5 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -792,6 +792,12 @@ align-default:
symlink:
Adds a symlink to the image with string given in the symlink property.
+overlap:
+ Indicates that this entry overlaps with others in the same section. These
+ entries should appear at the end of the section. Overlapping entries are not
+ packed with other entries, but their contents are written over other entries
+ in the section. Overlapping entries must have an explicit offset and size.
+
Examples of the above options can be found in the tests. See the
tools/binman/test directory.
@@ -1720,7 +1726,8 @@ implementation of Pack() is usually sufficient.
Note: for sections, this also checks that the entries do not overlap, nor extend
outside the section. If the section does not have a defined size, the size is
-set large enough to hold all the entries.
+set large enough to hold all the entries. For entries that are explicitly marked
+as overlapping, this check is skipped.
6. SetImagePos() - sets the image position of every entry. This is the absolute
position 'image-pos', as opposed to 'offset' which is relative to the containing
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index e6ff026ddb8..0c94665f7a8 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -98,6 +98,7 @@ class Entry(object):
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
+ overlap (bool): True if this entry overlaps with others
"""
fake_dir = None
@@ -142,6 +143,7 @@ class Entry(object):
self.auto_write_symbols = auto_write_symbols
self.absent = False
self.optional = False
+ self.overlap = False
@staticmethod
def FindEntryClass(etype, expanded):
@@ -294,6 +296,9 @@ class Entry(object):
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')
+ self.overlap = fdt_util.GetBool(self._node, 'overlap')
+ if self.overlap:
+ self.required_props += ['offset', 'size']
# This is only supported by blobs and sections at present
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index a22be7ec774..57b91ff726c 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -332,19 +332,31 @@ class Entry_section(Entry):
if not required and entry_data is None:
return None
+ entry_data_final = entry_data
if entry_data is None:
pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
else self._pad_byte)
- entry_data = tools.get_bytes(self._pad_byte, entry.size)
+ entry_data_final = tools.get_bytes(self._pad_byte, entry.size)
- data = self.GetPaddedDataForEntry(entry, entry_data)
+ data = self.GetPaddedDataForEntry(entry, entry_data_final)
# Handle empty space before the entry
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
if pad > 0:
section_data += tools.get_bytes(self._pad_byte, pad)
# Add in the actual entry data
- section_data += data
+ if entry.overlap:
+ end_offset = entry.offset + entry.size
+ if end_offset > len(section_data):
+ entry.Raise("Offset %#x (%d) ending at %#x (%d) must overlap with existing entries" %
+ (entry.offset, entry.offset, end_offset,
+ end_offset))
+ # Don't write anything for null entries'
+ if entry_data is not None:
+ section_data = (section_data[:entry.offset] + data +
+ section_data[entry.offset + entry.size:])
+ else:
+ section_data += data
self.Detail('GetData: %d entries, total size %#x' %
(len(self._entries), len(section_data)))
@@ -467,12 +479,13 @@ class Entry_section(Entry):
(entry.offset, entry.offset, entry.size, entry.size,
self._node.path, self._skip_at_start,
self._skip_at_start, max_size, max_size))
- if entry.offset < offset and entry.size:
- entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
- "ending at %#x (%d)" %
- (entry.offset, entry.offset, prev_name, offset, offset))
- offset = entry.offset + entry.size
- prev_name = entry.GetPath()
+ if not entry.overlap:
+ if entry.offset < offset and entry.size:
+ entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' ending at %#x (%d)" %
+ (entry.offset, entry.offset, prev_name, offset,
+ offset))
+ offset = entry.offset + entry.size
+ prev_name = entry.GetPath()
def WriteSymbols(self, section):
"""Write symbol values into binary files for access at run time"""
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index ac9b050fb6c..aea8a5f7589 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6199,6 +6199,69 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
data = self._DoReadFile('268_null.dts')
self.assertEqual(U_BOOT_DATA + b'\xff\xff\xff\xff' + U_BOOT_IMG_DATA, data)
+ def testOverlap(self):
+ """Test an image with a overlapping entry"""
+ data = self._DoReadFile('269_overlap.dts')
+ self.assertEqual(U_BOOT_DATA[:1] + b'aa' + U_BOOT_DATA[3:], data)
+
+ image = control.images['image']
+ entries = image.GetEntries()
+
+ self.assertIn('inset', entries)
+ inset = entries['inset']
+ self.assertEqual(1, inset.offset);
+ self.assertEqual(1, inset.image_pos);
+ self.assertEqual(2, inset.size);
+
+ def testOverlapNull(self):
+ """Test an image with a null overlap"""
+ data = self._DoReadFile('270_overlap_null.dts')
+ self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+
+ # Check the FMAP
+ fhdr, fentries = fmap_util.DecodeFmap(data[len(U_BOOT_DATA):])
+ self.assertEqual(4, fhdr.nareas)
+ fiter = iter(fentries)
+
+ fentry = next(fiter)
+ self.assertEqual(b'SECTION', fentry.name)
+ self.assertEqual(0, fentry.offset)
+ self.assertEqual(len(U_BOOT_DATA), fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ fentry = next(fiter)
+ self.assertEqual(b'U_BOOT', fentry.name)
+ self.assertEqual(0, fentry.offset)
+ self.assertEqual(len(U_BOOT_DATA), fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ # Make sure that the NULL entry appears in the FMAP
+ fentry = next(fiter)
+ self.assertEqual(b'NULL', fentry.name)
+ self.assertEqual(1, fentry.offset)
+ self.assertEqual(2, fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ fentry = next(fiter)
+ self.assertEqual(b'FMAP', fentry.name)
+ self.assertEqual(len(U_BOOT_DATA), fentry.offset)
+
+ def testOverlapBad(self):
+ """Test an image with a bad overlapping entry"""
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFile('271_overlap_bad.dts')
+ self.assertIn(
+ "Node '/binman/inset': Offset 0x10 (16) ending at 0x12 (18) must overlap with existing entries",
+ str(exc.exception))
+
+ def testOverlapNoOffset(self):
+ """Test an image with a bad overlapping entry"""
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFile('272_overlap_no_size.dts')
+ self.assertIn(
+ "Node '/binman/inset': 'fill' entry is missing properties: size",
+ str(exc.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/269_overlap.dts b/tools/binman/test/269_overlap.dts
new file mode 100644
index 00000000000..f949b8b359f
--- /dev/null
+++ b/tools/binman/test/269_overlap.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ offset = <1>;
+ size = <2>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/270_overlap_null.dts b/tools/binman/test/270_overlap_null.dts
new file mode 100644
index 00000000000..feed9ec8920
--- /dev/null
+++ b/tools/binman/test/270_overlap_null.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section {
+ u-boot {
+ };
+
+ null {
+ offset = <1>;
+ size = <2>;
+ overlap;
+ };
+ };
+
+ fmap {
+ };
+ };
+};
diff --git a/tools/binman/test/271_overlap_bad.dts b/tools/binman/test/271_overlap_bad.dts
new file mode 100644
index 00000000000..f2818021144
--- /dev/null
+++ b/tools/binman/test/271_overlap_bad.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ offset = <0x10>;
+ size = <2>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/272_overlap_no_size.dts b/tools/binman/test/272_overlap_no_size.dts
new file mode 100644
index 00000000000..4517536f2e6
--- /dev/null
+++ b/tools/binman/test/272_overlap_no_size.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ overlap;
+ };
+ };
+};
--
2.39.0.314.g84b9a713c41-goog
More information about the U-Boot
mailing list