diff --git a/tools/binman/README b/tools/binman/README index 196dda1..5ef1246 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -392,6 +392,45 @@ either by using a unit number suffix (u-boot@0, u-boot@1) or by using a different name for each and specifying the type with the 'type' attribute. +Sections and hiearchical images +------------------------------- + +Sometimes it is convenient to split an image into several pieces, each of which +contains its own set of binaries. An example is a flash device where part of +the image is read-only and part is read-write. We can set up sections for each +of these, and place binaries in them independently. The image is still produced +as a single output file. + +This feature provides a way of creating hierarchical images. For example here +is an example with two copies of U-Boot. One is read-only (ro), intended to be +written only in the factory. Another is read-write (rw), so that it can be +upgraded in the field. The sizes are fixed so that the ro/rw boundary is known +and can be programmed: + + binman { + section@0 { + read-only; + size = <0x100000>; + u-boot { + }; + }; + section@1 { + size = <0x100000>; + u-boot { + }; + }; + }; + +This image could be placed into a SPI flash chip, with the protection boundary +set at 1MB. + +A few special properties are provided for sections: + +read-only: + Indicates that this section is read-only. This has no impact on binman's + operation, but his property can be read at run time. + + Special properties ------------------ @@ -586,8 +625,6 @@ Some ideas: - Allow easy building of images by specifying just the board name - Produce a full Python binding for libfdt (for upstream) - Add an option to decode an image into the constituent binaries -- Suppoort hierarchical images (packing of binaries into another binary - which is then placed in the image) - Support building an image for a board (-b) more completely, with a configurable build directory - Consider making binman work with buildman, although if it is used in the diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py index 07c72d3..331f806 100644 --- a/tools/binman/bsection.py +++ b/tools/binman/bsection.py @@ -201,6 +201,7 @@ class Section(object): pos = 0 prev_name = 'None' for entry in self._entries.values(): + entry.CheckPosition() if (entry.pos < self._skip_at_start or entry.pos >= self._skip_at_start + self._size): entry.Raise("Position %#x (%d) is outside the section starting " diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 5374178..8b46fbb 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -220,3 +220,12 @@ class Entry(object): section: Section containing the entry """ pass + + def CheckPosition(self): + """Check that the entry positions are correct + + This is used for entries which have extra position requirements (other + than having to be fully inside their section). Sub-classes can implement + this function and raise if there is a problem. + """ + pass diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py new file mode 100644 index 0000000..4e2f686 --- /dev/null +++ b/tools/binman/etype/section.py @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2018 Google, Inc +# Written by Simon Glass +# +# Entry-type module for sections, which are entries which can contain other +# entries. +# + +from entry import Entry +import fdt_util +import tools + +import bsection + +class Entry_section(Entry): + def __init__(self, image, etype, node): + Entry.__init__(self, image, etype, node) + self._section = bsection.Section(node.name, node) + + def ObtainContents(self): + self._section.GetEntryContents() + + def GetData(self): + return self._section.GetData() + + def GetPositions(self): + """Handle entries that want to set the position/size of other entries + + This calls each entry's GetPositions() method. If it returns a list + of entries to update, it updates them. + """ + self._section.GetEntryPositions() + return {} + + def Pack(self, pos): + """Pack all entries into the section""" + self._section.PackEntries() + self.size = self._section.CheckSize() + return super(Entry_section, self).Pack(pos) + + def WriteSymbols(self, section): + """Write symbol values into binary files for access at run time""" + self._section.WriteSymbols() + + def ProcessContents(self): + self._section.ProcessEntryContents() + super(Entry_section, self).ProcessContents() + + def CheckPosition(self): + self._section.CheckEntries() diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 96a5535..06b8132 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -914,6 +914,11 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('54_unit_address.dts') self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data) + def testSections(self): + """Basic test of sections""" + data = self._DoReadFile('55_sections.dts') + expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 + '&' * 8 + self.assertEqual(expected, data) if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/55_sections.dts b/tools/binman/test/55_sections.dts new file mode 100644 index 0000000..2ada395 --- /dev/null +++ b/tools/binman/test/55_sections.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0x26>; + size = <0x28>; + section@0 { + read-only; + size = <0x10>; + pad-byte = <0x21>; + + u-boot { + }; + }; + section@1 { + size = <0x10>; + pad-byte = <0x61>; + + u-boot { + }; + }; + }; +};