commit-grub
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[1919] * loader/i386/linux.c (grub_rescue_cmd_initrd): Implement


From: Robert Millan
Subject: [1919] * loader/i386/linux.c (grub_rescue_cmd_initrd): Implement a few needed
Date: Wed, 19 Nov 2008 12:11:45 +0000

Revision: 1919
          http://svn.sv.gnu.org/viewvc/?view=rev&root=grub&revision=1919
Author:   robertmh
Date:     2008-11-19 12:11:44 +0000 (Wed, 19 Nov 2008)

Log Message:
-----------
        * 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.

Modified Paths:
--------------
    trunk/grub2/ChangeLog
    trunk/grub2/loader/i386/linux.c

Modified: trunk/grub2/ChangeLog
===================================================================
--- trunk/grub2/ChangeLog       2008-11-19 12:05:20 UTC (rev 1918)
+++ trunk/grub2/ChangeLog       2008-11-19 12:11:44 UTC (rev 1919)
@@ -1,6 +1,10 @@
 2008-11-19  Robert Millan  <address@hidden>
 
        * 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  <address@hidden>
 

Modified: trunk/grub2/loader/i386/linux.c
===================================================================
--- trunk/grub2/loader/i386/linux.c     2008-11-19 12:05:20 UTC (rev 1918)
+++ trunk/grub2/loader/i386/linux.c     2008-11-19 12:11:44 UTC (rev 1919)
@@ -529,8 +529,21 @@
   initrd_pages = (page_align (size) >> 12);
 
   lh = (struct linux_kernel_header *) real_mode_mem;
+
+  /* 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;
   
-  addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
   if (linux_mem_size != 0 && linux_mem_size < addr_max)
     addr_max = linux_mem_size;
   
@@ -544,18 +557,19 @@
   addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
              + page_align (size);
   
-  /* FIXME: This doesn't take addr_max & addr_min into account.  */
-  addr = (grub_addr_t) grub_malloc (page_align (size));
+  if (addr_max > grub_os_area_addr + grub_os_area_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;
     }
   
   initrd_mem = (void *) addr;
-  if (! initrd_mem)
-    grub_fatal ("cannot allocate pages");
   
   if (grub_file_read (file, initrd_mem, size) != size)
     {






reply via email to

[Prev in Thread] Current Thread [Next in Thread]