On 2/6/26 4:14 PM, Jamie Gibbons wrote:
Some platforms
All platforms, DTs and DTOs have to be 8 Byte aligned, always, period.
require device tree overlays (DTOs) to be 8-byte aligned
when applying them with libfdt. Previously, the code did not guarantee
this alignment, which could result in alignment errors during overlay
application.
Introduce a new runtime parameter, always_relocate_overlay, to
boot_get_fdt_fit(). When set, overlays are always copied to an 8-byte
aligned buffer before being passed to fdt_open_into().
This resolves issues with FDT overlay application on platforms that
require strict alignment.
Fixes: 8fbcc0e0e839 ("boot: Assure FDT is always at 8-byte aligned address")
Signed-off-by: Jamie Gibbons <[email protected]>
---
boot/image-fdt.c | 2 +-
boot/image-fit.c | 23 +++++++++++++++++------
include/image.h | 5 ++++-
3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index a3a4fb8b558..33fd4248acd 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -431,7 +431,7 @@ static int select_fdt(struct bootm_headers *images, const
char *select, u8 arch,
fdt_noffset = boot_get_fdt_fit(images, fdt_addr,
&fit_uname_fdt,
&fit_uname_config,
- arch, &load,
&len);
+ arch, &load,
&len, true);
This flag is always true, do we actually need it ?
if (fdt_noffset < 0)
return -ENOENT;
diff --git a/boot/image-fit.c b/boot/image-fit.c
index d2b0a7daccc..a3fa2a01463 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2370,7 +2370,8 @@ int boot_get_setup_fit(struct bootm_headers *images,
uint8_t arch,
#ifndef USE_HOSTCC
int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
const char **fit_unamep, const char **fit_uname_configp,
- int arch, ulong *datap, ulong *lenp)
+ int arch, ulong *datap, ulong *lenp,
+ bool always_relocate_overlay)
{
int fdt_noffset, cfg_noffset, count;
const void *fit;
@@ -2492,11 +2493,21 @@ int boot_get_fdt_fit(struct bootm_headers *images,
ulong addr,
ov = map_sysmem(ovload, ovlen);
ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K);
- ovcopy = malloc(ovcopylen);
- if (!ovcopy) {
- printf("failed to duplicate DTO before application\n");
- fdt_noffset = -ENOMEM;
- goto out;
+ if (always_relocate_overlay) {
+ ovcopy = aligned_alloc(8, ovcopylen);
+ if (!ovcopy) {
+ printf("failed to allocate aligned DTO
buffer\n");
+ fdt_noffset = -ENOMEM;
+ goto out;
+ }
+ memcpy(ovcopy, ov, ovlen);
+ } else {
+ ovcopy = malloc(ovcopylen);
+ if (!ovcopy) {
+ printf("failed to duplicate DTO before
application\n");
+ fdt_noffset = -ENOMEM;
+ goto out;
+ }
Looking at this, if the problem is $ov aligned to 4 Bytes, then $base a
bit below could also be aligned to 4 Bytes if there are two or more DTs
in the fitImage without external data. Can you please try the attached
patch and see if that still works ?
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 3ed69b5f7bc..845e769a7e3 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2368,6 +2368,48 @@ int boot_get_setup_fit(struct bootm_headers
*images, uint8_t arch,
}
#ifndef USE_HOSTCC
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+static int boot_get_fdt_fit_into_buffer(ulong loadaddr, ulong loadlen,
void **fdtdstbuf)
+{
+ void *fdtsrcbuf, *map;
+ ulong fdtdstlen;
+ int err;
+
+ map = map_sysmem(loadaddr, loadlen);
+
+ /* Set up source buffer, make sure DT in the buffer is 8-Bytes aligned
*/
+ if (!IS_ALIGNED((uintptr_t)map, 8)) {
+ fdtsrcbuf = aligned_alloc(8, loadlen);
+ if (!fdtsrcbuf)
+ return -ENOMEM;
+ memcpy(fdtsrcbuf, map, loadlen);
+ } else {
+ fdtsrcbuf = map;
+ }
+
+ /* Set up destination buffer, make sure DT in the buffer is 8-Bytes
aligned */
+ fdtdstlen = ALIGN(fdt_totalsize(fdtsrcbuf), SZ_4K);
+ fdtdstbuf = aligned_alloc(8, fdtdstlen);
+ if (!fdtdstbuf) {
+ printf("failed to duplicate DTO before application\n");
+ if (!IS_ALIGNED((uintptr_t)map, 8))
+ free(fdtsrcbuf);
+ return -ENOMEM;
+ }
+
+ err = fdt_open_into(fdtsrcbuf, *fdtdstbuf, fdtdstlen);
+ if (!IS_ALIGNED((uintptr_t)map, 8))
+ free(fdtsrcbuf);
+ if (err < 0) {
+ printf("failed on fdt_open_into for DTO: %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+
+ return 0;
+};
+#endif
+
int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
const char **fit_unamep, const char **fit_uname_configp,
int arch, ulong *datap, ulong *lenp)
@@ -2380,7 +2422,7 @@ int boot_get_fdt_fit(struct bootm_headers *images,
ulong addr,
char *next_config = NULL;
ulong load, len;
#ifdef CONFIG_OF_LIBFDT_OVERLAY
- ulong ovload, ovlen, ovcopylen;
+ ulong ovload, ovlen;
const char *uconfig;
const char *uname;
/*
@@ -2391,7 +2433,7 @@ int boot_get_fdt_fit(struct bootm_headers *images,
ulong addr,
* Instead, let's be lazy and use void *.
*/
char *of_flat_tree;
- void *base, *ov, *ovcopy = NULL;
+ void *base, *ovcopy = NULL;
int i, err, noffset, ov_noffset;
#endif
@@ -2489,17 +2531,7 @@ int boot_get_fdt_fit(struct bootm_headers
*images, ulong addr,
}
debug("%s loaded at 0x%08lx len=0x%08lx\n",
uname, ovload, ovlen);
- ov = map_sysmem(ovload, ovlen);
-
- ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K);
- ovcopy = malloc(ovcopylen);
- if (!ovcopy) {
- printf("failed to duplicate DTO before application\n");
- fdt_noffset = -ENOMEM;
- goto out;
- }
-
- err = fdt_open_into(ov, ovcopy, ovcopylen);
+ err = boot_get_fdt_fit_into_buffer(ovload, ovlen, &ovcopy);
if (err < 0) {
printf("failed on fdt_open_into for DTO: %s\n",
fdt_strerror(err));
@@ -2507,8 +2539,7 @@ int boot_get_fdt_fit(struct bootm_headers *images,
ulong addr,
goto out;
}
- base = map_sysmem(load, len + ovlen);
- err = fdt_open_into(base, base, len + ovlen);
+ err = boot_get_fdt_fit_into_buffer(load, len + ovlen, &base);
if (err < 0) {
printf("failed on fdt_open_into: %s\n",
fdt_strerror(err));
--
2.51.0
From 0444df2cb881cc4d943e224de795aa499b870a5c Mon Sep 17 00:00:00 2001
From: Jamie Gibbons <[email protected]>
Date: Fri, 6 Feb 2026 15:14:57 +0000
Subject: [PATCH] boot: image-fit: Add runtime flag to always relocate overlays
Some platforms require device tree overlays (DTOs) to be 8-byte aligned
when applying them with libfdt. Previously, the code did not guarantee
this alignment, which could result in alignment errors during overlay
application.
Introduce a new runtime parameter, always_relocate_overlay, to
boot_get_fdt_fit(). When set, overlays are always copied to an 8-byte
aligned buffer before being passed to fdt_open_into().
This resolves issues with FDT overlay application on platforms that
require strict alignment.
Fixes: 8fbcc0e0e839 ("boot: Assure FDT is always at 8-byte aligned address")
Signed-off-by: Jamie Gibbons <[email protected]>
---
boot/image-fit.c | 61 ++++++++++++++++++++++++++++++++++++------------
1 file changed, 46 insertions(+), 15 deletions(-)
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 3ed69b5f7bc..845e769a7e3 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2368,6 +2368,48 @@ int boot_get_setup_fit(struct bootm_headers *images, uint8_t arch,
}
#ifndef USE_HOSTCC
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+static int boot_get_fdt_fit_into_buffer(ulong loadaddr, ulong loadlen, void **fdtdstbuf)
+{
+ void *fdtsrcbuf, *map;
+ ulong fdtdstlen;
+ int err;
+
+ map = map_sysmem(loadaddr, loadlen);
+
+ /* Set up source buffer, make sure DT in the buffer is 8-Bytes aligned */
+ if (!IS_ALIGNED((uintptr_t)map, 8)) {
+ fdtsrcbuf = aligned_alloc(8, loadlen);
+ if (!fdtsrcbuf)
+ return -ENOMEM;
+ memcpy(fdtsrcbuf, map, loadlen);
+ } else {
+ fdtsrcbuf = map;
+ }
+
+ /* Set up destination buffer, make sure DT in the buffer is 8-Bytes aligned */
+ fdtdstlen = ALIGN(fdt_totalsize(fdtsrcbuf), SZ_4K);
+ fdtdstbuf = aligned_alloc(8, fdtdstlen);
+ if (!fdtdstbuf) {
+ printf("failed to duplicate DTO before application\n");
+ if (!IS_ALIGNED((uintptr_t)map, 8))
+ free(fdtsrcbuf);
+ return -ENOMEM;
+ }
+
+ err = fdt_open_into(fdtsrcbuf, *fdtdstbuf, fdtdstlen);
+ if (!IS_ALIGNED((uintptr_t)map, 8))
+ free(fdtsrcbuf);
+ if (err < 0) {
+ printf("failed on fdt_open_into for DTO: %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+
+ return 0;
+};
+#endif
+
int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
const char **fit_unamep, const char **fit_uname_configp,
int arch, ulong *datap, ulong *lenp)
@@ -2380,7 +2422,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
char *next_config = NULL;
ulong load, len;
#ifdef CONFIG_OF_LIBFDT_OVERLAY
- ulong ovload, ovlen, ovcopylen;
+ ulong ovload, ovlen;
const char *uconfig;
const char *uname;
/*
@@ -2391,7 +2433,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
* Instead, let's be lazy and use void *.
*/
char *of_flat_tree;
- void *base, *ov, *ovcopy = NULL;
+ void *base, *ovcopy = NULL;
int i, err, noffset, ov_noffset;
#endif
@@ -2489,17 +2531,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
}
debug("%s loaded at 0x%08lx len=0x%08lx\n",
uname, ovload, ovlen);
- ov = map_sysmem(ovload, ovlen);
-
- ovcopylen = ALIGN(fdt_totalsize(ov), SZ_4K);
- ovcopy = malloc(ovcopylen);
- if (!ovcopy) {
- printf("failed to duplicate DTO before application\n");
- fdt_noffset = -ENOMEM;
- goto out;
- }
-
- err = fdt_open_into(ov, ovcopy, ovcopylen);
+ err = boot_get_fdt_fit_into_buffer(ovload, ovlen, &ovcopy);
if (err < 0) {
printf("failed on fdt_open_into for DTO: %s\n",
fdt_strerror(err));
@@ -2507,8 +2539,7 @@ int boot_get_fdt_fit(struct bootm_headers *images, ulong addr,
goto out;
}
- base = map_sysmem(load, len + ovlen);
- err = fdt_open_into(base, base, len + ovlen);
+ err = boot_get_fdt_fit_into_buffer(load, len + ovlen, &base);
if (err < 0) {
printf("failed on fdt_open_into: %s\n",
fdt_strerror(err));
--
2.51.0