From 3b0299dd657cff4c5a0a65a8970d4dab4c7b889b Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Mon, 22 Dec 2014 23:15:02 +0000 Subject: [PATCH] bootloader: pass memory map to kernel Previously, the bootloader would only provide a single memory range. At least on VirtualBox, this memory range includes the ACPI tables, which the kernel then happily overwrites when executing VM. Much of the infrastructure to use a fullblown memory map is already in place; this patch adds the last (and strangely missing) bit of generating the memory map in a multiboot-compatible way. It should be noted that both the bootloader and the kernel actually violate the multiboot specification by not packing the structure for the memory ranges. This is a NetBSD bug, but it is also a nonissue for (our) practical purposes. It can be fixed without changing the code added in this patch. Change-Id: I7c0a307a8a8133239531e1d2b80f376849f90247 --- sys/arch/i386/stand/lib/exec.c | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/sys/arch/i386/stand/lib/exec.c b/sys/arch/i386/stand/lib/exec.c index 3c0b94c4b..b555b8774 100644 --- a/sys/arch/i386/stand/lib/exec.c +++ b/sys/arch/i386/stand/lib/exec.c @@ -666,6 +666,49 @@ userconf_init(void) } } +#if defined(PASS_MEMMAP) && defined(__minix) +/* + * Construct a memory map for the multiboot info structure, with memory ranges + * as reported by the BIOS. If successful, set the HAS_MMAP flag. Code copied + * largely from bootinfo_memmap.c. + */ +static void +memmap_init(struct multiboot_info * mbi) +{ + multiboot_memory_map_t *mmap; + int buf[5], i, nranges; + + nranges = 0; + i = 0; + do { + if (getmementry(&i, buf)) + break; + nranges++; + } while (i); + + if (nranges == 0) + return; + + mbi->mmap_length = sizeof(multiboot_memory_map_t) * nranges; + + mmap = alloc(mbi->mmap_length); + + mbi->mmap_addr = vtophys(mmap); + + i = 0; + while (nranges-- > 0) { + getmementry(&i, buf); + + /* Stupid tricks to deal with alignment issues. */ + memcpy(&mmap->mm_base_addr, buf, sizeof(buf)); + mmap->mm_size = sizeof(*mmap) - sizeof(mmap->mm_size); + mmap++; + } + + mbi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP; +} +#endif /* PASS_MEMMAP && __minix */ + int exec_multiboot(const char *file, char *args) { @@ -718,6 +761,14 @@ exec_multiboot(const char *file, char *args) } } +#if defined(PASS_MEMMAP) && defined(__minix) + /* + * The MINIX3 kernel needs a full memory map. Without it, it will do + * silly things such as overwriting the ACPI tables. + */ + memmap_init(mbi); +#endif /* PASS_MEMMAP && __minix */ + #ifdef DEBUG printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); -- 2.44.0