]> Zhao Yanbai Git Server - minix.git/commitdiff
bootloader: pass memory map to kernel 36/2936/1
authorDavid van Moolenbroek <david@minix3.org>
Mon, 22 Dec 2014 23:15:02 +0000 (23:15 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Tue, 10 Feb 2015 13:47:28 +0000 (13:47 +0000)
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

index 3c0b94c4bf049a99f6419b0923fb9ded126b870a..b555b87743abc39ecffdc5992fd55d6670bd4963 100644 (file)
@@ -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]);