binman: Add an image header
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@chromium.org>
This commit is contained in:
parent
086cec9f98
commit
cf2289435c
@ -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 preceded 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
|
||||
- Support updating binaries in an image (with no size change / repacking)
|
||||
|
@ -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
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
|
76
tools/binman/etype/image_header.py
Normal file
76
tools/binman/etype/image_header.py
Normal file
@ -0,0 +1,76 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2018 Google, Inc
|
||||
# Written by Simon Glass <sjg@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())
|
@ -2076,7 +2076,7 @@ class TestFunctional(unittest.TestCase):
|
||||
# Mangle the section name, which should cause a mismatch between the
|
||||
# correct FDT path and the one expected by the section
|
||||
image = control.images['image']
|
||||
image._section._node.path += '-suffix'
|
||||
image._node.path += '-suffix'
|
||||
entries = image.GetEntries()
|
||||
fdtmap = entries['fdtmap']
|
||||
with self.assertRaises(ValueError) as e:
|
||||
@ -2084,6 +2084,51 @@ 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.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
|
||||
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.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
|
||||
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.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
|
||||
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.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
|
||||
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.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
|
||||
self.assertIn("Invalid location 'None', expected 'start' or 'end'",
|
||||
str(e.exception))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
17
tools/binman/test/116_fdtmap_hdr.dts
Normal file
17
tools/binman/test/116_fdtmap_hdr.dts
Normal file
@ -0,0 +1,17 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
size = <0x400>;
|
||||
u-boot {
|
||||
};
|
||||
fdtmap {
|
||||
};
|
||||
image-header {
|
||||
location = "end";
|
||||
};
|
||||
};
|
||||
};
|
19
tools/binman/test/117_fdtmap_hdr_start.dts
Normal file
19
tools/binman/test/117_fdtmap_hdr_start.dts
Normal file
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
19
tools/binman/test/118_fdtmap_hdr_pos.dts
Normal file
19
tools/binman/test/118_fdtmap_hdr_pos.dts
Normal file
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
16
tools/binman/test/119_fdtmap_hdr_missing.dts
Normal file
16
tools/binman/test/119_fdtmap_hdr_missing.dts
Normal file
@ -0,0 +1,16 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
sort-by-offset;
|
||||
u-boot {
|
||||
};
|
||||
image-header {
|
||||
offset = <0x80>;
|
||||
location = "start";
|
||||
};
|
||||
};
|
||||
};
|
16
tools/binman/test/120_hdr_no_location.dts
Normal file
16
tools/binman/test/120_hdr_no_location.dts
Normal file
@ -0,0 +1,16 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
binman {
|
||||
sort-by-offset;
|
||||
u-boot {
|
||||
};
|
||||
fdtmap {
|
||||
};
|
||||
image-header {
|
||||
};
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user