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

Reply via email to