diff options
-rw-r--r-- | tools/binman/entries.rst | 154 | ||||
-rw-r--r-- | tools/binman/etype/atf_fip.py | 273 | ||||
-rw-r--r-- | tools/binman/ftest.py | 217 | ||||
-rw-r--r-- | tools/binman/test/203_fip.dts | 21 | ||||
-rw-r--r-- | tools/binman/test/204_fip_other.dts | 22 | ||||
-rw-r--r-- | tools/binman/test/205_fip_no_type.dts | 15 | ||||
-rw-r--r-- | tools/binman/test/206_fip_uuid.dts | 22 | ||||
-rw-r--r-- | tools/binman/test/207_fip_ls.dts | 25 | ||||
-rw-r--r-- | tools/binman/test/208_fip_replace.dts | 33 | ||||
-rw-r--r-- | tools/binman/test/209_fip_missing.dts | 19 | ||||
-rw-r--r-- | tools/binman/test/210_fip_size.dts | 19 | ||||
-rw-r--r-- | tools/binman/test/211_fip_bad_align.dts | 18 | ||||
-rw-r--r-- | tools/binman/test/212_fip_collection.dts | 24 |
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 { + }; + }; +}; |