Merge patch series "mkimage: validate image references in FIT configurations"

Aristo Chen <jj251510319013@gmail.com> says:

This series introduces a validation step in mkimage to ensure that all image
names referenced under the /configurations node of a FIT source (ITS) are
actually defined under the /images node.

### Motivation

When using mkimage to build FIT images, it's easy to mistakenly reference
nonexistent image nodes in configurations (e.g., referencing a missing `fdt` or
`firmware` node). Such issues are often not caught until runtime in U-Boot.

This series aims to catch these errors early during FIT image creation by
validating the configuration references in mkimage itself.

Link: https://lore.kernel.org/r/20250610074121.8308-1-aristo.chen@canonical.com
This commit is contained in:
Tom Rini
2025-06-26 08:33:42 -06:00
12 changed files with 297 additions and 4 deletions
@@ -400,11 +400,105 @@
};
&binman {
tifsstub-hs {
filename = "tifsstub.bin_hs";
ti-secure-rom {
content = <&tifsstub_hs_cert>;
core = "secure";
load = <0x40000>;
sw-rev = <CONFIG_K3_X509_SWRV>;
keyfile = "custMpk.pem";
countersign;
tifsstub;
};
tifsstub_hs_cert: tifsstub-hs-cert.bin {
filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin";
type = "blob-ext";
optional;
};
tifsstub_hs_enc: tifsstub-hs-enc.bin {
filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin";
type = "blob-ext";
optional;
};
};
tifsstub-fs {
filename = "tifsstub.bin_fs";
tifsstub_fs_cert: tifsstub-fs-cert.bin {
filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin";
type = "blob-ext";
optional;
};
tifsstub_fs_enc: tifsstub-fs-enc.bin {
filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin";
type = "blob-ext";
optional;
};
};
tifsstub-gp {
filename = "tifsstub.bin_gp";
ti-secure-rom {
content = <&tifsstub_gp>;
core = "secure";
load = <0x60000>;
sw-rev = <CONFIG_K3_X509_SWRV>;
keyfile = "ti-degenerate-key.pem";
tifsstub;
};
tifsstub_gp: tifsstub-gp.bin {
filename = "ti-sysfw/ti-fs-stub-firmware-am62x-gp.bin";
type = "blob-ext";
optional;
};
};
ti-spl_unsigned {
insert-template = <&ti_spl_unsigned_template>;
fit {
images {
tifsstub-hs {
description = "TIFSSTUB";
type = "firmware";
arch = "arm32";
compression = "none";
os = "tifsstub-hs";
load = <0x9dc00000>;
entry = <0x9dc00000>;
blob-ext {
filename = "tifsstub.bin_hs";
};
};
tifsstub-fs {
description = "TIFSSTUB";
type = "firmware";
arch = "arm32";
compression = "none";
os = "tifsstub-fs";
load = <0x9dc00000>;
entry = <0x9dc00000>;
blob-ext {
filename = "tifsstub.bin_fs";
};
};
tifsstub-gp {
description = "TIFSSTUB";
type = "firmware";
arch = "arm32";
compression = "none";
os = "tifsstub-gp";
load = <0x9dc00000>;
entry = <0x9dc00000>;
blob-ext {
filename = "tifsstub.bin_gp";
};
};
dm {
ti-dm {
filename = "ti-dm/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f";
@@ -0,0 +1,58 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2025
#
# Test that mkimage validates image references in configurations
import os
import subprocess
import pytest
import fit_util
@pytest.mark.boardspec('sandbox')
@pytest.mark.requiredtool('dtc')
def test_fit_invalid_image_reference(ubman):
"""Test that mkimage fails when configuration references a missing image"""
its_fname = fit_util.make_fname(ubman, "invalid.its")
itb_fname = fit_util.make_fname(ubman, "invalid.itb")
kernel = fit_util.make_kernel(ubman, 'kernel.bin', 'kernel')
# Write ITS with an invalid reference to a nonexistent image
its_text = '''
/dts-v1/;
/ {
images {
kernel@1 {
description = "Test Kernel";
data = /incbin/("kernel.bin");
type = "kernel";
arch = "sandbox";
os = "linux";
compression = "none";
load = <0x40000>;
entry = <0x40000>;
};
};
configurations {
default = "conf@1";
conf@1 {
kernel = "kernel@1";
fdt = "notexist";
};
};
};
'''
with open(its_fname, 'w') as f:
f.write(its_text)
mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage')
cmd = [mkimage, '-f', its_fname, itb_fname]
result = subprocess.run(cmd, capture_output=True, text=True)
assert result.returncode != 0, "mkimage should fail due to missing image reference"
assert "references undefined image 'notexist'" in result.stderr
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list = "of-list";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
@@ -12,7 +12,7 @@
#address-cells = <1>;
images {
test {
kernel {
description = "Something using a bintool";
type = "kernel";
arch = "arm";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list = "of-list";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list-val = "test-fdt1", "test-fdt2";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list-dir = "fdts";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list = "of-list";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list = "of-list";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+14
View File
@@ -15,6 +15,20 @@
fit,fdt-list = "of-list";
images {
atf {
description = "atf firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
uboot {
description = "U-Boot firmware";
type = "firmware";
compression = "none";
load = <00000000>;
entry = <00000000>;
};
kernel {
description = "Vanilla Linux kernel";
type = "kernel";
+40 -2
View File
@@ -627,6 +627,7 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
struct stat sbuf;
int ret;
int images;
int confs;
int node;
fd = mmap_fdt(params->cmdname, fname, 0, &old_fdt, &sbuf, false, false);
@@ -695,6 +696,43 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
}
}
confs = fdt_path_offset(fdt, FIT_CONFS_PATH);
static const char * const props[] = { FIT_KERNEL_PROP,
FIT_RAMDISK_PROP,
FIT_FDT_PROP,
FIT_LOADABLE_PROP,
FIT_FPGA_PROP,
FIT_FIRMWARE_PROP,
FIT_SCRIPT_PROP};
fdt_for_each_subnode(node, fdt, confs) {
const char *conf_name = fdt_get_name(fdt, node, NULL);
for (int i = 0; i < ARRAY_SIZE(props); i++) {
int count = fdt_stringlist_count(fdt, node, props[i]);
if (count < 0)
continue;
for (int j = 0; j < count; j++) {
const char *img_name =
fdt_stringlist_get(fdt, node, props[i], j, NULL);
if (!img_name || !*img_name)
continue;
int img = fdt_subnode_offset(fdt, images, img_name);
if (img < 0) {
fprintf(stderr,
"Error: configuration '%s' references undefined image '%s' in property '%s'\n",
conf_name, img_name, props[i]);
ret = FDT_ERR_NOTFOUND;
goto err_munmap;
}
}
}
}
munmap(old_fdt, sbuf.st_size);
/* Close the old fd so we can re-use it. */
@@ -750,7 +788,7 @@ static int fit_handle_file(struct image_tool_params *params)
char bakfile[MKIMAGE_MAX_TMPFILE_LEN + 4] = {0};
char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
size_t size_inc;
int ret;
int ret = EXIT_FAILURE;
/* Flattened Image Tree (FIT) format handling */
debug ("FIT format handling\n");
@@ -854,7 +892,7 @@ static int fit_handle_file(struct image_tool_params *params)
err_system:
unlink(tmpfile);
unlink(bakfile);
return -1;
return ret;
}
/**
+6 -1
View File
@@ -519,8 +519,13 @@ int main(int argc, char **argv)
*/
retval = tparams->fflag_handle(&params);
if (retval != EXIT_SUCCESS)
if (retval != EXIT_SUCCESS) {
if (retval == FDT_ERR_NOTFOUND) {
// Already printed error, exit cleanly
exit(EXIT_FAILURE);
}
usage("Bad parameters for FIT image type");
}
}
if (params.lflag || params.fflag) {