diff --git a/ChangeLog b/ChangeLog index 6018e6cc8..89955178e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-11-14 Robert Millan + + * include/grub/i386/coreboot/memory.h (GRUB_MEMORY_MACHINE_LOWER_SIZE): + Redefine to match with GRUB_MEMORY_MACHINE_UPPER_START (0x100000). We + don't want to mess with lower memory, because it is used in the Linux + loader. + + * loader/i386/linux.c (allocate_pages): Allocate `real_mode_mem' in + an appropiate place in lower memory, between 0x10000 and 0x90000, + like loader/i386/efi/linux.c does. Linux often panics if real_mode_mem + is in our heap (probably as a result of it being corrupted during + decompression). + 2008-11-14 Robert Millan * term/i386/pc/serial.c [! GRUB_MACHINE_PCBIOS] diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index b1b015472..faac757bd 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -28,9 +28,9 @@ #endif #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ -#define GRUB_MEMORY_MACHINE_LOWER_SIZE 0xf0000 /* 960 kiB */ #define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ +#define GRUB_MEMORY_MACHINE_LOWER_SIZE GRUB_MEMORY_MACHINE_UPPER_START #ifndef ASM_FILE diff --git a/loader/i386/linux.c b/loader/i386/linux.c index 20aea990b..333b9d6e7 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -142,23 +142,40 @@ allocate_pages (grub_size_t prot_size) real_mode_mem = 0; prot_mode_mem = 0; - real_mode_mem = grub_malloc (real_mode_pages << 12); - + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + { + /* We must put real mode code in the traditional space. */ + + if (type == GRUB_MACHINE_MEMORY_AVAILABLE + && addr <= 0x90000) + { + if (addr < 0x10000) + { + size += addr - 0x10000; + addr = 0x10000; + } + + if (addr + size > 0x90000) + size = 0x90000 - addr; + + if (real_size + mmap_size > size) + return 0; + + real_mode_mem = (addr + size) - (real_size + mmap_size); + return 1; + } + + return 0; + } + grub_machine_mmap_iterate (hook); if (! real_mode_mem) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); goto fail; } - /* Next, find free pages for the protected mode code. */ - /* XXX what happens if anything is using this address? */ prot_mode_mem = (void *) 0x100000; - if (! prot_mode_mem) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "cannot allocate protected mode pages"); - goto fail; - } grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, " "prot_mode_mem = %lx, prot_mode_pages = %x\n",