[PATCH 2/2] binman: Add support for ATF FIP
Ilias Apalodimas
ilias.apalodimas at linaro.org
Thu Nov 25 15:47:53 CET 2021
+CC Sandrine
On Wed, 24 Nov 2021 at 06:09, Simon Glass <sjg at chromium.org> wrote:
>
> This format is used in firmware binaries so we may as well supported it.
>
> With this patch binman supports creating, listing and updating FIPs, as
> well as extracting files from one, provided that an FDTMAP is also present
> somewhere in the image.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> scripts/pylint.base | 1 +
> tools/binman/entries.rst | 154 +++++++++++++
> tools/binman/etype/atf_fip.py | 273 +++++++++++++++++++++++
> tools/binman/ftest.py | 217 ++++++++++++++++++
> tools/binman/test/203_fip.dts | 21 ++
> tools/binman/test/204_fip_other.dts | 22 ++
> tools/binman/test/205_fip_no_type.dts | 15 ++
> tools/binman/test/206_fip_uuid.dts | 22 ++
> tools/binman/test/207_fip_ls.dts | 25 +++
> tools/binman/test/208_fip_replace.dts | 33 +++
> tools/binman/test/209_fip_missing.dts | 19 ++
> tools/binman/test/210_fip_size.dts | 19 ++
> tools/binman/test/211_fip_bad_align.dts | 18 ++
> tools/binman/test/212_fip_collection.dts | 24 ++
> 14 files changed, 863 insertions(+)
> create mode 100644 tools/binman/etype/atf_fip.py
> create mode 100644 tools/binman/test/203_fip.dts
> create mode 100644 tools/binman/test/204_fip_other.dts
> create mode 100644 tools/binman/test/205_fip_no_type.dts
> create mode 100644 tools/binman/test/206_fip_uuid.dts
> create mode 100644 tools/binman/test/207_fip_ls.dts
> create mode 100644 tools/binman/test/208_fip_replace.dts
> create mode 100644 tools/binman/test/209_fip_missing.dts
> create mode 100644 tools/binman/test/210_fip_size.dts
> create mode 100644 tools/binman/test/211_fip_bad_align.dts
> create mode 100644 tools/binman/test/212_fip_collection.dts
>
> diff --git a/scripts/pylint.base b/scripts/pylint.base
> index a35dbe34d2d..3d891edf261 100644
> --- a/scripts/pylint.base
> +++ b/scripts/pylint.base
> @@ -1,5 +1,6 @@
> _testing 0.83
> atf_bl31 -6.00
> +atf_fip 0.44
> binman.cbfs_util 7.70
> binman.cbfs_util_test 9.19
> binman.cmdline 9.06
> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
> index 748277c1cde..84f828a6352 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..f9039e14c0a
> --- /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 at 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):
> + 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 0f4330b6807..d8ddbc81c1f 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)
>
> @@ -4681,6 +4684,220 @@ class TestFunctional(unittest.TestCase):
> binary=False)
> self.assertEqual(version, state.GetVersion(self._indir))
>
> + 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 {
> + };
> + };
> +};
> --
> 2.34.0.rc2.393.gf8c9666880-goog
>
More information about the U-Boot
mailing list