NetBSD module support

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-16 11:47:12 +01:00
parent cefe39c94b
commit ae9eb98c7d
2 changed files with 176 additions and 7 deletions

View file

@ -212,6 +212,7 @@ struct grub_netbsd_bootinfo
#define NETBSD_BTINFO_CONSOLE 6
#define NETBSD_BTINFO_SYMTAB 8
#define NETBSD_BTINFO_MEMMAP 9
#define NETBSD_BTINFO_MODULES 11
#define NETBSD_BTINFO_FRAMEBUF 12
struct grub_netbsd_btinfo_common
@ -249,6 +250,21 @@ struct grub_netbsd_btinfo_serial
grub_uint32_t speed;
};
struct grub_netbsd_btinfo_modules
{
grub_uint32_t num;
grub_uint32_t last_addr;
struct grub_netbsd_btinfo_module
{
char name[80];
#define GRUB_NETBSD_MODULE_RAW 0
#define GRUB_NETBSD_MODULE_ELF 1
grub_uint32_t type;
grub_uint32_t size;
grub_uint32_t addr;
} mods[0];
};
struct grub_netbsd_btinfo_framebuf
{
grub_uint64_t fbaddr;

View file

@ -82,6 +82,14 @@ struct bsd_tag
struct bsd_tag *tags, *tags_last;
struct netbsd_module
{
struct netbsd_module *next;
struct grub_netbsd_btinfo_module mod;
};
struct netbsd_module *netbsd_mods, *netbsd_mods_last;
static const struct grub_arg_option freebsd_opts[] =
{
{"dual", 'D', 0, N_("Display output on all consoles."), 0, 0},
@ -452,6 +460,49 @@ grub_freebsd_list_modules (void)
}
}
static grub_err_t
grub_netbsd_add_meta_module (char *filename, grub_uint32_t type,
grub_addr_t addr, grub_uint32_t size)
{
char *name;
struct netbsd_module *mod;
name = grub_strrchr (filename, '/');
if (name)
name++;
else
name = filename;
mod = grub_zalloc (sizeof (*mod));
if (!mod)
return grub_errno;
grub_strncpy (mod->mod.name, name, sizeof (mod->mod.name) - 1);
mod->mod.addr = addr;
mod->mod.type = type;
mod->mod.size = size;
if (netbsd_mods_last)
netbsd_mods_last->next = mod;
else
netbsd_mods = mod;
netbsd_mods_last = mod;
return GRUB_ERR_NONE;
}
static void
grub_netbsd_list_modules (void)
{
struct netbsd_module *mod;
grub_printf (" %-18s%14s%14s%14s\n", "name", "type", "addr", "size");
for (mod = netbsd_mods; mod; mod = mod->next)
grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod->mod.name,
mod->mod.type, mod->mod.addr, mod->mod.size);
}
/* This function would be here but it's under different license. */
#include "bsd_pagetable.c"
@ -865,6 +916,38 @@ grub_netbsd_setup_video (void)
return err;
}
static grub_err_t
grub_netbsd_add_modules (void)
{
struct netbsd_module *mod;
unsigned modcnt = 0;
struct grub_netbsd_btinfo_modules *mods;
grub_addr_t last_addr = 0;
unsigned i;
grub_err_t err;
for (mod = netbsd_mods; mod; mod = mod->next)
{
if (mod->mod.addr + mod->mod.size > last_addr)
last_addr = mod->mod.addr + mod->mod.size;
modcnt++;
}
mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
if (!mods)
return grub_errno;
mods->num = modcnt;
mods->last_addr = last_addr;
for (mod = netbsd_mods, i = 0; mod; i++, mod = mod->next)
mods->mods[i] = mod->mod;
err = grub_bsd_add_meta (NETBSD_BTINFO_MODULES, mods,
sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
grub_free (mods);
return err;
}
static grub_err_t
grub_netbsd_boot (void)
{
@ -889,6 +972,10 @@ grub_netbsd_boot (void)
grub_errno = GRUB_ERR_NONE;
}
err = grub_netbsd_add_modules ();
if (err)
return err;
{
struct bsd_tag *tag;
tag_buf_len = 0;
@ -1535,13 +1622,8 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
grub_err_t err;
void *src;
if (kernel_type == KERNEL_TYPE_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the kernel first");
if (kernel_type != KERNEL_TYPE_FREEBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only FreeBSD supports module");
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded");
if (!is_elf_kernel)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
@ -1593,6 +1675,68 @@ fail:
return grub_errno;
}
static grub_err_t
grub_netbsd_module_load (char *filename, grub_uint32_t type)
{
grub_file_t file = 0;
void *src;
grub_err_t err;
file = grub_gzfile_open (filename, 1);
if ((!file) || (!file->size))
goto fail;
err = grub_relocator_alloc_chunk_addr (relocator, &src, kern_end,
file->size);
if (err)
goto fail;
grub_file_read (file, src, file->size);
if (grub_errno)
goto fail;
err = grub_netbsd_add_meta_module (filename, type, kern_end, file->size);
if (err)
goto fail;
kern_end = ALIGN_PAGE (kern_end + file->size);
fail:
if (file)
grub_file_close (file);
return grub_errno;
}
static grub_err_t
grub_cmd_netbsd_module (grub_command_t cmd,
int argc, char *argv[])
{
grub_uint32_t type;
if (kernel_type != KERNEL_TYPE_NETBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded");
if (!is_elf_kernel)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only ELF kernel supports module");
/* List the current modules if no parameter. */
if (!argc)
{
grub_netbsd_list_modules ();
return 0;
}
if (grub_strcmp (cmd->name, "knetbsd_module_elf") == 0)
type = GRUB_NETBSD_MODULE_ELF;
else
type = GRUB_NETBSD_MODULE_RAW;
return grub_netbsd_module_load (argv[0], type);
}
static grub_err_t
grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
@ -1642,7 +1786,8 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
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_freebsd_module_elf;
static grub_command_t cmd_netbsd_module, cmd_freebsd_module_elf;
static grub_command_t cmd_netbsd_module_elf;
GRUB_MOD_INIT (bsd)
{
@ -1664,6 +1809,12 @@ GRUB_MOD_INIT (bsd)
cmd_freebsd_module =
grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module,
0, N_("Load FreeBSD kernel module."));
cmd_netbsd_module =
grub_register_command ("knetbsd_module", grub_cmd_netbsd_module,
0, N_("Load NetBSD kernel module."));
cmd_netbsd_module_elf =
grub_register_command ("knetbsd_module_elf", grub_cmd_netbsd_module,
0, N_("Load NetBSD kernel module (ELF)."));
cmd_freebsd_module_elf =
grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf,
0, N_("Load FreeBSD kernel module (ELF)."));
@ -1679,7 +1830,9 @@ GRUB_MOD_FINI (bsd)
grub_unregister_command (cmd_freebsd_loadenv);
grub_unregister_command (cmd_freebsd_module);
grub_unregister_command (cmd_netbsd_module);
grub_unregister_command (cmd_freebsd_module_elf);
grub_unregister_command (cmd_netbsd_module_elf);
grub_bsd_unload ();
}