Preparation for mbh tag

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-03-08 15:40:57 +01:00
parent 8eb567e662
commit b1f6f35ae9
8 changed files with 318 additions and 305 deletions

View file

@ -34,16 +34,14 @@ setpci_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += multiboot.mod pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \ multiboot_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \ loader/i386/multiboot_mbi.c
loader/multiboot_loader.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS) multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
pkglib_MODULES += multiboot2.mod pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \ multiboot2_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi2.c \ loader/i386/multiboot_mbi2.c
loader/multiboot_loader.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)

View file

@ -20,6 +20,8 @@
#ifndef GRUB_MULTIBOOT_HEADER #ifndef GRUB_MULTIBOOT_HEADER
#define GRUB_MULTIBOOT_HEADER 1 #define GRUB_MULTIBOOT_HEADER 1
#include <grub/file.h>
#ifdef GRUB_USE_MULTIBOOT2 #ifdef GRUB_USE_MULTIBOOT2
#include <multiboot2.h> #include <multiboot2.h>
/* Same thing as far as our loader is concerned. */ /* Same thing as far as our loader is concerned. */
@ -63,4 +65,18 @@ grub_multiboot_fill_vbe_info_real (struct grub_vbe_info_block *vbe_control_info,
#define GRUB_MACHINE_HAS_VGA_TEXT 0 #define GRUB_MACHINE_HAS_VGA_TEXT 0
#endif #endif
#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1
#define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER 2
grub_err_t
grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth);
grub_err_t
grub_multiboot_load (grub_file_t file);
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer);
extern grub_size_t grub_multiboot_pure_size;
extern grub_size_t grub_multiboot_alloc_mbi;
#endif /* ! GRUB_MULTIBOOT_HEADER */ #endif /* ! GRUB_MULTIBOOT_HEADER */

View file

@ -24,6 +24,7 @@
/* How many bytes from the start of the file we search for the header. */ /* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192 #define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */ /* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 #define MULTIBOOT_HEADER_MAGIC 0x1BADB002

View file

@ -23,7 +23,8 @@
#define MULTIBOOT_HEADER 1 #define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */ /* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192 #define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */ /* The magic field should contain this. */
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 #define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
@ -62,6 +63,17 @@
#define MULTIBOOT_TAG_TYPE_VBE 7 #define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 #define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
#define GRUB_MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#ifndef ASM_FILE #ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t; typedef unsigned char multiboot_uint8_t;
@ -74,21 +86,73 @@ struct multiboot_header
/* Must be MULTIBOOT_MAGIC - see above. */ /* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic; multiboot_uint32_t magic;
/* Feature flags. */ /* ISA */
multiboot_uint32_t flags; multiboot_uint32_t architecture;
/* Total header length. */
multiboot_uint32_t header_length;
/* The above fields plus this one must equal 0 mod 2^32. */ /* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum; multiboot_uint32_t checksum;
};
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ struct multiboot_header_tag
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
};
struct multiboot_header_tag_information_request
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t requests[0];
};
struct multiboot_header_tag_address
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t header_addr; multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr; multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr; multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr; multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr; };
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ struct multiboot_header_tag_entry_address
multiboot_uint32_t mode_type; {
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
struct multiboot_header_tag_module_align
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t flags;
multiboot_uint32_t width; multiboot_uint32_t width;
multiboot_uint32_t height; multiboot_uint32_t height;
multiboot_uint32_t depth; multiboot_uint32_t depth;

View file

@ -26,10 +26,8 @@
* - APM table * - APM table
*/ */
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/command.h>
#include <grub/machine/loader.h> #include <grub/machine/loader.h>
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/multiboot.h> #include <grub/cpu/multiboot.h>
@ -45,6 +43,7 @@
#include <grub/i386/relocator.h> #include <grub/i386/relocator.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/memory.h> #include <grub/memory.h>
#include <grub/i18n.h>
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
@ -56,14 +55,15 @@
#define DEFAULT_VIDEO_MODE "auto" #define DEFAULT_VIDEO_MODE "auto"
#endif #endif
extern grub_dl_t my_mod; grub_size_t grub_multiboot_alloc_mbi;
static grub_size_t code_size, alloc_mbi;
char *grub_multiboot_payload_orig; char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest; grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size; grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip; grub_uint32_t grub_multiboot_payload_eip;
static int accepts_video; static int accepts_video;
static grub_dl_t my_mod;
/* Return the length of the Multiboot mmap that will be needed to allocate /* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */ our platform's map. */
@ -178,14 +178,14 @@ grub_multiboot_boot (void)
}; };
mbi_size = grub_multiboot_get_mbi_size (); mbi_size = grub_multiboot_get_mbi_size ();
if (alloc_mbi < mbi_size) if (grub_multiboot_alloc_mbi < mbi_size)
{ {
grub_multiboot_payload_orig grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig, = grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size); grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
return grub_errno; return grub_errno;
alloc_mbi = mbi_size; grub_multiboot_alloc_mbi = mbi_size;
} }
state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size; state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size;
@ -215,7 +215,7 @@ grub_multiboot_unload (void)
grub_relocator32_free (grub_multiboot_payload_orig); grub_relocator32_free (grub_multiboot_payload_orig);
alloc_mbi = 0; grub_multiboot_alloc_mbi = 0;
grub_multiboot_payload_orig = NULL; grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -232,7 +232,7 @@ grub_multiboot_unload (void)
#undef MULTIBOOT_LOAD_ELF32 #undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */ /* Load ELF32 or ELF64. */
static grub_err_t grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer) grub_multiboot_load_elf (grub_file_t file, void *buffer)
{ {
if (grub_multiboot_is_elf32 (buffer)) if (grub_multiboot_is_elf32 (buffer))
@ -243,137 +243,61 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer)
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
} }
void grub_err_t
grub_multiboot (int argc, char *argv[]) grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth)
{
if (console_type == GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER)
{
char *buf;
if (depth && width && height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", width,
height, depth, width, height);
else if (width && height)
buf = grub_xasprintf ("%dx%d,auto", width, height);
else
buf = grub_strdup ("auto");
if (!buf)
return grub_errno;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
}
else
grub_env_set ("gfxpayload", "text");
accepts_video = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
char buffer[MULTIBOOT_SEARCH]; grub_err_t err;
struct multiboot_header *header;
grub_ssize_t len;
grub_loader_unset (); grub_loader_unset ();
if (argc == 0) if (argc == 0)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1); file = grub_gzfile_open (argv[0], 1);
if (! file) if (! file)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH); grub_dl_ref (my_mod);
if (len < 32)
{
grub_error (GRUB_ERR_BAD_OS, "file too small");
goto fail;
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
if (header == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
goto fail;
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
goto fail;
}
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
/* Skip filename. */ /* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1); grub_multiboot_init_mbi (argc - 1, argv + 1);
if (header->flags & MULTIBOOT_AOUT_KLUDGE) grub_relocator32_free (grub_multiboot_payload_orig);
{ grub_multiboot_payload_orig = NULL;
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
if (header->bss_end_addr) err = grub_multiboot_load (file);
code_size = (header->bss_end_addr - header->load_addr); if (err)
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (! grub_multiboot_payload_orig)
goto fail;
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
goto fail;
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
goto fail;
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail; goto fail;
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
grub_env_set ("gfxpayload", "text");
break;
case 0:
{
char *buf;
if (header->depth && header->width && header->height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
else if (header->width && header->height)
buf = grub_xasprintf ("%dx%d,auto", header->width, header->height);
else
buf = grub_strdup ("auto");
if (!buf)
goto fail;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
break;
}
}
}
accepts_video = !!(header->flags & MULTIBOOT_VIDEO_MODE);
grub_multiboot_set_bootdev (); grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0); grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
@ -385,12 +309,16 @@ grub_multiboot (int argc, char *argv[])
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
grub_relocator32_free (grub_multiboot_payload_orig); grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_free_mbi ();
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
} }
return grub_errno;
} }
void static grub_err_t
grub_module (int argc, char *argv[]) grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{ {
grub_file_t file = 0; grub_file_t file = 0;
grub_ssize_t size; grub_ssize_t size;
@ -398,40 +326,64 @@ grub_module (int argc, char *argv[])
grub_err_t err; grub_err_t err;
if (argc == 0) if (argc == 0)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
goto fail;
}
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
{ return grub_error (GRUB_ERR_BAD_ARGUMENT,
grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the multiboot kernel first");
"you need to load the multiboot kernel first");
goto fail;
}
file = grub_gzfile_open (argv[0], 1); file = grub_gzfile_open (argv[0], 1);
if (! file) if (! file)
goto fail; return grub_errno;
size = grub_file_size (file); size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size); module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module) if (! module)
goto fail; {
grub_file_close (file);
return grub_errno;
}
err = grub_multiboot_add_module ((grub_addr_t) module, size, err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1); argc - 1, argv + 1);
if (err) if (err)
goto fail; {
grub_file_close (file);
return err;
}
if (grub_file_read (file, module, size) != size) if (grub_file_read (file, module, size) != size)
{ {
grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); grub_file_close (file);
goto fail; return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
} }
fail: grub_file_close (file);
if (file) return GRUB_ERR_NONE;;
grub_file_close (file);
} }
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

View file

@ -53,6 +53,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
char *phdr_base; char *phdr_base;
int lowest_segment = -1, highest_segment = -1; int lowest_segment = -1, highest_segment = -1;
int i; int i;
grub_size_t code_size;
if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX) if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
@ -102,9 +103,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
grub_multiboot_pure_size += code_size; grub_multiboot_pure_size += code_size;
alloc_mbi = grub_multiboot_get_mbi_size (); grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi + 65536); = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (!grub_multiboot_payload_orig) if (!grub_multiboot_payload_orig)
return grub_errno; return grub_errno;

View file

@ -23,6 +23,7 @@
#endif #endif
#include <grub/multiboot.h> #include <grub/multiboot.h>
#include <grub/cpu/multiboot.h> #include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/device.h> #include <grub/device.h>
#include <grub/partition.h> #include <grub/partition.h>
@ -30,6 +31,10 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/file.h>
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
struct module struct module
{ {
@ -48,6 +53,132 @@ static char *cmdline = NULL;
static grub_uint32_t bootdev; static grub_uint32_t bootdev;
static int bootdev_set; static int bootdev_set;
grub_err_t
grub_multiboot_load (grub_file_t file)
{
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
}
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
grub_size_t code_size;
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
0, 0, 0);
break;
case 0:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
header->width, header->height,
header->depth);
break;
}
}
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
0, 0, 0);
return err;
}
grub_size_t grub_size_t
grub_multiboot_get_mbi_size (void) grub_multiboot_get_mbi_size (void)
{ {

View file

@ -1,150 +0,0 @@
/* multiboot_loader.c - boot multiboot kernel image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/multiboot.h>
#include <grub/elf.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/i18n.h>
grub_dl_t my_mod;
static int
find_multi_boot1_header (grub_file_t file)
{
struct multiboot_header *header;
char buffer[MULTIBOOT_SEARCH];
int found_status = 0;
grub_ssize_t len;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
return found_status;
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
{
found_status = 1;
break;
}
}
return found_status;
}
static grub_err_t
grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
int header_multi_ver_found = 0;
grub_dl_ref (my_mod);
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
/* find which header is in the file */
if (find_multi_boot1_header (file))
header_multi_ver_found = 1;
else
{
grub_error (GRUB_ERR_BAD_OS, "multiboot header not found");
goto fail;
}
/* close file before calling functions */
if (file)
grub_file_close (file);
/* Launch multi boot with header */
grub_dprintf ("multiboot_loader",
"Launching multiboot 1 grub_multiboot() function\n");
grub_multiboot (argc, argv);
return grub_errno;
fail:
if (file)
grub_file_close (file);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_dprintf("multiboot_loader",
"Launching multiboot 1 grub_module() function\n");
grub_module (argc, argv);
return grub_errno;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot_loader,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot_loader,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module_loader,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}