An overlay listed in a FIT configuration is part of the requested devicetree, not an optional addition. Currently, a failed load or hash check can be ignored and boot continues with that overlay missing. For signed configurations, this also means using a combination that was not signed.
Reject the devicetree if any listed overlay cannot be loaded or verified. A missing image must be treated as an error too, rather than falling back to the default configuration's base devicetree. This also affects bootm, even when fdt fit is disabled. Boards which previously booted despite a broken overlay will now stop at the error. Add a bootm regression test covering a valid overlay, a corrupted overlay hash and a missing overlay image. Reviewed-by: Simon Glass <[email protected]> Signed-off-by: Carlo Caione <[email protected]> --- boot/image-fit.c | 12 +++++----- test/py/tests/test_fit.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index 4f4e7b4e06a..83e731402d6 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2675,7 +2675,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, void *ovcopy = NULL; void *base_buf = NULL; ulong base_buf_size = 0; - int i, err, noffset, ov_noffset; + int i, err, ov_noffset; #endif fit_uname = fit_unamep ? *fit_unamep : NULL; @@ -2752,9 +2752,8 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, /* apply extra configs in FIT first, followed by args */ for (i = 1; ; i++) { if (i < count) { - noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, - FIT_FDT_PROP, i); - uname = fit_get_name(fit, noffset, NULL); + uname = fdt_stringlist_get(fit, cfg_noffset, + FIT_FDT_PROP, i, NULL); uconfig = NULL; } else { if (!next_config) @@ -2786,8 +2785,9 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, BOOTSTAGE_ID_FIT_FDT_START, FIT_LOAD_IGNORED, &ovload, &ovlen); if (ov_noffset < 0) { - printf("load of %s failed\n", uname); - continue; + printf("load of %s failed\n", uname ? uname : uconfig); + fdt_noffset = ov_noffset; + goto out; } debug("%s loaded at 0x%08lx len=0x%08lx\n", uname, ovload, ovlen); diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 0edf875a9e1..3113209d911 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -397,6 +397,66 @@ class TestFitImage: self.check_not_equal(params, 'ramdisk', 'ramdisk_out', 'Ramdisk loaded but should not be') + @pytest.mark.buildconfigspec('cmd_bootm') + @pytest.mark.buildconfigspec('cmd_fdt') + @pytest.mark.buildconfigspec('of_libfdt_overlay') + @pytest.mark.requiredtool('fdtput') + @pytest.mark.parametrize('overlay_state', ['valid', 'bad-hash', 'missing']) + def test_fit_overlay_load(self, ubman, fsetup, overlay_state): + """bootm must not skip a listed overlay that fails to load or verify""" + overlay_dts = ''' +/dts-v1/; +/plugin/; + +&{/} { + test-overlay = "applied"; +}; +''' + overlay_image = ''' + overlay-1 { + data = /incbin/("%(overlay)s"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; +''' + params = dict(fsetup, overlay=fit_util.make_dtb( + ubman, overlay_dts, 'bootm-overlay')) + its = BASE_ITS.replace(' images {', + ' images {' + overlay_image) + its = its.replace('fdt = "fdt-1";', 'fdt = "fdt-1", "overlay-1";') + fit = fit_util.make_fit(ubman, params['mkimage'], its, params, + basename=f'bootm-overlay-{overlay_state}.fit') + if overlay_state == 'bad-hash': + utils.run_and_log(ubman, [ + 'fdtput', '-t', 'x', fit, '/images/overlay-1/hash-1', + 'value', *(['0'] * 8)]) + elif overlay_state == 'missing': + utils.run_and_log(ubman, ['fdtput', '-r', fit, '/images/overlay-1']) + + try: + ubman.run_command('setenv verify yes') + output = ubman.run_command( + f'host load hostfs 0 {params["fit_addr"]:x} {fit}') + assert 'bytes read' in output + output = ubman.run_command( + f'bootm start {params["fit_addr"]:x}#conf-1; echo rc=$?') + if overlay_state == 'valid': + assert output.rstrip().endswith('rc=0'), output + assert 'test-overlay = "applied"' in ubman.run_command( + 'fdt print / test-overlay') + else: + assert output.rstrip().endswith('rc=1'), output + assert 'load of overlay-1 failed' in output + assert 'Booting using the fdt blob' not in output + if overlay_state == 'bad-hash': + assert 'Bad hash value' in output + finally: + ubman.restart_uboot() + def test_fit_kernel_fdt_ramdisk_load(self, ubman, fsetup): """Test loading a FIT image with kernel, FDT, and ramdisk""" cmds, params, _ = self.prepare( -- 2.56.0
