binman: Add a SetCalculatedProperties() method

Once binman has packed the image, the position and size of each entry is
known. It is then possible for binman to update the device tree with these
positions. Since placeholder values have been added, this does not affect
the size of the device tree and therefore the packing does not need to be
performed again.

Add a new SetCalculatedProperties method to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2018-07-06 10:27:41 -06:00
parent ecab89737a
commit 078ab1a2f5
7 changed files with 67 additions and 9 deletions

View file

@ -462,14 +462,22 @@ Order of image creation
Image creation proceeds in the following order, for each entry in the image. Image creation proceeds in the following order, for each entry in the image.
1. ProcessFdt() - process the device tree information as required by the 1. AddMissingProperties() - binman can add calculated values to the device
tree as part of its processing, for example the position and size of each
entry. This method adds any properties associated with this, expanding the
device tree as needed. These properties can have placeholder values which are
set later by SetCalculatedProperties(). By that stage the size of sections
cannot be changed (since it would cause the images to need to be repacked),
but the correct values can be inserted.
2. ProcessFdt() - process the device tree information as required by the
particular entry. This may involve adding or deleting properties. If the particular entry. This may involve adding or deleting properties. If the
processing is complete, this method should return True. If the processing processing is complete, this method should return True. If the processing
cannot complete because it needs the ProcessFdt() method of another entry to cannot complete because it needs the ProcessFdt() method of another entry to
run first, this method should return False, in which case it will be called run first, this method should return False, in which case it will be called
again later. again later.
2. GetEntryContents() - the contents of each entry are obtained, normally by 3. GetEntryContents() - the contents of each entry are obtained, normally by
reading from a file. This calls the Entry.ObtainContents() to read the reading from a file. This calls the Entry.ObtainContents() to read the
contents. The default version of Entry.ObtainContents() calls contents. The default version of Entry.ObtainContents() calls
Entry.GetDefaultFilename() and then reads that file. So a common mechanism Entry.GetDefaultFilename() and then reads that file. So a common mechanism
@ -478,35 +486,38 @@ functions must return True when they have read the contents. Binman will
retry calling the functions a few times if False is returned, allowing retry calling the functions a few times if False is returned, allowing
dependencies between the contents of different entries. dependencies between the contents of different entries.
3. GetEntryPositions() - calls Entry.GetPositions() for each entry. This can 4. GetEntryPositions() - calls Entry.GetPositions() for each entry. This can
return a dict containing entries that need updating. The key should be the return a dict containing entries that need updating. The key should be the
entry name and the value is a tuple (pos, size). This allows an entry to entry name and the value is a tuple (pos, size). This allows an entry to
provide the position and size for other entries. The default implementation provide the position and size for other entries. The default implementation
of GetEntryPositions() returns {}. of GetEntryPositions() returns {}.
4. PackEntries() - calls Entry.Pack() which figures out the position and 5. PackEntries() - calls Entry.Pack() which figures out the position and
size of an entry. The 'current' image position is passed in, and the function size of an entry. The 'current' image position is passed in, and the function
returns the position immediately after the entry being packed. The default returns the position immediately after the entry being packed. The default
implementation of Pack() is usually sufficient. implementation of Pack() is usually sufficient.
5. CheckSize() - checks that the contents of all the entries fits within 6. CheckSize() - checks that the contents of all the entries fits within
the image size. If the image does not have a defined size, the size is set the image size. If the image does not have a defined size, the size is set
large enough to hold all the entries. large enough to hold all the entries.
6. CheckEntries() - checks that the entries do not overlap, nor extend 7. CheckEntries() - checks that the entries do not overlap, nor extend
outside the image. outside the image.
7. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry. 8. SetCalculatedProperties() - update any calculated properties in the device
tree. This sets the correct 'pos' and 'size' vaues, for example.
9. ProcessEntryContents() - this calls Entry.ProcessContents() on each entry.
The default implementatoin does nothing. This can be overriden to adjust the The default implementatoin does nothing. This can be overriden to adjust the
contents of an entry in some way. For example, it would be possible to create contents of an entry in some way. For example, it would be possible to create
an entry containing a hash of the contents of some other entries. At this an entry containing a hash of the contents of some other entries. At this
stage the position and size of entries should not be adjusted. stage the position and size of entries should not be adjusted.
8. WriteSymbols() - write the value of symbols into the U-Boot SPL binary. 10. WriteSymbols() - write the value of symbols into the U-Boot SPL binary.
See 'Access to binman entry positions at run time' below for a description of See 'Access to binman entry positions at run time' below for a description of
what happens in this stage. what happens in this stage.
9. BuildImage() - builds the image and writes it to a file. This is the final 11. BuildImage() - builds the image and writes it to a file. This is the final
step. step.

View file

@ -90,6 +90,14 @@ class Section(object):
entry.SetPrefix(self._name_prefix) entry.SetPrefix(self._name_prefix)
self._entries[node.name] = entry self._entries[node.name] = entry
def AddMissingProperties(self):
for entry in self._entries.values():
entry.AddMissingProperties()
def SetCalculatedProperties(self):
for entry in self._entries.values():
entry.SetCalculatedProperties()
def ProcessFdt(self, fdt): def ProcessFdt(self, fdt):
todo = self._entries.values() todo = self._entries.values()
for passnum in range(3): for passnum in range(3):

View file

@ -42,6 +42,8 @@ def ParseArgs(argv):
default=False, help='run tests') default=False, help='run tests')
parser.add_option('-T', '--test-coverage', action='store_true', parser.add_option('-T', '--test-coverage', action='store_true',
default=False, help='run tests and check for 100% coverage') default=False, help='run tests and check for 100% coverage')
parser.add_option('-u', '--update-fdt', action='store_true',
default=False, help='Update the binman node with position/size info')
parser.add_option('-v', '--verbosity', default=1, parser.add_option('-v', '--verbosity', default=1,
type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, ' type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, '
'4=debug') '4=debug')

View file

@ -144,6 +144,8 @@ def Binman(options, args):
# without changing the device-tree size, thus ensuring that our # without changing the device-tree size, thus ensuring that our
# entry positions remain the same. # entry positions remain the same.
for image in images.values(): for image in images.values():
if options.update_fdt:
image.AddMissingProperties()
image.ProcessFdt(dtb) image.ProcessFdt(dtb)
dtb.Pack() dtb.Pack()
@ -159,6 +161,8 @@ def Binman(options, args):
image.PackEntries() image.PackEntries()
image.CheckSize() image.CheckSize()
image.CheckEntries() image.CheckEntries()
if options.update_fdt:
image.SetCalculatedProperties()
image.ProcessEntryContents() image.ProcessEntryContents()
image.WriteSymbols() image.WriteSymbols()
image.BuildImage() image.BuildImage()

View file

@ -130,6 +130,17 @@ class Entry(object):
self.align_end = fdt_util.GetInt(self._node, 'align-end') self.align_end = fdt_util.GetInt(self._node, 'align-end')
self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset') self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset')
def AddMissingProperties(self):
"""Add new properties to the device tree as needed for this entry"""
for prop in ['pos', 'size']:
if not prop in self._node.props:
self._node.AddZeroProp(prop)
def SetCalculatedProperties(self):
"""Set the value of device-tree properties calculated by binman"""
self._node.SetInt('pos', self.pos)
self._node.SetInt('size', self.size)
def ProcessFdt(self, fdt): def ProcessFdt(self, fdt):
return True return True

View file

@ -20,6 +20,10 @@ class Entry_section(Entry):
def ProcessFdt(self, fdt): def ProcessFdt(self, fdt):
return self._section.ProcessFdt(fdt) return self._section.ProcessFdt(fdt)
def AddMissingProperties(self):
Entry.AddMissingProperties(self)
self._section.AddMissingProperties()
def ObtainContents(self): def ObtainContents(self):
return self._section.GetEntryContents() return self._section.GetEntryContents()
@ -45,6 +49,10 @@ class Entry_section(Entry):
"""Write symbol values into binary files for access at run time""" """Write symbol values into binary files for access at run time"""
self._section.WriteSymbols() self._section.WriteSymbols()
def SetCalculatedProperties(self):
Entry.SetCalculatedProperties(self)
self._section.SetCalculatedProperties()
def ProcessContents(self): def ProcessContents(self):
self._section.ProcessEntryContents() self._section.ProcessEntryContents()
super(Entry_section, self).ProcessContents() super(Entry_section, self).ProcessContents()

View file

@ -54,6 +54,17 @@ class Image:
self._filename = filename self._filename = filename
self._section = bsection.Section('main-section', self._node) self._section = bsection.Section('main-section', self._node)
def AddMissingProperties(self):
"""Add properties that are not present in the device tree
When binman has completed packing the entries the position and size of
each entry are known. But before this the device tree may not specify
these. Add any missing properties, with a dummy value, so that the
size of the entry is correct. That way we can insert the correct values
later.
"""
self._section.AddMissingProperties()
def ProcessFdt(self, fdt): def ProcessFdt(self, fdt):
return self._section.ProcessFdt(fdt) return self._section.ProcessFdt(fdt)
@ -82,6 +93,9 @@ class Image:
"""Check that entries do not overlap or extend outside the image""" """Check that entries do not overlap or extend outside the image"""
self._section.CheckEntries() self._section.CheckEntries()
def SetCalculatedProperties(self):
self._section.SetCalculatedProperties()
def ProcessEntryContents(self): def ProcessEntryContents(self):
"""Call the ProcessContents() method for each entry """Call the ProcessContents() method for each entry