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