All of lore.kernel.org
 help / color / mirror / Atom feed
From: phcoder <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Put multiboot module after the kernel
Date: Mon, 09 Mar 2009 23:24:54 +0100	[thread overview]
Message-ID: <49B59736.5000708@gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 526 bytes --]

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

[-- Attachment #2: vsta.diff --]
[-- Type: text/x-patch, Size: 9121 bytes --]

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  <phcoder@gmail.com>
+
+	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  <fzielcke@z-51.de>
 
 	* conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove duplicated

                 reply	other threads:[~2009-03-09 22:25 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49B59736.5000708@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.