kmod improvements

- unless otherwise specified, modules are now loaded from the same device
   as the kernel ('load miniroot' now implies 'load tftp:miniroot' if the
   boot command is 'boot tftp:netbsd')
 - the module name -> path expansion now works when a device prefix: is
   specified ('load tftp:miniroot' now works)
 - if the module name has been expanded to a path, print that path when
   loading the module rather than the symbolic name
 - only print an error in module_open if both the expanded path and the
   raw path fail to open
This commit is contained in:
jmcneill 2009-09-13 18:13:37 +00:00
parent b21564d63d
commit d2a59733be
1 changed files with 74 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec.c,v 1.40 2009/03/21 15:01:56 ad Exp $ */
/* $NetBSD: exec.c,v 1.41 2009/09/13 18:13:37 jmcneill Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -124,6 +124,8 @@
#define PAGE_SIZE 4096
#endif
#define MODULE_WARNING_DELAY 5000000
extern struct btinfo_console btinfo_console;
boot_module_t *boot_modules;
@ -138,7 +140,7 @@ static uint32_t image_end;
static char module_base[64] = "/";
static int howto;
static void module_init(void);
static void module_init(const char *);
void
framebuffer_configure(struct btinfo_framebuffer *fb)
@ -304,7 +306,7 @@ exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
/* pull in any modules if necessary */
if (boot_modules_enabled) {
module_init();
module_init(file);
if (btinfo_modulelist) {
BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
btinfo_modulelist_size);
@ -333,12 +335,26 @@ out:
return -1;
}
static void
extract_device(const char *path, char *buf, size_t buflen)
{
int i;
if (strchr(path, ':') != NULL) {
for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
buf[i] = path[i];
buf[i++] = ':';
buf[i] = '\0';
} else
buf[0] = '\0';
}
static const char *
module_path(boot_module_t *bm)
module_path(boot_module_t *bm, const char *kdev)
{
static char buf[256];
char name_buf[256];
const char *name, *name2;
char name_buf[256], dev_buf[64];
const char *name, *name2, *p;
name = bm->bm_path;
for (name2 = name; *name2; ++name2) {
@ -350,45 +366,69 @@ module_path(boot_module_t *bm)
break;
}
}
if (name[0] == '/')
snprintf(buf, sizeof(buf), "%s", name);
else
snprintf(buf, sizeof(buf), "%s/%s/%s.kmod",
module_base, name, name);
if ((p = strchr(name, ':')) != NULL) {
/* device specified, use it */
if (p[1] == '/')
snprintf(buf, sizeof(buf), "%s", name);
else {
p++;
extract_device(name, dev_buf, sizeof(dev_buf));
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
dev_buf, module_base, p, p);
}
} else {
/* device not specified; load from kernel device if known */
if (name[0] == '/')
snprintf(buf, sizeof(buf), "%s%s", kdev, name);
else
snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
kdev, module_base, name, name);
}
return buf;
}
static int
module_open(boot_module_t *bm, int mode)
module_open(boot_module_t *bm, int mode, const char *kdev, bool doload)
{
int fd;
const char *path;
/* check the expanded path first */
path = module_path(bm);
path = module_path(bm, kdev);
fd = open(path, mode);
if (fd == -1) {
printf("WARNING: couldn't open %s\n", path);
if (fd != -1) {
if ((howto & AB_SILENT) == 0 && doload)
printf("Loading %s ", path);
} else {
/* now attempt the raw path provided */
fd = open(bm->bm_path, mode);
if (fd == -1)
printf("WARNING: couldn't open %s\n", bm->bm_path);
if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
printf("Loading %s ", bm->bm_path);
}
if (!doload && fd == -1) {
printf("WARNING: couldn't open %s", bm->bm_path);
if (strcmp(bm->bm_path, path) != 0)
printf(" (%s)", path);
printf("\n");
}
return fd;
}
static void
module_init(void)
module_init(const char *kernel_path)
{
struct bi_modulelist_entry *bi;
struct stat st;
const char *machine;
char kdev[64];
char *buf;
boot_module_t *bm;
size_t len;
off_t off;
int err, fd;
int err, fd, nfail = 0;
extract_device(kernel_path, kdev, sizeof(kdev));
switch (netbsd_elf_class) {
case ELFCLASS32:
@ -419,9 +459,10 @@ module_init(void)
/* First, see which modules are valid and calculate btinfo size */
len = sizeof(struct btinfo_modulelist);
for (bm = boot_modules; bm; bm = bm->bm_next) {
fd = module_open(bm, 0);
fd = module_open(bm, 0, kdev, false);
if (fd == -1) {
bm->bm_len = -1;
++nfail;
continue;
}
err = fstat(fd, &st);
@ -429,6 +470,7 @@ module_init(void)
printf("WARNING: couldn't stat %s\n", bm->bm_path);
close(fd);
bm->bm_len = -1;
++nfail;
continue;
}
bm->bm_len = st.st_size;
@ -440,6 +482,7 @@ module_init(void)
btinfo_modulelist = alloc(len);
if (btinfo_modulelist == NULL) {
printf("WARNING: couldn't allocate module list\n");
delay(MODULE_WARNING_DELAY);
return;
}
memset(btinfo_modulelist, 0, len);
@ -453,13 +496,9 @@ module_init(void)
for (bm = boot_modules; bm; bm = bm->bm_next) {
if (bm->bm_len == -1)
continue;
if ((howto & AB_SILENT) == 0)
printf("Loading %s ", bm->bm_path);
fd = module_open(bm, 0);
if (fd == -1) {
printf("ERROR: couldn't open %s\n", bm->bm_path);
fd = module_open(bm, 0, kdev, true);
if (fd == -1)
continue;
}
image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
len = pread(fd, (void *)image_end, SSIZE_MAX);
if (len < bm->bm_len) {
@ -482,6 +521,14 @@ module_init(void)
close(fd);
}
btinfo_modulelist->endpa = image_end;
if (nfail > 0) {
printf("WARNING: %d module%s failed to load\n",
nfail, nfail == 1 ? "" : "s");
#if notyet
delay(MODULE_WARNING_DELAY);
#endif
}
}
int
@ -515,7 +562,7 @@ exec_multiboot(const char *file, char *args)
/* pull in any modules if necessary */
if (boot_modules_enabled) {
module_init();
module_init(file);
if (btinfo_modulelist) {
mbm = alloc(sizeof(struct multiboot_module) *
btinfo_modulelist->num);