binman: Add support for sections

It is useful to be able to split an image into multiple sections,
each with its own size and position, for cases where a flash device has
read-only and read-write portions.

Add support for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2018-06-01 09:38:16 -06:00
parent badf0ec6e4
commit 1854695bd8
6 changed files with 132 additions and 2 deletions

View file

@ -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

View file

@ -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 "

View file

@ -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

View file

@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2018 Google, Inc
# Written by Simon Glass <sjg@chromium.org>
#
# 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()

View file

@ -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()

View file

@ -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 {
};
};
};
};