binman: Support expanding entries
It is useful to have entries which can grow automatically to fill
available space. Add support for this.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/README b/tools/binman/README
index d687194..6aa5b38 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -330,6 +330,10 @@
for each entry. This makes it easy to find out exactly where the entry
ended up in the image, regardless of parent sections, etc.
+expand-size:
+ Expand the size of this entry to fit available space. This space is only
+ limited by the size of the image/section and the position of the next
+ entry.
The attributes supported for images are described below. Several are similar
to those for entries.
diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py
index 4bf2068..52ac31a 100644
--- a/tools/binman/bsection.py
+++ b/tools/binman/bsection.py
@@ -253,10 +253,26 @@
for entry in entries:
self._entries[entry._node.name] = entry
+ def _ExpandEntries(self):
+ """Expand any entries that are permitted to"""
+ exp_entry = None
+ for entry in self._entries.values():
+ if exp_entry:
+ exp_entry.ExpandToLimit(entry.offset)
+ exp_entry = None
+ if entry.expand_size:
+ exp_entry = entry
+ if exp_entry:
+ exp_entry.ExpandToLimit(self._size)
+
def CheckEntries(self):
- """Check that entries do not overlap or extend outside the section"""
+ """Check that entries do not overlap or extend outside the section
+
+ This also sorts entries, if needed and expands
+ """
if self._sort:
self._SortEntries()
+ self._ExpandEntries()
offset = 0
prev_name = 'None'
for entry in self._entries.values():
@@ -419,3 +435,7 @@
return None
return entry.data
source_entry.Raise("Cannot find entry for node '%s'" % node.name)
+
+ def ExpandSize(self, size):
+ if size != self._size:
+ self._size = size
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 7316ad4..0915b47 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -76,6 +76,7 @@
self.pad_after = 0
self.offset_unset = False
self.image_pos = None
+ self._expand_size = False
if read_node:
self.ReadNode()
@@ -161,6 +162,7 @@
"of two" % (self._node.path, self.align_size))
self.align_end = fdt_util.GetInt(self._node, 'align-end')
self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
+ self.expand_size = fdt_util.GetBool(self._node, 'expand-size')
def GetDefaultFilename(self):
return None
@@ -507,3 +509,12 @@
break
name = '%s.%s' % (node.name, name)
return name
+
+ def ExpandToLimit(self, limit):
+ """Expand an entry so that it ends at the given offset limit"""
+ if self.offset + self.size < limit:
+ self.size = limit - self.offset
+ # Request the contents again, since changing the size requires that
+ # the data grows. This should not fail, but check it to be sure.
+ if not self.ObtainContents():
+ self.Raise('Cannot obtain contents when expanding entry')
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index 02c165c..3e345bd 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -48,6 +48,8 @@
'return-unknown-contents')
self.bad_update_contents = fdt_util.GetBool(self._node,
'bad-update-contents')
+ self.return_contents_once = fdt_util.GetBool(self._node,
+ 'return-contents-once')
# Set to True when the entry is ready to process the FDT.
self.process_fdt_ready = False
@@ -68,12 +70,15 @@
EntryArg('test-existing-prop', str)], self.require_args)
if self.force_bad_datatype:
self.GetEntryArgsOrProps([EntryArg('test-bad-datatype-arg', bool)])
+ self.return_contents = True
def ObtainContents(self):
- if self.return_unknown_contents:
+ if self.return_unknown_contents or not self.return_contents:
return False
self.data = 'a'
self.contents_size = len(self.data)
+ if self.return_contents_once:
+ self.return_contents = False
return True
def GetOffsets(self):
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index a30cc91..005a9f9 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -40,6 +40,10 @@
def ProcessFdt(self, fdt):
return self._section.ProcessFdt(fdt)
+ def ExpandEntries(self):
+ Entry.ExpandEntries(self)
+ self._section.ExpandEntries()
+
def AddMissingProperties(self):
Entry.AddMissingProperties(self)
self._section.AddMissingProperties()
@@ -95,3 +99,7 @@
def GetEntries(self):
return self._section.GetEntries()
+
+ def ExpandToLimit(self, limit):
+ super(Entry_section, self).ExpandToLimit(limit)
+ self._section.ExpandSize(self.size)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index e919e70..b156943 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -1579,6 +1579,35 @@
self.assertIn("Node '/binman/files': Missing 'pattern' property",
str(e.exception))
+ def testExpandSize(self):
+ """Test an expanding entry"""
+ data, _, map_data, _ = self._DoReadFileDtb('88_expand_size.dts',
+ map=True)
+ expect = ('a' * 8 + U_BOOT_DATA +
+ MRC_DATA + 'b' * 1 + U_BOOT_DATA +
+ 'c' * 8 + U_BOOT_DATA +
+ 'd' * 8)
+ self.assertEqual(expect, data)
+ self.assertEqual('''ImagePos Offset Size Name
+00000000 00000000 00000028 main-section
+00000000 00000000 00000008 fill
+00000008 00000008 00000004 u-boot
+0000000c 0000000c 00000004 section
+0000000c 00000000 00000003 intel-mrc
+00000010 00000010 00000004 u-boot2
+00000014 00000014 0000000c section2
+00000014 00000000 00000008 fill
+0000001c 00000008 00000004 u-boot
+00000020 00000020 00000008 fill2
+''', map_data)
+
+ def testExpandSizeBad(self):
+ """Test an expanding entry which fails to provide contents"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
+ self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
+ 'expanding entry', str(e.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/88_expand_size.dts b/tools/binman/test/88_expand_size.dts
new file mode 100644
index 0000000..c8a0130
--- /dev/null
+++ b/tools/binman/test/88_expand_size.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ size = <40>;
+ fill {
+ expand-size;
+ fill-byte = [61];
+ size = <0>;
+ };
+ u-boot {
+ offset = <8>;
+ };
+ section {
+ expand-size;
+ pad-byte = <0x62>;
+ intel-mrc {
+ };
+ };
+ u-boot2 {
+ type = "u-boot";
+ offset = <16>;
+ };
+ section2 {
+ type = "section";
+ fill {
+ expand-size;
+ fill-byte = [63];
+ size = <0>;
+ };
+ u-boot {
+ offset = <8>;
+ };
+ };
+ fill2 {
+ type = "fill";
+ expand-size;
+ fill-byte = [64];
+ size = <0>;
+ };
+ };
+};
diff --git a/tools/binman/test/89_expand_size_bad.dts b/tools/binman/test/89_expand_size_bad.dts
new file mode 100644
index 0000000..edc0e5c
--- /dev/null
+++ b/tools/binman/test/89_expand_size_bad.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ binman {
+ _testing {
+ expand-size;
+ return-contents-once;
+ };
+ u-boot {
+ offset = <8>;
+ };
+ };
+};