mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
binman: Support overlapping entries
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@chromium.org>
This commit is contained in:
parent
97fb8081ec
commit
9766f69c98
8 changed files with 183 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -332,18 +332,30 @@ 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
|
||||
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' %
|
||||
|
@ -467,10 +479,11 @@ 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 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))
|
||||
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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
21
tools/binman/test/269_overlap.dts
Normal file
21
tools/binman/test/269_overlap.dts
Normal file
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
24
tools/binman/test/270_overlap_null.dts
Normal file
24
tools/binman/test/270_overlap_null.dts
Normal file
|
@ -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 {
|
||||
};
|
||||
};
|
||||
};
|
21
tools/binman/test/271_overlap_bad.dts
Normal file
21
tools/binman/test/271_overlap_bad.dts
Normal file
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
19
tools/binman/test/272_overlap_no_size.dts
Normal file
19
tools/binman/test/272_overlap_no_size.dts
Normal file
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue