[U-Boot] [PATCH 05/26] binman: Add an image header
Simon Glass
sjg at chromium.org
Tue Jul 2 00:24:34 UTC 2019
It is useful to be able to quickly locate the FDT map in the image. An
easy way to do this is with a pointer at the start or end of the image.
Add an 'image header' entry, which places a magic number followed by a
pointer to the FDT map. This can be located at the start or end of the
image, or at a chosen location.
As part of this, update GetSiblingImagePos() to detect missing siblings.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
tools/binman/README | 5 +-
tools/binman/README.entries | 19 +++++
tools/binman/entry.py | 11 +++
tools/binman/etype/image_header.py | 76 ++++++++++++++++++++
tools/binman/ftest.py | 50 +++++++++++++
tools/binman/test/116_fdtmap_hdr.dts | 17 +++++
tools/binman/test/117_fdtmap_hdr_start.dts | 19 +++++
tools/binman/test/118_fdtmap_hdr_pos.dts | 19 +++++
tools/binman/test/119_fdtmap_hdr_missing.dts | 16 +++++
tools/binman/test/120_hdr_no_location.dts | 16 +++++
10 files changed, 246 insertions(+), 2 deletions(-)
create mode 100644 tools/binman/etype/image_header.py
create mode 100644 tools/binman/test/116_fdtmap_hdr.dts
create mode 100644 tools/binman/test/117_fdtmap_hdr_start.dts
create mode 100644 tools/binman/test/118_fdtmap_hdr_pos.dts
create mode 100644 tools/binman/test/119_fdtmap_hdr_missing.dts
create mode 100644 tools/binman/test/120_hdr_no_location.dts
diff --git a/tools/binman/README b/tools/binman/README
index 77f047bf6a3..61a7a20f232 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -640,7 +640,9 @@ of each entry.
Alternatively, an FDT map entry can be used to add a special FDT containing
just the information about the image. This is preceeded by a magic string so can
-be located anywhere in the image.
+be located anywhere in the image. An image header (typically at the start or end
+of the image) can be used to point to the FDT map. See fdtmap and image-header
+entries for more information.
Compression
@@ -817,7 +819,6 @@ Some ideas:
- Add an option to decode an image into the constituent binaries
- Support building an image for a board (-b) more completely, with a
configurable build directory
-- Support putting the FDT in an image with a suitable magic number
- Support listing files in images
- Support logging of binman's operations, with different levels of verbosity
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
index 7014d36f5ff..598d8278a70 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/README.entries
@@ -331,6 +331,25 @@ README.chromium for how to obtain the required keys and tools.
+Entry: image-header: An entry which contains a pointer to the FDT map
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+ location: Location of header ("start" or "end" of image). This is
+ optional. If omitted then the entry must have an offset property.
+
+This adds an 8-byte entry to the start or end of the image, pointing to the
+location of the FDT map. The format is a magic number followed by an offset
+from the start or end of the image, in twos-compliment format.
+
+This entry must be in the top-level part of the image.
+
+NOTE: If the location is at the start/end, you will probably need to specify
+sort-by-offset for the image, unless you actually put the image header
+first/last in the entry list.
+
+
+
Entry: intel-cmc: Entry containing an Intel Chipset Micro Code (CMC) file
-------------------------------------------------------------------------
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 7356c49c626..e1cd0d3a882 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -561,3 +561,14 @@ features to produce new behaviours.
else False
"""
return name in self.section.GetEntries()
+
+ def GetSiblingImagePos(self, name):
+ """Return the image position of the given sibling
+
+ Returns:
+ Image position of sibling, or None if the sibling has no position,
+ or False if there is no such sibling
+ """
+ if not self.HasSibling(name):
+ return False
+ return self.section.GetEntries()[name].image_pos
diff --git a/tools/binman/etype/image_header.py b/tools/binman/etype/image_header.py
new file mode 100644
index 00000000000..9bc84ec01d4
--- /dev/null
+++ b/tools/binman/etype/image_header.py
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg at chromium.org>
+
+"""Entry-type module for an image header which points to the FDT map
+
+This creates an 8-byte entry with a magic number and the offset of the FDT map
+(which is another entry in the image), relative to the start or end of the
+image.
+"""
+
+import struct
+
+from entry import Entry
+import fdt_util
+
+IMAGE_HEADER_MAGIC = b'BinM'
+
+class Entry_image_header(Entry):
+ """An entry which contains a pointer to the FDT map
+
+ Properties / Entry arguments:
+ location: Location of header ("start" or "end" of image). This is
+ optional. If omitted then the entry must have an offset property.
+
+ This adds an 8-byte entry to the start or end of the image, pointing to the
+ location of the FDT map. The format is a magic number followed by an offset
+ from the start or end of the image, in twos-compliment format.
+
+ This entry must be in the top-level part of the image.
+
+ NOTE: If the location is at the start/end, you will probably need to specify
+ sort-by-offset for the image, unless you actually put the image header
+ first/last in the entry list.
+ """
+ def __init__(self, section, etype, node):
+ Entry.__init__(self, section, etype, node)
+ self.location = fdt_util.GetString(self._node, 'location')
+
+ def _GetHeader(self):
+ image_pos = self.GetSiblingImagePos('fdtmap')
+ if image_pos == False:
+ self.Raise("'image_header' section must have an 'fdtmap' sibling")
+ elif image_pos is None:
+ # This will be available when called from ProcessContents(), but not
+ # when called from ObtainContents()
+ offset = 0xffffffff
+ else:
+ image_size = self.section.GetImageSize() or 0
+ base = (0 if self.location != 'end' else image_size)
+ offset = (image_pos - base) & 0xffffffff
+ data = IMAGE_HEADER_MAGIC + struct.pack('<I', offset)
+ return data
+
+ def ObtainContents(self):
+ """Obtain a placeholder for the header contents"""
+ self.SetContents(self._GetHeader())
+ return True
+
+ def Pack(self, offset):
+ """Special pack method to set the offset to start/end of image"""
+ if not self.offset:
+ if self.location not in ['start', 'end']:
+ self.Raise("Invalid location '%s', expected 'start' or 'end'" %
+ self.location)
+ image_size = self.section.GetImageSize() or 0
+ self.offset = (0 if self.location != 'end' else image_size - 8)
+ return Entry.Pack(self, offset)
+
+ def ProcessContents(self):
+ """Write an updated version of the FDT map to this entry
+
+ This is necessary since image_pos is not available when ObtainContents()
+ is called, since by then the entries have not been packed in the image.
+ """
+ self.SetContents(self._GetHeader())
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 9e61f785d92..46540e8f5dd 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -2057,6 +2057,56 @@ class TestFunctional(unittest.TestCase):
self.assertIn("Cannot locate node for path '/binman-suffix'",
str(e.exception))
+ def testFdtmapHeader(self):
+ """Test an FDT map and image header can be inserted in the image"""
+ data = self._DoReadFileDtb('116_fdtmap_hdr.dts', use_real_dtb=True,
+ update_dtb=True)[0]
+ fdtmap_pos = len(U_BOOT_DATA)
+ fdtmap_data = data[fdtmap_pos:]
+ fdt_data = fdtmap_data[16:]
+ dtb = fdt.Fdt.FromData(fdt_data)
+ fdt_size = dtb.GetFdtObj().totalsize()
+ hdr_data = data[-8:]
+ self.assertEqual('BinM', hdr_data[:4])
+ offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
+ self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
+
+ def testFdtmapHeaderStart(self):
+ """Test an image header can be inserted at the image start"""
+ data = self._DoReadFileDtb('117_fdtmap_hdr_start.dts',
+ use_real_dtb=True, update_dtb=True)[0]
+ fdtmap_pos = 0x100 + len(U_BOOT_DATA)
+ hdr_data = data[:8]
+ self.assertEqual('BinM', hdr_data[:4])
+ offset = struct.unpack('<I', hdr_data[4:])[0]
+ self.assertEqual(fdtmap_pos, offset)
+
+ def testFdtmapHeaderPos(self):
+ """Test an image header can be inserted at a chosen position"""
+ data = self._DoReadFileDtb('118_fdtmap_hdr_pos.dts',
+ use_real_dtb=True, update_dtb=True)[0]
+ fdtmap_pos = 0x100 + len(U_BOOT_DATA)
+ hdr_data = data[0x80:0x88]
+ self.assertEqual('BinM', hdr_data[:4])
+ offset = struct.unpack('<I', hdr_data[4:])[0]
+ self.assertEqual(fdtmap_pos, offset)
+
+ def testHeaderMissingFdtmap(self):
+ """Test an image header requires an fdtmap"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('119_fdtmap_hdr_missing.dts',
+ use_real_dtb=True, update_dtb=True)
+ self.assertIn("'image_header' section must have an 'fdtmap' sibling",
+ str(e.exception))
+
+ def testHeaderNoLocation(self):
+ """Test an image header with a no specified location is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFileDtb('120_hdr_no_location.dts',
+ use_real_dtb=True, update_dtb=True)
+ self.assertIn("Invalid location 'None', expected 'start' or 'end'",
+ str(e.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/116_fdtmap_hdr.dts b/tools/binman/test/116_fdtmap_hdr.dts
new file mode 100644
index 00000000000..77a2194b394
--- /dev/null
+++ b/tools/binman/test/116_fdtmap_hdr.dts
@@ -0,0 +1,17 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <0x400>;
+ u-boot {
+ };
+ fdtmap {
+ };
+ image-header {
+ location = "end";
+ };
+ };
+};
diff --git a/tools/binman/test/117_fdtmap_hdr_start.dts b/tools/binman/test/117_fdtmap_hdr_start.dts
new file mode 100644
index 00000000000..17b6be00470
--- /dev/null
+++ b/tools/binman/test/117_fdtmap_hdr_start.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <0x400>;
+ sort-by-offset;
+ u-boot {
+ offset = <0x100>;
+ };
+ fdtmap {
+ };
+ image-header {
+ location = "start";
+ };
+ };
+};
diff --git a/tools/binman/test/118_fdtmap_hdr_pos.dts b/tools/binman/test/118_fdtmap_hdr_pos.dts
new file mode 100644
index 00000000000..fd803f57fba
--- /dev/null
+++ b/tools/binman/test/118_fdtmap_hdr_pos.dts
@@ -0,0 +1,19 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ size = <0x400>;
+ sort-by-offset;
+ u-boot {
+ offset = <0x100>;
+ };
+ fdtmap {
+ };
+ image-header {
+ offset = <0x80>;
+ };
+ };
+};
diff --git a/tools/binman/test/119_fdtmap_hdr_missing.dts b/tools/binman/test/119_fdtmap_hdr_missing.dts
new file mode 100644
index 00000000000..41bb680f08f
--- /dev/null
+++ b/tools/binman/test/119_fdtmap_hdr_missing.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-offset;
+ u-boot {
+ };
+ image-header {
+ offset = <0x80>;
+ location = "start";
+ };
+ };
+};
diff --git a/tools/binman/test/120_hdr_no_location.dts b/tools/binman/test/120_hdr_no_location.dts
new file mode 100644
index 00000000000..585e21f456b
--- /dev/null
+++ b/tools/binman/test/120_hdr_no_location.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ sort-by-offset;
+ u-boot {
+ };
+ fdtmap {
+ };
+ image-header {
+ };
+ };
+};
--
2.22.0.410.gd8fdbe21b5-goog
More information about the U-Boot
mailing list