From 0d1494108c9e072122e897f93a44fbebd9d4d12c Mon Sep 17 00:00:00 2001 From: Kent McLeod Date: Tue, 22 Feb 2022 17:00:16 +1100 Subject: [PATCH] elfloader: Don't overwrite the platform DTB If a DTB has been passed in from an earlier stage boot loader during an elfloader image relocation, make sure that it doesn't get overwritten. On Arm this isn't relevant as the protocol when relocation happens doesn't also pass in a DTB. Signed-off-by: Kent McLeod --- elfloader-tool/src/arch-arm/64/crt0.S | 1 + elfloader-tool/src/arch-riscv/crt0.S | 1 + elfloader-tool/src/common.c | 20 +++++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/elfloader-tool/src/arch-arm/64/crt0.S b/elfloader-tool/src/arch-arm/64/crt0.S index aa559303e..75abafc66 100644 --- a/elfloader-tool/src/arch-arm/64/crt0.S +++ b/elfloader-tool/src/arch-arm/64/crt0.S @@ -23,6 +23,7 @@ BEGIN_FUNC(_start) * Binary images may not be loaded in the correct location. * Try and move ourselves so we're in the right place. */ + mov x0, #0 /* Arg 0 of fixup_image_base is NULL */ bl fixup_image_base mov x2, x0 /* restore original arguments for next step */ diff --git a/elfloader-tool/src/arch-riscv/crt0.S b/elfloader-tool/src/arch-riscv/crt0.S index 223fb1a12..81b030ddf 100644 --- a/elfloader-tool/src/arch-riscv/crt0.S +++ b/elfloader-tool/src/arch-riscv/crt0.S @@ -62,6 +62,7 @@ _start: * Binary images may not be loaded in the correct location. * Try and move ourselves so we're in the right place. */ + mv a0, a1 /* Pass dtb as first argument */ jal fixup_image_base /* fixup_image_base returns 0 if no need to move */ beqz a0, 1f diff --git a/elfloader-tool/src/common.c b/elfloader-tool/src/common.c index 9f0858763..0e10774c1 100644 --- a/elfloader-tool/src/common.c +++ b/elfloader-tool/src/common.c @@ -635,7 +635,7 @@ extern void invalidate_icache(void); * to ensure that it doesn't occupy memory that it needs to load the * kernel and user applications into. */ -char * fixup_image_base(void) { +char * fixup_image_base(char const *fdt) { char *load_base = _start; char *target_base = (char *) IMAGE_START_ADDR; if (load_base == target_base) { @@ -659,6 +659,24 @@ char * fixup_image_base(void) { abort(); } + /* If a fdt was passed in from the previous boot stage, also + * check that it isn't overwritten. + */ + if (fdt) { + size_t dtb_size = fdt_size(fdt); + const char * fdt_end = fdt + dtb_size; + if (image_size < dtb_size) { + /* Assume the dtb is smaller than the images size to + * simplify region check */ + abort(); + } + if ((fdt >= target_base && fdt < target_end) || + (fdt_end >= target_base && fdt_end < target_end)) { + abort(); + } + } + + /* Perform the move and clean/invalidate caches if necessary */ char *ret = memmove(target_base, load_base, image_size); #ifdef CONFIG_ARCH_ARM