summaryrefslogtreecommitdiff
path: root/i386/i386at
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2009-10-20 17:51:07 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2009-10-20 17:54:20 +0100
commit4c06eab356ff4a0e528bf27e09dfbe9a9b4b9556 (patch)
treeeee3c8915e2305d5a07c04c2f0aff3d2202d363a /i386/i386at
parent2f58373a59815b46a19355f18227f2304bd651ef (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.
Diffstat (limited to 'i386/i386at')
-rw-r--r--i386/i386at/model_dep.c41
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.