From: Quentin Schulz <quentin.sch...@cherry.de> A FIT image which is NOT using -E when created by mkimage - that is with image data within the FIT - will fail to apply FDTO if the base FDT image node does not specify a load property (which points to an address in DRAM). This is because we check that the FDT address we want to apply overlay to (i.e. modify and likely increase in size) is not inside the FIT and give up otherwise. This is assumed necessary because we may then overwrite other data when applying in-place.
However, we can do better than giving up: relocating the FDT in another place in DRAM where it's safe to increase its size and apply FDTOs. While at it, do not discriminate anymore on whether the data is within the FIT data address space - that is FIT images created with mkimage -E - as that still may be susceptible to unintended data overwrites as mkimage -E simply concatenates all blobs after the FIT. If the FDT blob isn't the last, it'll result in overwriting later blobs when resizing. The side effect is that the load property in the FIT is only temporarily used to load the FDT but then relocated right before we start applying overlays. Suggested-by: Marek Vasut <ma...@denx.de> Reviewed-by: Marek Vasut <ma...@denx.de> Signed-off-by: Quentin Schulz <quentin.sch...@cherry.de> --- This actually forces the base FDT to always be relocated whenever FDTO are expected to be applied, regardless of the presence of the load property in the base FDT image node. Tested with extlinux with: - conf node with multiple fdt entries (scenario A) - conf node with base fdt + conf node with fdto (stored in fdt property) (scenario B) - conf node with multiple fdt entries with base fdt with load property (scenario C) - conf node with base fdt + conf node with fdto (stored in fdt property) with base fdt with load property (scenario D) """fit.its /dts-v1/; / { description = "Kernel fitImage for Jaguar"; #address-cells = <1>; images { kernel-1 { description = "Linux kernel"; data = /incbin/("arch/arm64/boot/Image.gz"); type = "kernel"; arch = "arm64"; os = "linux"; compression = "gzip"; load = <0x06000000>; entry = <0x06000000>; hash-1 { algo = "sha256"; }; }; fdt-rk3588-jaguar.dtb { description = "Flattened Device Tree blob"; data = /incbin/("arch/arm64/boot/dts/rockchip/rk3588-jaguar.dtb"); type = "flat_dt"; arch = "arm64"; compression = "none"; hash-1 { algo = "sha256"; }; }; fdt-rk3588-jaguar.dtb-load { description = "Flattened Device Tree blob"; data = /incbin/("arch/arm64/boot/dts/rockchip/rk3588-jaguar.dtb"); type = "flat_dt"; arch = "arm64"; compression = "none"; load = <0x12000000>; hash-1 { algo = "sha256"; }; }; fdt-rk3588-jaguar-pre-ict-tester.dtbo { description = "Flattened Device Tree blob"; data = /incbin/("arch/arm64/boot/dts/rockchip/rk3588-jaguar-pre-ict-tester.dtbo"); type = "flat_dt"; arch = "arm64"; compression = "none"; hash-1 { algo = "sha256"; }; }; }; configurations { default = "conf-rk3588-jaguar.dtb"; conf-rk3588-jaguar.dtb { description = "1 Linux kernel, FDT blob"; kernel = "kernel-1"; fdt = "fdt-rk3588-jaguar.dtb"; hash-1 { algo = "sha256"; }; }; conf-rk3588-jaguar.dtb-and-dtbo { description = "1 Linux kernel, FDT blob"; kernel = "kernel-1"; fdt = "fdt-rk3588-jaguar.dtb", "fdt-rk3588-jaguar-pre-ict-tester.dtbo"; hash-1 { algo = "sha256"; }; }; conf-rk3588-jaguar.dtb-load { description = "1 Linux kernel, FDT blob"; kernel = "kernel-1"; fdt = "fdt-rk3588-jaguar.dtb-load"; hash-1 { algo = "sha256"; }; }; conf-rk3588-jaguar.dtb-load-and-dtbo { description = "1 Linux kernel, FDT blob"; kernel = "kernel-1"; fdt = "fdt-rk3588-jaguar.dtb-load", "fdt-rk3588-jaguar-pre-ict-tester.dtbo"; hash-1 { algo = "sha256"; }; }; conf-rk3588-jaguar-pre-ict-tester.dtbo { description = "0 FDT blob"; fdt = "fdt-rk3588-jaguar-pre-ict-tester.dtbo"; hash-1 { algo = "sha256"; }; }; }; }; """ """extlinux.conf (scenario A) LABEL rk3588-jaguar LINUX /boot/fit#conf-rk3588-jaguar.dtb-and-dtbo APPEND root=PARTLABEL=debos-rootfs rw rootwait net.ifnames=0 """ Log: """ Using 'conf-rk3588-jaguar.dtb-and-dtbo' configuration Verifying Hash Integrity ... OK Trying 'kernel-1' kernel subimage Description: Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x020000cc Data Size: 11862415 Bytes = 11.3 MiB Architecture: AArch64 OS: Linux Load Address: 0x06000000 Entry Point: 0x06000000 Hash algo: sha256 Hash value: 51a2b828aec49d9ede09a2de2cd05226def258dedcc8e4c4098fa2ba38fb9690 Verifying Hash Integrity ... sha256+ OK Using 'conf-rk3588-jaguar.dtb-and-dtbo' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar.dtb' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02b50370 Data Size: 168750 Bytes = 164.8 KiB Architecture: AArch64 Hash algo: sha256 Hash value: 96213ce3930a5f926b27c90671ca779fc327e2e62c2135f7ed7d8b6dd659b973 Verifying Hash Integrity ... sha256+ OK Loading Device Tree to 00000000ece9d000, end 00000000ecec9fff ... OK Working FDT set to ece9d000 Trying 'fdt-rk3588-jaguar-pre-ict-tester.dtbo' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02ba2bb4 Data Size: 2753 Bytes = 2.7 KiB Architecture: AArch64 Hash algo: sha256 Hash value: e5eb1fe225d03b04e9bb27c04fe3278f294b48c6ab6757292c9650f6d3ce9f34 Verifying Hash Integrity ... sha256+ OK Booting using the fdt blob at 0xece9d000 Working FDT set to ece9d000 Uncompressing Kernel Image to 6000000 Loading Device Tree to 00000000ece70000, end 00000000ece9c62d ... OK Working FDT set to ece70000 """ """extlinux.conf (scenario B) LABEL rk3588-jaguar LINUX /boot/fit#conf-rk3588-jaguar.dtb-load-and-dtbo APPEND root=PARTLABEL=debos-rootfs rw rootwait net.ifnames=0 """ Log: """ Using 'conf-rk3588-jaguar.dtb-load-and-dtbo' configuration Verifying Hash Integrity ... OK Trying 'kernel-1' kernel subimage Description: Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x020000cc Data Size: 11862415 Bytes = 11.3 MiB Architecture: AArch64 OS: Linux Load Address: 0x06000000 Entry Point: 0x06000000 Hash algo: sha256 Hash value: 51a2b828aec49d9ede09a2de2cd05226def258dedcc8e4c4098fa2ba38fb9690 Verifying Hash Integrity ... sha256+ OK Using 'conf-rk3588-jaguar.dtb-load-and-dtbo' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar.dtb-load' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02b79784 Data Size: 168750 Bytes = 164.8 KiB Architecture: AArch64 Load Address: 0x12000000 Hash algo: sha256 Hash value: 96213ce3930a5f926b27c90671ca779fc327e2e62c2135f7ed7d8b6dd659b973 Verifying Hash Integrity ... sha256+ OK Loading fdt from 0x02b79784 to 0x12000000 Loading Device Tree to 00000000ece9d000, end 00000000ecec9fff ... OK Working FDT set to ece9d000 Trying 'fdt-rk3588-jaguar-pre-ict-tester.dtbo' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02ba2bb4 Data Size: 2753 Bytes = 2.7 KiB Architecture: AArch64 Hash algo: sha256 Hash value: e5eb1fe225d03b04e9bb27c04fe3278f294b48c6ab6757292c9650f6d3ce9f34 Verifying Hash Integrity ... sha256+ OK Booting using the fdt blob at 0xece9d000 Working FDT set to ece9d000 Uncompressing Kernel Image to 6000000 Loading Device Tree to 00000000ece70000, end 00000000ece9c62d ... OK Working FDT set to ece70000 """ """extlinux.conf (scenario C) LABEL rk3588-jaguar LINUX /boot/fit#conf-rk3588-jaguar.dtb#conf-rk3588-jaguar-pre-ict-tester.dtbo APPEND root=PARTLABEL=debos-rootfs rw rootwait net.ifnames=0 """ Log: """ Using 'conf-rk3588-jaguar.dtb' configuration Verifying Hash Integrity ... OK Trying 'kernel-1' kernel subimage Description: Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x020000cc Data Size: 11862415 Bytes = 11.3 MiB Architecture: AArch64 OS: Linux Load Address: 0x06000000 Entry Point: 0x06000000 Hash algo: sha256 Hash value: 51a2b828aec49d9ede09a2de2cd05226def258dedcc8e4c4098fa2ba38fb9690 Verifying Hash Integrity ... sha256+ OK Using 'conf-rk3588-jaguar.dtb' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar.dtb' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02b50370 Data Size: 168750 Bytes = 164.8 KiB Architecture: AArch64 Hash algo: sha256 Hash value: 96213ce3930a5f926b27c90671ca779fc327e2e62c2135f7ed7d8b6dd659b973 Verifying Hash Integrity ... sha256+ OK Loading Device Tree to 00000000ece9d000, end 00000000ecec9fff ... OK Working FDT set to ece9d000 Using 'conf-rk3588-jaguar-pre-ict-tester.dtbo' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar-pre-ict-tester.dtbo' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02ba2bb4 Data Size: 2753 Bytes = 2.7 KiB Architecture: AArch64 Hash algo: sha256 Hash value: e5eb1fe225d03b04e9bb27c04fe3278f294b48c6ab6757292c9650f6d3ce9f34 Verifying Hash Integrity ... sha256+ OK Booting using the fdt blob at 0xece9d000 Working FDT set to ece9d000 Uncompressing Kernel Image to 6000000 Loading Device Tree to 00000000ece70000, end 00000000ece9c62d ... OK Working FDT set to ece70000 """ """extlinux.conf (scenario D) LABEL rk3588-jaguar LINUX /boot/fit#conf-rk3588-jaguar.dtb-load#conf-rk3588-jaguar-pre-ict-tester.dtbo APPEND root=PARTLABEL=debos-rootfs rw rootwait net.ifnames=0 """ Log: """ Using 'conf-rk3588-jaguar.dtb-load' configuration Verifying Hash Integrity ... OK Trying 'kernel-1' kernel subimage Description: Linux kernel Type: Kernel Image Compression: gzip compressed Data Start: 0x020000cc Data Size: 11862415 Bytes = 11.3 MiB Architecture: AArch64 OS: Linux Load Address: 0x06000000 Entry Point: 0x06000000 Hash algo: sha256 Hash value: 51a2b828aec49d9ede09a2de2cd05226def258dedcc8e4c4098fa2ba38fb9690 Verifying Hash Integrity ... sha256+ OK Using 'conf-rk3588-jaguar.dtb-load' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar.dtb-load' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02b79784 Data Size: 168750 Bytes = 164.8 KiB Architecture: AArch64 Load Address: 0x12000000 Hash algo: sha256 Hash value: 96213ce3930a5f926b27c90671ca779fc327e2e62c2135f7ed7d8b6dd659b973 Verifying Hash Integrity ... sha256+ OK Loading fdt from 0x02b79784 to 0x12000000 Loading Device Tree to 00000000ece9d000, end 00000000ecec9fff ... OK Working FDT set to ece9d000 Using 'conf-rk3588-jaguar-pre-ict-tester.dtbo' configuration Verifying Hash Integrity ... OK Trying 'fdt-rk3588-jaguar-pre-ict-tester.dtbo' fdt subimage Description: Flattened Device Tree blob Type: Flat Device Tree Compression: uncompressed Data Start: 0x02ba2bb4 Data Size: 2753 Bytes = 2.7 KiB Architecture: AArch64 Hash algo: sha256 Hash value: e5eb1fe225d03b04e9bb27c04fe3278f294b48c6ab6757292c9650f6d3ce9f34 Verifying Hash Integrity ... sha256+ OK Booting using the fdt blob at 0xece9d000 Working FDT set to ece9d000 Uncompressing Kernel Image to 6000000 Loading Device Tree to 00000000ece70000, end 00000000ece9c62d ... OK Working FDT set to ece70000 """ Cc: Heiko Stuebner <he...@sntech.de> --- Changes in v3: - of_flat_tree type changed from char* to void*, - added Marek's Rb trailer, - Link to v2: https://lore.kernel.org/r/20250116-extlinux-relocate-dtb-when-dtbo-v2-1-d011582c2...@cherry.de Changes in v2: - Indiscriminately relocate, regardless of location of FDT to be on the safe side wrt data overlap/overwrite, - print return value of boot_relocate_fdt when it fails, - Link to v1: https://lore.kernel.org/r/20241219-extlinux-relocate-dtb-when-dtbo-v1-1-fe5eeb8fd...@cherry.de --- boot/image-fit.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/boot/image-fit.c b/boot/image-fit.c index db7fb61bca948e42a4136b9ceb263a53362ad3f8..5dd896d019a70742510dbf2a9987b0b6948181ea 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -2348,10 +2348,10 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, char *next_config = NULL; ulong load, len; #ifdef CONFIG_OF_LIBFDT_OVERLAY - ulong image_start, image_end; ulong ovload, ovlen, ovcopylen; const char *uconfig; const char *uname; + void *of_flat_tree; void *base, *ov, *ovcopy = NULL; int i, err, noffset, ov_noffset; #endif @@ -2395,17 +2395,18 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, /* we need to apply overlays */ #ifdef CONFIG_OF_LIBFDT_OVERLAY - image_start = addr; - image_end = addr + fit_get_size(fit); - /* verify that relocation took place by load address not being in fit */ - if (load >= image_start && load < image_end) { - /* check is simplified; fit load checks for overlaps */ - printf("Overlayed FDT requires relocation\n"); + /* Relocate FDT so resizing does not overwrite other data in FIT. */ + of_flat_tree = map_sysmem(load, len); + len = ALIGN(fdt_totalsize(load), SZ_4K); + err = boot_relocate_fdt(&of_flat_tree, &len); + if (err) { + printf("Required FDT relocation for applying DTOs failed: %d\n", + err); fdt_noffset = -EBADF; goto out; } - base = map_sysmem(load, len); + load = (ulong)of_flat_tree; /* apply extra configs in FIT first, followed by args */ for (i = 1; ; i++) { --- base-commit: 82d262ae162d859d3b0bbcd40a9464e890b009da change-id: 20241219-extlinux-relocate-dtb-when-dtbo-4c7536f880b2 Best regards, -- Quentin Schulz <quentin.sch...@cherry.de>