module.c revision 65613
138465Smsmith/*- 238465Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 338465Smsmith * All rights reserved. 438465Smsmith * 538465Smsmith * Redistribution and use in source and binary forms, with or without 638465Smsmith * modification, are permitted provided that the following conditions 738465Smsmith * are met: 838465Smsmith * 1. Redistributions of source code must retain the above copyright 938465Smsmith * notice, this list of conditions and the following disclaimer. 1038465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1138465Smsmith * notice, this list of conditions and the following disclaimer in the 1238465Smsmith * documentation and/or other materials provided with the distribution. 1338465Smsmith * 1438465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738465Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438465Smsmith * SUCH DAMAGE. 2538465Smsmith * 2650477Speter * $FreeBSD: head/sys/boot/common/module.c 65613 2000-09-08 16:47:05Z dcs $ 2738465Smsmith */ 2838465Smsmith 2938465Smsmith/* 3059854Sbp * file/module function dispatcher, support, etc. 3138465Smsmith */ 3238465Smsmith 3338465Smsmith#include <stand.h> 3438465Smsmith#include <string.h> 3540141Speter#include <sys/param.h> 3640141Speter#include <sys/linker.h> 3738465Smsmith 3838465Smsmith#include "bootstrap.h" 3938465Smsmith 4059854Sbpstatic int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); 4159854Sbpstatic int file_loadraw(char *type, char *name); 4259854Sbpstatic int file_load_dependancies(struct preloaded_file *base_mod); 4359854Sbpstatic char * file_search(char *name); 4459854Sbpstruct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname); 4538764Smsmithstatic char *mod_searchmodule(char *name); 4659854Sbpstatic void file_insert_tail(struct preloaded_file *mp); 4759854Sbpstruct file_metadata* metadata_next(struct file_metadata *base_mp, int type); 4838764Smsmith 4939178Smsmith/* load address should be tweaked by first module loaded (kernel) */ 5038465Smsmithstatic vm_offset_t loadaddr = 0; 5138465Smsmith 5265501Sobrienstatic const char *default_searchpath ="/boot/modules;/modules;/boot/kernel"; 5339178Smsmith 5459854Sbpstruct preloaded_file *preloaded_files = NULL; 5538465Smsmith 5638764Smsmith/* 5738764Smsmith * load an object, either a disk file or code module. 5838764Smsmith * 5938764Smsmith * To load a file, the syntax is: 6038764Smsmith * 6138764Smsmith * load -t <type> <path> 6238764Smsmith * 6338764Smsmith * code modules are loaded as: 6438764Smsmith * 6538764Smsmith * load <path> <options> 6638764Smsmith */ 6738764Smsmith 6838465SmsmithCOMMAND_SET(load, "load", "load a kernel or module", command_load); 6938465Smsmith 7038465Smsmithstatic int 7138465Smsmithcommand_load(int argc, char *argv[]) 7238465Smsmith{ 7338764Smsmith char *typestr; 7457468Sbp int dofile, ch, error; 7538764Smsmith 7638764Smsmith dofile = 0; 7738764Smsmith optind = 1; 7842512Smsmith optreset = 1; 7938764Smsmith typestr = NULL; 8053993Sdcs if (argc == 1) { 8153993Sdcs command_errmsg = "no filename specified"; 8253993Sdcs return(CMD_ERROR); 8353993Sdcs } 8438764Smsmith while ((ch = getopt(argc, argv, "t:")) != -1) { 8538764Smsmith switch(ch) { 8638764Smsmith case 't': 8738764Smsmith typestr = optarg; 8838764Smsmith dofile = 1; 8938764Smsmith break; 9038764Smsmith case '?': 9138764Smsmith default: 9238764Smsmith /* getopt has already reported an error */ 9338764Smsmith return(CMD_OK); 9438764Smsmith } 9538764Smsmith } 9638764Smsmith argv += (optind - 1); 9738764Smsmith argc -= (optind - 1); 9838764Smsmith 9938764Smsmith /* 10038764Smsmith * Request to load a raw file? 10138764Smsmith */ 10238764Smsmith if (dofile) { 10338764Smsmith if ((typestr == NULL) || (*typestr == 0)) { 10438764Smsmith command_errmsg = "invalid load type"; 10538764Smsmith return(CMD_ERROR); 10638764Smsmith } 10759854Sbp return(file_loadraw(typestr, argv[1])); 10838764Smsmith } 10938764Smsmith 11038764Smsmith /* 11138764Smsmith * Looks like a request for a module. 11238764Smsmith */ 11357468Sbp error = mod_load(argv[1], argc - 2, argv + 2); 11457468Sbp if (error == EEXIST) 11557468Sbp sprintf(command_errbuf, "warning: module '%s' already loaded", argv[1]); 11657468Sbp return (error == 0 ? CMD_OK : CMD_ERROR); 11738465Smsmith} 11838465Smsmith 11938712SmsmithCOMMAND_SET(unload, "unload", "unload all modules", command_unload); 12038712Smsmith 12138712Smsmithstatic int 12238712Smsmithcommand_unload(int argc, char *argv[]) 12338712Smsmith{ 12459854Sbp struct preloaded_file *fp; 12538712Smsmith 12659854Sbp while (preloaded_files != NULL) { 12759854Sbp fp = preloaded_files; 12859854Sbp preloaded_files = preloaded_files->f_next; 12959854Sbp file_discard(fp); 13038712Smsmith } 13138712Smsmith loadaddr = 0; 13265613Sdcs unsetenv("kernelname"); 13338712Smsmith return(CMD_OK); 13438712Smsmith} 13538712Smsmith 13638465SmsmithCOMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 13738465Smsmith 13838465Smsmithstatic int 13938465Smsmithcommand_lsmod(int argc, char *argv[]) 14038465Smsmith{ 14159854Sbp struct preloaded_file *fp; 14259854Sbp struct kernel_module *mp; 14359854Sbp struct file_metadata *md; 14438465Smsmith char lbuf[80]; 14538764Smsmith int ch, verbose; 14638764Smsmith 14738764Smsmith verbose = 0; 14838764Smsmith optind = 1; 14942512Smsmith optreset = 1; 15038764Smsmith while ((ch = getopt(argc, argv, "v")) != -1) { 15138764Smsmith switch(ch) { 15238764Smsmith case 'v': 15338764Smsmith verbose = 1; 15438764Smsmith break; 15538764Smsmith case '?': 15638764Smsmith default: 15738764Smsmith /* getopt has already reported an error */ 15838764Smsmith return(CMD_OK); 15938764Smsmith } 16038764Smsmith } 16138764Smsmith 16238465Smsmith pager_open(); 16359854Sbp for (fp = preloaded_files; fp; fp = fp->f_next) { 16439673Sdfr sprintf(lbuf, " %p: %s (%s, 0x%lx)\n", 16559854Sbp (void *) fp->f_addr, fp->f_name, fp->f_type, (long) fp->f_size); 16638465Smsmith pager_output(lbuf); 16759854Sbp if (fp->f_args != NULL) { 16838465Smsmith pager_output(" args: "); 16959854Sbp pager_output(fp->f_args); 17038465Smsmith pager_output("\n"); 17138465Smsmith } 17259854Sbp if (fp->f_modules) { 17359854Sbp pager_output(" modules: "); 17459854Sbp for (mp = fp->f_modules; mp; mp = mp->m_next) { 17559854Sbp sprintf(lbuf, "%s ", mp->m_name); 17659854Sbp pager_output(lbuf); 17759854Sbp } 17859854Sbp pager_output("\n"); 17959854Sbp } 18059854Sbp if (verbose) { 18138764Smsmith /* XXX could add some formatting smarts here to display some better */ 18259854Sbp for (md = fp->f_metadata; md != NULL; md = md->md_next) { 18339673Sdfr sprintf(lbuf, " 0x%04x, 0x%lx\n", md->md_type, (long) md->md_size); 18438764Smsmith pager_output(lbuf); 18538764Smsmith } 18659854Sbp } 18738465Smsmith } 18838465Smsmith pager_close(); 18938465Smsmith return(CMD_OK); 19038465Smsmith} 19138465Smsmith 19238764Smsmith/* 19359854Sbp * File level interface, functions file_* 19438764Smsmith */ 19538465Smsmithint 19659854Sbpfile_load(char *filename, vm_offset_t dest, struct preloaded_file **result) 19738465Smsmith{ 19859854Sbp struct preloaded_file *fp; 19959854Sbp int error; 20059854Sbp int i; 20138764Smsmith 20259854Sbp error = EFTYPE; 20359854Sbp for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) { 20459854Sbp error = (file_formats[i]->l_load)(filename, loadaddr, &fp); 20559854Sbp if (error == 0) { 20659854Sbp fp->f_loader = i; /* remember the loader */ 20759854Sbp *result = fp; 20859854Sbp break; 20959854Sbp } 21059854Sbp if (error == EFTYPE) 21159854Sbp continue; /* Unknown to this handler? */ 21259854Sbp if (error) { 21359854Sbp sprintf(command_errbuf, "can't load file '%s': %s", 21459854Sbp filename, strerror(error)); 21559854Sbp break; 21659854Sbp } 21759854Sbp } 21859854Sbp return (error); 21959854Sbp} 22038465Smsmith 22159854Sbpstatic int 22259854Sbpfile_load_dependancies(struct preloaded_file *base_file) { 22359854Sbp struct file_metadata *md; 22459854Sbp struct preloaded_file *fp; 22559854Sbp char *dmodname; 22659854Sbp int error; 22759854Sbp 22859854Sbp md = file_findmetadata(base_file, MODINFOMD_DEPLIST); 22959854Sbp if (md == NULL) 23059854Sbp return (0); 23159854Sbp error = 0; 23259854Sbp do { 23359854Sbp dmodname = (char *)md->md_data; 23459854Sbp if (file_findmodule(NULL, dmodname) == NULL) { 23559854Sbp printf("loading required module '%s'\n", dmodname); 23659854Sbp error = mod_load(dmodname, 0, NULL); 23759854Sbp if (error) 23859854Sbp break; 23959854Sbp } 24059854Sbp md = metadata_next(md, MODINFOMD_DEPLIST); 24159854Sbp } while (md); 24257468Sbp if (!error) 24357468Sbp return (0); 24457468Sbp /* Load failed; discard everything */ 24559854Sbp while (base_file != NULL) { 24659854Sbp fp = base_file; 24759854Sbp base_file = base_file->f_next; 24859854Sbp file_discard(fp); 24938764Smsmith } 25057468Sbp return (error); 25138764Smsmith} 25238764Smsmith/* 25338764Smsmith * We've been asked to load (name) as (type), so just suck it in, 25438764Smsmith * no arguments or anything. 25538764Smsmith */ 25638764Smsmithint 25759854Sbpfile_loadraw(char *type, char *name) 25838764Smsmith{ 25959854Sbp struct preloaded_file *fp; 26038764Smsmith char *cp; 26138764Smsmith int fd, got; 26238764Smsmith vm_offset_t laddr; 26338764Smsmith 26438764Smsmith /* We can't load first */ 26559854Sbp if ((file_findfile(NULL, NULL)) == NULL) { 26638764Smsmith command_errmsg = "can't load file before kernel"; 26738764Smsmith return(CMD_ERROR); 26838764Smsmith } 26938764Smsmith 27039178Smsmith /* locate the file on the load path */ 27159854Sbp cp = file_search(name); 27239178Smsmith if (cp == NULL) { 27339178Smsmith sprintf(command_errbuf, "can't find '%s'", name); 27439178Smsmith return(CMD_ERROR); 27539178Smsmith } 27639178Smsmith name = cp; 27738764Smsmith 27838764Smsmith if ((fd = open(name, O_RDONLY)) < 0) { 27938764Smsmith sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); 28044570Sdcs free(name); 28138764Smsmith return(CMD_ERROR); 28238764Smsmith } 28338764Smsmith 28438764Smsmith laddr = loadaddr; 28538764Smsmith for (;;) { 28638764Smsmith /* read in 4k chunks; size is not really important */ 28738764Smsmith got = archsw.arch_readin(fd, laddr, 4096); 28838764Smsmith if (got == 0) /* end of file */ 28938764Smsmith break; 29038764Smsmith if (got < 0) { /* error */ 29138764Smsmith sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); 29244210Sdcs free(name); 29357269Smsmith close(fd); 29438764Smsmith return(CMD_ERROR); 29538764Smsmith } 29638764Smsmith laddr += got; 29738764Smsmith } 29838764Smsmith 29938764Smsmith /* Looks OK so far; create & populate control structure */ 30059854Sbp fp = file_alloc(); 30159854Sbp fp->f_name = name; 30259854Sbp fp->f_type = strdup(type); 30359854Sbp fp->f_args = NULL; 30459854Sbp fp->f_metadata = NULL; 30559854Sbp fp->f_loader = -1; 30659854Sbp fp->f_addr = loadaddr; 30759854Sbp fp->f_size = laddr - loadaddr; 30838764Smsmith 30938764Smsmith /* recognise space consumption */ 31038764Smsmith loadaddr = laddr; 31138764Smsmith 31259854Sbp /* Add to the list of loaded files */ 31359854Sbp file_insert_tail(fp); 31457269Smsmith close(fd); 31538764Smsmith return(CMD_OK); 31638764Smsmith} 31738764Smsmith 31838764Smsmith/* 31959854Sbp * Load the module (name), pass it (argc),(argv), add container file 32059854Sbp * to the list of loaded files. 32159854Sbp * If module is already loaded just assign new argc/argv. 32238764Smsmith */ 32359854Sbpint 32459854Sbpmod_load(char *modname, int argc, char *argv[]) 32538764Smsmith{ 32659854Sbp struct preloaded_file *fp, *last_file; 32759854Sbp struct kernel_module *mp; 32859854Sbp int err; 32959854Sbp char *filename; 33038764Smsmith 33157468Sbp /* see if module is already loaded */ 33259854Sbp mp = file_findmodule(NULL, modname); 33357468Sbp if (mp) { 33459854Sbp#ifdef moduleargs 33559854Sbp if (mp->m_args) 33659854Sbp free(mp->m_args); 33759854Sbp mp->m_args = unargv(argc, argv); 33859854Sbp#endif 33959854Sbp sprintf(command_errbuf, "warning: module '%s' already loaded", mp->m_name); 34059854Sbp return (0); 34157468Sbp } 34259854Sbp /* locate file with the module on the search path */ 34359854Sbp filename = mod_searchmodule(modname); 34459854Sbp if (filename == NULL) { 34559854Sbp sprintf(command_errbuf, "can't find '%s'", modname); 34659854Sbp return (ENOENT); 34759854Sbp } 34859854Sbp for (last_file = preloaded_files; 34959854Sbp last_file != NULL && last_file->f_next != NULL; 35059854Sbp last_file = last_file->f_next) 35159854Sbp ; 35257468Sbp 35359854Sbp fp = NULL; 35459854Sbp do { 35559854Sbp err = file_load(filename, loadaddr, &fp); 35659854Sbp if (err) 35738764Smsmith break; 35859854Sbp#ifdef moduleargs 35959854Sbp mp = file_findmodule(fp, modname); 36059854Sbp if (mp == NULL) { 36159854Sbp sprintf(command_errbuf, "module '%s' not found in the file '%s': %s", 36259854Sbp modname, filename, strerror(err)); 36359854Sbp err = ENOENT; 36459854Sbp break; 36538465Smsmith } 36659854Sbp mp->m_args = unargv(argc, argv); 36759854Sbp#else 36859854Sbp fp->f_args = unargv(argc, argv); 36959854Sbp#endif 37059854Sbp loadaddr = fp->f_addr + fp->f_size; 37159854Sbp file_insert_tail(fp); /* Add to the list of loaded files */ 37259854Sbp if (file_load_dependancies(fp) != 0) { 37359854Sbp err = ENOENT; 37459854Sbp last_file->f_next = NULL; 37559854Sbp loadaddr = last_file->f_addr + last_file->f_size; 37659854Sbp fp = NULL; 37759854Sbp break; 37859854Sbp } 37959854Sbp } while(0); 38038764Smsmith if (err == EFTYPE) 38159854Sbp sprintf(command_errbuf, "don't know how to load module '%s'", filename); 38259854Sbp if (err && fp) 38359854Sbp file_discard(fp); 38459854Sbp free(filename); 38557468Sbp return (err); 38638764Smsmith} 38738764Smsmith 38859854Sbp/* 38959854Sbp * Find a file matching (name) and (type). 39059854Sbp * NULL may be passed as a wildcard to either. 39159854Sbp */ 39259854Sbpstruct preloaded_file * 39359854Sbpfile_findfile(char *name, char *type) 39438764Smsmith{ 39559854Sbp struct preloaded_file *fp; 39638764Smsmith 39759854Sbp for (fp = preloaded_files; fp != NULL; fp = fp->f_next) { 39859854Sbp if (((name == NULL) || !strcmp(name, fp->f_name)) && 39959854Sbp ((type == NULL) || !strcmp(type, fp->f_type))) 40059854Sbp break; 40159854Sbp } 40259854Sbp return (fp); 40338465Smsmith} 40438465Smsmith 40538764Smsmith/* 40659854Sbp * Find a module matching (name) inside of given file. 40759854Sbp * NULL may be passed as a wildcard. 40838764Smsmith */ 40959854Sbpstruct kernel_module * 41059854Sbpfile_findmodule(struct preloaded_file *fp, char *modname) 41138465Smsmith{ 41259854Sbp struct kernel_module *mp; 41359854Sbp 41459854Sbp if (fp == NULL) { 41559854Sbp for (fp = preloaded_files; fp; fp = fp->f_next) { 41659854Sbp for (mp = fp->f_modules; mp; mp = mp->m_next) { 41759854Sbp if (strcmp(modname, mp->m_name) == 0) 41859854Sbp return (mp); 41959854Sbp } 42059854Sbp } 42159854Sbp return (NULL); 42238465Smsmith } 42359854Sbp for (mp = fp->f_modules; mp; mp = mp->m_next) { 42459854Sbp if (strcmp(modname, mp->m_name) == 0) 42559854Sbp return (mp); 42659854Sbp } 42759854Sbp return (NULL); 42838465Smsmith} 42938764Smsmith/* 43038764Smsmith * Make a copy of (size) bytes of data from (p), and associate them as 43138764Smsmith * metadata of (type) to the module (mp). 43238764Smsmith */ 43338712Smsmithvoid 43459854Sbpfile_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p) 43538712Smsmith{ 43659854Sbp struct file_metadata *md; 43738712Smsmith 43864187Sjhb md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size); 43938712Smsmith md->md_size = size; 44038712Smsmith md->md_type = type; 44138712Smsmith bcopy(p, md->md_data, size); 44259854Sbp md->md_next = fp->f_metadata; 44359854Sbp fp->f_metadata = md; 44438712Smsmith} 44538712Smsmith 44638764Smsmith/* 44759854Sbp * Find a metadata object of (type) associated with the file (fp) 44838764Smsmith */ 44959854Sbpstruct file_metadata * 45059854Sbpfile_findmetadata(struct preloaded_file *fp, int type) 45138712Smsmith{ 45259854Sbp struct file_metadata *md; 45338712Smsmith 45459854Sbp for (md = fp->f_metadata; md != NULL; md = md->md_next) 45538712Smsmith if (md->md_type == type) 45638712Smsmith break; 45738712Smsmith return(md); 45838712Smsmith} 45938764Smsmith 46059854Sbpstruct file_metadata * 46159854Sbpmetadata_next(struct file_metadata *md, int type) 46257468Sbp{ 46357468Sbp if (md == NULL) 46457468Sbp return (NULL); 46557468Sbp while((md = md->md_next) != NULL) 46657468Sbp if (md->md_type == type) 46757468Sbp break; 46857468Sbp return (md); 46957468Sbp} 47057468Sbp 47138764Smsmith/* 47239178Smsmith * Attempt to find the file (name) on the module searchpath. 47338764Smsmith * If (name) is qualified in any way, we simply check it and 47438764Smsmith * return it or NULL. If it is not qualified, then we attempt 47538764Smsmith * to construct a path using entries in the environment variable 47638764Smsmith * module_path. 47738764Smsmith * 47838764Smsmith * The path we return a pointer to need never be freed, as we manage 47938764Smsmith * it internally. 48038764Smsmith */ 48138764Smsmithstatic char * 48259854Sbpfile_search(char *name) 48338764Smsmith{ 48444570Sdcs char *result; 48539673Sdfr char *path, *sp; 48639673Sdfr const char *cp; 48738764Smsmith struct stat sb; 48838764Smsmith 48938764Smsmith /* Don't look for nothing */ 49044210Sdcs if (name == NULL) 49138764Smsmith return(name); 49238764Smsmith 49344210Sdcs if (*name == 0) 49444210Sdcs return(strdup(name)); 49544210Sdcs 49638764Smsmith /* 49738764Smsmith * See if there's a device on the front, or a directory name. 49838764Smsmith */ 49938764Smsmith archsw.arch_getdev(NULL, name, &cp); 50038764Smsmith if ((cp != name) || (strchr(name, '/') != NULL)) { 50138764Smsmith /* Qualified, so just see if it exists */ 50238764Smsmith if (stat(name, &sb) == 0) 50344210Sdcs return(strdup(name)); 50438764Smsmith return(NULL); 50538764Smsmith } 50638764Smsmith 50738764Smsmith /* 50838764Smsmith * Get the module path 50938764Smsmith */ 51038764Smsmith if ((cp = getenv("module_path")) == NULL) 51139178Smsmith cp = default_searchpath; 51238764Smsmith sp = path = strdup(cp); 51338764Smsmith 51438764Smsmith /* 51538764Smsmith * Traverse the path, splitting off ';'-delimited components. 51638764Smsmith */ 51744570Sdcs result = NULL; 51838764Smsmith while((cp = strsep(&path, ";")) != NULL) { 51939178Smsmith result = malloc(strlen(cp) + strlen(name) + 5); 52039178Smsmith strcpy(result, cp); 52139178Smsmith if (cp[strlen(cp) - 1] != '/') 52239178Smsmith strcat(result, "/"); 52339178Smsmith strcat(result, name); 52439178Smsmith if ((stat(result, &sb) == 0) && 52539178Smsmith S_ISREG(sb.st_mode)) 52638764Smsmith break; 52738764Smsmith free(result); 52838764Smsmith result = NULL; 52938764Smsmith } 53038764Smsmith free(sp); 53138764Smsmith return(result); 53238764Smsmith} 53338764Smsmith 53438764Smsmith/* 53539178Smsmith * Attempt to locate the file containing the module (name) 53639178Smsmith */ 53739178Smsmithstatic char * 53839178Smsmithmod_searchmodule(char *name) 53939178Smsmith{ 54039178Smsmith char *tn, *result; 54139178Smsmith 54239178Smsmith /* Look for (name).ko */ 54339673Sdfr tn = malloc(strlen(name) + 3 + 1); 54439178Smsmith strcpy(tn, name); 54539178Smsmith strcat(tn, ".ko"); 54659854Sbp result = file_search(tn); 54739178Smsmith free(tn); 54839178Smsmith /* Look for just (name) (useful for finding kernels) */ 54939178Smsmith if (result == NULL) 55059854Sbp result = file_search(name); 55139178Smsmith 55239178Smsmith return(result); 55339178Smsmith} 55439178Smsmith 55559854Sbpint 55659854Sbpfile_addmodule(struct preloaded_file *fp, char *modname, 55759854Sbp struct kernel_module **newmp) 55859854Sbp{ 55959854Sbp struct kernel_module *mp; 56039178Smsmith 56159854Sbp mp = file_findmodule(fp, modname); 56259854Sbp if (mp) 56359854Sbp return (EEXIST); 56459854Sbp mp = malloc(sizeof(struct kernel_module)); 56559854Sbp if (mp == NULL) 56659854Sbp return (ENOMEM); 56759854Sbp bzero(mp, sizeof(struct kernel_module)); 56859854Sbp mp->m_name = strdup(modname); 56959854Sbp mp->m_fp = fp; 57059854Sbp mp->m_next = fp->f_modules; 57159854Sbp fp->f_modules = mp; 57259854Sbp if (newmp) 57359854Sbp *newmp = mp; 57459854Sbp return (0); 57559854Sbp} 57659854Sbp 57739178Smsmith/* 57859854Sbp * Throw a file away 57938764Smsmith */ 58038764Smsmithvoid 58159854Sbpfile_discard(struct preloaded_file *fp) 58238764Smsmith{ 58359854Sbp struct file_metadata *md, *md1; 58459854Sbp struct kernel_module *mp, *mp1; 58559854Sbp if (fp == NULL) 58659854Sbp return; 58759854Sbp md = fp->f_metadata; 58859854Sbp while (md) { 58959854Sbp md1 = md; 59059854Sbp md = md->md_next; 59159854Sbp free(md1); 59259854Sbp } 59359854Sbp mp = fp->f_modules; 59459854Sbp while (mp) { 59559854Sbp if (mp->m_name) 59639178Smsmith free(mp->m_name); 59759854Sbp mp1 = mp; 59859854Sbp mp = mp->m_next; 59959854Sbp free(mp1); 60059854Sbp } 60159854Sbp if (fp->f_name != NULL) 60259854Sbp free(fp->f_name); 60359854Sbp if (fp->f_type != NULL) 60459854Sbp free(fp->f_type); 60559854Sbp if (fp->f_args != NULL) 60659854Sbp free(fp->f_args); 60759854Sbp free(fp); 60838764Smsmith} 60938764Smsmith 61038764Smsmith/* 61159854Sbp * Allocate a new file; must be used instead of malloc() 61239178Smsmith * to ensure safe initialisation. 61339178Smsmith */ 61459854Sbpstruct preloaded_file * 61559854Sbpfile_alloc(void) 61639178Smsmith{ 61759854Sbp struct preloaded_file *fp; 61839178Smsmith 61959854Sbp if ((fp = malloc(sizeof(struct preloaded_file))) != NULL) { 62059854Sbp bzero(fp, sizeof(struct preloaded_file)); 62139178Smsmith } 62259854Sbp return (fp); 62339178Smsmith} 62439178Smsmith 62539178Smsmith/* 62638764Smsmith * Add a module to the chain 62738764Smsmith */ 62838764Smsmithstatic void 62959854Sbpfile_insert_tail(struct preloaded_file *fp) 63038764Smsmith{ 63159854Sbp struct preloaded_file *cm; 63238764Smsmith 63359854Sbp /* Append to list of loaded file */ 63459854Sbp fp->f_next = NULL; 63559854Sbp if (preloaded_files == NULL) { 63659854Sbp preloaded_files = fp; 63738764Smsmith } else { 63859854Sbp for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) 63938764Smsmith ; 64059854Sbp cm->f_next = fp; 64138764Smsmith } 64238764Smsmith} 64359854Sbp 644