[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] Put multiboot module after the kernel,
phcoder <=