Split relocators from mips branch

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-11-25 23:39:59 +01:00
parent 6717926e6e
commit 636813f768
19 changed files with 1356 additions and 216 deletions

View file

@ -48,18 +48,35 @@
#include <grub/device.h>
#include <grub/partition.h>
#endif
#include <grub/i386/relocator.h>
extern grub_dl_t my_mod;
static struct multiboot_info *mbi, *mbi_dest;
static grub_addr_t entry;
static char *playground = 0;
static grub_size_t code_size;
char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_payload_size;
grub_uint32_t grub_multiboot_payload_eip;
grub_uint32_t grub_multiboot_payload_esp;
static grub_err_t
grub_multiboot_boot (void)
{
grub_multiboot_real_boot (entry, mbi_dest);
struct grub_relocator32_state state =
{
.eax = MULTIBOOT_MAGIC2,
.ebx = PTR_TO_UINT32 (mbi_dest),
.ecx = 0,
.edx = 0,
.eip = grub_multiboot_payload_eip,
.esp = grub_multiboot_payload_esp
};
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
/* Not reached. */
return GRUB_ERR_NONE;
@ -68,7 +85,7 @@ grub_multiboot_boot (void)
static grub_err_t
grub_multiboot_unload (void)
{
if (playground)
if (mbi)
{
unsigned int i;
for (i = 0; i < mbi->mods_count; i++)
@ -79,11 +96,11 @@ grub_multiboot_unload (void)
((struct multiboot_mod_list *) mbi->mods_addr)[i].cmdline);
}
grub_free ((void *) mbi->mods_addr);
grub_free (playground);
}
grub_relocator32_free (grub_multiboot_payload_orig);
mbi = NULL;
playground = NULL;
grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
@ -250,11 +267,8 @@ grub_multiboot (int argc, char *argv[])
goto fail;
}
if (playground)
{
grub_free (playground);
playground = NULL;
}
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
mmap_length = grub_get_multiboot_mmap_len ();
@ -276,11 +290,13 @@ grub_multiboot (int argc, char *argv[])
((void *) ((x) + code_size + cmdline_length))
#define mbi_addr(x) ((void *) ((x) + code_size + cmdline_length + boot_loader_name_length))
#define mmap_addr(x) ((void *) ((x) + code_size + cmdline_length + boot_loader_name_length + sizeof (struct multiboot_info)))
#define stack_addr(x) ((void *) ((x) + code_size + cmdline_length + boot_loader_name_length + sizeof (struct multiboot_info) + mmap_length + GRUB_MULTIBOOT_STACK_SIZE))
grub_multiboot_payload_size = cmdline_length
/* boot_loader_name_length might need to grow for mbi,etc to be aligned (see below) */
+ boot_loader_name_length + 3
+ sizeof (struct multiboot_info) + mmap_length;
+ sizeof (struct multiboot_info) + mmap_length
+ GRUB_MULTIBOOT_STACK_SIZE;
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
@ -296,11 +312,12 @@ grub_multiboot (int argc, char *argv[])
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_payload_size += code_size;
playground = grub_malloc (RELOCATOR_SIZEOF(forward) + grub_multiboot_payload_size + RELOCATOR_SIZEOF(backward));
if (! playground)
goto fail;
grub_multiboot_payload_orig = (long) playground + RELOCATOR_SIZEOF(forward);
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_payload_size);
if (! grub_multiboot_payload_orig)
goto fail;
if ((grub_file_seek (file, offset)) == (grub_off_t) - 1)
goto fail;
@ -313,7 +330,7 @@ grub_multiboot (int argc, char *argv[])
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_entry_offset = header->entry_addr - header->load_addr;
grub_multiboot_payload_eip = header->entry_addr;
}
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
@ -334,23 +351,6 @@ grub_multiboot (int argc, char *argv[])
mbi->mmap_addr = (grub_uint32_t) 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",
(void *) grub_multiboot_payload_dest,
grub_multiboot_payload_size,
grub_multiboot_payload_entry_offset);
/* Convert from bytes to kilobytes. */
mbi->mem_lower = grub_mmap_get_lower () / 1024;
mbi->mem_upper = grub_mmap_get_upper () / 1024;
@ -382,6 +382,8 @@ grub_multiboot (int argc, char *argv[])
if (grub_multiboot_get_bootdev (&mbi->boot_device))
mbi->flags |= MULTIBOOT_INFO_BOOTDEV;
grub_multiboot_payload_esp = PTR_TO_UINT32 (stack_addr (grub_multiboot_payload_dest));
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1);
fail: