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

Reply via email to