[PATCH v5 7/8] libfdt: Allow non-64b aligned memreserve entries

Uros Stajic
2025-12-24T16:42:19Z

From: Chao-ying Fu <cfu@mips.com>

Although memreserve entries in an FDT are 64-bit aligned relative to the
start of the FDT, we cannot guarantee that the FDT itself is 64-bit aligned
in memory. This is especially common when using a FIT image, where the
alignment of the embedded DTB cannot be controlled.

On systems that do not support unaligned 64-bit memory accesses, this leads
to faults when accessing the memreserve section before the FDT is relocated.
To resolve this, copy the 64-bit values into suitably aligned on-stack
variables before accessing them.

Signed-off-by: Chao-ying Fu <cfu@mips.com>
Signed-off-by: Uros Stajic <uros.stajic@htecgroup.com>
---
scripts/dtc/libfdt/fdt_ro.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index d65656aaa8b..1c18aea66ab 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -174,6 +174,7 @@ static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)

int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
+ uint64_t u64;
const struct fdt_reserve_entry *re;

FDT_RO_PROBE(fdt);
@@ -181,8 +182,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (fdt_chk_extra() && !re)
return -FDT_ERR_BADOFFSET;

- *address = fdt64_to_cpu(re->address);
- *size = fdt64_to_cpu(re->size);
+ memcpy(&u64, &re->address, sizeof(u64));
+ *address = fdt64_to_cpu(u64);
+ memcpy(&u64, &re->size, sizeof(u64));
+ *size = fdt64_to_cpu(u64);
return 0;
}

@@ -190,9 +193,11 @@ int fdt_num_mem_rsv(const void *fdt)
{
int i;
const struct fdt_reserve_entry *re;
+ uint64_t u64;

for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_to_cpu(re->size) == 0)
+ memcpy(&u64, &re->size, sizeof(u64));
+ if (fdt64_to_cpu(u64) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
--
2.34.1