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-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);
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;
+ }
}
err = fdt_open_into(ov, ovcopy, ovcopylen);
diff --git a/include/image.h b/include/image.h
index 34efac6056d..9b174ea6233 100644
--- a/include/image.h
+++ b/include/image.h
@@ -707,12 +707,15 @@ int boot_get_setup_fit(struct bootm_headers *images,
uint8_t arch,
* @param arch Expected architecture (IH_ARCH_...)
* @param datap Returns address of loaded image
* @param lenp Returns length of loaded image
+ * @param always_relocate_overlay If true, always copy overlays to an
8-byte
+ * aligned buffer before applying (prevents alignment
errors)
*
* Return: node offset of base image, or -ve error code on error
*/
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);
/**
* fit_image_load() - load an image from a FIT
--
2.43.0