1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
| 1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
|
26 * $Id: module.c,v 1.2 1998/08/31 21:10:42 msmith Exp $
| 26 * $Id: module.c,v 1.3 1998/09/03 02:10:08 msmith Exp $
|
27 */ 28 29/* 30 * module function dispatcher, support, etc.
| 27 */ 28 29/* 30 * module function dispatcher, support, etc.
|
31 * 32 * XXX need a 'searchmodule' function that takes a name and 33 * traverses a search path.
| |
34 */ 35 36#include <stand.h> 37#include <string.h> 38 39#include "bootstrap.h" 40 41static struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]); 42static char *mod_searchdep(struct loaded_module *mp);
| 31 */ 32 33#include <stand.h> 34#include <string.h> 35 36#include "bootstrap.h" 37 38static struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]); 39static char *mod_searchdep(struct loaded_module *mp);
|
| 40static char *mod_searchfile(char *name);
|
43static char *mod_searchmodule(char *name); 44static void mod_append(struct loaded_module *mp); 45
| 41static char *mod_searchmodule(char *name); 42static void mod_append(struct loaded_module *mp); 43
|
46/* XXX load address should be tweaked by first module loaded (kernel) */
| 44/* load address should be tweaked by first module loaded (kernel) */
|
47static vm_offset_t loadaddr = 0; 48
| 45static vm_offset_t loadaddr = 0; 46
|
| 47static char *default_searchpath ="/;/boot"; 48
|
49struct loaded_module *loaded_modules = NULL; 50 51/* 52 * load an object, either a disk file or code module. 53 * 54 * To load a file, the syntax is: 55 * 56 * load -t <type> <path> 57 * 58 * code modules are loaded as: 59 * 60 * load <path> <options> 61 */ 62 63COMMAND_SET(load, "load", "load a kernel or module", command_load); 64 65static int 66command_load(int argc, char *argv[]) 67{ 68 char *typestr; 69 int dofile, ch; 70 71 dofile = 0; 72 optind = 1; 73 typestr = NULL; 74 while ((ch = getopt(argc, argv, "t:")) != -1) { 75 switch(ch) { 76 case 't': 77 typestr = optarg; 78 dofile = 1; 79 break; 80 case '?': 81 default: 82 /* getopt has already reported an error */ 83 return(CMD_OK); 84 } 85 } 86 argv += (optind - 1); 87 argc -= (optind - 1); 88 89 /* 90 * Request to load a raw file? 91 */ 92 if (dofile) { 93 if ((typestr == NULL) || (*typestr == 0)) { 94 command_errmsg = "invalid load type"; 95 return(CMD_ERROR); 96 } 97 return(mod_loadobj(typestr, argv[1])); 98 } 99 100 /* 101 * Looks like a request for a module. 102 */ 103 return(mod_load(argv[1], argc - 2, argv + 2)); 104} 105 106COMMAND_SET(unload, "unload", "unload all modules", command_unload); 107 108static int 109command_unload(int argc, char *argv[]) 110{ 111 struct loaded_module *mp; 112 113 while (loaded_modules != NULL) { 114 mp = loaded_modules; 115 loaded_modules = loaded_modules->m_next; 116 mod_discard(mp); 117 } 118 loadaddr = 0; 119 return(CMD_OK); 120} 121 122COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 123 124static int 125command_lsmod(int argc, char *argv[]) 126{ 127 struct loaded_module *am; 128 struct module_metadata *md; 129 char lbuf[80]; 130 int ch, verbose; 131 132 verbose = 0; 133 optind = 1; 134 while ((ch = getopt(argc, argv, "v")) != -1) { 135 switch(ch) { 136 case 'v': 137 verbose = 1; 138 break; 139 case '?': 140 default: 141 /* getopt has already reported an error */ 142 return(CMD_OK); 143 } 144 } 145 146 pager_open(); 147 for (am = loaded_modules; (am != NULL); am = am->m_next) { 148 sprintf(lbuf, " %x: %s (%s, 0x%x)\n", 149 am->m_addr, am->m_name, am->m_type, am->m_size); 150 pager_output(lbuf); 151 if (am->m_args != NULL) { 152 pager_output(" args: "); 153 pager_output(am->m_args); 154 pager_output("\n"); 155 } 156 if (verbose) 157 /* XXX could add some formatting smarts here to display some better */ 158 for (md = am->m_metadata; md != NULL; md = md->md_next) { 159 sprintf(lbuf, " 0x%04x, 0x%x\n", md->md_type, md->md_size); 160 pager_output(lbuf); 161 } 162 } 163 pager_close(); 164 return(CMD_OK); 165} 166 167/* 168 * We've been asked to load (name) and give it (argc),(argv). 169 * Start by trying to load it, and then attempt to load all of its 170 * dependancies. If we fail at any point, throw them all away and 171 * fail the entire load. 172 * 173 * XXX if a depended-on module requires arguments, it must be loaded 174 * explicitly first. 175 */ 176int 177mod_load(char *name, int argc, char *argv[]) 178{ 179 struct loaded_module *last_mod, *base_mod, *mp; 180 char *dep_name; 181 182 /* remember previous last module on chain */ 183 for (last_mod = loaded_modules; 184 (last_mod != NULL) && (last_mod->m_next != NULL); 185 last_mod = last_mod->m_next) 186 ; 187 188 /* 189 * Load the first module; note that it's the only one that gets 190 * arguments explicitly. 191 */ 192 if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL) 193 return(CMD_ERROR); 194 195 /* 196 * Look for dependancies. 197 */ 198 while ((dep_name = mod_searchdep(base_mod)) != NULL) { 199 printf("loading required module '%s'\n", dep_name); 200 if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) { 201 /* Load failed; discard everything */ 202 while (base_mod != NULL) { 203 mp = base_mod; 204 base_mod = base_mod->m_next; 205 mod_discard(mp); 206 } 207 last_mod->m_next = NULL; 208 loadaddr = last_mod->m_addr + last_mod->m_size; 209 /* error message already set by mod_loadmodule */ 210 return(CMD_ERROR); 211 } 212 } 213 return(CMD_OK); 214} 215 216/* 217 * We've been asked to load (name) as (type), so just suck it in, 218 * no arguments or anything. 219 */ 220int 221mod_loadobj(char *type, char *name) 222{ 223 struct loaded_module *mp; 224 char *cp; 225 int fd, got; 226 vm_offset_t laddr; 227 228 /* We can't load first */ 229 if ((mod_findmodule(NULL, NULL)) == NULL) { 230 command_errmsg = "can't load file before kernel"; 231 return(CMD_ERROR); 232 } 233
| 49struct loaded_module *loaded_modules = NULL; 50 51/* 52 * load an object, either a disk file or code module. 53 * 54 * To load a file, the syntax is: 55 * 56 * load -t <type> <path> 57 * 58 * code modules are loaded as: 59 * 60 * load <path> <options> 61 */ 62 63COMMAND_SET(load, "load", "load a kernel or module", command_load); 64 65static int 66command_load(int argc, char *argv[]) 67{ 68 char *typestr; 69 int dofile, ch; 70 71 dofile = 0; 72 optind = 1; 73 typestr = NULL; 74 while ((ch = getopt(argc, argv, "t:")) != -1) { 75 switch(ch) { 76 case 't': 77 typestr = optarg; 78 dofile = 1; 79 break; 80 case '?': 81 default: 82 /* getopt has already reported an error */ 83 return(CMD_OK); 84 } 85 } 86 argv += (optind - 1); 87 argc -= (optind - 1); 88 89 /* 90 * Request to load a raw file? 91 */ 92 if (dofile) { 93 if ((typestr == NULL) || (*typestr == 0)) { 94 command_errmsg = "invalid load type"; 95 return(CMD_ERROR); 96 } 97 return(mod_loadobj(typestr, argv[1])); 98 } 99 100 /* 101 * Looks like a request for a module. 102 */ 103 return(mod_load(argv[1], argc - 2, argv + 2)); 104} 105 106COMMAND_SET(unload, "unload", "unload all modules", command_unload); 107 108static int 109command_unload(int argc, char *argv[]) 110{ 111 struct loaded_module *mp; 112 113 while (loaded_modules != NULL) { 114 mp = loaded_modules; 115 loaded_modules = loaded_modules->m_next; 116 mod_discard(mp); 117 } 118 loadaddr = 0; 119 return(CMD_OK); 120} 121 122COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 123 124static int 125command_lsmod(int argc, char *argv[]) 126{ 127 struct loaded_module *am; 128 struct module_metadata *md; 129 char lbuf[80]; 130 int ch, verbose; 131 132 verbose = 0; 133 optind = 1; 134 while ((ch = getopt(argc, argv, "v")) != -1) { 135 switch(ch) { 136 case 'v': 137 verbose = 1; 138 break; 139 case '?': 140 default: 141 /* getopt has already reported an error */ 142 return(CMD_OK); 143 } 144 } 145 146 pager_open(); 147 for (am = loaded_modules; (am != NULL); am = am->m_next) { 148 sprintf(lbuf, " %x: %s (%s, 0x%x)\n", 149 am->m_addr, am->m_name, am->m_type, am->m_size); 150 pager_output(lbuf); 151 if (am->m_args != NULL) { 152 pager_output(" args: "); 153 pager_output(am->m_args); 154 pager_output("\n"); 155 } 156 if (verbose) 157 /* XXX could add some formatting smarts here to display some better */ 158 for (md = am->m_metadata; md != NULL; md = md->md_next) { 159 sprintf(lbuf, " 0x%04x, 0x%x\n", md->md_type, md->md_size); 160 pager_output(lbuf); 161 } 162 } 163 pager_close(); 164 return(CMD_OK); 165} 166 167/* 168 * We've been asked to load (name) and give it (argc),(argv). 169 * Start by trying to load it, and then attempt to load all of its 170 * dependancies. If we fail at any point, throw them all away and 171 * fail the entire load. 172 * 173 * XXX if a depended-on module requires arguments, it must be loaded 174 * explicitly first. 175 */ 176int 177mod_load(char *name, int argc, char *argv[]) 178{ 179 struct loaded_module *last_mod, *base_mod, *mp; 180 char *dep_name; 181 182 /* remember previous last module on chain */ 183 for (last_mod = loaded_modules; 184 (last_mod != NULL) && (last_mod->m_next != NULL); 185 last_mod = last_mod->m_next) 186 ; 187 188 /* 189 * Load the first module; note that it's the only one that gets 190 * arguments explicitly. 191 */ 192 if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL) 193 return(CMD_ERROR); 194 195 /* 196 * Look for dependancies. 197 */ 198 while ((dep_name = mod_searchdep(base_mod)) != NULL) { 199 printf("loading required module '%s'\n", dep_name); 200 if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) { 201 /* Load failed; discard everything */ 202 while (base_mod != NULL) { 203 mp = base_mod; 204 base_mod = base_mod->m_next; 205 mod_discard(mp); 206 } 207 last_mod->m_next = NULL; 208 loadaddr = last_mod->m_addr + last_mod->m_size; 209 /* error message already set by mod_loadmodule */ 210 return(CMD_ERROR); 211 } 212 } 213 return(CMD_OK); 214} 215 216/* 217 * We've been asked to load (name) as (type), so just suck it in, 218 * no arguments or anything. 219 */ 220int 221mod_loadobj(char *type, char *name) 222{ 223 struct loaded_module *mp; 224 char *cp; 225 int fd, got; 226 vm_offset_t laddr; 227 228 /* We can't load first */ 229 if ((mod_findmodule(NULL, NULL)) == NULL) { 230 command_errmsg = "can't load file before kernel"; 231 return(CMD_ERROR); 232 } 233
|
234 /* Try to come up with a fully-qualified name if we don't have one */ 235 if ((cp = mod_searchmodule(name)) != NULL) 236 name = cp;
| 234 /* locate the file on the load path */ 235 cp = mod_searchfile(name); 236 if (cp == NULL) { 237 sprintf(command_errbuf, "can't find '%s'", name); 238 return(CMD_ERROR); 239 } 240 name = cp;
|
237 238 if ((fd = open(name, O_RDONLY)) < 0) { 239 sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); 240 return(CMD_ERROR); 241 } 242 243 laddr = loadaddr; 244 for (;;) { 245 /* read in 4k chunks; size is not really important */ 246 got = archsw.arch_readin(fd, laddr, 4096); 247 if (got == 0) /* end of file */ 248 break; 249 if (got < 0) { /* error */ 250 sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); 251 return(CMD_ERROR); 252 } 253 laddr += got; 254 } 255 256 /* Looks OK so far; create & populate control structure */ 257 mp = malloc(sizeof(struct loaded_module)); 258 mp->m_name = strdup(name); 259 mp->m_type = strdup(type); 260 mp->m_args = NULL; 261 mp->m_metadata = NULL; 262 mp->m_loader = -1; 263 mp->m_addr = loadaddr; 264 mp->m_size = laddr - loadaddr; 265 266 /* recognise space consumption */ 267 loadaddr = laddr; 268 269 /* Add to the list of loaded modules */ 270 mod_append(mp); 271 return(CMD_OK); 272} 273 274/* 275 * Load the module (name), pass it (argc),(argv). 276 * Don't do any dependancy checking. 277 */ 278static struct loaded_module * 279mod_loadmodule(char *name, int argc, char *argv[]) 280{ 281 struct loaded_module *mp; 282 int i, err; 283 char *cp; 284
| 241 242 if ((fd = open(name, O_RDONLY)) < 0) { 243 sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); 244 return(CMD_ERROR); 245 } 246 247 laddr = loadaddr; 248 for (;;) { 249 /* read in 4k chunks; size is not really important */ 250 got = archsw.arch_readin(fd, laddr, 4096); 251 if (got == 0) /* end of file */ 252 break; 253 if (got < 0) { /* error */ 254 sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); 255 return(CMD_ERROR); 256 } 257 laddr += got; 258 } 259 260 /* Looks OK so far; create & populate control structure */ 261 mp = malloc(sizeof(struct loaded_module)); 262 mp->m_name = strdup(name); 263 mp->m_type = strdup(type); 264 mp->m_args = NULL; 265 mp->m_metadata = NULL; 266 mp->m_loader = -1; 267 mp->m_addr = loadaddr; 268 mp->m_size = laddr - loadaddr; 269 270 /* recognise space consumption */ 271 loadaddr = laddr; 272 273 /* Add to the list of loaded modules */ 274 mod_append(mp); 275 return(CMD_OK); 276} 277 278/* 279 * Load the module (name), pass it (argc),(argv). 280 * Don't do any dependancy checking. 281 */ 282static struct loaded_module * 283mod_loadmodule(char *name, int argc, char *argv[]) 284{ 285 struct loaded_module *mp; 286 int i, err; 287 char *cp; 288
|
285 /* Try to come up with a fully-qualified name if we don't have one */ 286 if ((cp = mod_searchmodule(name)) != NULL) 287 name = cp;
| 289 /* locate the module on the search path */ 290 cp = mod_searchmodule(name); 291 if (cp == NULL) { 292 sprintf(command_errbuf, "can't find '%s'", name); 293 return(NULL); 294 } 295 name = cp; 296
|
288 err = 0; 289 for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) { 290 if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) { 291 292 /* Unknown to this handler? */ 293 if (err == EFTYPE) 294 continue; 295 296 /* Fatal error */ 297 sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err)); 298 return(NULL); 299 } else { 300 301 /* Load was OK, set args */ 302 mp->m_args = unargv(argc, argv); 303 304 /* where can we put the next one? */ 305 loadaddr = mp->m_addr + mp->m_size; 306 307 /* remember the loader */ 308 mp->m_loader = i; 309 310 /* Add to the list of loaded modules */ 311 mod_append(mp); 312 313 break; 314 } 315 } 316 if (err == EFTYPE) 317 sprintf(command_errbuf, "don't know how to load module '%s'", name); 318 return(mp); 319} 320 321/* 322 * Search the modules from (mp) onwards, and return the name of the 323 * first unresolved dependancy, or NULL if none were found. 324 */ 325static char * 326mod_searchdep(struct loaded_module *mp) 327{ 328 struct kld_module_identifier *ident, *dident; 329 struct kld_module_dependancy *deps, *dp; 330 struct module_metadata *md; 331 struct loaded_module *dmp; 332 int dindex; 333 334 for (; mp != NULL; mp = mp->m_next) { 335 336 /* 337 * Get KLD module data 338 */ 339 ident = NULL; 340 deps = NULL; 341 if ((md = mod_findmetadata(mp, MODINFOMD_KLDIDENT)) != NULL) 342 ident = (struct kld_module_identifier *)md->md_data; 343 if ((md = mod_findmetadata(mp, MODINFOMD_KLDDEP)) != NULL) 344 deps = (struct kld_module_dependancy *)md->md_data; 345 346 /* 347 * Both must exist for this module to depend on anything 348 */ 349 if ((ident != NULL) && (deps != NULL)) { 350 351 /* Iterate over dependancies */ 352 for (dindex = 0; dindex < ident->ki_ndeps; dindex++) { 353 dp = KLD_GETDEP(ident, deps, dindex); 354 355 /* 356 * Look for a module matching the dependancy; if we don't have it, 357 * we need it. 358 */ 359 if ((dmp = mod_findmodule(dp->kd_name, NULL)) == NULL) 360 return(dp->kd_name); 361 362 /* Version check */ 363 if ((md = mod_findmetadata(dmp, MODINFOMD_KLDIDENT)) != NULL) { 364 dident = (struct kld_module_identifier *)md->md_data; 365 if (dp->kd_version != dident->ki_version) 366 printf("module '%s' requires '%s' version %d, but version %d is loaded\n", 367 mp->m_name, dp->kd_name, dp->kd_version, dident->ki_version); 368 } 369 } 370 } 371 } 372 return(NULL); 373} 374 375/* 376 * Find a module matching (name) and (type). 377 * NULL may be passed as a wildcard to either. 378 */ 379struct loaded_module * 380mod_findmodule(char *name, char *type) 381{ 382 struct loaded_module *mp; 383 384 for (mp = loaded_modules; mp != NULL; mp = mp->m_next) { 385 if (((name == NULL) || !strcmp(name, mp->m_name)) && 386 ((type == NULL) || !strcmp(type, mp->m_type))) 387 break; 388 } 389 return(mp); 390} 391 392/* 393 * Make a copy of (size) bytes of data from (p), and associate them as 394 * metadata of (type) to the module (mp). 395 */ 396void 397mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p) 398{ 399 struct module_metadata *md; 400 401 md = malloc(sizeof(struct module_metadata) + size); 402 md->md_size = size; 403 md->md_type = type; 404 bcopy(p, md->md_data, size); 405 md->md_next = mp->m_metadata; 406 mp->m_metadata = md; 407} 408 409/* 410 * Find a metadata object of (type) associated with the module 411 * (mp) 412 */ 413struct module_metadata * 414mod_findmetadata(struct loaded_module *mp, int type) 415{ 416 struct module_metadata *md; 417 418 for (md = mp->m_metadata; md != NULL; md = md->md_next) 419 if (md->md_type == type) 420 break; 421 return(md); 422} 423 424/*
| 297 err = 0; 298 for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) { 299 if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) { 300 301 /* Unknown to this handler? */ 302 if (err == EFTYPE) 303 continue; 304 305 /* Fatal error */ 306 sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err)); 307 return(NULL); 308 } else { 309 310 /* Load was OK, set args */ 311 mp->m_args = unargv(argc, argv); 312 313 /* where can we put the next one? */ 314 loadaddr = mp->m_addr + mp->m_size; 315 316 /* remember the loader */ 317 mp->m_loader = i; 318 319 /* Add to the list of loaded modules */ 320 mod_append(mp); 321 322 break; 323 } 324 } 325 if (err == EFTYPE) 326 sprintf(command_errbuf, "don't know how to load module '%s'", name); 327 return(mp); 328} 329 330/* 331 * Search the modules from (mp) onwards, and return the name of the 332 * first unresolved dependancy, or NULL if none were found. 333 */ 334static char * 335mod_searchdep(struct loaded_module *mp) 336{ 337 struct kld_module_identifier *ident, *dident; 338 struct kld_module_dependancy *deps, *dp; 339 struct module_metadata *md; 340 struct loaded_module *dmp; 341 int dindex; 342 343 for (; mp != NULL; mp = mp->m_next) { 344 345 /* 346 * Get KLD module data 347 */ 348 ident = NULL; 349 deps = NULL; 350 if ((md = mod_findmetadata(mp, MODINFOMD_KLDIDENT)) != NULL) 351 ident = (struct kld_module_identifier *)md->md_data; 352 if ((md = mod_findmetadata(mp, MODINFOMD_KLDDEP)) != NULL) 353 deps = (struct kld_module_dependancy *)md->md_data; 354 355 /* 356 * Both must exist for this module to depend on anything 357 */ 358 if ((ident != NULL) && (deps != NULL)) { 359 360 /* Iterate over dependancies */ 361 for (dindex = 0; dindex < ident->ki_ndeps; dindex++) { 362 dp = KLD_GETDEP(ident, deps, dindex); 363 364 /* 365 * Look for a module matching the dependancy; if we don't have it, 366 * we need it. 367 */ 368 if ((dmp = mod_findmodule(dp->kd_name, NULL)) == NULL) 369 return(dp->kd_name); 370 371 /* Version check */ 372 if ((md = mod_findmetadata(dmp, MODINFOMD_KLDIDENT)) != NULL) { 373 dident = (struct kld_module_identifier *)md->md_data; 374 if (dp->kd_version != dident->ki_version) 375 printf("module '%s' requires '%s' version %d, but version %d is loaded\n", 376 mp->m_name, dp->kd_name, dp->kd_version, dident->ki_version); 377 } 378 } 379 } 380 } 381 return(NULL); 382} 383 384/* 385 * Find a module matching (name) and (type). 386 * NULL may be passed as a wildcard to either. 387 */ 388struct loaded_module * 389mod_findmodule(char *name, char *type) 390{ 391 struct loaded_module *mp; 392 393 for (mp = loaded_modules; mp != NULL; mp = mp->m_next) { 394 if (((name == NULL) || !strcmp(name, mp->m_name)) && 395 ((type == NULL) || !strcmp(type, mp->m_type))) 396 break; 397 } 398 return(mp); 399} 400 401/* 402 * Make a copy of (size) bytes of data from (p), and associate them as 403 * metadata of (type) to the module (mp). 404 */ 405void 406mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p) 407{ 408 struct module_metadata *md; 409 410 md = malloc(sizeof(struct module_metadata) + size); 411 md->md_size = size; 412 md->md_type = type; 413 bcopy(p, md->md_data, size); 414 md->md_next = mp->m_metadata; 415 mp->m_metadata = md; 416} 417 418/* 419 * Find a metadata object of (type) associated with the module 420 * (mp) 421 */ 422struct module_metadata * 423mod_findmetadata(struct loaded_module *mp, int type) 424{ 425 struct module_metadata *md; 426 427 for (md = mp->m_metadata; md != NULL; md = md->md_next) 428 if (md->md_type == type) 429 break; 430 return(md); 431} 432 433/*
|
425 * Attempt to locate a kernel module file for the module (name).
| 434 * Attempt to find the file (name) on the module searchpath.
|
426 * If (name) is qualified in any way, we simply check it and 427 * return it or NULL. If it is not qualified, then we attempt 428 * to construct a path using entries in the environment variable 429 * module_path. 430 * 431 * The path we return a pointer to need never be freed, as we manage 432 * it internally. 433 */ 434static char *
| 435 * If (name) is qualified in any way, we simply check it and 436 * return it or NULL. If it is not qualified, then we attempt 437 * to construct a path using entries in the environment variable 438 * module_path. 439 * 440 * The path we return a pointer to need never be freed, as we manage 441 * it internally. 442 */ 443static char *
|
435mod_searchmodule(char *name)
| 444mod_searchfile(char *name)
|
436{ 437 static char *result = NULL;
| 445{ 446 static char *result = NULL;
|
438 static char *defpath = "/boot", *path;
| 447 char *path;
|
439 char *cp, *sp; 440 struct stat sb; 441 442 /* Don't look for nothing */ 443 if ((name == NULL) || (*name == 0)) 444 return(name); 445 446 /* 447 * See if there's a device on the front, or a directory name. 448 */ 449 archsw.arch_getdev(NULL, name, &cp); 450 if ((cp != name) || (strchr(name, '/') != NULL)) { 451 /* Qualified, so just see if it exists */ 452 if (stat(name, &sb) == 0) 453 return(name); 454 return(NULL); 455 } 456 457 /* 458 * Get the module path 459 */ 460 if ((cp = getenv("module_path")) == NULL)
| 448 char *cp, *sp; 449 struct stat sb; 450 451 /* Don't look for nothing */ 452 if ((name == NULL) || (*name == 0)) 453 return(name); 454 455 /* 456 * See if there's a device on the front, or a directory name. 457 */ 458 archsw.arch_getdev(NULL, name, &cp); 459 if ((cp != name) || (strchr(name, '/') != NULL)) { 460 /* Qualified, so just see if it exists */ 461 if (stat(name, &sb) == 0) 462 return(name); 463 return(NULL); 464 } 465 466 /* 467 * Get the module path 468 */ 469 if ((cp = getenv("module_path")) == NULL)
|
461 cp = defpath;
| 470 cp = default_searchpath;
|
462 sp = path = strdup(cp); 463 464 /* 465 * Traverse the path, splitting off ';'-delimited components. 466 */ 467 if (result != NULL) 468 free(result); 469 while((cp = strsep(&path, ";")) != NULL) {
| 471 sp = path = strdup(cp); 472 473 /* 474 * Traverse the path, splitting off ';'-delimited components. 475 */ 476 if (result != NULL) 477 free(result); 478 while((cp = strsep(&path, ";")) != NULL) {
|
470 result = malloc(strlen(cp) + strlen(name) + 2); 471 sprintf(result, "%s/%s", cp, name); 472 if (stat(result, &sb) == 0)
| 479 result = malloc(strlen(cp) + strlen(name) + 5); 480 strcpy(result, cp); 481 if (cp[strlen(cp) - 1] != '/') 482 strcat(result, "/"); 483 strcat(result, name); 484/* printf("search '%s'\n", result); */ 485 if ((stat(result, &sb) == 0) && 486 S_ISREG(sb.st_mode))
|
473 break; 474 free(result); 475 result = NULL; 476 } 477 free(sp); 478 return(result); 479} 480 481/*
| 487 break; 488 free(result); 489 result = NULL; 490 } 491 free(sp); 492 return(result); 493} 494 495/*
|
| 496 * Attempt to locate the file containing the module (name) 497 */ 498static char * 499mod_searchmodule(char *name) 500{ 501 char *tn, *result; 502 503 /* Look for (name).ko */ 504 tn = malloc(strlen(name) + 3); 505 strcpy(tn, name); 506 strcat(tn, ".ko"); 507 result = mod_searchfile(tn); 508 free(tn); 509 /* Look for just (name) (useful for finding kernels) */ 510 if (result == NULL) 511 result = mod_searchfile(name); 512 513 return(result); 514} 515 516 517/*
|
482 * Throw a module away 483 */ 484void 485mod_discard(struct loaded_module *mp) 486{ 487 struct module_metadata *md; 488
| 518 * Throw a module away 519 */ 520void 521mod_discard(struct loaded_module *mp) 522{ 523 struct module_metadata *md; 524
|
489 while (mp->m_metadata != NULL) { 490 md = mp->m_metadata; 491 mp->m_metadata = mp->m_metadata->md_next; 492 free(md); 493 } 494 if (mp->m_name != NULL) 495 free(mp->m_name); 496 if (mp->m_type != NULL) 497 free(mp->m_type); 498 if (mp->m_args != NULL) 499 free(mp->m_args); 500 free(mp);
| 525 if (mp != NULL) { 526 while (mp->m_metadata != NULL) { 527 md = mp->m_metadata; 528 mp->m_metadata = mp->m_metadata->md_next; 529 free(md); 530 } 531 if (mp->m_name != NULL) 532 free(mp->m_name); 533 if (mp->m_type != NULL) 534 free(mp->m_type); 535 if (mp->m_args != NULL) 536 free(mp->m_args); 537 free(mp); 538 }
|
501} 502 503/*
| 539} 540 541/*
|
| 542 * Allocate a new module; must be used instead of malloc() 543 * to ensure safe initialisation. 544 */ 545struct loaded_module * 546mod_allocmodule(void) 547{ 548 struct loaded_module *mp; 549 550 if ((mp = malloc(sizeof(struct loaded_module))) != NULL) { 551 bzero(mp, sizeof(struct loaded_module)); 552 } 553 return(mp); 554} 555 556 557/*
|
504 * Add a module to the chain 505 */ 506static void 507mod_append(struct loaded_module *mp) 508{ 509 struct loaded_module *cm; 510 511 /* Append to list of loaded modules */ 512 mp->m_next = NULL; 513 if (loaded_modules == NULL) { 514 loaded_modules = mp; 515 } else { 516 for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next) 517 ; 518 cm->m_next = mp; 519 } 520}
| 558 * Add a module to the chain 559 */ 560static void 561mod_append(struct loaded_module *mp) 562{ 563 struct loaded_module *cm; 564 565 /* Append to list of loaded modules */ 566 mp->m_next = NULL; 567 if (loaded_modules == NULL) { 568 loaded_modules = mp; 569 } else { 570 for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next) 571 ; 572 cm->m_next = mp; 573 } 574}
|