* loader/i386/linux.c (grub_rescue_cmd_initrd): Implement a few needed

constraints to initrd allocation (based on code from
        loader/i386/pc/linux.c).  Without them, initrd was allocated too high
        for Linux to find it.
This commit is contained in:
robertmh 2008-11-19 12:11:44 +00:00
parent ebaaf49b02
commit 9290711060
2 changed files with 25 additions and 7 deletions

View file

@ -1,6 +1,10 @@
2008-11-19 Robert Millan <rmh@aybabtu.com> 2008-11-19 Robert Millan <rmh@aybabtu.com>
* loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Fix a typo. * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Fix a typo.
* loader/i386/linux.c (grub_rescue_cmd_initrd): Implement a few needed
constraints to initrd allocation (based on code from
loader/i386/pc/linux.c). Without them, initrd was allocated too high
for Linux to find it.
2008-11-14 Robert Millan <rmh@aybabtu.com> 2008-11-14 Robert Millan <rmh@aybabtu.com>

View file

@ -530,7 +530,20 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
lh = (struct linux_kernel_header *) real_mode_mem; lh = (struct linux_kernel_header *) real_mode_mem;
addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10); /* Get the highest address available for the initrd. */
if (grub_le_to_cpu16 (lh->version) >= 0x0203)
{
addr_max = grub_cpu_to_le32 (lh->initrd_addr_max);
/* XXX in reality, Linux specifies a bogus value, so
it is necessary to make sure that ADDR_MAX does not exceed
0x3fffffff. */
if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
}
else
addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
if (linux_mem_size != 0 && linux_mem_size < addr_max) if (linux_mem_size != 0 && linux_mem_size < addr_max)
addr_max = linux_mem_size; addr_max = linux_mem_size;
@ -544,18 +557,19 @@ grub_rescue_cmd_initrd (int argc, char *argv[])
addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12) addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
+ page_align (size); + page_align (size);
/* FIXME: This doesn't take addr_max & addr_min into account. */ if (addr_max > grub_os_area_addr + grub_os_area_size)
addr = (grub_addr_t) grub_malloc (page_align (size)); addr_max = grub_os_area_addr + grub_os_area_size;
if (addr == 0) /* Put the initrd as high as possible, 4KiB aligned. */
addr = (addr_max - size) & ~0xFFF;
if (addr < addr_min)
{ {
grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available"); grub_error (GRUB_ERR_OUT_OF_RANGE, "The initrd is too big");
goto fail; goto fail;
} }
initrd_mem = (void *) addr; initrd_mem = (void *) addr;
if (! initrd_mem)
grub_fatal ("cannot allocate pages");
if (grub_file_read (file, initrd_mem, size) != size) if (grub_file_read (file, initrd_mem, size) != size)
{ {