1 /*- 2 * Copyright (c) 1997 Doug Rabson 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: kern_linker.c,v 1.12 1998/11/03 13:09:31 peter Exp $ 27 */ 28 29 #include "opt_ddb.h" 30 31 #include <sys/param.h> 32 #include <sys/kernel.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/sysproto.h> 36 #include <sys/sysent.h> 37 #include <sys/proc.h> 38 #include <sys/lock.h> 39 #include <machine/cpu.h> 40 #include <machine/bootinfo.h> 41 #include <sys/module.h> 42 #include <sys/linker.h> 43 #include <sys/unistd.h> 44 #include <sys/fcntl.h> 45 #include <sys/libkern.h> 46 #include <sys/namei.h> 47 #include <sys/vnode.h> 48 #include <sys/sysctl.h> 49 50 MALLOC_DEFINE(M_LINKER, "kld", "kernel linker"); 51 linker_file_t linker_current_file; 52 53 static struct lock lock; /* lock for the file list */ 54 static linker_class_list_t classes; 55 static linker_file_list_t files; 56 static int next_file_id = 1; 57 58 static void 59 linker_init(void* arg) 60 { 61 lockinit(&lock, PVM, "klink", 0, 0); 62 TAILQ_INIT(&classes); 63 TAILQ_INIT(&files); 64 } 65 66 SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0); 67 68 int 69 linker_add_class(const char* desc, void* priv, 70 struct linker_class_ops* ops) 71 { 72 linker_class_t lc; 73 74 lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT); 75 if (!lc) 76 return ENOMEM; 77 bzero(lc, sizeof(*lc)); 78 79 lc->desc = desc; 80 lc->priv = priv; 81 lc->ops = ops; 82 TAILQ_INSERT_HEAD(&classes, lc, link); 83 84 return 0; 85 } 86 87 static void 88 linker_file_sysinit(linker_file_t lf) 89 { 90 struct linker_set* sysinits; 91 struct sysinit** sipp; 92 struct sysinit** xipp; 93 struct sysinit* save; 94 moduledata_t *moddata; 95 96 KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n", 97 lf->filename)); 98 99 sysinits = (struct linker_set*) 100 linker_file_lookup_symbol(lf, "sysinit_set", 0); 101 102 KLD_DPF(FILE, ("linker_file_sysinit: SYSINITs %p\n", sysinits)); 103 if (!sysinits) 104 return; 105 106 /* HACK ALERT! */ 107 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 108 if ((*sipp)->func == module_register_init) { 109 moddata = (*sipp)->udata; 110 moddata->_file = lf; 111 } 112 } 113 114 /* 115 * Perform a bubble sort of the system initialization objects by 116 * their subsystem (primary key) and order (secondary key). 117 * 118 * Since some things care about execution order, this is the 119 * operation which ensures continued function. 120 */ 121 for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 122 for( xipp = sipp + 1; *xipp; xipp++) { 123 if( (*sipp)->subsystem < (*xipp)->subsystem || 124 ( (*sipp)->subsystem == (*xipp)->subsystem && 125 (*sipp)->order < (*xipp)->order)) 126 continue; /* skip*/ 127 save = *sipp; 128 *sipp = *xipp; 129 *xipp = save; 130 } 131 } 132 133 134 /* 135 * Traverse the (now) ordered list of system initialization tasks. 136 * Perform each task, and continue on to the next task. 137 * 138 * The last item on the list is expected to be the scheduler, 139 * which will not return. 140 */ 141 for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 142 if( (*sipp)->subsystem == SI_SUB_DUMMY) 143 continue; /* skip dummy task(s)*/ 144 145 switch( (*sipp)->type) { 146 case SI_TYPE_DEFAULT: 147 /* no special processing*/ 148 (*((*sipp)->func))( (*sipp)->udata); 149 break; 150 151 case SI_TYPE_KTHREAD: 152 #if !defined(SMP) 153 /* kernel thread*/ 154 if (fork1(&proc0, RFFDG|RFPROC|RFMEM)) 155 panic("fork kernel thread"); 156 cpu_set_fork_handler(pfind(proc0.p_retval[0]), 157 (*sipp)->func, (*sipp)->udata); 158 break; 159 #endif 160 161 case SI_TYPE_KPROCESS: 162 /* kernel thread*/ 163 if (fork1(&proc0, RFFDG|RFPROC)) 164 panic("fork kernel process"); 165 cpu_set_fork_handler(pfind(proc0.p_retval[0]), 166 (*sipp)->func, (*sipp)->udata); 167 break; 168 169 default: 170 panic( "linker_file_sysinit: unrecognized init type"); 171 } 172 } 173 } 174 175 int 176 linker_load_file(const char* filename, linker_file_t* result) 177 { 178 linker_class_t lc; 179 linker_file_t lf; 180 int error = 0; 181 char *koname = NULL; 182 183 lf = linker_find_file_by_name(filename); 184 if (lf) { 185 KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename)); 186 *result = lf; 187 lf->refs++; 188 goto out; 189 } 190 191 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 192 if (koname == NULL) { 193 error = ENOMEM; 194 goto out; 195 } 196 sprintf(koname, "%s.ko", filename); 197 lf = NULL; 198 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 199 KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n", 200 filename, lc->desc)); 201 error = lc->ops->load_file(koname, &lf); 202 if (lf == NULL && error && error != ENOENT) 203 goto out; 204 if (lf == NULL) 205 error = lc->ops->load_file(filename, &lf); 206 if (lf == NULL && error && error != ENOENT) 207 goto out; 208 if (lf) { 209 linker_file_sysinit(lf); 210 211 *result = lf; 212 error = 0; 213 goto out; 214 } 215 } 216 error = ENOEXEC; /* format not recognised */ 217 218 out: 219 if (koname) 220 free(koname, M_LINKER); 221 return error; 222 } 223 224 linker_file_t 225 linker_find_file_by_name(const char* filename) 226 { 227 linker_file_t lf = 0; 228 char *koname; 229 230 koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK); 231 if (koname == NULL) 232 goto out; 233 sprintf(koname, "%s.ko", filename); 234 235 lockmgr(&lock, LK_SHARED, 0, curproc); 236 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) { 237 if (!strcmp(lf->filename, koname)) 238 break; 239 if (!strcmp(lf->filename, filename)) 240 break; 241 } 242 lockmgr(&lock, LK_RELEASE, 0, curproc); 243 244 out: 245 if (koname) 246 free(koname, M_LINKER); 247 return lf; 248 } 249 250 linker_file_t 251 linker_find_file_by_id(int fileid) 252 { 253 linker_file_t lf = 0; 254 255 lockmgr(&lock, LK_SHARED, 0, curproc); 256 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) 257 if (lf->id == fileid) 258 break; 259 lockmgr(&lock, LK_RELEASE, 0, curproc); 260 261 return lf; 262 } 263 264 linker_file_t 265 linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops) 266 { 267 linker_file_t lf = 0; 268 int namelen; 269 const char *filename; 270 271 filename = rindex(pathname, '/'); 272 if (filename && filename[1]) 273 filename++; 274 else 275 filename = pathname; 276 277 KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename)); 278 lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc); 279 namelen = strlen(filename) + 1; 280 lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK); 281 if (!lf) 282 goto out; 283 bzero(lf, sizeof(*lf)); 284 285 lf->refs = 1; 286 lf->userrefs = 0; 287 lf->filename = (char*) (lf + 1); 288 strcpy(lf->filename, filename); 289 lf->id = next_file_id++; 290 lf->ndeps = 0; 291 lf->deps = NULL; 292 STAILQ_INIT(&lf->common); 293 TAILQ_INIT(&lf->modules); 294 295 lf->priv = priv; 296 lf->ops = ops; 297 TAILQ_INSERT_TAIL(&files, lf, link); 298 299 out: 300 lockmgr(&lock, LK_RELEASE, 0, curproc); 301 return lf; 302 } 303 304 int 305 linker_file_unload(linker_file_t file) 306 { 307 module_t mod, next; 308 struct common_symbol* cp; 309 int error = 0; 310 int i; 311 312 KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs)); 313 lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc); 314 if (file->refs == 1) { 315 KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n")); 316 /* 317 * Inform any modules associated with this file. 318 */ 319 for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) { 320 next = module_getfnext(mod); 321 322 /* 323 * Give the module a chance to veto the unload. 324 */ 325 if (error = module_unload(mod)) { 326 KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n", 327 mod)); 328 lockmgr(&lock, LK_RELEASE, 0, curproc); 329 goto out; 330 } 331 332 module_release(mod); 333 } 334 } 335 336 file->refs--; 337 if (file->refs > 0) { 338 lockmgr(&lock, LK_RELEASE, 0, curproc); 339 goto out; 340 } 341 342 TAILQ_REMOVE(&files, file, link); 343 lockmgr(&lock, LK_RELEASE, 0, curproc); 344 345 for (i = 0; i < file->ndeps; i++) 346 linker_file_unload(file->deps[i]); 347 free(file->deps, M_LINKER); 348 349 for (cp = STAILQ_FIRST(&file->common); cp; 350 cp = STAILQ_FIRST(&file->common)) { 351 STAILQ_REMOVE(&file->common, cp, common_symbol, link); 352 free(cp, M_LINKER); 353 } 354 355 file->ops->unload(file); 356 free(file, M_LINKER); 357 358 out: 359 return error; 360 } 361 362 int 363 linker_file_add_dependancy(linker_file_t file, linker_file_t dep) 364 { 365 linker_file_t* newdeps; 366 367 newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*), 368 M_LINKER, M_WAITOK); 369 if (newdeps == NULL) 370 return ENOMEM; 371 bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*)); 372 373 if (file->deps) { 374 bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*)); 375 free(file->deps, M_LINKER); 376 } 377 file->deps = newdeps; 378 file->deps[file->ndeps] = dep; 379 file->ndeps++; 380 381 return 0; 382 } 383 384 caddr_t 385 linker_file_lookup_symbol(linker_file_t file, const char* name, int deps) 386 { 387 linker_sym_t sym; 388 linker_symval_t symval; 389 caddr_t address; 390 size_t common_size = 0; 391 int i; 392 393 KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n", 394 file, name, deps)); 395 396 if (file->ops->lookup_symbol(file, name, &sym) == 0) { 397 file->ops->symbol_values(file, sym, &symval); 398 if (symval.value == 0) 399 /* 400 * For commons, first look them up in the dependancies and 401 * only allocate space if not found there. 402 */ 403 common_size = symval.size; 404 else { 405 KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value)); 406 return symval.value; 407 } 408 } 409 410 if (deps) 411 for (i = 0; i < file->ndeps; i++) { 412 address = linker_file_lookup_symbol(file->deps[i], name, 0); 413 if (address) { 414 KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address)); 415 return address; 416 } 417 } 418 419 if (common_size > 0) { 420 /* 421 * This is a common symbol which was not found in the 422 * dependancies. We maintain a simple common symbol table in 423 * the file object. 424 */ 425 struct common_symbol* cp; 426 427 for (cp = STAILQ_FIRST(&file->common); cp; 428 cp = STAILQ_NEXT(cp, link)) 429 if (!strcmp(cp->name, name)) { 430 KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address)); 431 return cp->address; 432 } 433 434 /* 435 * Round the symbol size up to align. 436 */ 437 common_size = (common_size + sizeof(int) - 1) & -sizeof(int); 438 cp = malloc(sizeof(struct common_symbol) 439 + common_size 440 + strlen(name) + 1, 441 M_LINKER, M_WAITOK); 442 if (!cp) { 443 KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n")); 444 return 0; 445 } 446 bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1); 447 448 cp->address = (caddr_t) (cp + 1); 449 cp->name = cp->address + common_size; 450 strcpy(cp->name, name); 451 bzero(cp->address, common_size); 452 STAILQ_INSERT_TAIL(&file->common, cp, link); 453 454 KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address)); 455 return cp->address; 456 } 457 458 KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n")); 459 return 0; 460 } 461 462 #ifdef DDB 463 /* 464 * DDB Helpers. DDB has to look across multiple files with their own 465 * symbol tables and string tables. 466 * 467 * Note that we do not obey list locking protocols here. We really don't 468 * need DDB to hang because somebody's got the lock held. We'll take the 469 * chance that the files list is inconsistant instead. 470 */ 471 472 int 473 linker_ddb_lookup(char *symstr, linker_sym_t *sym) 474 { 475 linker_file_t lf; 476 477 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) { 478 if (lf->ops->lookup_symbol(lf, symstr, sym) == 0) 479 return 0; 480 } 481 return ENOENT; 482 } 483 484 int 485 linker_ddb_search_symbol(caddr_t value, linker_sym_t *sym, long *diffp) 486 { 487 linker_file_t lf; 488 u_long off = (u_long)value; 489 u_long diff, bestdiff; 490 linker_sym_t best; 491 linker_sym_t es; 492 493 best = 0; 494 bestdiff = off; 495 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) { 496 if (lf->ops->search_symbol(lf, value, &es, &diff) != 0) 497 continue; 498 if (es != 0 && diff < bestdiff) { 499 best = es; 500 bestdiff = diff; 501 } 502 if (bestdiff == 0) 503 break; 504 } 505 if (best) { 506 *sym = best; 507 *diffp = bestdiff; 508 return 0; 509 } else { 510 *sym = 0; 511 *diffp = off; 512 return ENOENT; 513 } 514 } 515 516 int 517 linker_ddb_symbol_values(linker_sym_t sym, linker_symval_t *symval) 518 { 519 linker_file_t lf; 520 521 for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) { 522 if (lf->ops->symbol_values(lf, sym, symval) == 0) 523 return 0; 524 } 525 return ENOENT; 526 } 527 528 #endif 529 530 /* 531 * Syscalls. 532 */ 533 534 int 535 kldload(struct proc* p, struct kldload_args* uap) 536 { 537 char* filename = NULL; 538 linker_file_t lf; 539 int error = 0; 540 541 p->p_retval[0] = -1; 542 543 if (securelevel > 0) 544 return EPERM; 545 546 if (error = suser(p->p_ucred, &p->p_acflag)) 547 return error; 548 549 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 550 if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) 551 goto out; 552 553 if (error = linker_load_file(filename, &lf)) 554 goto out; 555 556 lf->userrefs++; 557 p->p_retval[0] = lf->id; 558 559 out: 560 if (filename) 561 free(filename, M_TEMP); 562 return error; 563 } 564 565 int 566 kldunload(struct proc* p, struct kldunload_args* uap) 567 { 568 linker_file_t lf; 569 int error = 0; 570 571 if (securelevel > 0) 572 return EPERM; 573 574 if (error = suser(p->p_ucred, &p->p_acflag)) 575 return error; 576 577 lf = linker_find_file_by_id(SCARG(uap, fileid)); 578 if (lf) { 579 KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs)); 580 if (lf->userrefs == 0) { 581 printf("linkerunload: attempt to unload file which was not loaded by user\n"); 582 error = EBUSY; 583 goto out; 584 } 585 lf->userrefs--; 586 error = linker_file_unload(lf); 587 } else 588 error = ENOENT; 589 590 out: 591 return error; 592 } 593 594 int 595 kldfind(struct proc* p, struct kldfind_args* uap) 596 { 597 char* filename = NULL; 598 linker_file_t lf; 599 int error = 0; 600 601 p->p_retval[0] = -1; 602 603 filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 604 if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL)) 605 goto out; 606 607 lf = linker_find_file_by_name(filename); 608 if (lf) 609 p->p_retval[0] = lf->id; 610 else 611 error = ENOENT; 612 613 out: 614 if (filename) 615 free(filename, M_TEMP); 616 return error; 617 } 618 619 int 620 kldnext(struct proc* p, struct kldnext_args* uap) 621 { 622 linker_file_t lf; 623 int error = 0; 624 625 if (SCARG(uap, fileid) == 0) { 626 if (TAILQ_FIRST(&files)) 627 p->p_retval[0] = TAILQ_FIRST(&files)->id; 628 else 629 p->p_retval[0] = 0; 630 return 0; 631 } 632 633 lf = linker_find_file_by_id(SCARG(uap, fileid)); 634 if (lf) { 635 if (TAILQ_NEXT(lf, link)) 636 p->p_retval[0] = TAILQ_NEXT(lf, link)->id; 637 else 638 p->p_retval[0] = 0; 639 } else 640 error = ENOENT; 641 642 return error; 643 } 644 645 int 646 kldstat(struct proc* p, struct kldstat_args* uap) 647 { 648 linker_file_t lf; 649 int error = 0; 650 int version; 651 struct kld_file_stat* stat; 652 int namelen; 653 654 lf = linker_find_file_by_id(SCARG(uap, fileid)); 655 if (!lf) { 656 error = ENOENT; 657 goto out; 658 } 659 660 stat = SCARG(uap, stat); 661 662 /* 663 * Check the version of the user's structure. 664 */ 665 if (error = copyin(&stat->version, &version, sizeof(version))) 666 goto out; 667 if (version != sizeof(struct kld_file_stat)) { 668 error = EINVAL; 669 goto out; 670 } 671 672 namelen = strlen(lf->filename) + 1; 673 if (namelen > MAXPATHLEN) 674 namelen = MAXPATHLEN; 675 if (error = copyout(lf->filename, &stat->name[0], namelen)) 676 goto out; 677 if (error = copyout(&lf->refs, &stat->refs, sizeof(int))) 678 goto out; 679 if (error = copyout(&lf->id, &stat->id, sizeof(int))) 680 goto out; 681 if (error = copyout(&lf->address, &stat->address, sizeof(caddr_t))) 682 goto out; 683 if (error = copyout(&lf->size, &stat->size, sizeof(size_t))) 684 goto out; 685 686 p->p_retval[0] = 0; 687 688 out: 689 return error; 690 } 691 692 int 693 kldfirstmod(struct proc* p, struct kldfirstmod_args* uap) 694 { 695 linker_file_t lf; 696 int error = 0; 697 698 lf = linker_find_file_by_id(SCARG(uap, fileid)); 699 if (lf) { 700 if (TAILQ_FIRST(&lf->modules)) 701 p->p_retval[0] = module_getid(TAILQ_FIRST(&lf->modules)); 702 else 703 p->p_retval[0] = 0; 704 } else 705 error = ENOENT; 706 707 return error; 708 } 709 710 /* 711 * Preloaded module support 712 */ 713 714 static void 715 linker_preload(void* arg) 716 { 717 caddr_t modptr; 718 char *modname; 719 char *modtype; 720 linker_file_t lf; 721 linker_class_t lc; 722 int error; 723 struct linker_set *sysinits; 724 struct sysinit **sipp; 725 moduledata_t *moddata; 726 727 modptr = NULL; 728 while ((modptr = preload_search_next_name(modptr)) != NULL) { 729 modname = (char *)preload_search_info(modptr, MODINFO_NAME); 730 modtype = (char *)preload_search_info(modptr, MODINFO_TYPE); 731 if (modname == NULL) { 732 printf("Preloaded module at %p does not have a name!\n", modptr); 733 continue; 734 } 735 if (modtype == NULL) { 736 printf("Preloaded module at %p does not have a type!\n", modptr); 737 continue; 738 } 739 printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr); 740 lf = linker_find_file_by_name(modname); 741 if (lf) { 742 lf->userrefs++; 743 continue; 744 } 745 lf = NULL; 746 for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) { 747 error = lc->ops->load_file(modname, &lf); 748 if (error) { 749 lf = NULL; 750 break; 751 } 752 } 753 if (lf) { 754 lf->userrefs++; 755 756 sysinits = (struct linker_set*) 757 linker_file_lookup_symbol(lf, "sysinit_set", 0); 758 if (sysinits) { 759 /* HACK ALERT! 760 * This is to set the sysinit moduledata so that the module 761 * can attach itself to the correct containing file. 762 * The sysinit could be run at *any* time. 763 */ 764 for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) { 765 if ((*sipp)->func == module_register_init) { 766 moddata = (*sipp)->udata; 767 moddata->_file = lf; 768 } 769 } 770 sysinit_add((struct sysinit **)sysinits->ls_items); 771 } 772 } 773 } 774 } 775 776 SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0); 777 778 /* 779 * Search for a not-loaded module by name. 780 * 781 * Modules may be found in the following locations: 782 * 783 * - preloaded (result is just the module name) 784 * - on disk (result is full path to module) 785 * 786 * If the module name is qualified in any way (contains path, etc.) 787 * the we simply return a copy of it. 788 * 789 * The search path can be manipulated via sysctl. Note that we use the ';' 790 * character as a separator to be consistent with the bootloader. 791 */ 792 793 static char linker_path[MAXPATHLEN + 1] = "/;/boot/;/modules/"; 794 795 SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path, 796 sizeof(linker_path), "module load search path"); 797 798 static char * 799 linker_strdup(const char *str) 800 { 801 char *result; 802 803 if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL) 804 strcpy(result, str); 805 return(result); 806 } 807 808 char * 809 linker_search_path(const char *name) 810 { 811 struct nameidata nd; 812 struct proc *p = curproc; /* XXX */ 813 char *cp, *ep, *result; 814 int error; 815 enum vtype type; 816 817 /* qualified at all? */ 818 if (index(name, '/')) 819 return(linker_strdup(name)); 820 821 /* traverse the linker path */ 822 cp = linker_path; 823 for (;;) { 824 825 /* find the end of this component */ 826 for (ep = cp; (*ep != 0) && (*ep != ';'); ep++) 827 ; 828 result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK); 829 if (result == NULL) /* actually ENOMEM */ 830 return(NULL); 831 832 strncpy(result, cp, ep - cp); 833 strcpy(result + (ep - cp), name); 834 835 /* 836 * Attempt to open the file, and return the path if we succeed and it's 837 * a regular file. 838 */ 839 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p); 840 error = vn_open(&nd, FREAD, 0); 841 if (error == 0) { 842 type = nd.ni_vp->v_type; 843 VOP_UNLOCK(nd.ni_vp, 0, p); 844 vn_close(nd.ni_vp, FREAD, p->p_ucred, p); 845 if (type == VREG) 846 return(result); 847 } 848 free(result, M_LINKER); 849 850 if (*ep == 0) 851 break; 852 cp = ep + 1; 853 } 854 return(NULL); 855 } 856