binman: Add a return value to ProcessContentsUpdate()

At present if this function tries to update the contents such that the
size changes, it raises an error. We plan to add the ability to change
the size of entries after packing is completed, since in some cases it is
not possible to determine the size in advance.

An example of this is with a compressed device tree, where the values
of the device tree change in SetCalculatedProperties() or
ProcessEntryContents(). While the device tree itself does not change size,
since placeholders for any new properties have already bee added by
AddMissingProperties(), we cannot predict the size of the device tree
after compression. If a value changes from 0 to 0x1234 (say), then the
compressed device tree may expand.

As a first step towards supporting this, make ProcessContentsUpdate()
return a value indicating whether the content size is OK. For now this is
always True (since otherwise binman raises an error), but later patches
will adjust this.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2019-07-08 14:25:35 -06:00
parent 7f9e00a2a6
commit a0dcaf2049
10 changed files with 44 additions and 15 deletions

View File

@ -317,9 +317,15 @@ class Section(object):
"""Call the ProcessContents() method for each entry
This is intended to adjust the contents as needed by the entry type.
Returns:
True if no entries needed to change their size
"""
sizes_ok = True
for entry in self._entries.values():
entry.ProcessContents()
if not entry.ProcessContents():
sizes_ok = False
return sizes_ok
def WriteSymbols(self):
"""Write symbol values into binary files for access at run time"""

View File

@ -245,7 +245,8 @@ class Entry(object):
def ProcessContentsUpdate(self, data):
"""Update the contents of an entry, after the size is fixed
This checks that the new data is the same size as the old.
This checks that the new data is the same size as the old. If the size
has changed, this triggers a re-run of the packing algorithm.
Args:
data: Data to set to the contents (bytes)
@ -253,10 +254,12 @@ class Entry(object):
Raises:
ValueError if the new data size is not the same as the old
"""
size_ok = True
if len(data) != self.contents_size:
self.Raise('Cannot update entry size from %d to %d' %
(self.contents_size, len(data)))
self.SetContents(data)
return size_ok
def ObtainContents(self):
"""Figure out the contents of an entry.
@ -401,7 +404,22 @@ class Entry(object):
self.image_pos = image_pos + self.offset
def ProcessContents(self):
pass
"""Do any post-packing updates of entry contents
This function should call ProcessContentsUpdate() to update the entry
contents, if necessary, returning its return value here.
Args:
data: Data to set to the contents (bytes)
Returns:
True if the new data size is OK, False if expansion is needed
Raises:
ValueError if the new data size is not the same as the old and
state.AllowEntryExpansion() is False
"""
return True
def WriteSymbols(self, section):
"""Write symbol values into binary files for access at run time

View File

@ -88,9 +88,10 @@ class Entry__testing(Entry):
def ProcessContents(self):
if self.bad_update_contents:
# Request to update the conents with something larger, to cause a
# Request to update the contents with something larger, to cause a
# failure.
self.ProcessContentsUpdate('aa')
return self.ProcessContentsUpdate('aa')
return True
def ProcessFdt(self, fdt):
"""Force reprocessing the first time"""

View File

@ -30,4 +30,4 @@ class Entry_blob_dtb(Entry_blob):
def ProcessContents(self):
"""Re-read the DTB contents so that we get any calculated properties"""
_, data = state.GetFdtContents(self._filename)
self.ProcessContentsUpdate(data)
return self.ProcessContentsUpdate(data)

View File

@ -106,4 +106,4 @@ class Entry_fdtmap(Entry):
This is necessary since new data may have been written back to it during
processing, e.g. the image-pos properties.
"""
self.ProcessContentsUpdate(self._GetFdtmap())
return self.ProcessContentsUpdate(self._GetFdtmap())

View File

@ -62,4 +62,4 @@ class Entry_fmap(Entry):
return True
def ProcessContents(self):
self.ProcessContentsUpdate(self._GetFmap())
return self.ProcessContentsUpdate(self._GetFmap())

View File

@ -73,4 +73,4 @@ class Entry_image_header(Entry):
This is necessary since image_pos is not available when ObtainContents()
is called, since by then the entries have not been packed in the image.
"""
self.ProcessContentsUpdate(self._GetHeader())
return self.ProcessContentsUpdate(self._GetHeader())

View File

@ -85,8 +85,9 @@ class Entry_section(Entry):
self._section.SetCalculatedProperties()
def ProcessContents(self):
self._section.ProcessEntryContents()
super(Entry_section, self).ProcessContents()
sizes_ok = self._section.ProcessEntryContents()
sizes_ok_base = super(Entry_section, self).ProcessContents()
return sizes_ok and sizes_ok_base
def CheckOffset(self):
self._section.CheckEntries()

View File

@ -91,6 +91,6 @@ class Entry_u_boot_with_ucode_ptr(Entry_blob):
# Write the microcode offset and size into the entry
offset_and_size = struct.pack('<2L', offset, size)
self.target_offset -= self.image_pos
self.ProcessContentsUpdate(self.data[:self.target_offset] +
offset_and_size +
self.data[self.target_offset + 8:])
return self.ProcessContentsUpdate(self.data[:self.target_offset] +
offset_and_size +
self.data[self.target_offset + 8:])

View File

@ -122,8 +122,11 @@ class Image:
"""Call the ProcessContents() method for each entry
This is intended to adjust the contents as needed by the entry type.
Returns:
True if the new data size is OK, False if expansion is needed
"""
self._section.ProcessEntryContents()
return self._section.ProcessEntryContents()
def WriteSymbols(self):
"""Write symbol values into binary files for access at run time"""