grub-devel
[Top][All Lists]
Advanced

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

[PATCH] Put multiboot module after the kernel


From: phcoder
Subject: [PATCH] Put multiboot module after the kernel
Date: Mon, 09 Mar 2009 23:24:54 +0100
User-agent: Thunderbird 2.0.0.19 (X11/20090105)

Hello. Here is the patch to load the modules in the space after the kernel. This patch isn't meant to be commited right now because it breaks loading huge modules (and solaris relies on it). For clean solution I'm waiting for Vesa Jääskeläinen's new memory allocator Second reason is that command line for kernel, bootloader version, mbi and so on should also be allocated the same way as the memory for modules. I will do everything this once new memory allocator is available
--

Regards
Vladimir 'phcoder' Serbinenko
Index: loader/i386/multiboot.c
===================================================================
--- loader/i386/multiboot.c     (revision 2023)
+++ loader/i386/multiboot.c     (working copy)
@@ -42,16 +42,60 @@
 #include <grub/misc.h>
 #include <grub/gzio.h>
 #include <grub/env.h>
 #include <grub/cpu/loader.h>
 #include <grub/cpu/multiboot.h>
 
+static grub_err_t
+grub_multiboot_unload (void);
+
+static inline void *
+grub_multiboot_relocated (void *orig)
+{
+  return (((char *) orig) - grub_multiboot_payload_orig
+         + grub_multiboot_payload_dest);
+}
+
 extern grub_dl_t my_mod;
 static struct grub_multiboot_info *mbi, *mbi_dest;
-static grub_addr_t entry;
+struct grub_mod_list *modlist = 0;
 
 static char *playground = NULL;
 
+/* Allocate space from multiboot_payload aligned at ALIGN*/
+static char *
+grub_multiboot_memalign (grub_size_t align, grub_size_t size)
+{
+  grub_size_t align_overhead;
+  grub_off_t mbioff = (char *)mbi - playground;
+  char *ret;
+  align_overhead = align - (grub_multiboot_payload_dest 
+                           + grub_multiboot_payload_size) % align;
+  if (align_overhead == align)
+    align_overhead = 0;
+
+  playground = grub_realloc (playground, RELOCATOR_SIZEOF (forward) 
+                            + grub_multiboot_payload_size + align_overhead
+                            + size);
+  if (!playground)
+    {
+      grub_multiboot_unload ();
+      return 0;
+    }
+
+  grub_multiboot_payload_orig 
+    = (grub_uint32_t) (playground + RELOCATOR_SIZEOF (forward));
+  mbi = (struct grub_multiboot_info *) (playground + mbioff);
+  ret = playground + RELOCATOR_SIZEOF (forward) 
+    + grub_multiboot_payload_size + align_overhead;
+  grub_multiboot_payload_size += align_overhead + size;
+  return ret;
+}
+
 static grub_err_t
 grub_multiboot_boot (void)
 {
+  struct grub_mod_list *modlist2;
+  grub_addr_t entry;
+  char *back_dest;
+
   grub_stop_floppy ();

+  /* Dirty hack VSTa overwrites the page following last module so put module 
+     index further */
+  grub_multiboot_memalign (1, 1048576);
+
+  modlist2 = (struct grub_mod_list *) 
+    grub_multiboot_memalign (1, mbi->mods_count 
+                            * sizeof (struct grub_mod_list));
+  if (!modlist2)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, 
+                      "couldn't allocate space for module index");
+  grub_memcpy (modlist2, modlist, mbi->mods_count
+              * sizeof (struct grub_mod_list));
+  mbi->mods_addr = (grub_uint32_t) grub_multiboot_relocated (modlist2);
+
+  back_dest = grub_multiboot_memalign (1, RELOCATOR_SIZEOF(backward));
+
+  if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
+    {
+      grub_memmove (playground, &grub_multiboot_forward_relocator, 
+                   RELOCATOR_SIZEOF(forward));
+      entry = (grub_addr_t) playground;
+    }
+  else
+    {
+      grub_memmove (back_dest, &grub_multiboot_backward_relocator, 
+                   RELOCATOR_SIZEOF(backward));
+      grub_multiboot_payload_size -= RELOCATOR_SIZEOF(backward);
+      entry = (grub_addr_t) grub_multiboot_payload_orig 
+       + grub_multiboot_payload_size;
+    } 
+
   grub_multiboot_real_boot (entry, mbi_dest);
 
   /* Not reached.  */
@@ -61,21 +140,11 @@ grub_multiboot_boot (void)
 static grub_err_t
 grub_multiboot_unload (void)
 {
-  if (mbi)
-    {
-      unsigned int i;
-      for (i = 0; i < mbi->mods_count; i++)
-       {
-         grub_free ((void *)
-                    ((struct grub_mod_list *) mbi->mods_addr)[i].mod_start);
-         grub_free ((void *)
-                    ((struct grub_mod_list *) mbi->mods_addr)[i].cmdline);
-       }
-      grub_free ((void *) mbi->mods_addr);
-      grub_free ((void *) mbi->cmdline);
-      grub_free (mbi);
-    }
-  
+  grub_free (playground);
+  grub_free (modlist);
+
+  playground = 0;
+  modlist = 0;
   mbi = 0;
   grub_dl_unref (my_mod);
 
@@ -283,7 +352,9 @@ grub_multiboot (int argc, char *argv[])
        grub_multiboot_payload_size += load_size;
       grub_multiboot_payload_dest = header->load_addr;
 
-      playground = grub_malloc (RELOCATOR_SIZEOF(forward) + 
grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
+      playground = grub_malloc (RELOCATOR_SIZEOF(forward) 
+                               + grub_multiboot_payload_size 
+                               + RELOCATOR_SIZEOF(backward));
       if (! playground)
        goto fail;
 
@@ -318,19 +389,7 @@ grub_multiboot (int argc, char *argv[])
   mbi->mmap_addr = mmap_addr (grub_multiboot_payload_dest);
   mbi->flags |= MULTIBOOT_INFO_MEM_MAP;
 
-  if (grub_multiboot_payload_dest >= grub_multiboot_payload_orig)
-    {
-      grub_memmove (playground, &grub_multiboot_forward_relocator, 
RELOCATOR_SIZEOF(forward));
-      entry = (grub_addr_t) playground;
-    }
-  else
-    {
-      grub_memmove ((char *) (grub_multiboot_payload_orig + 
grub_multiboot_payload_size),
-                   &grub_multiboot_backward_relocator, 
RELOCATOR_SIZEOF(backward));
-      entry = (grub_addr_t) grub_multiboot_payload_orig + 
grub_multiboot_payload_size;
-    }
-  
-  grub_dprintf ("multiboot_loader", "dest=%p, size=0x%x, entry_offset=0x%x\n",
+  grub_dprintf ("multiboot_loader", "mbi_dest=%p, dest=%p, size=0x%x, 
entry_offset=0x%x\n", mbi_dest,
                (void *) grub_multiboot_payload_dest,
                grub_multiboot_payload_size,
                grub_multiboot_payload_entry_offset);
@@ -385,6 +444,7 @@ grub_module  (int argc, char *argv[])
   grub_file_t file = 0;
   grub_ssize_t size, len = 0;
   char *module = 0, *cmdline = 0, *p;
+  grub_uint32_t moduledest, cmdlinedest;
   int i;
 
   if (argc == 0)
@@ -400,27 +460,13 @@ grub_module  (int argc, char *argv[])
       goto fail;
     }
 
-  file = grub_gzfile_open (argv[0], 1);
-  if (! file)
-    goto fail;
-
-  size = grub_file_size (file);
-  module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
-  if (! module)
-    goto fail;
-
-  if (grub_file_read (file, module, size) != size)
-    {
-      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
-      goto fail;
-    }
-
   for (i = 0; i < argc; i++)
     len += grub_strlen (argv[i]) + 1;
 
-  cmdline = p = grub_malloc (len);
+  cmdline = p = grub_multiboot_memalign (1, len);
   if (! cmdline)
     goto fail;
+  cmdlinedest = (grub_uint32_t) grub_multiboot_relocated (cmdline);
 
   for (i = 0; i < argc; i++)
     {
@@ -431,33 +477,46 @@ grub_module  (int argc, char *argv[])
   /* Remove the space after the last word.  */
   *(--p) = '\0';
 
+  file = grub_gzfile_open (argv[0], 1);
+  if (! file)
+    goto fail;
+
+  /* Specification doesn't require modules to be page-aligned however grub1 
+     does it and we want maximal compatibility */
+  size = grub_file_size (file);
+  module = grub_multiboot_memalign (MULTIBOOT_MOD_ALIGN, size);
+  if (! module)
+    goto fail;
+  moduledest = (grub_uint32_t) grub_multiboot_relocated (module);
+
+  if (grub_file_read (file, module, size) != size)
+    {
+      grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file");
+      goto fail;
+    }
+
   if (mbi->flags & MULTIBOOT_INFO_MODS)
     {
-      struct grub_mod_list *modlist = (struct grub_mod_list *) mbi->mods_addr;
-
       modlist = grub_realloc (modlist, (mbi->mods_count + 1)
                                       * sizeof (struct grub_mod_list));
       if (! modlist)
        goto fail;
-      mbi->mods_addr = (grub_uint32_t) modlist;
-      modlist += mbi->mods_count;
-      modlist->mod_start = (grub_uint32_t) module;
-      modlist->mod_end = (grub_uint32_t) module + size;
-      modlist->cmdline = (grub_uint32_t) cmdline;
-      modlist->pad = 0;
+      modlist[mbi->mods_count].mod_start = moduledest;
+      modlist[mbi->mods_count].mod_end = moduledest + size;
+      modlist[mbi->mods_count].cmdline = cmdlinedest;
+      modlist[mbi->mods_count].pad = 0;
       mbi->mods_count++;
     }
   else
     {
-      struct grub_mod_list *modlist = grub_malloc (sizeof (struct 
grub_mod_list));
+      modlist = grub_malloc (sizeof (struct grub_mod_list));
       if (! modlist)
        goto fail;
-      modlist->mod_start = (grub_uint32_t) module;
-      modlist->mod_end = (grub_uint32_t) module + size;
-      modlist->cmdline = (grub_uint32_t) cmdline;
+      modlist->mod_start = moduledest;
+      modlist->mod_end = moduledest + size;
+      modlist->cmdline = cmdlinedest;
       modlist->pad = 0;
       mbi->mods_count = 1;
-      mbi->mods_addr = (grub_uint32_t) modlist;
       mbi->flags |= MULTIBOOT_INFO_MODS;
     }
 
@@ -465,9 +524,4 @@ grub_module  (int argc, char *argv[])
   if (file)
     grub_file_close (file);
 
-  if (grub_errno != GRUB_ERR_NONE)
-    {
-      grub_free (module);
-      grub_free (cmdline);
-    }
 }
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 2023)
+++ ChangeLog   (working copy)
@@ -1,3 +1,14 @@
+2009-03-10  Vladimir Serbinenko  <address@hidden>
+
+       Put multiboot modules directly after the kernel
+
+       * loader/i386/multiboot.c (grub_multiboot_relocated): new function
+       (grub_multiboot_memalign): likewise
+       (grub_multiboot_boot): finalise multiboot index and copy relocator
+       (grub_multiboot_unload): don't free pointers in playground 
+       (grub_multiboot): defer copying relocator
+       (grub_module): use new allocator functions
+
 2009-03-09  Felix Zielcke  <address@hidden>
 
        * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove duplicated

reply via email to

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