]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Possibility to prefer higher or lower chunks in relocator
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 12 Jan 2010 21:14:26 +0000 (22:14 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Tue, 12 Jan 2010 21:14:26 +0000 (22:14 +0100)
include/grub/relocator.h
lib/i386/relocator.c
lib/relocator.c
loader/i386/bsd.c
loader/i386/linux.c
loader/i386/multiboot.c
loader/i386/multiboot_mbi.c
loader/xnu_resume.c

index 2ea74b77532e9cb121f59c291cd14dc6f13a149c..32bab705375444ec169a74c6a38770fed3869892 100644 (file)
@@ -34,7 +34,12 @@ grub_err_t
 grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src, 
                                  grub_addr_t *target,
                                  grub_addr_t min_addr, grub_addr_t max_addr,
-                                 grub_size_t size, grub_size_t align);
+                                 grub_size_t size, grub_size_t align,
+                                 int preference);
+
+#define GRUB_RELOCATOR_PREFERENCE_NONE 0
+#define GRUB_RELOCATOR_PREFERENCE_LOW 1
+#define GRUB_RELOCATOR_PREFERENCE_HIGH 2
 
 void
 grub_relocator_unload (struct grub_relocator *rel);
index e81dd8e1e6f7c5c155e5d7cdd607471f5b87528b..6e1e13b045f707424bce99a2217c042c4dbb61da 100644 (file)
@@ -129,7 +129,8 @@ grub_relocator32_boot (struct grub_relocator *rel,
 
   err = grub_relocator_alloc_chunk_align (rel, &src, &target, 0,
                                          (0xffffffff - RELOCATOR_SIZEOF (32))
-                                         + 1, RELOCATOR_SIZEOF (32), 16);
+                                         + 1, RELOCATOR_SIZEOF (32), 16,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     return err;
 
@@ -166,7 +167,8 @@ grub_relocator64_boot (struct grub_relocator *rel,
 
   err = grub_relocator_alloc_chunk_align (rel, &src, &target, min_addr,
                                          max_addr - RELOCATOR_SIZEOF (64),
-                                         RELOCATOR_SIZEOF (64), 16);
+                                         RELOCATOR_SIZEOF (64), 16,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     return err;
 
index 3085932c5e0c476ead8f09d58dd71a4d69695124..a5b3c6daf8de4ed8d5f9150aa07fe2cfbad6d0a6 100644 (file)
@@ -446,7 +446,8 @@ grub_err_t
 grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
                                  grub_addr_t *target,
                                  grub_addr_t min_addr, grub_addr_t max_addr,
-                                 grub_size_t size, grub_size_t align)
+                                 grub_size_t size, grub_size_t align,
+                                 int preference)
 {
   grub_addr_t min_addr2 = 0, max_addr2;
   struct grub_relocator_chunk *chunk;
@@ -455,6 +456,11 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
   if (max_addr > ~size)
     max_addr = ~size;
 
+#ifdef GRUB_MACHINE_PCBIOS
+  if (min_addr < 0x1000)
+    min_addr = 0x1000;
+#endif
+
   grub_dprintf ("relocator", "chunks = %p\n", rel->chunks);
 
   chunk = grub_malloc (sizeof (struct grub_relocator_chunk));
@@ -462,7 +468,8 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
     return grub_errno;
 
   if (malloc_in_range (rel, min_addr, max_addr, align,
-                      size, &start, 1, 1))
+                      size, &start,
+                      preference != GRUB_RELOCATOR_PREFERENCE_HIGH, 1))
     {
       grub_dprintf ("relocator", "allocated 0x%llx/0x%llx\n",
                    (unsigned long long) start, (unsigned long long) start);
@@ -500,7 +507,10 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
   while (0);
 
   /* FIXME: check memory map.  */
-  chunk->target = ALIGN_UP (min_addr, align);
+  if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH)
+    chunk->target = ALIGN_DOWN (max_addr, align);
+  else
+    chunk->target = ALIGN_UP (min_addr, align);    
   while (1)
     {
       struct grub_relocator_chunk *chunk2;
@@ -514,7 +524,10 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, void **src,
            || (chunk->target <= chunk2->target + chunk2->size
                && chunk2->target + chunk2->size < chunk->target + size))
          {
-           chunk->target = ALIGN_UP (chunk2->target + chunk2->size, align);
+           if (preference == GRUB_RELOCATOR_PREFERENCE_HIGH)
+             chunk->target = ALIGN_DOWN (chunk2->target, align);
+           else
+             chunk->target = ALIGN_UP (chunk2->target + chunk2->size, align);
            break;
          }
       if (!chunk2)
index 90cd8a9a4f3937e74a9808cade5c94cea83227bc..28bcde15ea5db1b7f93529b04905a7b65f0f69fd 100644 (file)
@@ -550,7 +550,8 @@ grub_freebsd_boot (void)
                                              &stack_target,
                                              0x10000, 0x90000,
                                              3 * sizeof (grub_uint32_t)
-                                             + sizeof (bi), 4);
+                                             + sizeof (bi), 4,
+                                             GRUB_RELOCATOR_PREFERENCE_NONE);
       if (err)
        return err;
 
@@ -575,7 +576,8 @@ grub_freebsd_boot (void)
                                              &stack_target,
                                              0x10000, 0x90000,
                                              9 * sizeof (grub_uint32_t)
-                                             + sizeof (bi), 4);
+                                             + sizeof (bi), 4,
+                                             GRUB_RELOCATOR_PREFERENCE_NONE);
       if (err)
        return err;
       grub_memcpy (&stack[8], &bi, sizeof (bi));
@@ -798,7 +800,8 @@ grub_netbsd_boot (void)
 
   err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack,
                                          &stack_target, 0x10000, 0x90000,
-                                         7 * sizeof (grub_uint32_t), 4);
+                                         7 * sizeof (grub_uint32_t), 4,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     return err;
 
index e8d06b0e7866d116758031c41235189d5fe8755a..b6298d0bb43285bcfd9c50ed370de496c3fd695a 100644 (file)
@@ -943,9 +943,6 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
   addr_min = (grub_addr_t) prot_mode_target + ((prot_mode_pages * 3) << 12)
              + page_align (size);
 
-  if (addr_max > grub_os_area_addr + grub_os_area_size)
-    addr_max = grub_os_area_addr + grub_os_area_size;
-
   /* Put the initrd as high as possible, 4KiB aligned.  */
   addr = (addr_max - size) & ~0xFFF;
 
@@ -957,7 +954,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 
   err = grub_relocator_alloc_chunk_align (relocator, &initrd_mem,
                                          &initrd_mem_target,
-                                         addr_min, addr, size, 0x1000);
+                                         addr_min, addr, size, 0x1000,
+                                         GRUB_RELOCATOR_PREFERENCE_HIGH);
   if (err)
     return err;
 
index c5a7f7f9dfbe0d0eb0507eed4ffafb534b2b7c3e..2f9cc73c9692b8d18f28bf271d9d8da645f2376d 100644 (file)
@@ -259,7 +259,8 @@ grub_module  (int argc, char *argv[])
   err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &module, 
                                          &target,
                                          0, (0xffffffff - size) + 1,
-                                         size, MULTIBOOT_MOD_ALIGN);
+                                         size, MULTIBOOT_MOD_ALIGN,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     goto fail;
 
index ddaca7a1baf2eed4b02b6f8f193bf694283b4694..4fc9a7ac1f98bf871a16b0f51500bd56260594f8 100644 (file)
@@ -125,7 +125,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
   err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, 
                                          (void **) &ptrorig, &ptrdest,
                                          0, 0xffffffff - bufsize,
-                                         bufsize, 4);
+                                         bufsize, 4,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     return err;
 
index a7d5fbad87352311ece40373db6ada288a7f8d59..2d47df601c3d829322ee2e12e63771210e3a04e2 100644 (file)
@@ -115,7 +115,8 @@ grub_xnu_resume (char *imagename)
                                          &target_image, 0,
                                          (0xffffffff - hibhead.image_size) + 1,
                                          hibhead.image_size,
-                                         GRUB_XNU_PAGESIZE);
+                                         GRUB_XNU_PAGESIZE,
+                                         GRUB_RELOCATOR_PREFERENCE_NONE);
   if (err)
     {
       grub_file_close (file);