diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2009-10-20 17:51:07 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2009-10-20 17:54:20 +0100 |
commit | 4c06eab356ff4a0e528bf27e09dfbe9a9b4b9556 (patch) | |
tree | eee3c8915e2305d5a07c04c2f0aff3d2202d363a | |
parent | 2f58373a59815b46a19355f18227f2304bd651ef (diff) |
Fix boot from grub2 with more than 800MiB memory
* i386/i386at/model_dep.c (init_alloc_aligned): Add declaration.
(i386at_init): Use init_alloc_aligned to allocate memory to save the
content pointed by boot_info: cmdline, mods_addr, mod_start, and string.
Set kernel_cmdline to the newly allocated string.
(c_boot_entry): Do not set kernel_cmdline.
-rw-r--r-- | i386/i386at/model_dep.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c index 975f60a..3929293 100644 --- a/i386/i386at/model_dep.c +++ b/i386/i386at/model_dep.c @@ -117,6 +117,8 @@ vm_offset_t int_stack_top, int_stack_high; extern void linux_init(void); #endif +boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp); + /* * Find devices. The system is alive. */ @@ -267,6 +269,41 @@ i386at_init(void) */ mem_size_init(); + /* Copy content pointed by boot_info before losing access to it when it + * is too far in physical memory. */ + if (boot_info.flags & MULTIBOOT_CMDLINE) { + vm_offset_t addr; + int len = strlen ((char*)phystokv(boot_info.cmdline)) + 1; + assert(init_alloc_aligned(round_page(len), &addr)); + kernel_cmdline = (char*) addr; + memcpy(kernel_cmdline, (char*)phystokv(boot_info.cmdline), len); + boot_info.cmdline = (vm_offset_t) kernel_cmdline; + } + + if (boot_info.flags & MULTIBOOT_MODS) { + struct multiboot_module *m; + vm_offset_t addr; + int i; + + assert(init_alloc_aligned(round_page(boot_info.mods_count * sizeof(*m)), &addr)); + m = (void*) addr; + memcpy(m, (void*) phystokv(boot_info.mods_addr), boot_info.mods_count * sizeof(*m)); + boot_info.mods_addr = (vm_offset_t) m; + + for (i = 0; i < boot_info.mods_count; i++) { + vm_size_t size = m[i].mod_end - m[i].mod_start; + assert(init_alloc_aligned(round_page(size), &addr)); + memcpy((void*) addr, (void*) phystokv(m[i].mod_start), size); + m[i].mod_start = addr; + m[i].mod_end = addr + size; + + size = strlen((char*) phystokv(m[i].string)) + 1; + assert(init_alloc_aligned(round_page(size), &addr)); + memcpy((void*) addr, (void*) phystokv(m[i].string), size); + m[i].string = addr; + } + } + /* * Initialize kernel physical map, mapping the * region from loadpt to avail_start. @@ -349,10 +386,6 @@ void c_boot_entry(vm_offset_t bi) printf(version); printf("\n"); - /* Find the kernel command line, if there is one. */ - if (boot_info.flags & MULTIBOOT_CMDLINE) - kernel_cmdline = (char*)phystokv(boot_info.cmdline); - #if MACH_KDB /* * Locate the kernel's symbol table, if the boot loader provided it. |