From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6A38C433F5 for ; Thu, 25 Nov 2021 14:48:46 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 497168365E; Thu, 25 Nov 2021 15:48:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ldaJi7+R"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8B1C2835EA; Thu, 25 Nov 2021 15:48:42 +0100 (CET) Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 704D2836C5 for ; Thu, 25 Nov 2021 15:48:32 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-yb1-xb35.google.com with SMTP id e136so12409184ybc.4 for ; Thu, 25 Nov 2021 06:48:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=tBtnsZHYO+E4spxyK1sfZX881DtisZtPvuMLt/TV3do=; b=ldaJi7+Ryx/9ONWplk/fZsYTDM/H2t/xsTjqAhHE1WWQo2sODJUtCjmcOwBoMkpey6 f9InwShoTbn0Qv5mVLeA6N0Zc9anMNVcxrIJdzjyJbJfsxRd8vJCppEZus7W0zmmVagH /W5j+t19gtNNq8QvMtJpWwIo1w9alGM4IeUPWcQ4TM+53k98/UcjPgk5ploaQ7lsbZa8 02O+c8MYUiUPzuZ/bqN9oKcqDC1fy52TX2HoB5HwBEQ4PWFMgoLcP5G07O13U0Rx5w5n 56tV16+vZcnZr8j1HoH08IppAjzX5GZfgEL920xvdGAwL83LGaR2YNykqhmTkmggifuL nIwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=tBtnsZHYO+E4spxyK1sfZX881DtisZtPvuMLt/TV3do=; b=Ur15rwuoJYHwAPKWgZ/UMuoFY6De0bASz7ZpERn767XrPIKBCaBg+i07Q5voMygoBq qTPfGElZ9nonSRy67XDAjGl5pRii3giQMfZOp9zea2KbuNt48l3ulOzMb4u75ZG6K+Ef cnPtMtGrBs+WpDQzDQNxpmofBFhmvppOa5sqVqFB0Y+IlsMD4hzAGfniqPcZJ3FAa62G RznFO4lNKlOgWVwTZKMUVaK2+rIX51obOt3MhlLLcJadzXeEnC0irwG3J8HANtpwSml7 FFTAhmbE+0ChOjOt62reZOqVLkmR3WsojjnxmQkbFDjReWrQ4k/sUqncxTtm3socgZGP Q9nA== X-Gm-Message-State: AOAM531a1iFoUZd39i+ML5ANO107qtyKG4FdXmdyuET//7KFfPNtcgjI zzO2GYTbfAELHH3hPaOg1BS1vN5kli7eDmjxQChOJA== X-Google-Smtp-Source: ABdhPJy+InmQvtr7imBLnZnorRsXMvIhIRvhxbp6QpqtEMSc6JjDCiKnNsHrJvrqieNHSPdnNOFRljX7B9jDkt9I42c= X-Received: by 2002:a25:8388:: with SMTP id t8mr6928989ybk.79.1637851709260; Thu, 25 Nov 2021 06:48:29 -0800 (PST) MIME-Version: 1.0 References: <20211124040900.699274-1-sjg@chromium.org> <20211123210849.2.Idf2f2a46d26cdecb56b6e9f40472f62fd062e346@changeid> In-Reply-To: <20211123210849.2.Idf2f2a46d26cdecb56b6e9f40472f62fd062e346@changeid> From: Ilias Apalodimas Date: Thu, 25 Nov 2021 16:47:53 +0200 Message-ID: Subject: Re: [PATCH 2/2] binman: Add support for ATF FIP To: Simon Glass Cc: U-Boot Mailing List , Sandrine Bailleux Content-Type: text/plain; charset="UTF-8" X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.37 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean +CC Sandrine On Wed, 24 Nov 2021 at 06:09, Simon Glass 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 > --- > > 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 > +# > +# 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 >