Get the pre-loaded module code working.
This commit is contained in:
parent
03b1eeebc1
commit
8ef40c772a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: init_main.c,v 1.354 2008/04/28 20:24:02 martin Exp $ */
|
||||
/* $NetBSD: init_main.c,v 1.355 2008/05/01 14:44:48 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -97,7 +97,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.354 2008/04/28 20:24:02 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.355 2008/05/01 14:44:48 ad Exp $");
|
||||
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_ntp.h"
|
||||
@ -346,9 +346,6 @@ main(void)
|
||||
/* Do machine-dependent initialization. */
|
||||
cpu_startup();
|
||||
|
||||
/* Start module system. */
|
||||
module_init();
|
||||
|
||||
/* Initialize callouts, part 1. */
|
||||
callout_startup();
|
||||
|
||||
@ -430,6 +427,9 @@ main(void)
|
||||
/* Initialize the log device. */
|
||||
loginit();
|
||||
|
||||
/* Start module system. */
|
||||
module_init();
|
||||
|
||||
/* Initialize the file systems. */
|
||||
#ifdef NVNODE_IMPLICIT
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kern_module.c,v 1.10 2008/04/28 20:24:03 martin Exp $ */
|
||||
/* $NetBSD: kern_module.c,v 1.11 2008/05/01 14:44:48 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.10 2008/04/28 20:24:03 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.11 2008/05/01 14:44:48 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -71,6 +71,7 @@ static int module_do_load(const char *, bool, int, prop_dictionary_t,
|
||||
static int module_do_unload(const char *);
|
||||
static void module_error(const char *, ...);
|
||||
static int module_do_builtin(const char *, module_t **);
|
||||
static int module_fetch_info(module_t *);
|
||||
|
||||
/*
|
||||
* module_error:
|
||||
@ -102,6 +103,7 @@ module_init(void)
|
||||
if (lkm_map == NULL)
|
||||
lkm_map = kernel_map;
|
||||
mutex_init(&module_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
module_init_md();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -135,10 +137,16 @@ module_init_class(modclass_t class)
|
||||
* Now preloaded modules. These will be pulled off the
|
||||
* list as we call module_do_load();
|
||||
*/
|
||||
while ((mod = TAILQ_FIRST(&module_bootlist)) != NULL) {
|
||||
module_do_load(mod->mod_info->mi_name, false, 0,
|
||||
NULL, NULL);
|
||||
}
|
||||
do {
|
||||
TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
|
||||
mi = mod->mod_info;
|
||||
if (class != MODULE_CLASS_ANY &&
|
||||
class != mi->mi_class)
|
||||
continue;
|
||||
module_do_load(mi->mi_name, false, 0, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
} while (mod != NULL);
|
||||
mutex_exit(&module_lock);
|
||||
}
|
||||
|
||||
@ -378,8 +386,6 @@ module_do_load(const char *filename, bool isdep, int flags,
|
||||
module_t *mod, *mod2;
|
||||
char buf[MAXMODNAME];
|
||||
const char *s, *p;
|
||||
void *addr;
|
||||
size_t size;
|
||||
int error;
|
||||
size_t len;
|
||||
u_int i;
|
||||
@ -433,25 +439,17 @@ module_do_load(const char *filename, bool isdep, int flags,
|
||||
return error;
|
||||
}
|
||||
mod->mod_source = MODULE_SOURCE_FILESYS;
|
||||
error = module_fetch_info(mod);
|
||||
if (error != 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
|
||||
|
||||
/*
|
||||
* Find module info record and check compatibility.
|
||||
* Check compatibility.
|
||||
*/
|
||||
error = kobj_find_section(mod->mod_kobj, "link_set_modules",
|
||||
&addr, &size);
|
||||
if (error != 0) {
|
||||
module_error("`link_set_modules' section not present");
|
||||
goto fail;
|
||||
}
|
||||
if (size != sizeof(modinfo_t **)) {
|
||||
module_error("`link_set_modules' section wrong size");
|
||||
goto fail;
|
||||
}
|
||||
mod->mod_info = *(modinfo_t **)addr;
|
||||
mi = mod->mod_info;
|
||||
|
||||
if (strlen(mi->mi_name) >= MAXMODNAME) {
|
||||
error = EINVAL;
|
||||
module_error("module name too long");
|
||||
@ -642,19 +640,59 @@ module_prime(void *base, size_t size)
|
||||
mod->mod_source = MODULE_SOURCE_BOOT;
|
||||
|
||||
error = kobj_open_mem(&mod->mod_kobj, base, size);
|
||||
if (error == 0) {
|
||||
if (error != 0) {
|
||||
kmem_free(mod, sizeof(*mod));
|
||||
module_error("unable to open object pushed by boot loader");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = kobj_load(mod->mod_kobj);
|
||||
if (error != 0) {
|
||||
kobj_close(mod->mod_kobj);
|
||||
kmem_free(mod, sizeof(*mod));
|
||||
module_error("unable to push object pushed by boot loader");
|
||||
module_error("unable to load object pushed by boot loader");
|
||||
return error;
|
||||
}
|
||||
mod->mod_source = MODULE_SOURCE_FILESYS;
|
||||
error = module_fetch_info(mod);
|
||||
if (error != 0) {
|
||||
kobj_close(mod->mod_kobj);
|
||||
kobj_unload(mod->mod_kobj);
|
||||
kmem_free(mod, sizeof(*mod));
|
||||
module_error("unable to load object pushed by boot loader");
|
||||
return error;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* module_fetch_into:
|
||||
*
|
||||
* Fetch modinfo record from a loaded module.
|
||||
*/
|
||||
static int
|
||||
module_fetch_info(module_t *mod)
|
||||
{
|
||||
int error;
|
||||
void *addr;
|
||||
size_t size;
|
||||
|
||||
/*
|
||||
* Find module info record and check compatibility.
|
||||
*/
|
||||
error = kobj_find_section(mod->mod_kobj, "link_set_modules",
|
||||
&addr, &size);
|
||||
if (error != 0) {
|
||||
module_error("`link_set_modules' section not present");
|
||||
return error;
|
||||
}
|
||||
if (size != sizeof(modinfo_t **)) {
|
||||
module_error("`link_set_modules' section wrong size");
|
||||
return error;
|
||||
}
|
||||
mod->mod_info = *(modinfo_t **)addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: subr_kobj.c,v 1.11 2008/04/28 20:24:04 martin Exp $ */
|
||||
/* $NetBSD: subr_kobj.c,v 1.12 2008/05/01 14:44:48 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -62,7 +62,7 @@
|
||||
#include "opt_modular.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.11 2008/04/28 20:24:04 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.12 2008/05/01 14:44:48 ad Exp $");
|
||||
|
||||
#define ELFSIZE ARCH_ELFSIZE
|
||||
|
||||
@ -141,8 +141,10 @@ struct kobj {
|
||||
|
||||
static int kobj_relocate(kobj_t);
|
||||
static void kobj_error(const char *, ...);
|
||||
static int kobj_read(kobj_t, void *, size_t, off_t);
|
||||
static int kobj_read(kobj_t, void **, size_t, off_t);
|
||||
static int kobj_read_bits(kobj_t, void *, size_t, off_t);
|
||||
static void kobj_release_mem(kobj_t);
|
||||
static void kobj_free(kobj_t, void *, size_t);
|
||||
|
||||
extern struct vm_map *lkm_map;
|
||||
static const char *kobj_path = "/modules"; /* XXX ??? */
|
||||
@ -252,16 +254,15 @@ kobj_close(kobj_t ko)
|
||||
}
|
||||
|
||||
ko->ko_source = NULL;
|
||||
ko->ko_type = KT_UNSET;
|
||||
|
||||
/* Program table and section strings are no longer needed. */
|
||||
if (ko->ko_progtab != NULL) {
|
||||
kmem_free(ko->ko_progtab, ko->ko_nprogtab *
|
||||
kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab *
|
||||
sizeof(*ko->ko_progtab));
|
||||
ko->ko_progtab = NULL;
|
||||
}
|
||||
if (ko->ko_shstrtab) {
|
||||
kmem_free(ko->ko_shstrtab, ko->ko_shstrtabsz);
|
||||
kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz);
|
||||
ko->ko_shstrtab = NULL;
|
||||
}
|
||||
|
||||
@ -304,12 +305,7 @@ kobj_load(kobj_t ko)
|
||||
/*
|
||||
* Read the elf header from the file.
|
||||
*/
|
||||
hdr = kmem_alloc(sizeof(*hdr), KM_SLEEP);
|
||||
if (hdr == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
error = kobj_read(ko, hdr, sizeof(*hdr), 0);
|
||||
error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) {
|
||||
@ -355,16 +351,11 @@ kobj_load(kobj_t ko)
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
shdr = kmem_alloc(ko->ko_shdrsz, KM_SLEEP);
|
||||
if (shdr == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ko->ko_shdr = shdr;
|
||||
error = kobj_read(ko, shdr, ko->ko_shdrsz, hdr->e_shoff);
|
||||
error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff);
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
}
|
||||
ko->ko_shdr = shdr;
|
||||
|
||||
/*
|
||||
* Scan the section header for information and table sizing.
|
||||
@ -451,12 +442,8 @@ kobj_load(kobj_t ko)
|
||||
kobj_error("no symbol table");
|
||||
goto out;
|
||||
}
|
||||
ko->ko_symtab = kmem_alloc(ko->ko_symcnt * sizeof(Elf_Sym), KM_SLEEP);
|
||||
if (ko->ko_symtab == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
error = kobj_read(ko, ko->ko_symtab, shdr[symtabindex].sh_size,
|
||||
error = kobj_read(ko, (void **)&ko->ko_symtab,
|
||||
ko->ko_symcnt * sizeof(Elf_Sym),
|
||||
shdr[symtabindex].sh_offset);
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
@ -470,12 +457,7 @@ kobj_load(kobj_t ko)
|
||||
kobj_error("no symbol strings");
|
||||
goto out;
|
||||
}
|
||||
ko->ko_strtab = kmem_alloc(ko->ko_strtabsz, KM_SLEEP);
|
||||
if (ko->ko_strtab == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
error = kobj_read(ko, ko->ko_strtab, shdr[symstrindex].sh_size,
|
||||
error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz,
|
||||
shdr[symstrindex].sh_offset);
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
@ -487,13 +469,7 @@ kobj_load(kobj_t ko)
|
||||
if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 &&
|
||||
shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
|
||||
ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size;
|
||||
ko->ko_shstrtab = kmem_alloc(shdr[hdr->e_shstrndx].sh_size,
|
||||
KM_SLEEP);
|
||||
if (ko->ko_shstrtab == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
error = kobj_read(ko, ko->ko_shstrtab,
|
||||
error = kobj_read(ko, (void *)&ko->ko_shstrtab,
|
||||
shdr[hdr->e_shstrndx].sh_size,
|
||||
shdr[hdr->e_shstrndx].sh_offset);
|
||||
if (error != 0) {
|
||||
@ -505,10 +481,13 @@ kobj_load(kobj_t ko)
|
||||
* Size up code/data(progbits) and bss(nobits).
|
||||
*/
|
||||
alignmask = 0;
|
||||
mapbase = 0;
|
||||
for (i = 0; i < hdr->e_shnum; i++) {
|
||||
switch (shdr[i].sh_type) {
|
||||
case SHT_PROGBITS:
|
||||
case SHT_NOBITS:
|
||||
if (mapbase == 0)
|
||||
mapbase = shdr[i].sh_offset;
|
||||
alignmask = shdr[i].sh_addralign - 1;
|
||||
mapsize += alignmask;
|
||||
mapsize &= ~alignmask;
|
||||
@ -526,11 +505,15 @@ kobj_load(kobj_t ko)
|
||||
kobj_error("no text/data/bss");
|
||||
goto out;
|
||||
}
|
||||
mapbase = uvm_km_alloc(lkm_map, round_page(mapsize), 0,
|
||||
UVM_KMF_WIRED | UVM_KMF_EXEC);
|
||||
if (mapbase == 0) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
if (ko->ko_type == KT_MEMORY) {
|
||||
mapbase += (vaddr_t)ko->ko_source;
|
||||
} else {
|
||||
mapbase = uvm_km_alloc(lkm_map, round_page(mapsize), 0,
|
||||
UVM_KMF_WIRED | UVM_KMF_EXEC);
|
||||
if (mapbase == 0) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ko->ko_address = mapbase;
|
||||
ko->ko_size = mapsize;
|
||||
@ -553,7 +536,7 @@ kobj_load(kobj_t ko)
|
||||
ko->ko_progtab[pb].addr = (void *)mapbase;
|
||||
if (shdr[i].sh_type == SHT_PROGBITS) {
|
||||
ko->ko_progtab[pb].name = "<<PROGBITS>>";
|
||||
error = kobj_read(ko,
|
||||
error = kobj_read_bits(ko,
|
||||
ko->ko_progtab[pb].addr, shdr[i].sh_size,
|
||||
shdr[i].sh_offset);
|
||||
if (error != 0) {
|
||||
@ -588,14 +571,11 @@ kobj_load(kobj_t ko)
|
||||
ko->ko_reltab[rl].size -=
|
||||
shdr[i].sh_size % sizeof(Elf_Rel);
|
||||
if (ko->ko_reltab[rl].size != 0) {
|
||||
ko->ko_reltab[rl].rel =
|
||||
kmem_alloc(ko->ko_reltab[rl].size,
|
||||
KM_SLEEP);
|
||||
ko->ko_reltab[rl].nrel =
|
||||
shdr[i].sh_size / sizeof(Elf_Rel);
|
||||
ko->ko_reltab[rl].sec = shdr[i].sh_info;
|
||||
error = kobj_read(ko,
|
||||
ko->ko_reltab[rl].rel,
|
||||
(void **)&ko->ko_reltab[rl].rel,
|
||||
ko->ko_reltab[rl].size,
|
||||
shdr[i].sh_offset);
|
||||
if (error != 0) {
|
||||
@ -609,14 +589,11 @@ kobj_load(kobj_t ko)
|
||||
ko->ko_relatab[ra].size -=
|
||||
shdr[i].sh_size % sizeof(Elf_Rela);
|
||||
if (ko->ko_relatab[ra].size != 0) {
|
||||
ko->ko_relatab[ra].rela =
|
||||
kmem_alloc(ko->ko_relatab[ra].size,
|
||||
KM_SLEEP);
|
||||
ko->ko_relatab[ra].nrela =
|
||||
shdr[i].sh_size / sizeof(Elf_Rela);
|
||||
ko->ko_relatab[ra].sec = shdr[i].sh_info;
|
||||
error = kobj_read(ko,
|
||||
ko->ko_relatab[ra].rela,
|
||||
(void **)&ko->ko_relatab[ra].rela,
|
||||
shdr[i].sh_size,
|
||||
shdr[i].sh_offset);
|
||||
if (error != 0) {
|
||||
@ -663,7 +640,7 @@ kobj_load(kobj_t ko)
|
||||
out:
|
||||
kobj_release_mem(ko);
|
||||
if (hdr != NULL) {
|
||||
kmem_free(hdr, sizeof(*hdr));
|
||||
kobj_free(ko, hdr, sizeof(*hdr));
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -682,7 +659,7 @@ kobj_unload(kobj_t ko)
|
||||
KASSERT(ko->ko_progtab == NULL);
|
||||
KASSERT(ko->ko_shstrtab == NULL);
|
||||
|
||||
if (ko->ko_address != 0) {
|
||||
if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) {
|
||||
uvm_km_free(lkm_map, ko->ko_address, round_page(ko->ko_size),
|
||||
UVM_KMF_WIRED);
|
||||
}
|
||||
@ -690,10 +667,10 @@ kobj_unload(kobj_t ko)
|
||||
ksyms_delsymtab(ko->ko_name);
|
||||
}
|
||||
if (ko->ko_symtab != NULL) {
|
||||
kmem_free(ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym));
|
||||
kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym));
|
||||
}
|
||||
if (ko->ko_strtab != NULL) {
|
||||
kmem_free(ko->ko_strtab, ko->ko_strtabsz);
|
||||
kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -796,30 +773,30 @@ kobj_release_mem(kobj_t ko)
|
||||
|
||||
for (i = 0; i < ko->ko_nrel; i++) {
|
||||
if (ko->ko_reltab[i].rel) {
|
||||
kmem_free(ko->ko_reltab[i].rel,
|
||||
kobj_free(ko, ko->ko_reltab[i].rel,
|
||||
ko->ko_reltab[i].size);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ko->ko_nrela; i++) {
|
||||
if (ko->ko_relatab[i].rela) {
|
||||
kmem_free(ko->ko_relatab[i].rela,
|
||||
kobj_free(ko, ko->ko_relatab[i].rela,
|
||||
ko->ko_relatab[i].size);
|
||||
}
|
||||
}
|
||||
if (ko->ko_reltab != NULL) {
|
||||
kmem_free(ko->ko_reltab, ko->ko_nrel *
|
||||
kobj_free(ko, ko->ko_reltab, ko->ko_nrel *
|
||||
sizeof(*ko->ko_reltab));
|
||||
ko->ko_reltab = NULL;
|
||||
ko->ko_nrel = 0;
|
||||
}
|
||||
if (ko->ko_relatab != NULL) {
|
||||
kmem_free(ko->ko_relatab, ko->ko_nrela *
|
||||
kobj_free(ko, ko->ko_relatab, ko->ko_nrela *
|
||||
sizeof(*ko->ko_relatab));
|
||||
ko->ko_relatab = NULL;
|
||||
ko->ko_nrela = 0;
|
||||
}
|
||||
if (ko->ko_shdr != NULL) {
|
||||
kmem_free(ko->ko_shdr, ko->ko_shdrsz);
|
||||
kobj_free(ko, ko->ko_shdr, ko->ko_shdrsz);
|
||||
ko->ko_shdr = NULL;
|
||||
}
|
||||
}
|
||||
@ -997,7 +974,54 @@ kobj_error(const char *fmt, ...)
|
||||
* Utility function: read from the object.
|
||||
*/
|
||||
static int
|
||||
kobj_read(kobj_t ko, void *base, size_t size, off_t off)
|
||||
kobj_read(kobj_t ko, void **basep, size_t size, off_t off)
|
||||
{
|
||||
size_t resid;
|
||||
void *base;
|
||||
int error;
|
||||
|
||||
KASSERT(ko->ko_source != NULL);
|
||||
|
||||
switch (ko->ko_type) {
|
||||
case KT_VNODE:
|
||||
base = kmem_alloc(size, KM_SLEEP);
|
||||
if (base == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off,
|
||||
UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid,
|
||||
curlwp);
|
||||
if (error == 0 && resid != 0) {
|
||||
kmem_free(base, size);
|
||||
error = EINVAL;
|
||||
}
|
||||
break;
|
||||
case KT_MEMORY:
|
||||
if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) {
|
||||
kobj_error("kobj_read: preloaded object short");
|
||||
error = EINVAL;
|
||||
base = NULL;
|
||||
} else {
|
||||
base = (uint8_t *)ko->ko_source + off;
|
||||
error = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
panic("kobj_read: invalid type");
|
||||
}
|
||||
|
||||
*basep = base;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* kobj_read_bits:
|
||||
*
|
||||
* Utility function: load a section from the object.
|
||||
*/
|
||||
static int
|
||||
kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off)
|
||||
{
|
||||
size_t resid;
|
||||
int error;
|
||||
@ -1015,10 +1039,15 @@ kobj_read(kobj_t ko, void *base, size_t size, off_t off)
|
||||
break;
|
||||
case KT_MEMORY:
|
||||
if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) {
|
||||
kobj_error("kobj_read: preloaded object short");
|
||||
kobj_error("kobj_read_bits: preloaded object short");
|
||||
error = EINVAL;
|
||||
} else if ((uint8_t *)base != (uint8_t *)ko->ko_source + off) {
|
||||
kobj_error("kobj_read_bits: object not aligned");
|
||||
kobj_error("source=%p base=%p off=%d size=%zd",
|
||||
ko->ko_source, base, (int)off, size);
|
||||
error = EINVAL;
|
||||
} else {
|
||||
memcpy(base, (uint8_t *)ko->ko_source + off, size);
|
||||
/* Nothing to do. Loading in-situ. */
|
||||
error = 0;
|
||||
}
|
||||
break;
|
||||
@ -1029,6 +1058,19 @@ kobj_read(kobj_t ko, void *base, size_t size, off_t off)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* kobj_free:
|
||||
*
|
||||
* Utility function: free memory if it was allocated from the heap.
|
||||
*/
|
||||
static void
|
||||
kobj_free(kobj_t ko, void *base, size_t size)
|
||||
{
|
||||
|
||||
if (ko->ko_type != KT_MEMORY)
|
||||
kmem_free(base, size);
|
||||
}
|
||||
|
||||
#else /* MODULAR */
|
||||
|
||||
int
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: module.h,v 1.3 2008/04/28 20:24:11 martin Exp $ */
|
||||
/* $NetBSD: module.h,v 1.4 2008/05/01 14:44:48 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
||||
@ -112,6 +112,7 @@ extern u_int module_count;
|
||||
extern struct modlist module_list;
|
||||
|
||||
void module_init(void);
|
||||
void module_init_md(void);
|
||||
void module_init_class(modclass_t);
|
||||
int module_prime(void *, size_t);
|
||||
void module_jettison(void);
|
||||
|
Loading…
Reference in New Issue
Block a user