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:
|
symlink:
|
||||||
Adds a symlink to the image with string given in the symlink property.
|
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
|
Examples of the above options can be found in the tests. See the
|
||||||
tools/binman/test directory.
|
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
|
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
|
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
|
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
|
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
|
An absent entry is removed during processing so that it does not
|
||||||
appear in the map
|
appear in the map
|
||||||
optional (bool): True if this entry contains an optional external blob
|
optional (bool): True if this entry contains an optional external blob
|
||||||
|
overlap (bool): True if this entry overlaps with others
|
||||||
"""
|
"""
|
||||||
fake_dir = None
|
fake_dir = None
|
||||||
|
|
||||||
|
@ -142,6 +143,7 @@ class Entry(object):
|
||||||
self.auto_write_symbols = auto_write_symbols
|
self.auto_write_symbols = auto_write_symbols
|
||||||
self.absent = False
|
self.absent = False
|
||||||
self.optional = False
|
self.optional = False
|
||||||
|
self.overlap = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def FindEntryClass(etype, expanded):
|
def FindEntryClass(etype, expanded):
|
||||||
|
@ -294,6 +296,9 @@ class Entry(object):
|
||||||
self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
|
self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
|
||||||
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
|
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
|
||||||
self.optional = fdt_util.GetBool(self._node, 'optional')
|
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
|
# This is only supported by blobs and sections at present
|
||||||
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
|
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:
|
if not required and entry_data is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
entry_data_final = entry_data
|
||||||
if entry_data is None:
|
if entry_data is None:
|
||||||
pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
|
pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
|
||||||
else self._pad_byte)
|
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
|
# Handle empty space before the entry
|
||||||
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
|
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
|
||||||
if pad > 0:
|
if pad > 0:
|
||||||
section_data += tools.get_bytes(self._pad_byte, pad)
|
section_data += tools.get_bytes(self._pad_byte, pad)
|
||||||
|
|
||||||
# Add in the actual entry data
|
# 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
|
section_data += data
|
||||||
|
|
||||||
self.Detail('GetData: %d entries, total size %#x' %
|
self.Detail('GetData: %d entries, total size %#x' %
|
||||||
|
@ -467,10 +479,11 @@ class Entry_section(Entry):
|
||||||
(entry.offset, entry.offset, entry.size, entry.size,
|
(entry.offset, entry.offset, entry.size, entry.size,
|
||||||
self._node.path, self._skip_at_start,
|
self._node.path, self._skip_at_start,
|
||||||
self._skip_at_start, max_size, max_size))
|
self._skip_at_start, max_size, max_size))
|
||||||
|
if not entry.overlap:
|
||||||
if entry.offset < offset and entry.size:
|
if entry.offset < offset and entry.size:
|
||||||
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
|
entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' ending at %#x (%d)" %
|
||||||
"ending at %#x (%d)" %
|
(entry.offset, entry.offset, prev_name, offset,
|
||||||
(entry.offset, entry.offset, prev_name, offset, offset))
|
offset))
|
||||||
offset = entry.offset + entry.size
|
offset = entry.offset + entry.size
|
||||||
prev_name = entry.GetPath()
|
prev_name = entry.GetPath()
|
||||||
|
|
||||||
|
|
|
@ -6199,6 +6199,69 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
|
||||||
data = self._DoReadFile('268_null.dts')
|
data = self._DoReadFile('268_null.dts')
|
||||||
self.assertEqual(U_BOOT_DATA + b'\xff\xff\xff\xff' + U_BOOT_IMG_DATA, data)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.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