[PATCH v4] image: apply FDTOs on FDT image node without a load property
Quentin Schulz
foss+uboot at 0leil.net
Wed Jan 22 16:53:15 CET 2025
From: Quentin Schulz <quentin.schulz at 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 <marex at denx.de>
Reviewed-by: Marek Vasut <marex at denx.de>
Signed-off-by: Quentin Schulz <quentin.schulz at 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 <heiko at sntech.de>
---
Changes in v4:
- of_flat_tree type changed to char* from void*, as v3 wouldn't compile,
- add comment explaining why char * for of_flat_tree
- Link to v3: https://lore.kernel.org/r/20250122-extlinux-relocate-dtb-when-dtbo-v3-1-46bef4eac720@cherry.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-d011582c2b7e@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-fe5eeb8fd4f1@cherry.de
---
boot/image-fit.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/boot/image-fit.c b/boot/image-fit.c
index db7fb61bca948e42a4136b9ceb263a53362ad3f8..8ebe54fd663fc4cf09a0f744160b63554c787ff4 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2348,10 +2348,17 @@ 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;
+ /*
+ * of_flat_tree is storing the void * returned by map_sysmem, then its
+ * address is passed to boot_relocate_fdt which expects a char ** and it
+ * is then cast into a ulong. Setting its type to void * would require
+ * to cast its address to char ** when passing it to boot_relocate_fdt.
+ * Instead, let's be lazy and use void *.
+ */
+ char *of_flat_tree;
void *base, *ov, *ovcopy = NULL;
int i, err, noffset, ov_noffset;
#endif
@@ -2395,17 +2402,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.schulz at cherry.de>
More information about the U-Boot
mailing list