hw/arm/boot: Diagnose layouts that put initrd or DTB off the end of RAM

We calculate the locations in memory where we want to put the
initrd and the DTB based on the size of the kernel, since they
come after it. Add some explicit checks that these aren't off the
end of RAM entirely.

(At the moment the way we calculate the initrd_start means that
it can't ever be off the end of RAM, but that will change with
the next commit.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Message-id: 20190516144733.32399-3-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2019-05-16 15:47:31 +01:00
parent e70af24b42
commit 852dc64d66
1 changed files with 23 additions and 0 deletions

View File

@ -1056,11 +1056,25 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
error_report("could not load kernel '%s'", info->kernel_filename);
exit(1);
}
if (kernel_size > info->ram_size) {
error_report("kernel '%s' is too large to fit in RAM "
"(kernel size %d, RAM size %" PRId64 ")",
info->kernel_filename, kernel_size, info->ram_size);
exit(1);
}
info->entry = entry;
if (is_linux) {
uint32_t fixupcontext[FIXUP_MAX];
if (info->initrd_filename) {
if (info->initrd_start >= ram_end) {
error_report("not enough space after kernel to load initrd");
exit(1);
}
initrd_size = load_ramdisk_as(info->initrd_filename,
info->initrd_start,
ram_end - info->initrd_start, as);
@ -1076,6 +1090,11 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
info->initrd_filename);
exit(1);
}
if (info->initrd_start + initrd_size > info->ram_size) {
error_report("could not load initrd '%s': "
"too big to fit into RAM after the kernel",
info->initrd_filename);
}
} else {
initrd_size = 0;
}
@ -1111,6 +1130,10 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
/* Place the DTB after the initrd in memory with alignment. */
info->dtb_start = QEMU_ALIGN_UP(info->initrd_start + initrd_size,
align);
if (info->dtb_start >= ram_end) {
error_report("Not enough space for DTB after kernel/initrd");
exit(1);
}
fixupcontext[FIXUP_ARGPTR_LO] = info->dtb_start;
fixupcontext[FIXUP_ARGPTR_HI] = info->dtb_start >> 32;
} else {