src/update_ram.c: fix RAMBOOT skipping payload relocation when uImage ih_load differs from WOLFBOOT_LOAD_ADDRESS#827
Open
94xhn wants to merge 1 commit into
Conversation
…OT_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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When
WOLFBOOT_USE_RAMBOOTis active (EXT_FLASH+NO_XIP, orEXT_ENCRYPTED+MMU),wolfBoot_ramboot()copies the entire signed image to a fixed RAM staging address derived fromWOLFBOOT_LOAD_ADDRESS.If the image is also a
WOLFBOOT_UBOOT_LEGACY(uImage) payload whose header fieldih_loadis non-zero,wolfBoot_start()only rewrites the jump target (load_address = ih_load) — it never copies the payload bytes there. The generic "copy image to RAM"memcpya few lines below is compiled out entirely under#ifndef WOLFBOOT_USE_RAMBOOT, because it assumes RAMBOOT already placed the data where it needs to be. That assumption only holds whenih_loadhappens to coincide with the RAMBOOT staging address (WOLFBOOT_LOAD_ADDRESS+ the 64-byte uImage header). When it doesn't,do_boot()jumps toih_load, which was never written.The non-RAMBOOT path does not have this problem, since its
memcpyruns afterload_addresshas already been corrected toih_load.Reachability
arch.mkunconditionally enablesWOLFBOOT_UBOOT_LEGACYforTARGET=zynq(ZynqMP),TARGET=zynq7000, andTARGET=versal. The shippedconfig/examples/zynqmp.config,zynq7000.config, andversal_vmk180.configall setEXT_FLASH=1+NO_XIP=1, which is exactly theWOLFBOOT_USE_RAMBOOTtrigger condition, andWOLFBOOT_NO_RAMBOOTis never set anywhere in the repo. So all three of these example targets compile in both features simultaneously. The officially-tested Linux flow for these targets currently boots a rawzImagerather than amkimage-wrapped uImage, so this isn't hit by the documented/tested path today — but theih_loadhandling is unconditionally compiled in as an opportunistic feature, and any user whomkimage-wraps a kernel with a real, non-zeroih_loadfor one of these targets (standard PetaLinux/U-Boot practice) would hit it.Fix
When
ih_load != 0underWOLFBOOT_USE_RAMBOOT, relocate the payload from its current RAM location (os_image.fw_base, where RAMBOOT already staged it) toih_loadviamemmoveif the two addresses differ — mirroring what the non-RAMBOOT arm already does with itsmemcpy. Theih_load == 0(Linux/PPC) path is untouched.Testing
Built a standalone C harness that replays the exact control flow of
wolfBoot_ramboot()(header + body copy to a fixed RAM staging address) and theWOLFBOOT_UBOOT_LEGACYblock'sih_loadhandling against a simulated flat RAM buffer, using the literal post-fix code from this diff:ih_loadcoincidentally equal to the RAMBOOT staging address: payload present (no relocation needed, none performed) — pass.ih_loada distinct, higher address (realistic board load address): without this fix, payload is missing at the jump target (bug reproduced); with this fix,memmoverelocates it correctly — pass.ih_loada distinct, lower address (exercisesmemmove's backward-overlap safety): same result — pass.ih_load == 0(Linux/PPC convention): unaffected by this diff, behavior identical before/after — pass.No CI/hardware available locally to exercise a full Zynq/Versal build; this was validated via the isolated control-flow harness described above rather than an end-to-end board boot.