kern_module.c revision 40158
125537Sdfr/*- 225537Sdfr * Copyright (c) 1997 Doug Rabson 325537Sdfr * All rights reserved. 425537Sdfr * 525537Sdfr * Redistribution and use in source and binary forms, with or without 625537Sdfr * modification, are permitted provided that the following conditions 725537Sdfr * are met: 825537Sdfr * 1. Redistributions of source code must retain the above copyright 925537Sdfr * notice, this list of conditions and the following disclaimer. 1025537Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1125537Sdfr * notice, this list of conditions and the following disclaimer in the 1225537Sdfr * documentation and/or other materials provided with the distribution. 1325537Sdfr * 1425537Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1525537Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1625537Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1725537Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1825537Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1925537Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2025537Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2125537Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2225537Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2325537Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2425537Sdfr * SUCH DAMAGE. 2525537Sdfr * 2640158Speter * $Id: kern_module.c,v 1.9 1998/10/03 11:05:45 dfr Exp $ 2725537Sdfr */ 2825537Sdfr 2925537Sdfr#include <sys/param.h> 3025537Sdfr#include <sys/kernel.h> 3125537Sdfr#include <sys/systm.h> 3225537Sdfr#include <sys/malloc.h> 3325537Sdfr#include <sys/sysproto.h> 3425537Sdfr#include <sys/sysent.h> 3525537Sdfr#include <sys/module.h> 3625537Sdfr#include <sys/linker.h> 3730994Sphk#include <sys/proc.h> 3825537Sdfr 3925537Sdfr#define M_MODULE M_TEMP /* XXX */ 4025537Sdfr 4125537Sdfrtypedef TAILQ_HEAD(, module) modulelist_t; 4225537Sdfrstruct module { 4325537Sdfr TAILQ_ENTRY(module) link; /* chain together all modules */ 4425537Sdfr TAILQ_ENTRY(module) flink; /* all modules in a file */ 4525537Sdfr struct linker_file* file; /* file which contains this module */ 4625537Sdfr int refs; /* reference count */ 4725537Sdfr int id; /* unique id number */ 4825537Sdfr char *name; /* module name */ 4925537Sdfr modeventhand_t handler; /* event handler */ 5025537Sdfr void *arg; /* argument for handler */ 5125537Sdfr}; 5225537Sdfr 5325537Sdfr#define MOD_EVENT(mod, type) (mod)->handler((mod), (type), (mod)->arg) 5425537Sdfr 5525537Sdfrstatic modulelist_t modules; 5625537Sdfrstatic int nextid = 1; 5725537Sdfr 5825537Sdfrstatic void module_shutdown(int, void*); 5925537Sdfr 6025537Sdfrstatic void 6125537Sdfrmodule_init(void* arg) 6225537Sdfr{ 6325537Sdfr TAILQ_INIT(&modules); 6425537Sdfr at_shutdown(module_shutdown, 0, SHUTDOWN_POST_SYNC); 6525537Sdfr} 6625537Sdfr 6740158SpeterSYSINIT(module, SI_SUB_KLD, SI_ORDER_ANY, module_init, 0); 6825537Sdfr 6925537Sdfrstatic void 7025537Sdfrmodule_shutdown(int arg1, void* arg2) 7125537Sdfr{ 7225537Sdfr module_t mod; 7325537Sdfr 7425537Sdfr for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) 7525537Sdfr MOD_EVENT(mod, MOD_SHUTDOWN); 7625537Sdfr} 7725537Sdfr 7825537Sdfrvoid 7930683Sjmgmodule_register_init(void *arg) 8025537Sdfr{ 8125537Sdfr moduledata_t* data = (moduledata_t*) arg; 8225537Sdfr int error; 8325537Sdfr 8440158Speter error = module_register(data->name, data->evhand, data->priv, data->_file); 8540158Speter if (error) 8637555Sbde printf("module_register_init: module_register(%s, %lx, %p) returned %d", 8737629Sbde data->name, (u_long)(uintfptr_t)data->evhand, data->priv, error); 8825537Sdfr} 8925537Sdfr 9025537Sdfrint 9140158Spetermodule_register(const char* name, modeventhand_t handler, void* arg, void *file) 9225537Sdfr{ 9325537Sdfr size_t namelen; 9425537Sdfr module_t newmod; 9525537Sdfr int error; 9640158Speter linker_file_t container = file; 9725537Sdfr 9825537Sdfr namelen = strlen(name) + 1; 9925537Sdfr newmod = (module_t) malloc(sizeof(struct module) + namelen, 10025537Sdfr M_MODULE, M_WAITOK); 10125537Sdfr if (newmod == 0) 10225537Sdfr return ENOMEM; 10325537Sdfr 10425537Sdfr newmod->refs = 1; 10525537Sdfr newmod->id = nextid++; 10625537Sdfr newmod->name = (char *) (newmod + 1); 10725537Sdfr strcpy(newmod->name, name); 10825537Sdfr newmod->handler = handler; 10925537Sdfr newmod->arg = arg; 11025537Sdfr TAILQ_INSERT_TAIL(&modules, newmod, link); 11125537Sdfr 11240158Speter if (container == NULL) 11340158Speter container = linker_current_file; 11440158Speter if (container) { 11540158Speter TAILQ_INSERT_TAIL(&container->modules, newmod, flink); 11640158Speter newmod->file = container; 11725537Sdfr } else 11825537Sdfr newmod->file = 0; 11925537Sdfr 12025537Sdfr if (error = MOD_EVENT(newmod, MOD_LOAD)) { 12139916Sdfr MOD_EVENT(newmod, MOD_UNLOAD); 12225537Sdfr module_release(newmod); 12325537Sdfr return error; 12425537Sdfr } 12525537Sdfr 12625537Sdfr return 0; 12725537Sdfr} 12825537Sdfr 12925537Sdfrvoid 13025537Sdfrmodule_reference(module_t mod) 13125537Sdfr{ 13225537Sdfr MOD_DPF(REFS, ("module_reference: before, refs=%d\n", mod->refs)); 13325537Sdfr 13425537Sdfr mod->refs++; 13525537Sdfr} 13625537Sdfr 13725537Sdfrvoid 13825537Sdfrmodule_release(module_t mod) 13925537Sdfr{ 14025537Sdfr if (mod->refs <= 0) 14125537Sdfr panic("module_release: bad reference count"); 14225537Sdfr 14325537Sdfr MOD_DPF(REFS, ("module_release: before, refs=%d\n", mod->refs)); 14425537Sdfr 14525537Sdfr mod->refs--; 14625537Sdfr if (mod->refs == 0) { 14725537Sdfr TAILQ_REMOVE(&modules, mod, link); 14825537Sdfr if (mod->file) { 14925537Sdfr TAILQ_REMOVE(&mod->file->modules, mod, flink); 15025537Sdfr } 15125537Sdfr free(mod, M_MODULE); 15225537Sdfr } 15325537Sdfr} 15425537Sdfr 15525537Sdfrmodule_t 15625537Sdfrmodule_lookupbyname(const char* name) 15725537Sdfr{ 15825537Sdfr module_t mod; 15925537Sdfr 16025537Sdfr for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) { 16125537Sdfr if (!strcmp(mod->name, name)) 16225537Sdfr return mod; 16325537Sdfr } 16425537Sdfr 16525537Sdfr return 0; 16625537Sdfr} 16725537Sdfr 16825537Sdfrmodule_t 16925537Sdfrmodule_lookupbyid(int modid) 17025537Sdfr{ 17125537Sdfr module_t mod; 17225537Sdfr 17325537Sdfr for (mod = TAILQ_FIRST(&modules); mod; mod = TAILQ_NEXT(mod, link)) { 17425537Sdfr if (mod->id == modid) 17525537Sdfr return mod; 17625537Sdfr } 17725537Sdfr 17825537Sdfr return 0; 17925537Sdfr} 18025537Sdfr 18125537Sdfrint 18225537Sdfrmodule_unload(module_t mod) 18325537Sdfr{ 18425537Sdfr return MOD_EVENT(mod, MOD_UNLOAD); 18525537Sdfr} 18625537Sdfr 18725537Sdfrint 18825537Sdfrmodule_getid(module_t mod) 18925537Sdfr{ 19025537Sdfr return mod->id; 19125537Sdfr} 19225537Sdfr 19325537Sdfrmodule_t 19425537Sdfrmodule_getfnext(module_t mod) 19525537Sdfr{ 19625537Sdfr return TAILQ_NEXT(mod, flink); 19725537Sdfr} 19825537Sdfr 19925537Sdfr/* 20025537Sdfr * Syscalls. 20125537Sdfr */ 20225537Sdfrint 20330994Sphkmodnext(struct proc* p, struct modnext_args* uap) 20425537Sdfr{ 20525537Sdfr module_t mod; 20625537Sdfr 20730994Sphk p->p_retval[0] = -1; 20825537Sdfr if (SCARG(uap, modid) == 0) { 20925537Sdfr mod = TAILQ_FIRST(&modules); 21025537Sdfr if (mod) { 21130994Sphk p->p_retval[0] = mod->id; 21225537Sdfr return 0; 21325537Sdfr } else 21425537Sdfr return ENOENT; 21525537Sdfr } 21625537Sdfr 21725537Sdfr mod = module_lookupbyid(SCARG(uap, modid)); 21825537Sdfr if (!mod) 21925537Sdfr return ENOENT; 22025537Sdfr 22125537Sdfr if (TAILQ_NEXT(mod, link)) 22230994Sphk p->p_retval[0] = TAILQ_NEXT(mod, link)->id; 22325537Sdfr else 22430994Sphk p->p_retval[0] = 0; 22525537Sdfr return 0; 22625537Sdfr} 22725537Sdfr 22825537Sdfrint 22930994Sphkmodfnext(struct proc* p, struct modfnext_args* uap) 23025537Sdfr{ 23125537Sdfr module_t mod; 23225537Sdfr 23330994Sphk p->p_retval[0] = -1; 23425537Sdfr 23525537Sdfr mod = module_lookupbyid(SCARG(uap, modid)); 23625537Sdfr if (!mod) 23725537Sdfr return ENOENT; 23825537Sdfr 23925537Sdfr if (TAILQ_NEXT(mod, flink)) 24030994Sphk p->p_retval[0] = TAILQ_NEXT(mod, flink)->id; 24125537Sdfr else 24230994Sphk p->p_retval[0] = 0; 24325537Sdfr return 0; 24425537Sdfr} 24525537Sdfr 24625537Sdfrint 24730994Sphkmodstat(struct proc* p, struct modstat_args* uap) 24825537Sdfr{ 24925537Sdfr module_t mod; 25025537Sdfr int error = 0; 25125537Sdfr int namelen; 25225537Sdfr int version; 25325537Sdfr struct module_stat* stat; 25425537Sdfr 25525537Sdfr mod = module_lookupbyid(SCARG(uap, modid)); 25625537Sdfr if (!mod) 25725537Sdfr return ENOENT; 25825537Sdfr 25925537Sdfr stat = SCARG(uap, stat); 26025537Sdfr 26125537Sdfr /* 26225537Sdfr * Check the version of the user's structure. 26325537Sdfr */ 26425537Sdfr if (error = copyin(&stat->version, &version, sizeof(version))) 26525537Sdfr goto out; 26625537Sdfr if (version != sizeof(struct module_stat)) { 26725537Sdfr error = EINVAL; 26825537Sdfr goto out; 26925537Sdfr } 27025537Sdfr 27125537Sdfr namelen = strlen(mod->name) + 1; 27225537Sdfr if (namelen > MAXMODNAME) 27325537Sdfr namelen = MAXMODNAME; 27425537Sdfr if (error = copyout(mod->name, &stat->name[0], namelen)) 27525537Sdfr goto out; 27625537Sdfr 27725537Sdfr if (error = copyout(&mod->refs, &stat->refs, sizeof(int))) 27825537Sdfr goto out; 27925537Sdfr if (error = copyout(&mod->id, &stat->id, sizeof(int))) 28025537Sdfr goto out; 28125537Sdfr 28230994Sphk p->p_retval[0] = 0; 28325537Sdfr 28425537Sdfrout: 28525537Sdfr return error; 28625537Sdfr} 28725537Sdfr 28825537Sdfrint 28930994Sphkmodfind(struct proc* p, struct modfind_args* uap) 29025537Sdfr{ 29125537Sdfr int error = 0; 29225537Sdfr char name[MAXMODNAME]; 29325537Sdfr module_t mod; 29425537Sdfr 29525537Sdfr if (error = copyinstr(SCARG(uap, name), name, sizeof name, 0)) 29625537Sdfr goto out; 29725537Sdfr 29825537Sdfr mod = module_lookupbyname(name); 29925537Sdfr if (!mod) 30025537Sdfr error = ENOENT; 30125537Sdfr else 30230994Sphk p->p_retval[0] = mod->id; 30325537Sdfr 30425537Sdfrout: 30525537Sdfr return error; 30625537Sdfr} 307