* grub-core/loader/multiboot.c: Add support for multiboot kernels
quirks.
This commit is contained in:
parent
81afc5cce6
commit
00bfa988fc
6 changed files with 137 additions and 54 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/loader/multiboot.c: Add support for multiboot kernels
|
||||||
|
quirks.
|
||||||
|
|
||||||
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
2013-10-28 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/loader/i386/linux.c (allocate_pages): Allocate at least
|
* grub-core/loader/i386/linux.c (allocate_pages): Allocate at least
|
||||||
|
|
|
@ -3680,6 +3680,8 @@ you forget a command, you can run the command @command{help}
|
||||||
* lsfonts:: List loaded fonts
|
* lsfonts:: List loaded fonts
|
||||||
* lsmod:: Show loaded modules
|
* lsmod:: Show loaded modules
|
||||||
* md5sum:: Compute or check MD5 hash
|
* md5sum:: Compute or check MD5 hash
|
||||||
|
* module:: Load module for multiboot kernel
|
||||||
|
* multiboot:: Load multiboot compliant kernel
|
||||||
* nativedisk:: Switch to native disk drivers
|
* nativedisk:: Switch to native disk drivers
|
||||||
* normal:: Enter normal mode
|
* normal:: Enter normal mode
|
||||||
* normal_exit:: Exit from normal mode
|
* normal_exit:: Exit from normal mode
|
||||||
|
@ -4369,7 +4371,6 @@ List loaded fonts.
|
||||||
Show list of loaded modules.
|
Show list of loaded modules.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@node md5sum
|
@node md5sum
|
||||||
@subsection md5sum
|
@subsection md5sum
|
||||||
|
|
||||||
|
@ -4378,6 +4379,34 @@ Alias for @code{hashsum --hash md5 arg @dots{}}. See command @command{hashsum}
|
||||||
(@pxref{hashsum}) for full description.
|
(@pxref{hashsum}) for full description.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@node module
|
||||||
|
@subsection module
|
||||||
|
|
||||||
|
@deffn Command module [--nounzip] file [arguments]
|
||||||
|
Load a module for multiboot kernel image. The rest of the
|
||||||
|
line is passed verbatim as the module command line.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@node multiboot
|
||||||
|
@subsection multiboot
|
||||||
|
|
||||||
|
@deffn Command multiboot [--quirk-bad-kludge] [--quirk-modules-after-kernel] file @dots{}
|
||||||
|
Load a multiboot kernel image from @var{file}. The rest of the
|
||||||
|
line is passed verbatim as the @dfn{kernel command-line}. Any module must
|
||||||
|
be reloaded after using this command (@pxref{module}).
|
||||||
|
|
||||||
|
Some kernels have known problems. You need to specify --quirk-* for those.
|
||||||
|
--quirk-bad-kludge is a problem seen in several products that they include
|
||||||
|
loading kludge information with invalid data in ELF file. GRUB prior to 0.97
|
||||||
|
and some custom builds prefered ELF information while 0.97 and GRUB 2
|
||||||
|
use kludge. Use this option to ignore kludge.
|
||||||
|
Known affected systems: old Solaris, SkyOS.
|
||||||
|
|
||||||
|
--quirk-modules-after-kernel is needed for kernels which load at relatively
|
||||||
|
high address e.g. 16MiB mark and can't cope with modules stuffed between
|
||||||
|
1MiB mark and beginning of the kernel.
|
||||||
|
Known afftected systems: VMWare.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
@node nativedisk
|
@node nativedisk
|
||||||
@subsection nativedisk
|
@subsection nativedisk
|
||||||
|
|
|
@ -58,7 +58,63 @@ static int bootdev_set;
|
||||||
static grub_size_t elf_sec_num, elf_sec_entsize;
|
static grub_size_t elf_sec_num, elf_sec_entsize;
|
||||||
static unsigned elf_sec_shstrndx;
|
static unsigned elf_sec_shstrndx;
|
||||||
static void *elf_sections;
|
static void *elf_sections;
|
||||||
|
grub_multiboot_quirks_t grub_multiboot_quirks;
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
load_kernel (grub_file_t file, const char *filename,
|
||||||
|
char *buffer, struct multiboot_header *header)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
|
||||||
|
{
|
||||||
|
err = grub_multiboot_load_elf (file, filename, buffer);
|
||||||
|
if (err == GRUB_ERR_UNKNOWN_OS && (header->flags & MULTIBOOT_AOUT_KLUDGE))
|
||||||
|
grub_errno = err = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
void *source;
|
||||||
|
grub_relocator_chunk_t ch;
|
||||||
|
|
||||||
|
if (header->bss_end_addr)
|
||||||
|
code_size = (header->bss_end_addr - header->load_addr);
|
||||||
|
else
|
||||||
|
code_size = load_size;
|
||||||
|
|
||||||
|
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
|
||||||
|
&ch, header->load_addr,
|
||||||
|
code_size);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
source = get_virtual_current_address (ch);
|
||||||
|
|
||||||
|
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
|
||||||
|
{
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_file_read (file, source, load_size);
|
||||||
|
if (grub_errno)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
if (header->bss_end_addr)
|
||||||
|
grub_memset ((grub_uint8_t *) source + load_size, 0,
|
||||||
|
header->bss_end_addr - header->load_addr - load_size);
|
||||||
|
|
||||||
|
grub_multiboot_payload_eip = header->entry_addr;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_multiboot_load_elf (file, filename, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_multiboot_load (grub_file_t file, const char *filename)
|
grub_multiboot_load (grub_file_t file, const char *filename)
|
||||||
|
@ -106,59 +162,11 @@ grub_multiboot_load (grub_file_t file, const char *filename)
|
||||||
"unsupported flag: 0x%x", header->flags);
|
"unsupported flag: 0x%x", header->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
|
err = load_kernel (file, filename, buffer, header);
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
int offset = ((char *) header - buffer -
|
grub_free (buffer);
|
||||||
(header->header_addr - header->load_addr));
|
return err;
|
||||||
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
|
|
||||||
header->load_end_addr - header->load_addr);
|
|
||||||
grub_size_t code_size;
|
|
||||||
void *source;
|
|
||||||
grub_relocator_chunk_t ch;
|
|
||||||
|
|
||||||
if (header->bss_end_addr)
|
|
||||||
code_size = (header->bss_end_addr - header->load_addr);
|
|
||||||
else
|
|
||||||
code_size = load_size;
|
|
||||||
|
|
||||||
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
|
|
||||||
&ch, header->load_addr,
|
|
||||||
code_size);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
|
|
||||||
grub_free (buffer);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
source = get_virtual_current_address (ch);
|
|
||||||
|
|
||||||
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
|
|
||||||
{
|
|
||||||
grub_free (buffer);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_file_read (file, source, load_size);
|
|
||||||
if (grub_errno)
|
|
||||||
{
|
|
||||||
grub_free (buffer);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header->bss_end_addr)
|
|
||||||
grub_memset ((grub_uint8_t *) source + 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, filename, buffer);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_free (buffer);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->flags & MULTIBOOT_VIDEO_MODE)
|
if (header->flags & MULTIBOOT_VIDEO_MODE)
|
||||||
|
|
|
@ -160,6 +160,8 @@ grub_multiboot_unload (void)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_uint64_t highest_load;
|
||||||
|
|
||||||
#define MULTIBOOT_LOAD_ELF64
|
#define MULTIBOOT_LOAD_ELF64
|
||||||
#include "multiboot_elfxx.c"
|
#include "multiboot_elfxx.c"
|
||||||
#undef MULTIBOOT_LOAD_ELF64
|
#undef MULTIBOOT_LOAD_ELF64
|
||||||
|
@ -240,6 +242,26 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
grub_loader_unset ();
|
grub_loader_unset ();
|
||||||
|
|
||||||
|
highest_load = 0;
|
||||||
|
|
||||||
|
#ifndef GRUB_USE_MULTIBOOT2
|
||||||
|
grub_multiboot_quirks = GRUB_MULTIBOOT_QUIRKS_NONE;
|
||||||
|
|
||||||
|
if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||||
|
|
||||||
|
@ -290,6 +312,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
||||||
grub_addr_t target;
|
grub_addr_t target;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
int nounzip = 0;
|
int nounzip = 0;
|
||||||
|
grub_uint64_t lowest_addr = 0;
|
||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||||
|
@ -315,12 +338,17 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
||||||
if (! file)
|
if (! file)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
#ifndef GRUB_USE_MULTIBOOT2
|
||||||
|
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL)
|
||||||
|
lowest_addr = ALIGN_UP (highest_load + 1048576, 4096);
|
||||||
|
#endif
|
||||||
|
|
||||||
size = grub_file_size (file);
|
size = grub_file_size (file);
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
grub_relocator_chunk_t ch;
|
grub_relocator_chunk_t ch;
|
||||||
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
|
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
|
||||||
0, (0xffffffff - size) + 1,
|
lowest_addr, (0xffffffff - size) + 1,
|
||||||
size, MULTIBOOT_MOD_ALIGN,
|
size, MULTIBOOT_MOD_ALIGN,
|
||||||
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
GRUB_RELOCATOR_PREFERENCE_NONE, 0);
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
@ -86,6 +86,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
void *source;
|
void *source;
|
||||||
|
|
||||||
|
if (phdr(i)->p_paddr + phdr(i)->p_memsz > highest_load)
|
||||||
|
highest_load = phdr(i)->p_paddr + phdr(i)->p_memsz;
|
||||||
|
|
||||||
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
|
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
|
||||||
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
|
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,16 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
|
|
||||||
|
#ifndef GRUB_USE_MULTIBOOT2
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GRUB_MULTIBOOT_QUIRKS_NONE = 0,
|
||||||
|
GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE = 1,
|
||||||
|
GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL = 2
|
||||||
|
} grub_multiboot_quirks_t;
|
||||||
|
extern grub_multiboot_quirks_t grub_multiboot_quirks;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct grub_relocator *grub_multiboot_relocator;
|
extern struct grub_relocator *grub_multiboot_relocator;
|
||||||
|
|
||||||
void grub_multiboot (int argc, char *argv[]);
|
void grub_multiboot (int argc, char *argv[]);
|
||||||
|
|
Loading…
Reference in a new issue