From e5b0c2662dabe5cb22a478c14df9be6b0ae4c8c1 Mon Sep 17 00:00:00 2001 From: 94xhn <87560781+94xhn@users.noreply.github.com> Date: Sat, 18 Jul 2026 22:49:43 +0800 Subject: [PATCH] Fix RAMBOOT skipping payload relocation when uImage ih_load != WOLFBOOT_LOAD_ADDRESS When WOLFBOOT_USE_RAMBOOT is active (EXT_FLASH+NO_XIP, or EXT_ENCRYPTED+MMU), wolfBoot_ramboot() copies the whole signed image to a fixed RAM staging address derived from WOLFBOOT_LOAD_ADDRESS. If the image is also a WOLFBOOT_UBOOT_LEGACY (uImage) payload with a non-zero ih_load field, the code only rewrites the jump target (load_address = ih_load) but never copies the payload bytes there, because the generic "copy image to RAM" memcpy is compiled out entirely under #ifndef WOLFBOOT_USE_RAMBOOT (it assumes RAMBOOT already placed the data where it needs to be, which is only true when ih_load happens to coincide with the RAMBOOT staging address). do_boot() then jumps to ih_load, which was never written. This is reachable structurally: the zynqmp, zynq7000 and versal_vmk180 example configs all set EXT_FLASH+NO_XIP (enabling RAMBOOT) while arch.mk unconditionally enables WOLFBOOT_UBOOT_LEGACY for those targets, and WOLFBOOT_NO_RAMBOOT is never set anywhere in the repo. Any user who mkimage-wraps a Linux/RTOS kernel with a real, non-zero ih_load for one of these targets (standard PetaLinux/U-Boot practice) would hit this. Fix: when ih_load != 0 under WOLFBOOT_USE_RAMBOOT, relocate the payload from its current RAM location (os_image.fw_base, where RAMBOOT already staged it) to ih_load via memmove if the two addresses differ, mirroring what the non-RAMBOOT arm already does with its memcpy. The ih_load == 0 (Linux/PPC) path is untouched. --- src/update_ram.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/update_ram.c b/src/update_ram.c index 9407e0a93a..44cd4e2dd7 100644 --- a/src/update_ram.c +++ b/src/update_ram.c @@ -452,6 +452,25 @@ void RAMFUNCTION wolfBoot_start(void) if (ih_load != 0) { load_address = (uint32_t*)(uintptr_t)ih_load; +#ifdef WOLFBOOT_USE_RAMBOOT + /* WOLFBOOT_USE_RAMBOOT already placed the payload in RAM at + * os_image.fw_base via the early wolfBoot_ramboot() copy, but + * the generic "copy image to RAM" memcpy further below is + * compiled out entirely when RAMBOOT is active (RAMBOOT is + * expected to have already put the data where it needs to be). + * That is only true when ih_load coincides with where RAMBOOT + * staged the payload -- if the uImage requests a different + * ih_load, the payload must be relocated here, or do_boot() + * below will jump into RAM that was never written. */ + if ((uint8_t*)load_address != os_image.fw_base) { + wolfBoot_printf( + "RAMBOOT: relocating uImage payload from %p to %p " + "(%d bytes) to honor ih_load\n", + os_image.fw_base, load_address, os_image.fw_size); + memmove((void*)load_address, os_image.fw_base, + os_image.fw_size); + } +#endif } else { /* Linux PPC path: leave load_address alone, just advance it * past the header to match upstream behaviour. load_address is