From 078ab1a2f5a9901f5f9983163d4f98b8d94bfda0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 6 Jul 2018 10:27:41 -0600 Subject: [PATCH] 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 --- tools/binman/README | 29 ++++++++++++++++++++--------- tools/binman/bsection.py | 8 ++++++++ tools/binman/cmdline.py | 2 ++ tools/binman/control.py | 4 ++++ tools/binman/entry.py | 11 +++++++++++ tools/binman/etype/section.py | 8 ++++++++ tools/binman/image.py | 14 ++++++++++++++ 7 files changed, 67 insertions(+), 9 deletions(-) diff --git a/tools/binman/README b/tools/binman/README index 008d575052..8b598a75c8 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -462,14 +462,22 @@ Order of image creation 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 processing is complete, this method should return True. If the processing 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 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 contents. The default version of Entry.ObtainContents() calls 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 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 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 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 returns the position immediately after the entry being packed. The default 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 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. -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 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 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 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. diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index 3ed361d69a..de439ef625 100644 --- a/tools/binman/bsection.py +++ b/tools/binman/bsection.py @@ -90,6 +90,14 @@ class Section(object): entry.SetPrefix(self._name_prefix) 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): todo = self._entries.values() for passnum in range(3): diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py index bf63919eb7..ae2d1670f9 100644 --- a/tools/binman/cmdline.py +++ b/tools/binman/cmdline.py @@ -42,6 +42,8 @@ def ParseArgs(argv): default=False, help='run tests') parser.add_option('-T', '--test-coverage', action='store_true', 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, type='int', help='Control verbosity: 0=silent, 1=progress, 3=full, ' '4=debug') diff --git a/tools/binman/control.py b/tools/binman/control.py index 5325a6a006..eafabf05c7 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -144,6 +144,8 @@ def Binman(options, args): # without changing the device-tree size, thus ensuring that our # entry positions remain the same. for image in images.values(): + if options.update_fdt: + image.AddMissingProperties() image.ProcessFdt(dtb) dtb.Pack() @@ -159,6 +161,8 @@ def Binman(options, args): image.PackEntries() image.CheckSize() image.CheckEntries() + if options.update_fdt: + image.SetCalculatedProperties() image.ProcessEntryContents() image.WriteSymbols() image.BuildImage() diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 62e65c9126..6a173e663d 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -130,6 +130,17 @@ class Entry(object): self.align_end = fdt_util.GetInt(self._node, 'align-end') 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): return True diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index 9b38738d38..787257d3ec 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -20,6 +20,10 @@ class Entry_section(Entry): def ProcessFdt(self, fdt): return self._section.ProcessFdt(fdt) + def AddMissingProperties(self): + Entry.AddMissingProperties(self) + self._section.AddMissingProperties() + def ObtainContents(self): return self._section.GetEntryContents() @@ -45,6 +49,10 @@ class Entry_section(Entry): """Write symbol values into binary files for access at run time""" self._section.WriteSymbols() + def SetCalculatedProperties(self): + Entry.SetCalculatedProperties(self) + self._section.SetCalculatedProperties() + def ProcessContents(self): self._section.ProcessEntryContents() super(Entry_section, self).ProcessContents() diff --git a/tools/binman/image.py b/tools/binman/image.py index 9732493709..94028f19a5 100644 --- a/tools/binman/image.py +++ b/tools/binman/image.py @@ -54,6 +54,17 @@ class Image: self._filename = filename 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): return self._section.ProcessFdt(fdt) @@ -82,6 +93,9 @@ class Image: """Check that entries do not overlap or extend outside the image""" self._section.CheckEntries() + def SetCalculatedProperties(self): + self._section.SetCalculatedProperties() + def ProcessEntryContents(self): """Call the ProcessContents() method for each entry -- 2.39.2