Preparation for mbh tag
This commit is contained in:
parent
8eb567e662
commit
b1f6f35ae9
8 changed files with 318 additions and 305 deletions
|
@ -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)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
Reference in a new issue