openbsd ramdisk support
This commit is contained in:
parent
72d14db9ba
commit
ecde61b490
3 changed files with 197 additions and 3 deletions
|
@ -67,6 +67,7 @@ static grub_uint32_t bootflags;
|
|||
static int is_elf_kernel, is_64bit;
|
||||
static grub_uint32_t openbsd_root;
|
||||
struct grub_relocator *relocator = NULL;
|
||||
static struct grub_openbsd_ramdisk_descriptor openbsd_ramdisk;
|
||||
|
||||
struct bsd_tag
|
||||
{
|
||||
|
@ -1253,7 +1254,13 @@ grub_bsd_load_elf (grub_elf_t elf)
|
|||
|
||||
kern_chunk_src = get_virtual_current_address (ch);
|
||||
|
||||
return grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
|
||||
err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (kernel_type != KERNEL_TYPE_OPENBSD)
|
||||
return GRUB_ERR_NONE;
|
||||
return grub_openbsd_find_ramdisk32 (elf->file, kern_start,
|
||||
kern_chunk_src, &openbsd_ramdisk);
|
||||
}
|
||||
else if (grub_elf_is_elf64 (elf))
|
||||
{
|
||||
|
@ -1290,7 +1297,13 @@ grub_bsd_load_elf (grub_elf_t elf)
|
|||
kern_chunk_src = get_virtual_current_address (ch);
|
||||
}
|
||||
|
||||
return grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0);
|
||||
err = grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
if (kernel_type != KERNEL_TYPE_OPENBSD)
|
||||
return GRUB_ERR_NONE;
|
||||
return grub_openbsd_find_ramdisk64 (elf->file, kern_start,
|
||||
kern_chunk_src, &openbsd_ramdisk);
|
||||
}
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||
|
@ -1306,6 +1319,8 @@ grub_bsd_load (int argc, char *argv[])
|
|||
|
||||
grub_loader_unset ();
|
||||
|
||||
grub_memset (&openbsd_ramdisk, 0, sizeof (openbsd_ramdisk));
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
|
||||
|
@ -1874,11 +1889,55 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
|
|||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *args[])
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_size_t size;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
if (kernel_type != KERNEL_TYPE_OPENBSD)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded");
|
||||
|
||||
if (!openbsd_ramdisk.max_size)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD doesn't support ramdisk");
|
||||
|
||||
file = grub_gzfile_open (args[0], 1);
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||
"couldn't load ramdisk");
|
||||
|
||||
size = grub_file_size (file);
|
||||
|
||||
if (size > openbsd_ramdisk.max_size)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD supports ramdisk only"
|
||||
" up to %u bytes, however you supplied a %u bytes one",
|
||||
openbsd_ramdisk.max_size, size);
|
||||
}
|
||||
|
||||
if (grub_file_read (file, openbsd_ramdisk.target, size)
|
||||
!= (grub_ssize_t) (size))
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_error_push ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]);
|
||||
}
|
||||
grub_memset (openbsd_ramdisk.target + size, 0,
|
||||
openbsd_ramdisk.max_size - size);
|
||||
*openbsd_ramdisk.size = ALIGN_UP (size, 512);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd_freebsd, cmd_openbsd, cmd_netbsd;
|
||||
static grub_command_t cmd_freebsd_loadenv, cmd_freebsd_module;
|
||||
static grub_command_t cmd_netbsd_module, cmd_freebsd_module_elf;
|
||||
static grub_command_t cmd_netbsd_module_elf;
|
||||
static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
|
||||
|
||||
GRUB_MOD_INIT (bsd)
|
||||
{
|
||||
|
@ -1910,6 +1969,10 @@ GRUB_MOD_INIT (bsd)
|
|||
grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf,
|
||||
0, N_("Load FreeBSD kernel module (ELF)."));
|
||||
|
||||
cmd_openbsd_ramdisk = grub_register_command ("kopenbsd_ramdisk",
|
||||
grub_cmd_openbsd_ramdisk, 0,
|
||||
"Load kOpenBSD ramdisk. ");
|
||||
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
|
@ -1924,6 +1987,7 @@ GRUB_MOD_FINI (bsd)
|
|||
grub_unregister_command (cmd_netbsd_module);
|
||||
grub_unregister_command (cmd_freebsd_module_elf);
|
||||
grub_unregister_command (cmd_netbsd_module_elf);
|
||||
grub_unregister_command (cmd_openbsd_ramdisk);
|
||||
|
||||
grub_bsd_unload ();
|
||||
}
|
||||
|
|
|
@ -503,4 +503,118 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
|
||||
grub_addr_t kern_start,
|
||||
void *kern_chunk_src,
|
||||
struct grub_openbsd_ramdisk_descriptor *desc)
|
||||
{
|
||||
unsigned symoff, stroff, symsize, strsize, symentsize;
|
||||
|
||||
{
|
||||
grub_err_t err;
|
||||
Elf_Ehdr e;
|
||||
Elf_Shdr *s;
|
||||
char *shdr;
|
||||
|
||||
err = read_headers (file, &e, &shdr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
|
||||
+ e.e_shnum * e.e_shentsize);
|
||||
s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize))
|
||||
{
|
||||
grub_free (shdr);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
symsize = s->sh_size;
|
||||
symentsize = s->sh_entsize;
|
||||
symoff = s->sh_offset;
|
||||
|
||||
s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
|
||||
stroff = s->sh_offset;
|
||||
strsize = s->sh_size;
|
||||
grub_free (shdr);
|
||||
}
|
||||
{
|
||||
Elf_Sym *syms, *sym, *imagesym = NULL, *sizesym = NULL;
|
||||
unsigned i;
|
||||
char *strs;
|
||||
|
||||
syms = grub_malloc (symsize);
|
||||
if (!syms)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_file_seek (file, symoff) == (grub_off_t) -1)
|
||||
{
|
||||
grub_free (syms);
|
||||
return grub_errno;
|
||||
}
|
||||
if (grub_file_read (file, syms, symsize) != (grub_ssize_t) symsize)
|
||||
{
|
||||
grub_free (syms);
|
||||
if (! grub_errno)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
strs = grub_malloc (strsize);
|
||||
if (!strs)
|
||||
{
|
||||
grub_free (syms);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_file_seek (file, stroff) == (grub_off_t) -1)
|
||||
return grub_errno;
|
||||
if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize)
|
||||
{
|
||||
grub_free (syms);
|
||||
grub_free (strs);
|
||||
if (! grub_errno)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
for (i = 0, sym = syms; i < symsize / symentsize;
|
||||
i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
|
||||
{
|
||||
if (ELF_ST_TYPE (sym->st_info) != STT_OBJECT)
|
||||
continue;
|
||||
if (!sym->st_name)
|
||||
continue;
|
||||
if (grub_strcmp (strs + sym->st_name, "rd_root_image") == 0)
|
||||
imagesym = sym;
|
||||
if (grub_strcmp (strs + sym->st_name, "rd_root_size") == 0)
|
||||
sizesym = sym;
|
||||
if (imagesym && sizesym)
|
||||
break;
|
||||
}
|
||||
if (!imagesym || !sizesym)
|
||||
{
|
||||
grub_free (syms);
|
||||
grub_free (strs);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (sizeof (*desc->size) != sizesym->st_size)
|
||||
{
|
||||
grub_free (syms);
|
||||
grub_free (strs);
|
||||
return grub_error (GRUB_ERR_BAD_OS, "unexpected size of rd_root_size");
|
||||
}
|
||||
desc->max_size = imagesym->st_size;
|
||||
desc->target = (imagesym->st_value & 0xFFFFFF) - kern_start
|
||||
+ (grub_uint8_t *) kern_chunk_src;
|
||||
desc->size = (grub_uint32_t *) ((sizesym->st_value & 0xFFFFFF) - kern_start
|
||||
+ (grub_uint8_t *) kern_chunk_src);
|
||||
grub_free (syms);
|
||||
grub_free (strs);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,6 +99,22 @@ grub_err_t grub_freebsd_add_meta_module (char *filename, char *type,
|
|||
int argc, char **argv,
|
||||
grub_addr_t addr, grub_uint32_t size);
|
||||
|
||||
struct grub_openbsd_ramdisk_descriptor
|
||||
{
|
||||
grub_size_t max_size;
|
||||
grub_uint8_t *target;
|
||||
grub_uint32_t *size;
|
||||
};
|
||||
|
||||
grub_err_t grub_openbsd_find_ramdisk32 (grub_file_t file,
|
||||
grub_addr_t kern_start,
|
||||
void *kern_chunk_src,
|
||||
struct grub_openbsd_ramdisk_descriptor *desc);
|
||||
grub_err_t grub_openbsd_find_ramdisk64 (grub_file_t file,
|
||||
grub_addr_t kern_start,
|
||||
void *kern_chunk_src,
|
||||
struct grub_openbsd_ramdisk_descriptor *desc);
|
||||
|
||||
extern grub_uint8_t grub_bsd64_trampoline_start, grub_bsd64_trampoline_end;
|
||||
extern grub_uint32_t grub_bsd64_trampoline_selfjump;
|
||||
extern grub_uint32_t grub_bsd64_trampoline_gdt;
|
||||
|
|
Loading…
Reference in a new issue