mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-09-21 15:12:04 +00:00
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:
parent
badf0ec6e4
commit
1854695bd8
6 changed files with 132 additions and 2 deletions
|
@ -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.
|
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
|
Special properties
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -586,8 +625,6 @@ Some ideas:
|
||||||
- Allow easy building of images by specifying just the board name
|
- Allow easy building of images by specifying just the board name
|
||||||
- Produce a full Python binding for libfdt (for upstream)
|
- Produce a full Python binding for libfdt (for upstream)
|
||||||
- Add an option to decode an image into the constituent binaries
|
- 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
|
- Support building an image for a board (-b) more completely, with a
|
||||||
configurable build directory
|
configurable build directory
|
||||||
- Consider making binman work with buildman, although if it is used in the
|
- Consider making binman work with buildman, although if it is used in the
|
||||||
|
|
|
@ -201,6 +201,7 @@ class Section(object):
|
||||||
pos = 0
|
pos = 0
|
||||||
prev_name = 'None'
|
prev_name = 'None'
|
||||||
for entry in self._entries.values():
|
for entry in self._entries.values():
|
||||||
|
entry.CheckPosition()
|
||||||
if (entry.pos < self._skip_at_start or
|
if (entry.pos < self._skip_at_start or
|
||||||
entry.pos >= self._skip_at_start + self._size):
|
entry.pos >= self._skip_at_start + self._size):
|
||||||
entry.Raise("Position %#x (%d) is outside the section starting "
|
entry.Raise("Position %#x (%d) is outside the section starting "
|
||||||
|
|
|
@ -220,3 +220,12 @@ class Entry(object):
|
||||||
section: Section containing the entry
|
section: Section containing the entry
|
||||||
"""
|
"""
|
||||||
pass
|
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
|
||||||
|
|
50
tools/binman/etype/section.py
Normal file
50
tools/binman/etype/section.py
Normal 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()
|
|
@ -914,6 +914,11 @@ class TestFunctional(unittest.TestCase):
|
||||||
data = self._DoReadFile('54_unit_address.dts')
|
data = self._DoReadFile('54_unit_address.dts')
|
||||||
self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
28
tools/binman/test/55_sections.dts
Normal file
28
tools/binman/test/55_sections.dts
Normal 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 {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in a new issue