A U-Boot image may embed its device tree, but a FIT which explicitly
names an FDT must not boot after that FDT fails to load or verify.
External FDT data is copied to its load address before verification,
so ignoring the error can leave an unverified device tree for U-Boot.
Keep support for U-Boot images without a separate FDT, but reject
failures for an explicitly requested FDT in both firmware and loadables.
Fixes: d879616e9e64 ("spl: fit: simplify logic for FDT loading for non-OS
boots")
Signed-off-by: Carlo Caione <[email protected]>
---
common/spl/spl_fit.c | 14 +++++++++++---
test/image/spl_load.c | 42 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 64e5f95546f..a520db76506 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -491,11 +491,14 @@ static int spl_fit_append_fdt(struct spl_image_info
*spl_image,
image_info.load_addr = ALIGN(spl_image->load_addr + spl_image->size, 8);
/* Figure out which device tree the board wants to use */
+ spl_image->fdt_addr = NULL;
node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index++);
if (node < 0) {
size_t size;
debug("%s: cannot find FDT node\n", __func__);
+ if (fdt_getprop(ctx->fit, ctx->conf_node, FIT_FDT_PROP, NULL))
+ return node;
/*
* U-Boot did not find a device tree inside the FIT image. Use
@@ -896,6 +899,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
int ret;
int index = 0;
int firmware_node;
+ bool has_fdt;
ret = spl_simple_fit_read(&ctx, info, offset, fit);
if (ret < 0)
@@ -911,6 +915,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
if (ret < 0)
return ret;
+ has_fdt = fdt_getprop(ctx.fit, ctx.conf_node, FIT_FDT_PROP, NULL);
+
if (IS_ENABLED(CONFIG_SPL_FPGA))
spl_fit_load_fpga(&ctx, info, offset);
@@ -958,11 +964,11 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
/*
* Booting a next-stage U-Boot may require us to append the FDT.
- * We allow this to fail, as the U-Boot image might embed its FDT.
+ * A U-Boot image may omit it when the FDT is embedded in the binary.
*/
if (os_takes_devicetree(spl_image->os)) {
ret = spl_fit_append_fdt(spl_image, info, offset, &ctx);
- if (ret < 0 && spl_image->os != IH_OS_U_BOOT)
+ if (ret < 0 && (has_fdt || spl_image->os != IH_OS_U_BOOT))
return ret;
}
@@ -999,7 +1005,9 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
debug("Loadable is %s\n", genimg_get_os_name(os_type));
if (os_takes_devicetree(os_type)) {
- spl_fit_append_fdt(&image_info, info, offset, &ctx);
+ ret = spl_fit_append_fdt(&image_info, info, offset,
&ctx);
+ if (ret < 0 && has_fdt)
+ return ret;
spl_image->fdt_addr = image_info.fdt_addr;
}
diff --git a/test/image/spl_load.c b/test/image/spl_load.c
index 334ec77b18e..166cf331194 100644
--- a/test/image/spl_load.c
+++ b/test/image/spl_load.c
@@ -367,6 +367,48 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0);
SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0);
SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+static int spl_test_fit_missing_fdt(struct unit_test_state *uts)
+{
+ struct spl_image_info expected = {
+ .name = "missing FDT",
+ .size = SPL_TEST_DATA_SIZE,
+ };
+ struct spl_image_info loaded = {};
+ struct spl_load_info load;
+ size_t size, offset;
+ void *image;
+ int node, ret;
+
+ if (!IS_ENABLED(CONFIG_SPL_LOAD_FIT))
+ return -EAGAIN;
+ size = create_image(NULL, FIT_INTERNAL, &expected, &offset);
+ image = calloc(1, size + 128);
+ ut_assertnonnull(image);
+ generate_data(image + offset, expected.size, expected.name);
+ if (create_image(image, FIT_INTERNAL, &expected, NULL) != size) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = fdt_open_into(image, image, size + 128);
+ if (ret)
+ goto out;
+ node = fdt_path_offset(image, "/configurations/config-1");
+ ret = fdt_setprop_string(image, node, FIT_FDT_PROP, "missing");
+ if (ret)
+ goto out;
+ spl_load_init(&load, spl_test_read, image, 1);
+ ret = spl_load_simple_fit(&loaded, &load, 0, image);
+ free(image);
+ ut_assert(ret < 0);
+ return 0;
+out:
+ free(image);
+ ut_assertok(ret);
+ return 0;
+}
+
+SPL_TEST(spl_test_fit_missing_fdt, 0);
+
/*
* Build a FIT with external data, overwrite one property of the image node
* with a hostile value and check that loading fails with the expected error.
--
2.56.0