summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/binman/entries.rst154
-rw-r--r--tools/binman/etype/atf_fip.py273
-rw-r--r--tools/binman/ftest.py217
-rw-r--r--tools/binman/test/203_fip.dts21
-rw-r--r--tools/binman/test/204_fip_other.dts22
-rw-r--r--tools/binman/test/205_fip_no_type.dts15
-rw-r--r--tools/binman/test/206_fip_uuid.dts22
-rw-r--r--tools/binman/test/207_fip_ls.dts25
-rw-r--r--tools/binman/test/208_fip_replace.dts33
-rw-r--r--tools/binman/test/209_fip_missing.dts19
-rw-r--r--tools/binman/test/210_fip_size.dts19
-rw-r--r--tools/binman/test/211_fip_bad_align.dts18
-rw-r--r--tools/binman/test/212_fip_collection.dts24
13 files changed, 862 insertions, 0 deletions
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index d5aa3b0f4a4..c47f7df0980 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -25,6 +25,160 @@ about ATF.
+Entry: atf-fip: ARM Trusted Firmware's Firmware Image Package (FIP)
+-------------------------------------------------------------------
+
+A FIP_ provides a way to group binaries in a firmware image, used by ARM's
+Trusted Firmware A (TF-A) code. It is a simple format consisting of a
+table of contents with information about the type, offset and size of the
+binaries in the FIP. It is quite similar to FMAP, with the major difference
+that it uses UUIDs to indicate the type of each entry.
+
+Note: It is recommended to always add an fdtmap to every image, as well as
+any FIPs so that binman and other tools can access the entire image
+correctly.
+
+The UUIDs correspond to useful names in `fiptool`, provided by ATF to
+operate on FIPs. Binman uses these names to make it easier to understand
+what is going on, although it is possible to provide a UUID if needed.
+
+The contents of the FIP are defined by subnodes of the atf-fip entry, e.g.::
+
+ atf-fip {
+ soc-fw {
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+
+ u-boot {
+ fip-type = "nt-fw";
+ };
+ };
+
+This describes a FIP with three entries: soc-fw, scp-fwu-cfg and nt-fw.
+You can use normal (non-external) binaries like U-Boot simply by adding a
+FIP type, with the `fip-type` property, as above.
+
+Since FIP exists to bring blobs together, Binman assumes that all FIP
+entries are external binaries. If a binary may not exist, you can use the
+`--allow-missing` flag to Binman, in which case the image is still created,
+even though it will not actually work.
+
+The size of the FIP depends on the size of the binaries. There is currently
+no way to specify a fixed size. If the `atf-fip` node has a `size` entry,
+this affects the space taken up by the `atf-fip` entry, but the FIP itself
+does not expand to use that space.
+
+Some other FIP features are available with Binman. The header and the
+entries have 64-bit flag works. The flag flags do not seem to be defined
+anywhere, but you can use `fip-hdr-flags` and fip-flags` to set the values
+of the header and entries respectively.
+
+FIP entries can be aligned to a particular power-of-two boundary. Use
+fip-align for this.
+
+Binman only understands the entry types that are included in its
+implementation. It is possible to specify a 16-byte UUID instead, using the
+fip-uuid property. In this case Binman doesn't know what its type is, so
+just uses the UUID. See the `u-boot` node in this example::
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ fip-align = <16>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x456>;
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+
+ u-boot {
+ fip-uuid = [fc 65 13 92 4a 5b 11 ec
+ 94 35 ff 2d 1c fc 79 9c];
+ };
+ };
+ fdtmap {
+ };
+ };
+
+Binman allows reading and updating FIP entries after the image is created,
+provided that an FDPMAP is present too. Updates which change the size of a
+FIP entry will cause it to be expanded or contracted as needed.
+
+Properties for top-level atf-fip node
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+fip-hdr-flags (64 bits)
+ Sets the flags for the FIP header.
+
+Properties for subnodes
+~~~~~~~~~~~~~~~~~~~~~~~
+
+fip-type (str)
+ FIP type to use for this entry. This is needed if the entry
+ name is not a valid type. Value types are defined in `fip_util.py`.
+ The FIP type defines the UUID that is used (they map 1:1).
+
+fip-uuid (16 bytes)
+ If there is no FIP-type name defined, or it is not supported by Binman,
+ this property sets the UUID. It should be a 16-byte value, following the
+ hex digits of the UUID.
+
+fip-flags (64 bits)
+ Set the flags for a FIP entry. Use in one of the subnodes of the
+ 7atf-fip entry.
+
+fip-align
+ Set the alignment for a FIP entry, FIP entries can be aligned to a
+ particular power-of-two boundary. The default is 1.
+
+Adding new FIP-entry types
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When new FIP entries are defined by TF-A they appear in the
+`TF-A source tree`_. You can use `fip_util.py` to update Binman to support
+new types, then `send a patch`_ to the U-Boot mailing list. There are two
+source files that the tool examples:
+
+- `include/tools_share/firmware_image_package.h` has the UUIDs
+- `tools/fiptool/tbbr_config.c` has the name and descripion for each UUID
+
+To run the tool::
+
+ $ tools/binman/fip_util.py -s /path/to/arm-trusted-firmware
+ Warning: UUID 'UUID_NON_TRUSTED_WORLD_KEY_CERT' is not mentioned in tbbr_config.c file
+ Existing code in 'tools/binman/fip_util.py' is up-to-date
+
+If it shows there is an update, it writes a new version of `fip_util.py`
+to `fip_util.py.out`. You can change the output file using the `-i` flag.
+If you have a problem, use `-D` to enable traceback debugging.
+
+FIP commentary
+~~~~~~~~~~~~~~
+
+As a side effect of use of UUIDs, FIP does not support multiple
+entries of the same type, such as might be used to store fonts or graphics
+icons, for example. For verified boot it could be used for each part of the
+image (e.g. separate FIPs for A and B) but cannot describe the whole
+firmware image. As with FMAP there is no hierarchy defined, although FMAP
+works around this by having 'section' areas which encompass others. A
+similar workaround would be possible with FIP but is not currently defined.
+
+It is recommended to always add an fdtmap to every image, as well as any
+FIPs so that binman and other tools can access the entire image correctly.
+
+.. _FIP: https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#firmware-image-package-fip
+.. _`TF-A source tree`: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+.. _`send a patch`: https://www.denx.de/wiki/U-Boot/Patches
+
+
+
Entry: blob: Arbitrary binary blob
----------------------------------
diff --git a/tools/binman/etype/atf_fip.py b/tools/binman/etype/atf_fip.py
new file mode 100644
index 00000000000..07e6c645b06
--- /dev/null
+++ b/tools/binman/etype/atf_fip.py
@@ -0,0 +1,273 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2019 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for the ARM Trusted Firmware's Firmware Image Package (FIP)
+# format
+
+from collections import OrderedDict
+
+from binman.entry import Entry
+from binman.etype.section import Entry_section
+from binman.fip_util import FIP_TYPES, FipReader, FipWriter, UUID_LEN
+from dtoc import fdt_util
+from patman import tools
+
+class Entry_atf_fip(Entry_section):
+ """ARM Trusted Firmware's Firmware Image Package (FIP)
+
+ A FIP_ provides a way to group binaries in a firmware image, used by ARM's
+ Trusted Firmware A (TF-A) code. It is a simple format consisting of a
+ table of contents with information about the type, offset and size of the
+ binaries in the FIP. It is quite similar to FMAP, with the major difference
+ that it uses UUIDs to indicate the type of each entry.
+
+ Note: It is recommended to always add an fdtmap to every image, as well as
+ any FIPs so that binman and other tools can access the entire image
+ correctly.
+
+ The UUIDs correspond to useful names in `fiptool`, provided by ATF to
+ operate on FIPs. Binman uses these names to make it easier to understand
+ what is going on, although it is possible to provide a UUID if needed.
+
+ The contents of the FIP are defined by subnodes of the atf-fip entry, e.g.::
+
+ atf-fip {
+ soc-fw {
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+
+ u-boot {
+ fip-type = "nt-fw";
+ };
+ };
+
+ This describes a FIP with three entries: soc-fw, scp-fwu-cfg and nt-fw.
+ You can use normal (non-external) binaries like U-Boot simply by adding a
+ FIP type, with the `fip-type` property, as above.
+
+ Since FIP exists to bring blobs together, Binman assumes that all FIP
+ entries are external binaries. If a binary may not exist, you can use the
+ `--allow-missing` flag to Binman, in which case the image is still created,
+ even though it will not actually work.
+
+ The size of the FIP depends on the size of the binaries. There is currently
+ no way to specify a fixed size. If the `atf-fip` node has a `size` entry,
+ this affects the space taken up by the `atf-fip` entry, but the FIP itself
+ does not expand to use that space.
+
+ Some other FIP features are available with Binman. The header and the
+ entries have 64-bit flag works. The flag flags do not seem to be defined
+ anywhere, but you can use `fip-hdr-flags` and fip-flags` to set the values
+ of the header and entries respectively.
+
+ FIP entries can be aligned to a particular power-of-two boundary. Use
+ fip-align for this.
+
+ Binman only understands the entry types that are included in its
+ implementation. It is possible to specify a 16-byte UUID instead, using the
+ fip-uuid property. In this case Binman doesn't know what its type is, so
+ just uses the UUID. See the `u-boot` node in this example::
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ fip-align = <16>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x456>;
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+
+ u-boot {
+ fip-uuid = [fc 65 13 92 4a 5b 11 ec
+ 94 35 ff 2d 1c fc 79 9c];
+ };
+ };
+ fdtmap {
+ };
+ };
+
+ Binman allows reading and updating FIP entries after the image is created,
+ provided that an FDPMAP is present too. Updates which change the size of a
+ FIP entry will cause it to be expanded or contracted as needed.
+
+ Properties for top-level atf-fip node
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ fip-hdr-flags (64 bits)
+ Sets the flags for the FIP header.
+
+ Properties for subnodes
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ fip-type (str)
+ FIP type to use for this entry. This is needed if the entry
+ name is not a valid type. Value types are defined in `fip_util.py`.
+ The FIP type defines the UUID that is used (they map 1:1).
+
+ fip-uuid (16 bytes)
+ If there is no FIP-type name defined, or it is not supported by Binman,
+ this property sets the UUID. It should be a 16-byte value, following the
+ hex digits of the UUID.
+
+ fip-flags (64 bits)
+ Set the flags for a FIP entry. Use in one of the subnodes of the
+ 7atf-fip entry.
+
+ fip-align
+ Set the alignment for a FIP entry, FIP entries can be aligned to a
+ particular power-of-two boundary. The default is 1.
+
+ Adding new FIP-entry types
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ When new FIP entries are defined by TF-A they appear in the
+ `TF-A source tree`_. You can use `fip_util.py` to update Binman to support
+ new types, then `send a patch`_ to the U-Boot mailing list. There are two
+ source files that the tool examples:
+
+ - `include/tools_share/firmware_image_package.h` has the UUIDs
+ - `tools/fiptool/tbbr_config.c` has the name and descripion for each UUID
+
+ To run the tool::
+
+ $ tools/binman/fip_util.py -s /path/to/arm-trusted-firmware
+ Warning: UUID 'UUID_NON_TRUSTED_WORLD_KEY_CERT' is not mentioned in tbbr_config.c file
+ Existing code in 'tools/binman/fip_util.py' is up-to-date
+
+ If it shows there is an update, it writes a new version of `fip_util.py`
+ to `fip_util.py.out`. You can change the output file using the `-i` flag.
+ If you have a problem, use `-D` to enable traceback debugging.
+
+ FIP commentary
+ ~~~~~~~~~~~~~~
+
+ As a side effect of use of UUIDs, FIP does not support multiple
+ entries of the same type, such as might be used to store fonts or graphics
+ icons, for example. For verified boot it could be used for each part of the
+ image (e.g. separate FIPs for A and B) but cannot describe the whole
+ firmware image. As with FMAP there is no hierarchy defined, although FMAP
+ works around this by having 'section' areas which encompass others. A
+ similar workaround would be possible with FIP but is not currently defined.
+
+ It is recommended to always add an fdtmap to every image, as well as any
+ FIPs so that binman and other tools can access the entire image correctly.
+
+ .. _FIP: https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#firmware-image-package-fip
+ .. _`TF-A source tree`: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+ .. _`send a patch`: https://www.denx.de/wiki/U-Boot/Patches
+ """
+ def __init__(self, section, etype, node):
+ # Put this here to allow entry-docs and help to work without libfdt
+ global state
+ from binman import state
+
+ super().__init__(section, etype, node)
+ self.align_default = None
+ self._entries = OrderedDict()
+ self.reader = None
+
+ def ReadNode(self):
+ """Read properties from the atf-fip node"""
+ super().ReadNode()
+ self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0)
+ self._fip_flags = fdt_util.GetInt64(self._node, 'fip-hdr-flags', 0)
+ self._fip_align = fdt_util.GetInt(self._node, 'fip-align', 1)
+ if tools.NotPowerOfTwo(self._fip_align):
+ raise ValueError("Node '%s': FIP alignment %s must be a power of two" %
+ (self._node.path, self._fip_align))
+ self.ReadEntries()
+
+ def ReadEntries(self):
+ """Read the subnodes to find out what should go in this FIP"""
+ for node in self._node.subnodes:
+ fip_type = None
+ etype = None
+ if node.name in FIP_TYPES:
+ fip_type = node.name
+ etype = 'blob-ext'
+
+ entry = Entry.Create(self, node, etype)
+ entry._fip_uuid = fdt_util.GetBytes(node, 'fip-uuid', UUID_LEN)
+ if not fip_type and not entry._fip_uuid:
+ fip_type = fdt_util.GetString(node, 'fip-type')
+ if not fip_type:
+ self.Raise("Must provide a fip-type (node name '%s' is not a known FIP type)" %
+ node.name)
+
+ entry._fip_type = fip_type
+ entry._fip_flags = fdt_util.GetInt64(node, 'fip-flags', 0)
+ entry.ReadNode()
+ entry._fip_name = node.name
+ self._entries[entry._fip_name] = entry
+
+ def BuildSectionData(self, required):
+ """Override this function to create a custom format for the entries
+
+ Arguments:
+ required (bool): True if the data must be valid, False if it may
+ be missing (entry.GetData() returns None
+
+ Returns:
+ bytes: Data obtained, or None if None
+ """
+ fip = FipWriter(self._fip_flags, self._fip_align)
+ for entry in self._entries.values():
+ # First get the input data and put it in an entry. If not available,
+ # try later.
+ entry_data = entry.GetData(required)
+ if not required and entry_data is None:
+ return None
+ fent = fip.add_entry(entry._fip_type or entry._fip_uuid, entry_data,
+ entry._fip_flags)
+ if fent:
+ entry._fip_entry = fent
+ data = fip.get_data()
+ return data
+
+ def SetImagePos(self, image_pos):
+ """Override this function to set all the entry properties from FIP
+
+ We can only do this once image_pos is known
+
+ Args:
+ image_pos: Position of this entry in the image
+ """
+ super().SetImagePos(image_pos)
+
+ # Now update the entries with info from the FIP entries
+ for entry in self._entries.values():
+ fent = entry._fip_entry
+ entry.size = fent.size
+ entry.offset = fent.offset
+ entry.image_pos = self.image_pos + entry.offset
+
+ def ReadChildData(self, child, decomp=True, alt_format=None):
+ if not self.reader:
+ self.fip_data = super().ReadData(True)
+ self.reader = FipReader(self.fip_data)
+ reader = self.reader
+
+ # It is tricky to obtain the data from a FIP entry since it is indexed
+ # by its UUID.
+ fent = reader.get_entry(child._fip_type or child._fip_uuid)
+ return fent.data
+
+ # Note:
+ # It is also possible to extract it using the offsets directly, but this
+ # seems less FIP_friendly:
+ # return self.fip_data[child.offset:child.offset + child.size]
+
+ def WriteChildData(self, child):
+ # Recreate the data structure, leaving the data for this child alone,
+ # so that child.data is used to pack into the FIP.
+ self.ObtainContents(skip_entry=child)
+ return True
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index f5ceb9fb17d..2f3ec69709b 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -23,6 +23,7 @@ from binman import cmdline
from binman import control
from binman import elf
from binman import elf_test
+from binman import fip_util
from binman import fmap_util
from binman import state
from dtoc import fdt
@@ -76,6 +77,7 @@ FSP_M_DATA = b'fsp_m'
FSP_S_DATA = b'fsp_s'
FSP_T_DATA = b'fsp_t'
ATF_BL31_DATA = b'bl31'
+ATF_BL2U_DATA = b'bl2u'
OPENSBI_DATA = b'opensbi'
SCP_DATA = b'scp'
TEST_FDT1_DATA = b'fdt1'
@@ -179,6 +181,7 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
TestFunctional._MakeInputFile('compress_big', COMPRESS_DATA_BIG)
TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
+ TestFunctional._MakeInputFile('bl2u.bin', ATF_BL2U_DATA)
TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA)
TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
@@ -4735,6 +4738,220 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
err = stderr.getvalue()
self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
+ def testFip(self):
+ """Basic test of generation of an ARM Firmware Image Package (FIP)"""
+ data = self._DoReadFile('203_fip.dts')
+ hdr, fents = fip_util.decode_fip(data)
+ self.assertEqual(fip_util.HEADER_MAGIC, hdr.name)
+ self.assertEqual(fip_util.HEADER_SERIAL, hdr.serial)
+ self.assertEqual(0x123, hdr.flags)
+
+ self.assertEqual(2, len(fents))
+
+ fent = fents[0]
+ self.assertEqual(
+ bytes([0x47, 0xd4, 0x08, 0x6d, 0x4c, 0xfe, 0x98, 0x46,
+ 0x9b, 0x95, 0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x0]), fent.uuid)
+ self.assertEqual('soc-fw', fent.fip_type)
+ self.assertEqual(0x88, fent.offset)
+ self.assertEqual(len(ATF_BL31_DATA), fent.size)
+ self.assertEqual(0x123456789abcdef, fent.flags)
+ self.assertEqual(ATF_BL31_DATA, fent.data)
+ self.assertEqual(True, fent.valid)
+
+ fent = fents[1]
+ self.assertEqual(
+ bytes([0x65, 0x92, 0x27, 0x03, 0x2f, 0x74, 0xe6, 0x44,
+ 0x8d, 0xff, 0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10]), fent.uuid)
+ self.assertEqual('scp-fwu-cfg', fent.fip_type)
+ self.assertEqual(0x8c, fent.offset)
+ self.assertEqual(len(ATF_BL31_DATA), fent.size)
+ self.assertEqual(0, fent.flags)
+ self.assertEqual(ATF_BL2U_DATA, fent.data)
+ self.assertEqual(True, fent.valid)
+
+ def testFipOther(self):
+ """Basic FIP with something that isn't a external blob"""
+ data = self._DoReadFile('204_fip_other.dts')
+ hdr, fents = fip_util.decode_fip(data)
+
+ self.assertEqual(2, len(fents))
+ fent = fents[1]
+ self.assertEqual('rot-cert', fent.fip_type)
+ self.assertEqual(b'aa', fent.data)
+
+ def testFipOther(self):
+ """Basic FIP with something that isn't a external blob"""
+ data = self._DoReadFile('204_fip_other.dts')
+ hdr, fents = fip_util.decode_fip(data)
+
+ self.assertEqual(2, len(fents))
+ fent = fents[1]
+ self.assertEqual('rot-cert', fent.fip_type)
+ self.assertEqual(b'aa', fent.data)
+
+ def testFipNoType(self):
+ """FIP with an entry of an unknown type"""
+ with self.assertRaises(ValueError) as e:
+ self._DoReadFile('205_fip_no_type.dts')
+ self.assertIn("Must provide a fip-type (node name 'u-boot' is not a known FIP type)",
+ str(e.exception))
+
+ def testFipUuid(self):
+ """Basic FIP with a manual uuid"""
+ data = self._DoReadFile('206_fip_uuid.dts')
+ hdr, fents = fip_util.decode_fip(data)
+
+ self.assertEqual(2, len(fents))
+ fent = fents[1]
+ self.assertEqual(None, fent.fip_type)
+ self.assertEqual(
+ bytes([0xfc, 0x65, 0x13, 0x92, 0x4a, 0x5b, 0x11, 0xec,
+ 0x94, 0x35, 0xff, 0x2d, 0x1c, 0xfc, 0x79, 0x9c]),
+ fent.uuid)
+ self.assertEqual(U_BOOT_DATA, fent.data)
+
+ def testFipLs(self):
+ """Test listing a FIP"""
+ data = self._DoReadFileRealDtb('207_fip_ls.dts')
+ hdr, fents = fip_util.decode_fip(data)
+
+ try:
+ tmpdir, updated_fname = self._SetupImageInTmpdir()
+ with test_util.capture_sys_output() as (stdout, stderr):
+ self._DoBinman('ls', '-i', updated_fname)
+ finally:
+ shutil.rmtree(tmpdir)
+ lines = stdout.getvalue().splitlines()
+ expected = [
+'Name Image-pos Size Entry-type Offset Uncomp-size',
+'----------------------------------------------------------------',
+'main-section 0 2d3 section 0',
+' atf-fip 0 90 atf-fip 0',
+' soc-fw 88 4 blob-ext 88',
+' u-boot 8c 4 u-boot 8c',
+' fdtmap 90 243 fdtmap 90',
+]
+ self.assertEqual(expected, lines)
+
+ image = control.images['image']
+ entries = image.GetEntries()
+ fdtmap = entries['fdtmap']
+
+ fdtmap_data = data[fdtmap.image_pos:fdtmap.image_pos + fdtmap.size]
+ magic = fdtmap_data[:8]
+ self.assertEqual(b'_FDTMAP_', magic)
+ self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
+
+ fdt_data = fdtmap_data[16:]
+ dtb = fdt.Fdt.FromData(fdt_data)
+ dtb.Scan()
+ props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
+ self.assertEqual({
+ 'atf-fip/soc-fw:image-pos': 136,
+ 'atf-fip/soc-fw:offset': 136,
+ 'atf-fip/soc-fw:size': 4,
+ 'atf-fip/u-boot:image-pos': 140,
+ 'atf-fip/u-boot:offset': 140,
+ 'atf-fip/u-boot:size': 4,
+ 'atf-fip:image-pos': 0,
+ 'atf-fip:offset': 0,
+ 'atf-fip:size': 144,
+ 'image-pos': 0,
+ 'offset': 0,
+ 'fdtmap:image-pos': fdtmap.image_pos,
+ 'fdtmap:offset': fdtmap.offset,
+ 'fdtmap:size': len(fdtmap_data),
+ 'size': len(data),
+ }, props)
+
+ def testFipExtractOneEntry(self):
+ """Test extracting a single entry fron an FIP"""
+ self._DoReadFileRealDtb('207_fip_ls.dts')
+ image_fname = tools.GetOutputFilename('image.bin')
+ fname = os.path.join(self._indir, 'output.extact')
+ control.ExtractEntries(image_fname, fname, None, ['atf-fip/u-boot'])
+ data = tools.ReadFile(fname)
+ self.assertEqual(U_BOOT_DATA, data)
+
+ def testFipReplace(self):
+ """Test replacing a single file in a FIP"""
+ expected = U_BOOT_DATA + tools.GetBytes(0x78, 50)
+ data = self._DoReadFileRealDtb('208_fip_replace.dts')
+ updated_fname = tools.GetOutputFilename('image-updated.bin')
+ tools.WriteFile(updated_fname, data)
+ entry_name = 'atf-fip/u-boot'
+ control.WriteEntry(updated_fname, entry_name, expected,
+ allow_resize=True)
+ actual = control.ReadEntry(updated_fname, entry_name)
+ self.assertEqual(expected, actual)
+
+ new_data = tools.ReadFile(updated_fname)
+ hdr, fents = fip_util.decode_fip(new_data)
+
+ self.assertEqual(2, len(fents))
+
+ # Check that the FIP entry is updated
+ fent = fents[1]
+ self.assertEqual(0x8c, fent.offset)
+ self.assertEqual(len(expected), fent.size)
+ self.assertEqual(0, fent.flags)
+ self.assertEqual(expected, fent.data)
+ self.assertEqual(True, fent.valid)
+
+ def testFipMissing(self):
+ with test_util.capture_sys_output() as (stdout, stderr):
+ self._DoTestFile('209_fip_missing.dts', allow_missing=True)
+ err = stderr.getvalue()
+ self.assertRegex(err, "Image 'main-section'.*missing.*: rmm-fw")
+
+ def testFipSize(self):
+ """Test a FIP with a size property"""
+ data = self._DoReadFile('210_fip_size.dts')
+ self.assertEqual(0x100 + len(U_BOOT_DATA), len(data))
+ hdr, fents = fip_util.decode_fip(data)
+ self.assertEqual(fip_util.HEADER_MAGIC, hdr.name)
+ self.assertEqual(fip_util.HEADER_SERIAL, hdr.serial)
+
+ self.assertEqual(1, len(fents))
+
+ fent = fents[0]
+ self.assertEqual('soc-fw', fent.fip_type)
+ self.assertEqual(0x60, fent.offset)
+ self.assertEqual(len(ATF_BL31_DATA), fent.size)
+ self.assertEqual(ATF_BL31_DATA, fent.data)
+ self.assertEqual(True, fent.valid)
+
+ rest = data[0x60 + len(ATF_BL31_DATA):0x100]
+ self.assertEqual(tools.GetBytes(0xff, len(rest)), rest)
+
+ def testFipBadAlign(self):
+ """Test that an invalid alignment value in a FIP is detected"""
+ with self.assertRaises(ValueError) as e:
+ self._DoTestFile('211_fip_bad_align.dts')
+ self.assertIn(
+ "Node \'/binman/atf-fip\': FIP alignment 31 must be a power of two",
+ str(e.exception))
+
+ def testFipCollection(self):
+ """Test using a FIP in a collection"""
+ data = self._DoReadFile('212_fip_collection.dts')
+ entry1 = control.images['image'].GetEntries()['collection']
+ data1 = data[:entry1.size]
+ hdr1, fents2 = fip_util.decode_fip(data1)
+
+ entry2 = control.images['image'].GetEntries()['atf-fip']
+ data2 = data[entry2.offset:entry2.offset + entry2.size]
+ hdr1, fents2 = fip_util.decode_fip(data2)
+
+ # The 'collection' entry should have U-Boot included at the end
+ self.assertEqual(entry1.size - len(U_BOOT_DATA), entry2.size)
+ self.assertEqual(data1, data2 + U_BOOT_DATA)
+ self.assertEqual(U_BOOT_DATA, data1[-4:])
+
+ # There should be a U-Boot after the final FIP
+ self.assertEqual(U_BOOT_DATA, data[-4:])
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/test/203_fip.dts b/tools/binman/test/203_fip.dts
new file mode 100644
index 00000000000..08973373240
--- /dev/null
+++ b/tools/binman/test/203_fip.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x123456789abcdef>;
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/204_fip_other.dts b/tools/binman/test/204_fip_other.dts
new file mode 100644
index 00000000000..65039410986
--- /dev/null
+++ b/tools/binman/test/204_fip_other.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x123456789abcdef>;
+ filename = "bl31.bin";
+ };
+
+ _testing {
+ fip-type = "rot-cert";
+ return-contents-later;
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/205_fip_no_type.dts b/tools/binman/test/205_fip_no_type.dts
new file mode 100644
index 00000000000..23c8c3bc37e
--- /dev/null
+++ b/tools/binman/test/205_fip_no_type.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ u-boot {
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/206_fip_uuid.dts b/tools/binman/test/206_fip_uuid.dts
new file mode 100644
index 00000000000..c9bd44f9c31
--- /dev/null
+++ b/tools/binman/test/206_fip_uuid.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x123456789abcdef>;
+ filename = "bl31.bin";
+ };
+
+ u-boot {
+ fip-uuid = [fc 65 13 92 4a 5b 11 ec
+ 94 35 ff 2d 1c fc 79 9c];
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/207_fip_ls.dts b/tools/binman/test/207_fip_ls.dts
new file mode 100644
index 00000000000..630fca15024
--- /dev/null
+++ b/tools/binman/test/207_fip_ls.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x123456789abcdef>;
+ filename = "bl31.bin";
+ };
+
+ u-boot {
+ fip-uuid = [fc 65 13 92 4a 5b 11 ec
+ 94 35 ff 2d 1c fc 79 9c];
+ };
+ };
+
+ fdtmap {
+ };
+ };
+};
diff --git a/tools/binman/test/208_fip_replace.dts b/tools/binman/test/208_fip_replace.dts
new file mode 100644
index 00000000000..432c12474df
--- /dev/null
+++ b/tools/binman/test/208_fip_replace.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ allow-repack;
+ atf-fip {
+ fip-hdr-flags = /bits/ 64 <0x123>;
+ soc-fw {
+ fip-flags = /bits/ 64 <0x123456789abcdef>;
+ filename = "bl31.bin";
+ };
+
+ u-boot {
+ fip-uuid = [fc 65 13 92 4a 5b 11 ec
+ 94 35 ff 2d 1c fc 79 9c];
+ };
+
+ };
+
+ u-boot {
+ };
+
+ u-boot-dtb {
+ };
+
+ fdtmap {
+ };
+ };
+};
diff --git a/tools/binman/test/209_fip_missing.dts b/tools/binman/test/209_fip_missing.dts
new file mode 100644
index 00000000000..43bb600d047
--- /dev/null
+++ b/tools/binman/test/209_fip_missing.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ soc-fw {
+ filename = "bl31.bin";
+ };
+
+ rmm-fw {
+ filename = "rmm.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/210_fip_size.dts b/tools/binman/test/210_fip_size.dts
new file mode 100644
index 00000000000..9dfee796459
--- /dev/null
+++ b/tools/binman/test/210_fip_size.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ size = <0x100>;
+ pad-byte = <0xff>;
+ soc-fw {
+ filename = "bl31.bin";
+ };
+ };
+ u-boot {
+ };
+ };
+};
diff --git a/tools/binman/test/211_fip_bad_align.dts b/tools/binman/test/211_fip_bad_align.dts
new file mode 100644
index 00000000000..a0901496d80
--- /dev/null
+++ b/tools/binman/test/211_fip_bad_align.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ atf-fip {
+ fip-align = <31>;
+ size = <0x100>;
+ pad-byte = <0xff>;
+ soc-fw {
+ filename = "bl31.bin";
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/212_fip_collection.dts b/tools/binman/test/212_fip_collection.dts
new file mode 100644
index 00000000000..332c023af87
--- /dev/null
+++ b/tools/binman/test/212_fip_collection.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ collection {
+ content = <&fip &u_boot>;
+ };
+ fip: atf-fip {
+ soc-fw {
+ filename = "bl31.bin";
+ };
+
+ scp-fwu-cfg {
+ filename = "bl2u.bin";
+ };
+ };
+ u_boot: u-boot {
+ };
+ };
+};