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 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 /* 31 * file/module function dispatcher, support, etc. 32 */ 33 34 #include <stand.h> 35 #include <string.h> 36 #include <sys/param.h> 37 #include <sys/linker.h> 38 #include <sys/module.h> 39 #include <sys/queue.h> 40 #include <sys/stdint.h> 41 #include <sys/font.h> 42 #include <gfx_fb.h> 43 44 #if defined(LOADER_FDT_SUPPORT) 45 #include <fdt_platform.h> 46 #endif 47 48 #include "bootstrap.h" 49 50 #define MDIR_REMOVED 0x0001 51 #define MDIR_NOHINTS 0x0002 52 53 struct moduledir { 54 char *d_path; /* path of modules directory */ 55 u_char *d_hints; /* content of linker.hints file */ 56 int d_hintsz; /* size of hints data */ 57 int d_flags; 58 STAILQ_ENTRY(moduledir) d_link; 59 }; 60 61 static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); 62 static int file_load_dependencies(struct preloaded_file *base_mod); 63 static char * file_search(const char *name, char **extlist); 64 static struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo); 65 static int file_havepath(const char *name); 66 static char *mod_searchmodule(char *name, struct mod_depend *verinfo); 67 static char * mod_searchmodule_pnpinfo(const char *bus, const char *pnpinfo); 68 static void file_insert_tail(struct preloaded_file *mp); 69 static void file_remove(struct preloaded_file *fp); 70 struct file_metadata* metadata_next(struct file_metadata *base_mp, int type); 71 static void moduledir_readhints(struct moduledir *mdp); 72 static void moduledir_rebuild(void); 73 74 /* load address should be tweaked by first module loaded (kernel) */ 75 static vm_offset_t loadaddr = 0; 76 77 #if defined(LOADER_FDT_SUPPORT) 78 static const char *default_searchpath = 79 "/boot/kernel;/boot/modules;/boot/dtb"; 80 #else 81 static const char *default_searchpath = "/boot/kernel;/boot/modules"; 82 #endif 83 84 static STAILQ_HEAD(, moduledir) moduledir_list = 85 STAILQ_HEAD_INITIALIZER(moduledir_list); 86 87 struct preloaded_file *preloaded_files = NULL; 88 89 static char *kld_ext_list[] = { 90 ".ko", 91 "", 92 ".debug", 93 NULL 94 }; 95 96 /* 97 * load an object, either a disk file or code module. 98 * 99 * To load a file, the syntax is: 100 * 101 * load -t <type> <path> 102 * 103 * code modules are loaded as: 104 * 105 * load <path> <options> 106 */ 107 108 COMMAND_SET(load, "load", "load a kernel or module", command_load); 109 110 static int 111 command_load(int argc, char *argv[]) 112 { 113 struct preloaded_file *fp; 114 char *typestr; 115 #ifdef LOADER_VERIEXEC 116 char *prefix, *skip; 117 #endif 118 int dflag, dofile, dokld, ch, error; 119 120 dflag = dokld = dofile = 0; 121 optind = 1; 122 optreset = 1; 123 typestr = NULL; 124 if (argc == 1) { 125 command_errmsg = "no filename specified"; 126 return (CMD_CRIT); 127 } 128 #ifdef LOADER_VERIEXEC 129 prefix = NULL; 130 skip = NULL; 131 #endif 132 while ((ch = getopt(argc, argv, "dkp:s:t:")) != -1) { 133 switch(ch) { 134 case 'd': 135 dflag++; 136 break; 137 case 'k': 138 dokld = 1; 139 break; 140 #ifdef LOADER_VERIEXEC 141 case 'p': 142 prefix = optarg; 143 break; 144 case 's': 145 skip = optarg; 146 break; 147 #endif 148 case 't': 149 typestr = optarg; 150 dofile = 1; 151 break; 152 case '?': 153 default: 154 /* getopt has already reported an error */ 155 return (CMD_OK); 156 } 157 } 158 argv += (optind - 1); 159 argc -= (optind - 1); 160 161 /* 162 * Request to load a raw file? 163 */ 164 if (dofile) { 165 if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) { 166 command_errmsg = "invalid load type"; 167 return (CMD_CRIT); 168 } 169 170 #ifdef LOADER_VERIEXEC 171 if (strncmp(typestr, "manifest", 8) == 0) { 172 if (dflag > 0) 173 ve_debug_set(dflag); 174 return (load_manifest(argv[1], prefix, skip, NULL)); 175 } 176 #ifdef LOADER_VERIEXEC_PASS_MANIFEST 177 if (strncmp(typestr, "pass_manifest", 13) == 0) { 178 if (dflag > 0) 179 ve_debug_set(dflag); 180 return (pass_manifest(argv[1], prefix)); 181 } 182 #endif 183 #endif 184 185 fp = file_findfile(argv[1], typestr); 186 if (fp) { 187 snprintf(command_errbuf, sizeof(command_errbuf), 188 "warning: file '%s' already loaded", argv[1]); 189 return (CMD_WARN); 190 } 191 192 if (file_loadraw(argv[1], typestr, 1) != NULL) 193 return (CMD_OK); 194 195 /* Failing to load mfs_root is never going to end well! */ 196 if (strcmp("mfs_root", typestr) == 0) 197 return (CMD_FATAL); 198 199 return (CMD_ERROR); 200 } 201 /* 202 * Do we have explicit KLD load ? 203 */ 204 if (dokld || file_havepath(argv[1])) { 205 error = mod_loadkld(argv[1], argc - 2, argv + 2); 206 if (error == EEXIST) { 207 snprintf(command_errbuf, sizeof(command_errbuf), 208 "warning: KLD '%s' already loaded", argv[1]); 209 return (CMD_WARN); 210 } 211 212 return (error == 0 ? CMD_OK : CMD_CRIT); 213 } 214 /* 215 * Looks like a request for a module. 216 */ 217 error = mod_load(argv[1], NULL, argc - 2, argv + 2); 218 if (error == EEXIST) { 219 snprintf(command_errbuf, sizeof(command_errbuf), 220 "warning: module '%s' already loaded", argv[1]); 221 return (CMD_WARN); 222 } 223 224 return (error == 0 ? CMD_OK : CMD_CRIT); 225 } 226 227 #ifdef LOADER_GELI_SUPPORT 228 COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli); 229 230 static int 231 command_load_geli(int argc, char *argv[]) 232 { 233 char typestr[80]; 234 char *cp; 235 int ch, num; 236 237 if (argc < 3) { 238 command_errmsg = "usage is [-n key#] <prov> <file>"; 239 return(CMD_ERROR); 240 } 241 242 num = 0; 243 optind = 1; 244 optreset = 1; 245 while ((ch = getopt(argc, argv, "n:")) != -1) { 246 switch(ch) { 247 case 'n': 248 num = strtol(optarg, &cp, 0); 249 if (cp == optarg) { 250 snprintf(command_errbuf, sizeof(command_errbuf), 251 "bad key index '%s'", optarg); 252 return(CMD_ERROR); 253 } 254 break; 255 case '?': 256 default: 257 /* getopt has already reported an error */ 258 return(CMD_OK); 259 } 260 } 261 argv += (optind - 1); 262 argc -= (optind - 1); 263 sprintf(typestr, "%s:geli_keyfile%d", argv[1], num); 264 return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR); 265 } 266 #endif 267 268 void 269 unload(void) 270 { 271 struct preloaded_file *fp; 272 273 while (preloaded_files != NULL) { 274 fp = preloaded_files; 275 preloaded_files = preloaded_files->f_next; 276 file_discard(fp); 277 } 278 loadaddr = 0; 279 unsetenv("kernelname"); 280 } 281 282 COMMAND_SET(unload, "unload", "unload all modules", command_unload); 283 284 static int 285 command_unload(int argc, char *argv[]) 286 { 287 unload(); 288 return(CMD_OK); 289 } 290 291 COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 292 293 static int 294 command_lsmod(int argc, char *argv[]) 295 { 296 struct preloaded_file *fp; 297 struct kernel_module *mp; 298 struct file_metadata *md; 299 char lbuf[80]; 300 int ch, verbose, ret = 0; 301 302 verbose = 0; 303 optind = 1; 304 optreset = 1; 305 while ((ch = getopt(argc, argv, "v")) != -1) { 306 switch(ch) { 307 case 'v': 308 verbose = 1; 309 break; 310 case '?': 311 default: 312 /* getopt has already reported an error */ 313 return(CMD_OK); 314 } 315 } 316 317 pager_open(); 318 for (fp = preloaded_files; fp; fp = fp->f_next) { 319 snprintf(lbuf, sizeof(lbuf), " %p: ", (void *) fp->f_addr); 320 pager_output(lbuf); 321 pager_output(fp->f_name); 322 snprintf(lbuf, sizeof(lbuf), " (%s, 0x%lx)\n", fp->f_type, 323 (long)fp->f_size); 324 if (pager_output(lbuf)) 325 break; 326 if (fp->f_args != NULL) { 327 pager_output(" args: "); 328 pager_output(fp->f_args); 329 if (pager_output("\n")) 330 break; 331 } 332 if (fp->f_modules) { 333 pager_output(" modules: "); 334 for (mp = fp->f_modules; mp; mp = mp->m_next) { 335 snprintf(lbuf, sizeof(lbuf), "%s.%d ", mp->m_name, 336 mp->m_version); 337 pager_output(lbuf); 338 } 339 if (pager_output("\n")) 340 break; 341 } 342 if (verbose) { 343 /* XXX could add some formatting smarts here to display some better */ 344 for (md = fp->f_metadata; md != NULL; md = md->md_next) { 345 snprintf(lbuf, sizeof(lbuf), " 0x%04x, 0x%lx\n", 346 md->md_type, (long) md->md_size); 347 if (pager_output(lbuf)) 348 break; 349 } 350 } 351 if (ret) 352 break; 353 } 354 pager_close(); 355 return(CMD_OK); 356 } 357 358 COMMAND_SET(pnpmatch, "pnpmatch", "list matched modules based on pnpinfo", command_pnpmatch); 359 360 static int pnp_dump_flag = 0; 361 static int pnp_unbound_flag = 0; 362 static int pnp_verbose_flag = 0; 363 364 static int 365 command_pnpmatch(int argc, char *argv[]) 366 { 367 char *module; 368 int ch; 369 370 pnp_verbose_flag = 0; 371 pnp_dump_flag = 0; 372 optind = 1; 373 optreset = 1; 374 while ((ch = getopt(argc, argv, "vd")) != -1) { 375 switch(ch) { 376 case 'v': 377 pnp_verbose_flag = 1; 378 break; 379 case 'd': 380 pnp_dump_flag = 1; 381 break; 382 case '?': 383 default: 384 /* getopt has already reported an error */ 385 return(CMD_OK); 386 } 387 } 388 argv += optind; 389 argc -= optind; 390 391 if (argc != 2) { 392 command_errmsg = "Usage: pnpmatch <busname> compat=<compatdata>"; 393 return (CMD_CRIT); 394 } 395 396 module = mod_searchmodule_pnpinfo(argv[0], argv[1]); 397 if (module) 398 printf("Matched module: %s\n", module); 399 else 400 printf("No module matches %s on bus %s\n", argv[1], argv[0]); 401 402 return (CMD_OK); 403 } 404 405 COMMAND_SET(pnpload, "pnpload", "load matched modules based on pnpinfo", command_pnpload); 406 407 static int 408 command_pnpload(int argc, char *argv[]) 409 { 410 char *module; 411 int ch, error; 412 413 pnp_verbose_flag = 0; 414 pnp_dump_flag = 0; 415 optind = 1; 416 optreset = 1; 417 while ((ch = getopt(argc, argv, "vd")) != -1) { 418 switch(ch) { 419 case 'v': 420 pnp_verbose_flag = 1; 421 break; 422 case 'd': 423 pnp_dump_flag = 1; 424 break; 425 case '?': 426 default: 427 /* getopt has already reported an error */ 428 return(CMD_OK); 429 } 430 } 431 argv += optind; 432 argc -= optind; 433 434 if (argc != 2) { 435 command_errmsg = "Usage: pnpload <busname> compat=<compatdata>"; 436 return (CMD_ERROR); 437 } 438 439 module = mod_searchmodule_pnpinfo(argv[0], argv[1]); 440 441 error = mod_load(module, NULL, 0, NULL); 442 if (error == EEXIST) { 443 snprintf(command_errbuf, sizeof(command_errbuf), 444 "warning: module '%s' already loaded", argv[1]); 445 return (CMD_WARN); 446 } 447 448 return (error == 0 ? CMD_OK : CMD_CRIT); 449 } 450 451 #if defined(LOADER_FDT_SUPPORT) 452 static void 453 pnpautoload_fdt_bus(const char *busname) { 454 const char *pnpstring; 455 const char *compatstr; 456 char *pnpinfo = NULL; 457 char *module = NULL; 458 int tag = 0, len, pnplen; 459 int error; 460 461 while (1) { 462 pnpstring = fdt_devmatch_next(&tag, &len); 463 if (pnpstring == NULL) 464 return; 465 466 compatstr = pnpstring; 467 for (pnplen = 0; pnplen != len; compatstr = pnpstring + pnplen) { 468 pnplen += strlen(compatstr) + 1; 469 asprintf(&pnpinfo, "compat=%s", compatstr); 470 471 module = mod_searchmodule_pnpinfo(busname, pnpinfo); 472 if (module) { 473 error = mod_loadkld(module, 0, NULL); 474 if (error) 475 printf("Cannot load module %s\n", module); 476 break; 477 } 478 } 479 free(pnpinfo); 480 free(module); 481 } 482 } 483 #endif 484 485 struct pnp_bus { 486 const char *name; 487 void (*load)(const char *busname); 488 }; 489 490 struct pnp_bus pnp_buses[] = { 491 #if defined(LOADER_FDT_SUPPORT) 492 {"simplebus", pnpautoload_fdt_bus}, 493 {"ofwbus", pnpautoload_fdt_bus}, 494 {"iicbus", pnpautoload_fdt_bus}, 495 {"spibus", pnpautoload_fdt_bus}, 496 #endif 497 }; 498 499 COMMAND_SET(pnpautoload, "pnpautoload", "auto load modules based on pnpinfo", command_pnpautoload); 500 501 static int 502 command_pnpautoload(int argc, char *argv[]) 503 { 504 int i; 505 int verbose; 506 int ch, match; 507 508 pnp_verbose_flag = 0; 509 pnp_dump_flag = 0; 510 verbose = 0; 511 optind = 1; 512 optreset = 1; 513 match = 0; 514 while ((ch = getopt(argc, argv, "v")) != -1) { 515 switch(ch) { 516 case 'v': 517 verbose = 1; 518 break; 519 case '?': 520 default: 521 /* getopt has already reported an error */ 522 return(CMD_OK); 523 } 524 } 525 argv += (optind - 1); 526 argc -= (optind - 1); 527 528 if (argc > 2) 529 return (CMD_ERROR); 530 531 for (i = 0; i < nitems(pnp_buses); i++) { 532 if (argc == 2 && strcmp(argv[1], pnp_buses[i].name) != 0) { 533 if (verbose) 534 printf("Skipping bus %s\n", pnp_buses[i].name); 535 continue; 536 } 537 if (verbose) 538 printf("Autoloading modules for %s\n", pnp_buses[i].name); 539 pnp_buses[i].load(pnp_buses[i].name); 540 match = 1; 541 } 542 if (match == 0) 543 printf("Unsupported bus %s\n", argv[1]); 544 545 return (CMD_OK); 546 } 547 548 /* 549 * File level interface, functions file_* 550 */ 551 int 552 file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) 553 { 554 static int last_file_format = 0; 555 struct preloaded_file *fp; 556 int error; 557 int i; 558 559 TSENTER2(filename); 560 if (archsw.arch_loadaddr != NULL) 561 dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest); 562 563 error = EFTYPE; 564 for (i = last_file_format, fp = NULL; 565 file_formats[i] && fp == NULL; i++) { 566 error = (file_formats[i]->l_load)(filename, dest, &fp); 567 if (error == 0) { 568 fp->f_loader = last_file_format = i; /* remember the loader */ 569 *result = fp; 570 break; 571 } else if (last_file_format == i && i != 0) { 572 /* Restart from the beginning */ 573 i = -1; 574 last_file_format = 0; 575 fp = NULL; 576 continue; 577 } 578 if (error == EFTYPE) 579 continue; /* Unknown to this handler? */ 580 if (error) { 581 snprintf(command_errbuf, sizeof(command_errbuf), 582 "can't load file '%s': %s", filename, strerror(error)); 583 break; 584 } 585 } 586 TSEXIT(); 587 return (error); 588 } 589 590 static int 591 file_load_dependencies(struct preloaded_file *base_file) 592 { 593 struct file_metadata *md; 594 struct preloaded_file *fp; 595 struct mod_depend *verinfo; 596 struct kernel_module *mp; 597 char *dmodname; 598 int error; 599 600 md = file_findmetadata(base_file, MODINFOMD_DEPLIST); 601 if (md == NULL) 602 return (0); 603 error = 0; 604 do { 605 verinfo = (struct mod_depend*)md->md_data; 606 dmodname = (char *)(verinfo + 1); 607 if (file_findmodule(NULL, dmodname, verinfo) == NULL) { 608 printf("loading required module '%s'\n", dmodname); 609 error = mod_load(dmodname, verinfo, 0, NULL); 610 if (error) 611 break; 612 /* 613 * If module loaded via kld name which isn't listed 614 * in the linker.hints file, we should check if it have 615 * required version. 616 */ 617 mp = file_findmodule(NULL, dmodname, verinfo); 618 if (mp == NULL) { 619 snprintf(command_errbuf, sizeof(command_errbuf), 620 "module '%s' exists but with wrong version", dmodname); 621 error = ENOENT; 622 break; 623 } 624 } 625 md = metadata_next(md, MODINFOMD_DEPLIST); 626 } while (md); 627 if (!error) 628 return (0); 629 /* Load failed; discard everything */ 630 while (base_file != NULL) { 631 fp = base_file; 632 base_file = base_file->f_next; 633 file_discard(fp); 634 } 635 return (error); 636 } 637 638 vm_offset_t 639 build_font_module(vm_offset_t addr) 640 { 641 vt_font_bitmap_data_t *bd; 642 struct vt_font *fd; 643 struct preloaded_file *fp; 644 size_t size; 645 uint32_t checksum; 646 int i; 647 struct font_info fi; 648 struct fontlist *fl; 649 uint64_t fontp; 650 651 if (STAILQ_EMPTY(&fonts)) 652 return (addr); 653 654 /* We can't load first */ 655 if ((file_findfile(NULL, NULL)) == NULL) { 656 printf("Can not load font module: %s\n", 657 "the kernel is not loaded"); 658 return (addr); 659 } 660 661 /* helper pointers */ 662 bd = NULL; 663 STAILQ_FOREACH(fl, &fonts, font_next) { 664 if (gfx_state.tg_font.vf_width == fl->font_data->vfbd_width && 665 gfx_state.tg_font.vf_height == fl->font_data->vfbd_height) { 666 /* 667 * Kernel does have better built in font. 668 */ 669 if (fl->font_flags == FONT_BUILTIN) 670 return (addr); 671 672 bd = fl->font_data; 673 break; 674 } 675 } 676 if (bd == NULL) 677 return (addr); 678 fd = bd->vfbd_font; 679 680 fi.fi_width = fd->vf_width; 681 checksum = fi.fi_width; 682 fi.fi_height = fd->vf_height; 683 checksum += fi.fi_height; 684 fi.fi_bitmap_size = bd->vfbd_uncompressed_size; 685 checksum += fi.fi_bitmap_size; 686 687 size = roundup2(sizeof (struct font_info), 8); 688 for (i = 0; i < VFNT_MAPS; i++) { 689 fi.fi_map_count[i] = fd->vf_map_count[i]; 690 checksum += fi.fi_map_count[i]; 691 size += fd->vf_map_count[i] * sizeof (struct vfnt_map); 692 size += roundup2(size, 8); 693 } 694 size += bd->vfbd_uncompressed_size; 695 696 fi.fi_checksum = -checksum; 697 698 fp = file_findfile(NULL, "elf kernel"); 699 if (fp == NULL) 700 fp = file_findfile(NULL, "elf64 kernel"); 701 if (fp == NULL) 702 panic("can't find kernel file"); 703 704 fontp = addr; 705 addr += archsw.arch_copyin(&fi, addr, sizeof (struct font_info)); 706 addr = roundup2(addr, 8); 707 708 /* Copy maps. */ 709 for (i = 0; i < VFNT_MAPS; i++) { 710 if (fd->vf_map_count[i] != 0) { 711 addr += archsw.arch_copyin(fd->vf_map[i], addr, 712 fd->vf_map_count[i] * sizeof (struct vfnt_map)); 713 addr = roundup2(addr, 8); 714 } 715 } 716 717 /* Copy the bitmap. */ 718 addr += archsw.arch_copyin(fd->vf_bytes, addr, fi.fi_bitmap_size); 719 720 /* Looks OK so far; populate control structure */ 721 file_addmetadata(fp, MODINFOMD_FONT, sizeof(fontp), &fontp); 722 return (addr); 723 } 724 725 #ifdef LOADER_VERIEXEC_VECTX 726 #define VECTX_HANDLE(fd) vctx 727 #else 728 #define VECTX_HANDLE(fd) fd 729 #endif 730 731 732 /* 733 * We've been asked to load (fname) as (type), so just suck it in, 734 * no arguments or anything. 735 */ 736 struct preloaded_file * 737 file_loadraw(const char *fname, char *type, int insert) 738 { 739 struct preloaded_file *fp; 740 char *name; 741 int fd, got; 742 vm_offset_t laddr; 743 #ifdef LOADER_VERIEXEC_VECTX 744 struct vectx *vctx; 745 int verror; 746 #endif 747 748 TSENTER2(fname); 749 /* We can't load first */ 750 if ((file_findfile(NULL, NULL)) == NULL) { 751 command_errmsg = "can't load file before kernel"; 752 TSEXIT(); 753 return(NULL); 754 } 755 756 /* locate the file on the load path */ 757 name = file_search(fname, NULL); 758 if (name == NULL) { 759 snprintf(command_errbuf, sizeof(command_errbuf), 760 "can't find '%s'", fname); 761 TSEXIT(); 762 return(NULL); 763 } 764 765 if ((fd = open(name, O_RDONLY)) < 0) { 766 snprintf(command_errbuf, sizeof(command_errbuf), 767 "can't open '%s': %s", name, strerror(errno)); 768 free(name); 769 TSEXIT(); 770 return(NULL); 771 } 772 773 #ifdef LOADER_VERIEXEC_VECTX 774 vctx = vectx_open(fd, name, 0L, NULL, &verror, __func__); 775 if (verror) { 776 sprintf(command_errbuf, "can't verify '%s': %s", 777 name, ve_error_get()); 778 free(name); 779 free(vctx); 780 close(fd); 781 TSEXIT(); 782 return(NULL); 783 } 784 #else 785 #ifdef LOADER_VERIEXEC 786 if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) { 787 sprintf(command_errbuf, "can't verify '%s': %s", 788 name, ve_error_get()); 789 free(name); 790 close(fd); 791 TSEXIT(); 792 return(NULL); 793 } 794 #endif 795 #endif 796 797 if (archsw.arch_loadaddr != NULL) 798 loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); 799 800 printf("%s ", name); 801 802 laddr = loadaddr; 803 for (;;) { 804 /* read in 4k chunks; size is not really important */ 805 got = archsw.arch_readin(VECTX_HANDLE(fd), laddr, 4096); 806 if (got == 0) /* end of file */ 807 break; 808 if (got < 0) { /* error */ 809 snprintf(command_errbuf, sizeof(command_errbuf), 810 "error reading '%s': %s", name, strerror(errno)); 811 free(name); 812 close(fd); 813 #ifdef LOADER_VERIEXEC_VECTX 814 free(vctx); 815 #endif 816 TSEXIT(); 817 return(NULL); 818 } 819 laddr += got; 820 } 821 822 printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr)); 823 #ifdef LOADER_VERIEXEC_VECTX 824 verror = vectx_close(vctx, VE_MUST, __func__); 825 if (verror) { 826 free(name); 827 close(fd); 828 free(vctx); 829 TSEXIT(); 830 return(NULL); 831 } 832 #endif 833 834 /* Looks OK so far; create & populate control structure */ 835 fp = file_alloc(); 836 if (fp == NULL) { 837 snprintf(command_errbuf, sizeof (command_errbuf), 838 "no memory to load %s", name); 839 free(name); 840 close(fd); 841 TSEXIT(); 842 return (NULL); 843 } 844 fp->f_name = name; 845 fp->f_type = strdup(type); 846 fp->f_args = NULL; 847 fp->f_metadata = NULL; 848 fp->f_loader = -1; 849 fp->f_addr = loadaddr; 850 fp->f_size = laddr - loadaddr; 851 852 if (fp->f_type == NULL) { 853 snprintf(command_errbuf, sizeof (command_errbuf), 854 "no memory to load %s", name); 855 free(name); 856 close(fd); 857 TSEXIT(); 858 return (NULL); 859 } 860 /* recognise space consumption */ 861 loadaddr = laddr; 862 863 /* Add to the list of loaded files */ 864 if (insert != 0) 865 file_insert_tail(fp); 866 close(fd); 867 TSEXIT(); 868 return(fp); 869 } 870 871 /* 872 * Load the module (name), pass it (argc),(argv), add container file 873 * to the list of loaded files. 874 * If module is already loaded just assign new argc/argv. 875 */ 876 int 877 mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[]) 878 { 879 struct kernel_module *mp; 880 int err; 881 char *filename; 882 883 TSENTER2(modname); 884 if (file_havepath(modname)) { 885 printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname); 886 TSEXIT(); 887 return (mod_loadkld(modname, argc, argv)); 888 } 889 /* see if module is already loaded */ 890 mp = file_findmodule(NULL, modname, verinfo); 891 if (mp) { 892 #ifdef moduleargs 893 free(mp->m_args); 894 mp->m_args = unargv(argc, argv); 895 #endif 896 snprintf(command_errbuf, sizeof(command_errbuf), 897 "warning: module '%s' already loaded", mp->m_name); 898 TSEXIT(); 899 return (0); 900 } 901 /* locate file with the module on the search path */ 902 filename = mod_searchmodule(modname, verinfo); 903 if (filename == NULL) { 904 snprintf(command_errbuf, sizeof(command_errbuf), 905 "can't find '%s'", modname); 906 TSEXIT(); 907 return (ENOENT); 908 } 909 err = mod_loadkld(filename, argc, argv); 910 free(filename); 911 TSEXIT(); 912 return (err); 913 } 914 915 /* 916 * Load specified KLD. If path is omitted, then try to locate it via 917 * search path. 918 */ 919 int 920 mod_loadkld(const char *kldname, int argc, char *argv[]) 921 { 922 struct preloaded_file *fp; 923 int err; 924 char *filename; 925 vm_offset_t loadaddr_saved; 926 927 TSENTER2(kldname); 928 /* 929 * Get fully qualified KLD name 930 */ 931 filename = file_search(kldname, kld_ext_list); 932 if (filename == NULL) { 933 snprintf(command_errbuf, sizeof(command_errbuf), 934 "can't find '%s'", kldname); 935 TSEXIT(); 936 return (ENOENT); 937 } 938 /* 939 * Check if KLD already loaded 940 */ 941 fp = file_findfile(filename, NULL); 942 if (fp) { 943 snprintf(command_errbuf, sizeof(command_errbuf), 944 "warning: KLD '%s' already loaded", filename); 945 free(filename); 946 TSEXIT(); 947 return (0); 948 } 949 950 do { 951 err = file_load(filename, loadaddr, &fp); 952 if (err) 953 break; 954 fp->f_args = unargv(argc, argv); 955 loadaddr_saved = loadaddr; 956 loadaddr = fp->f_addr + fp->f_size; 957 file_insert_tail(fp); /* Add to the list of loaded files */ 958 if (file_load_dependencies(fp) != 0) { 959 err = ENOENT; 960 file_remove(fp); 961 loadaddr = loadaddr_saved; 962 fp = NULL; 963 break; 964 } 965 } while(0); 966 if (err == EFTYPE) { 967 snprintf(command_errbuf, sizeof(command_errbuf), 968 "don't know how to load module '%s'", filename); 969 } 970 if (err) 971 file_discard(fp); 972 free(filename); 973 TSEXIT(); 974 return (err); 975 } 976 977 /* 978 * Find a file matching (name) and (type). 979 * NULL may be passed as a wildcard to either. 980 */ 981 struct preloaded_file * 982 file_findfile(const char *name, const char *type) 983 { 984 struct preloaded_file *fp; 985 986 for (fp = preloaded_files; fp != NULL; fp = fp->f_next) { 987 if (((name == NULL) || !strcmp(name, fp->f_name)) && 988 ((type == NULL) || !strcmp(type, fp->f_type))) 989 break; 990 } 991 return (fp); 992 } 993 994 /* 995 * Find a module matching (name) inside of given file. 996 * NULL may be passed as a wildcard. 997 */ 998 struct kernel_module * 999 file_findmodule(struct preloaded_file *fp, char *modname, 1000 struct mod_depend *verinfo) 1001 { 1002 struct kernel_module *mp, *best; 1003 int bestver, mver; 1004 1005 if (fp == NULL) { 1006 for (fp = preloaded_files; fp; fp = fp->f_next) { 1007 mp = file_findmodule(fp, modname, verinfo); 1008 if (mp) 1009 return (mp); 1010 } 1011 return (NULL); 1012 } 1013 best = NULL; 1014 bestver = 0; 1015 for (mp = fp->f_modules; mp; mp = mp->m_next) { 1016 if (strcmp(modname, mp->m_name) == 0) { 1017 if (verinfo == NULL) 1018 return (mp); 1019 mver = mp->m_version; 1020 if (mver == verinfo->md_ver_preferred) 1021 return (mp); 1022 if (mver >= verinfo->md_ver_minimum && 1023 mver <= verinfo->md_ver_maximum && 1024 mver > bestver) { 1025 best = mp; 1026 bestver = mver; 1027 } 1028 } 1029 } 1030 return (best); 1031 } 1032 /* 1033 * Make a copy of (size) bytes of data from (p), and associate them as 1034 * metadata of (type) to the module (mp). 1035 */ 1036 void 1037 file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p) 1038 { 1039 struct file_metadata *md; 1040 1041 md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size); 1042 if (md != NULL) { 1043 md->md_size = size; 1044 md->md_type = type; 1045 bcopy(p, md->md_data, size); 1046 md->md_next = fp->f_metadata; 1047 } 1048 fp->f_metadata = md; 1049 } 1050 1051 /* 1052 * Find a metadata object of (type) associated with the file (fp) 1053 */ 1054 struct file_metadata * 1055 file_findmetadata(struct preloaded_file *fp, int type) 1056 { 1057 struct file_metadata *md; 1058 1059 for (md = fp->f_metadata; md != NULL; md = md->md_next) 1060 if (md->md_type == type) 1061 break; 1062 return(md); 1063 } 1064 1065 /* 1066 * Remove all metadata from the file. 1067 */ 1068 void 1069 file_removemetadata(struct preloaded_file *fp) 1070 { 1071 struct file_metadata *md, *next; 1072 1073 for (md = fp->f_metadata; md != NULL; md = next) 1074 { 1075 next = md->md_next; 1076 free(md); 1077 } 1078 fp->f_metadata = NULL; 1079 } 1080 1081 /* 1082 * Add a buffer to the list of preloaded "files". 1083 */ 1084 int 1085 file_addbuf(const char *name, const char *type, size_t len, void *buf) 1086 { 1087 struct preloaded_file *fp; 1088 vm_offset_t dest; 1089 1090 /* We can't load first */ 1091 if ((file_findfile(NULL, NULL)) == NULL) { 1092 command_errmsg = "can't load file before kernel"; 1093 return (-1); 1094 } 1095 1096 /* Figure out where to load the data. */ 1097 dest = loadaddr; 1098 if (archsw.arch_loadaddr != NULL) 1099 dest = archsw.arch_loadaddr(LOAD_RAW, (void *)name, dest); 1100 1101 /* Create & populate control structure */ 1102 fp = file_alloc(); 1103 if (fp == NULL) { 1104 snprintf(command_errbuf, sizeof (command_errbuf), 1105 "no memory to load %s", name); 1106 return (-1); 1107 } 1108 fp->f_name = strdup(name); 1109 fp->f_type = strdup(type); 1110 fp->f_args = NULL; 1111 fp->f_metadata = NULL; 1112 fp->f_loader = -1; 1113 fp->f_addr = dest; 1114 fp->f_size = len; 1115 if ((fp->f_name == NULL) || (fp->f_type == NULL)) { 1116 snprintf(command_errbuf, sizeof (command_errbuf), 1117 "no memory to load %s", name); 1118 free(fp->f_name); 1119 free(fp->f_type); 1120 return (-1); 1121 } 1122 1123 /* Copy the data in. */ 1124 archsw.arch_copyin(buf, fp->f_addr, len); 1125 loadaddr = fp->f_addr + len; 1126 1127 /* Add to the list of loaded files */ 1128 file_insert_tail(fp); 1129 return(0); 1130 } 1131 1132 struct file_metadata * 1133 metadata_next(struct file_metadata *md, int type) 1134 { 1135 1136 if (md == NULL) 1137 return (NULL); 1138 while((md = md->md_next) != NULL) 1139 if (md->md_type == type) 1140 break; 1141 return (md); 1142 } 1143 1144 static char *emptyextlist[] = { "", NULL }; 1145 1146 /* 1147 * Check if the given file is in place and return full path to it. 1148 */ 1149 static char * 1150 file_lookup(const char *path, const char *name, int namelen, char **extlist) 1151 { 1152 struct stat st; 1153 char *result, *cp, **cpp; 1154 int pathlen, extlen, len; 1155 1156 pathlen = strlen(path); 1157 extlen = 0; 1158 if (extlist == NULL) 1159 extlist = emptyextlist; 1160 for (cpp = extlist; *cpp; cpp++) { 1161 len = strlen(*cpp); 1162 if (len > extlen) 1163 extlen = len; 1164 } 1165 result = malloc(pathlen + namelen + extlen + 2); 1166 if (result == NULL) 1167 return (NULL); 1168 bcopy(path, result, pathlen); 1169 if (pathlen > 0 && result[pathlen - 1] != '/') 1170 result[pathlen++] = '/'; 1171 cp = result + pathlen; 1172 bcopy(name, cp, namelen); 1173 cp += namelen; 1174 for (cpp = extlist; *cpp; cpp++) { 1175 strcpy(cp, *cpp); 1176 if (stat(result, &st) == 0 && S_ISREG(st.st_mode)) 1177 return result; 1178 } 1179 free(result); 1180 return NULL; 1181 } 1182 1183 /* 1184 * Check if file name have any qualifiers 1185 */ 1186 static int 1187 file_havepath(const char *name) 1188 { 1189 const char *cp; 1190 1191 archsw.arch_getdev(NULL, name, &cp); 1192 return (cp != name || strchr(name, '/') != NULL); 1193 } 1194 1195 /* 1196 * Attempt to find the file (name) on the module searchpath. 1197 * If (name) is qualified in any way, we simply check it and 1198 * return it or NULL. If it is not qualified, then we attempt 1199 * to construct a path using entries in the environment variable 1200 * module_path. 1201 * 1202 * The path we return a pointer to need never be freed, as we manage 1203 * it internally. 1204 */ 1205 static char * 1206 file_search(const char *name, char **extlist) 1207 { 1208 struct moduledir *mdp; 1209 struct stat sb; 1210 char *result; 1211 int namelen; 1212 1213 /* Don't look for nothing */ 1214 if (name == NULL) 1215 return(NULL); 1216 1217 if (*name == 0) 1218 return(strdup(name)); 1219 1220 if (file_havepath(name)) { 1221 /* Qualified, so just see if it exists */ 1222 if (stat(name, &sb) == 0) 1223 return(strdup(name)); 1224 return(NULL); 1225 } 1226 moduledir_rebuild(); 1227 result = NULL; 1228 namelen = strlen(name); 1229 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1230 result = file_lookup(mdp->d_path, name, namelen, extlist); 1231 if (result) 1232 break; 1233 } 1234 return(result); 1235 } 1236 1237 #define INT_ALIGN(base, ptr) ptr = \ 1238 (base) + roundup2((ptr) - (base), sizeof(int)) 1239 1240 static char * 1241 mod_search_hints(struct moduledir *mdp, const char *modname, 1242 struct mod_depend *verinfo) 1243 { 1244 u_char *cp, *recptr, *bufend, *best; 1245 char *result; 1246 int *intp, bestver, blen, clen, found, ival, modnamelen, reclen; 1247 1248 moduledir_readhints(mdp); 1249 modnamelen = strlen(modname); 1250 found = 0; 1251 result = NULL; 1252 bestver = 0; 1253 if (mdp->d_hints == NULL) 1254 goto bad; 1255 recptr = mdp->d_hints; 1256 bufend = recptr + mdp->d_hintsz; 1257 clen = blen = 0; 1258 best = cp = NULL; 1259 while (recptr < bufend && !found) { 1260 intp = (int*)recptr; 1261 reclen = *intp++; 1262 ival = *intp++; 1263 cp = (u_char*)intp; 1264 switch (ival) { 1265 case MDT_VERSION: 1266 clen = *cp++; 1267 if (clen != modnamelen || bcmp(cp, modname, clen) != 0) 1268 break; 1269 cp += clen; 1270 INT_ALIGN(mdp->d_hints, cp); 1271 ival = *(int*)cp; 1272 cp += sizeof(int); 1273 clen = *cp++; 1274 if (verinfo == NULL || ival == verinfo->md_ver_preferred) { 1275 found = 1; 1276 break; 1277 } 1278 if (ival >= verinfo->md_ver_minimum && 1279 ival <= verinfo->md_ver_maximum && 1280 ival > bestver) { 1281 bestver = ival; 1282 best = cp; 1283 blen = clen; 1284 } 1285 break; 1286 default: 1287 break; 1288 } 1289 recptr += reclen + sizeof(int); 1290 } 1291 /* 1292 * Finally check if KLD is in the place 1293 */ 1294 if (found) 1295 result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL); 1296 else if (best) 1297 result = file_lookup(mdp->d_path, (const char *)best, blen, NULL); 1298 bad: 1299 /* 1300 * If nothing found or hints is absent - fallback to the old way 1301 * by using "kldname[.ko]" as module name. 1302 */ 1303 if (!found && !bestver && result == NULL) 1304 result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list); 1305 return result; 1306 } 1307 1308 static int 1309 getint(void **ptr) 1310 { 1311 int *p = *ptr; 1312 int rv; 1313 1314 p = (int *)roundup2((intptr_t)p, sizeof(int)); 1315 rv = *p++; 1316 *ptr = p; 1317 return rv; 1318 } 1319 1320 static void 1321 getstr(void **ptr, char *val) 1322 { 1323 int *p = *ptr; 1324 char *c = (char *)p; 1325 int len = *(uint8_t *)c; 1326 1327 memcpy(val, c + 1, len); 1328 val[len] = 0; 1329 c += len + 1; 1330 *ptr = (void *)c; 1331 } 1332 1333 static int 1334 pnpval_as_int(const char *val, const char *pnpinfo) 1335 { 1336 int rv; 1337 char key[256]; 1338 char *cp; 1339 1340 if (pnpinfo == NULL) 1341 return -1; 1342 1343 cp = strchr(val, ';'); 1344 key[0] = ' '; 1345 if (cp == NULL) 1346 strlcpy(key + 1, val, sizeof(key) - 1); 1347 else { 1348 memcpy(key + 1, val, cp - val); 1349 key[cp - val + 1] = '\0'; 1350 } 1351 strlcat(key, "=", sizeof(key)); 1352 if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0) 1353 rv = strtol(pnpinfo + strlen(key + 1), NULL, 0); 1354 else { 1355 cp = strstr(pnpinfo, key); 1356 if (cp == NULL) 1357 rv = -1; 1358 else 1359 rv = strtol(cp + strlen(key), NULL, 0); 1360 } 1361 return rv; 1362 } 1363 1364 static void 1365 quoted_strcpy(char *dst, const char *src) 1366 { 1367 char q = ' '; 1368 1369 if (*src == '\'' || *src == '"') 1370 q = *src++; 1371 while (*src && *src != q) 1372 *dst++ = *src++; // XXX backtick quoting 1373 *dst++ = '\0'; 1374 // XXX overflow 1375 } 1376 1377 static char * 1378 pnpval_as_str(const char *val, const char *pnpinfo) 1379 { 1380 static char retval[256]; 1381 char key[256]; 1382 char *cp; 1383 1384 if (pnpinfo == NULL) { 1385 *retval = '\0'; 1386 return retval; 1387 } 1388 1389 cp = strchr(val, ';'); 1390 key[0] = ' '; 1391 if (cp == NULL) 1392 strlcpy(key + 1, val, sizeof(key) - 1); 1393 else { 1394 memcpy(key + 1, val, cp - val); 1395 key[cp - val + 1] = '\0'; 1396 } 1397 strlcat(key, "=", sizeof(key)); 1398 if (strncmp(key + 1, pnpinfo, strlen(key + 1)) == 0) 1399 quoted_strcpy(retval, pnpinfo + strlen(key + 1)); 1400 else { 1401 cp = strstr(pnpinfo, key); 1402 if (cp == NULL) 1403 strcpy(retval, "MISSING"); 1404 else 1405 quoted_strcpy(retval, cp + strlen(key)); 1406 } 1407 return retval; 1408 } 1409 1410 static char * 1411 devmatch_search_hints(struct moduledir *mdp, const char *bus, const char *dev, const char *pnpinfo) 1412 { 1413 char val1[256], val2[256]; 1414 int ival, len, ents, i, notme, mask, bit, v, found; 1415 void *ptr, *walker, *hints_end; 1416 char *lastmod = NULL, *cp, *s; 1417 1418 moduledir_readhints(mdp); 1419 found = 0; 1420 if (mdp->d_hints == NULL) 1421 goto bad; 1422 walker = mdp->d_hints; 1423 hints_end = walker + mdp->d_hintsz; 1424 while (walker < hints_end && !found) { 1425 len = getint(&walker); 1426 ival = getint(&walker); 1427 ptr = walker; 1428 switch (ival) { 1429 case MDT_VERSION: 1430 getstr(&ptr, val1); 1431 ival = getint(&ptr); 1432 getstr(&ptr, val2); 1433 if (pnp_dump_flag || pnp_verbose_flag) 1434 printf("Version: if %s.%d kmod %s\n", val1, ival, val2); 1435 break; 1436 case MDT_MODULE: 1437 getstr(&ptr, val1); 1438 getstr(&ptr, val2); 1439 if (lastmod) 1440 free(lastmod); 1441 lastmod = strdup(val2); 1442 if (pnp_dump_flag || pnp_verbose_flag) 1443 printf("module %s in %s\n", val1, val1); 1444 break; 1445 case MDT_PNP_INFO: 1446 if (!pnp_dump_flag && !pnp_unbound_flag && lastmod && strcmp(lastmod, "kernel") == 0) 1447 break; 1448 getstr(&ptr, val1); 1449 getstr(&ptr, val2); 1450 ents = getint(&ptr); 1451 if (pnp_dump_flag || pnp_verbose_flag) 1452 printf("PNP info for bus %s format %s %d entries (%s)\n", 1453 val1, val2, ents, lastmod); 1454 if (strcmp(val1, "usb") == 0) { 1455 if (pnp_verbose_flag) 1456 printf("Treating usb as uhub -- bug in source table still?\n"); 1457 strcpy(val1, "uhub"); 1458 } 1459 if (bus && strcmp(val1, bus) != 0) { 1460 if (pnp_verbose_flag) 1461 printf("Skipped because table for bus %s, looking for %s\n", 1462 val1, bus); 1463 break; 1464 } 1465 for (i = 0; i < ents; i++) { 1466 if (pnp_verbose_flag) 1467 printf("---------- Entry %d ----------\n", i); 1468 if (pnp_dump_flag) 1469 printf(" "); 1470 cp = val2; 1471 notme = 0; 1472 mask = -1; 1473 bit = -1; 1474 do { 1475 switch (*cp) { 1476 /* All integer fields */ 1477 case 'I': 1478 case 'J': 1479 case 'G': 1480 case 'L': 1481 case 'M': 1482 ival = getint(&ptr); 1483 if (pnp_dump_flag) { 1484 printf("%#x:", ival); 1485 break; 1486 } 1487 if (bit >= 0 && ((1 << bit) & mask) == 0) 1488 break; 1489 v = pnpval_as_int(cp + 2, pnpinfo); 1490 if (pnp_verbose_flag) 1491 printf("Matching %s (%c) table=%#x tomatch=%#x\n", 1492 cp + 2, *cp, v, ival); 1493 switch (*cp) { 1494 case 'J': 1495 if (ival == -1) 1496 break; 1497 /*FALLTHROUGH*/ 1498 case 'I': 1499 if (v != ival) 1500 notme++; 1501 break; 1502 case 'G': 1503 if (v < ival) 1504 notme++; 1505 break; 1506 case 'L': 1507 if (v > ival) 1508 notme++; 1509 break; 1510 case 'M': 1511 mask = ival; 1512 break; 1513 } 1514 break; 1515 /* String fields */ 1516 case 'D': 1517 case 'Z': 1518 getstr(&ptr, val1); 1519 if (pnp_dump_flag) { 1520 printf("'%s':", val1); 1521 break; 1522 } 1523 if (*cp == 'D') 1524 break; 1525 s = pnpval_as_str(cp + 2, pnpinfo); 1526 if (strcmp(s, val1) != 0) 1527 notme++; 1528 break; 1529 /* Key override fields, required to be last in the string */ 1530 case 'T': 1531 /* 1532 * This is imperfect and only does one key and will be redone 1533 * to be more general for multiple keys. Currently, nothing 1534 * does that. 1535 */ 1536 if (pnp_dump_flag) /* No per-row data stored */ 1537 break; 1538 if (cp[strlen(cp) - 1] == ';') /* Skip required ; at end */ 1539 cp[strlen(cp) - 1] = '\0'; /* in case it's not there */ 1540 if ((s = strstr(pnpinfo, cp + 2)) == NULL) 1541 notme++; 1542 else if (s > pnpinfo && s[-1] != ' ') 1543 notme++; 1544 break; 1545 default: 1546 printf("Unknown field type %c\n:", *cp); 1547 break; 1548 } 1549 bit++; 1550 cp = strchr(cp, ';'); 1551 if (cp) 1552 cp++; 1553 } while (cp && *cp); 1554 if (pnp_dump_flag) 1555 printf("\n"); 1556 else if (!notme) { 1557 if (!pnp_unbound_flag) { 1558 if (pnp_verbose_flag) 1559 printf("Matches --- %s ---\n", lastmod); 1560 } 1561 found++; 1562 } 1563 } 1564 break; 1565 default: 1566 break; 1567 } 1568 walker = (void *)(len - sizeof(int) + (intptr_t)walker); 1569 } 1570 if (pnp_unbound_flag && found == 0 && *pnpinfo) { 1571 if (pnp_verbose_flag) 1572 printf("------------------------- "); 1573 printf("%s on %s pnpinfo %s", *dev ? dev : "unattached", bus, pnpinfo); 1574 if (pnp_verbose_flag) 1575 printf(" -------------------------"); 1576 printf("\n"); 1577 } 1578 if (found != 0) 1579 return (lastmod); 1580 free(lastmod); 1581 1582 bad: 1583 return (NULL); 1584 } 1585 1586 /* 1587 * Attempt to locate the file containing the module (name) 1588 */ 1589 static char * 1590 mod_searchmodule(char *name, struct mod_depend *verinfo) 1591 { 1592 struct moduledir *mdp; 1593 char *result; 1594 1595 moduledir_rebuild(); 1596 /* 1597 * Now we ready to lookup module in the given directories 1598 */ 1599 result = NULL; 1600 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1601 result = mod_search_hints(mdp, name, verinfo); 1602 if (result) 1603 break; 1604 } 1605 1606 return(result); 1607 } 1608 1609 static char * 1610 mod_searchmodule_pnpinfo(const char *bus, const char *pnpinfo) 1611 { 1612 struct moduledir *mdp; 1613 char *result; 1614 1615 moduledir_rebuild(); 1616 /* 1617 * Now we ready to lookup module in the given directories 1618 */ 1619 result = NULL; 1620 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1621 result = devmatch_search_hints(mdp, bus, NULL, pnpinfo); 1622 if (result) 1623 break; 1624 } 1625 1626 return(result); 1627 } 1628 1629 int 1630 file_addmodule(struct preloaded_file *fp, char *modname, int version, 1631 struct kernel_module **newmp) 1632 { 1633 struct kernel_module *mp; 1634 struct mod_depend mdepend; 1635 1636 bzero(&mdepend, sizeof(mdepend)); 1637 mdepend.md_ver_preferred = version; 1638 mp = file_findmodule(fp, modname, &mdepend); 1639 if (mp) 1640 return (EEXIST); 1641 mp = calloc(1, sizeof(struct kernel_module)); 1642 if (mp == NULL) 1643 return (ENOMEM); 1644 mp->m_name = strdup(modname); 1645 if (mp->m_name == NULL) { 1646 free(mp); 1647 return (ENOMEM); 1648 } 1649 mp->m_version = version; 1650 mp->m_fp = fp; 1651 mp->m_next = fp->f_modules; 1652 fp->f_modules = mp; 1653 if (newmp) 1654 *newmp = mp; 1655 return (0); 1656 } 1657 1658 /* 1659 * Throw a file away 1660 */ 1661 void 1662 file_discard(struct preloaded_file *fp) 1663 { 1664 struct file_metadata *md, *md1; 1665 struct kernel_module *mp, *mp1; 1666 if (fp == NULL) 1667 return; 1668 md = fp->f_metadata; 1669 while (md) { 1670 md1 = md; 1671 md = md->md_next; 1672 free(md1); 1673 } 1674 mp = fp->f_modules; 1675 while (mp) { 1676 free(mp->m_name); 1677 mp1 = mp; 1678 mp = mp->m_next; 1679 free(mp1); 1680 } 1681 free(fp->f_name); 1682 free(fp->f_type); 1683 free(fp->f_args); 1684 free(fp); 1685 } 1686 1687 /* 1688 * Allocate a new file; must be used instead of malloc() 1689 * to ensure safe initialisation. 1690 */ 1691 struct preloaded_file * 1692 file_alloc(void) 1693 { 1694 1695 return (calloc(1, sizeof(struct preloaded_file))); 1696 } 1697 1698 /* 1699 * Add a module to the chain 1700 */ 1701 static void 1702 file_insert_tail(struct preloaded_file *fp) 1703 { 1704 struct preloaded_file *cm; 1705 1706 /* Append to list of loaded file */ 1707 fp->f_next = NULL; 1708 if (preloaded_files == NULL) { 1709 preloaded_files = fp; 1710 } else { 1711 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) 1712 ; 1713 cm->f_next = fp; 1714 } 1715 } 1716 1717 /* 1718 * Remove module from the chain 1719 */ 1720 static void 1721 file_remove(struct preloaded_file *fp) 1722 { 1723 struct preloaded_file *cm; 1724 1725 if (preloaded_files == NULL) 1726 return; 1727 1728 if (preloaded_files == fp) { 1729 preloaded_files = fp->f_next; 1730 return; 1731 } 1732 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) { 1733 if (cm->f_next == fp) { 1734 cm->f_next = fp->f_next; 1735 return; 1736 } 1737 } 1738 } 1739 1740 static char * 1741 moduledir_fullpath(struct moduledir *mdp, const char *fname) 1742 { 1743 char *cp; 1744 1745 cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2); 1746 if (cp == NULL) 1747 return NULL; 1748 strcpy(cp, mdp->d_path); 1749 strcat(cp, "/"); 1750 strcat(cp, fname); 1751 return (cp); 1752 } 1753 1754 /* 1755 * Read linker.hints file into memory performing some sanity checks. 1756 */ 1757 static void 1758 moduledir_readhints(struct moduledir *mdp) 1759 { 1760 struct stat st; 1761 char *path; 1762 int fd, size, version; 1763 1764 if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS)) 1765 return; 1766 path = moduledir_fullpath(mdp, "linker.hints"); 1767 if (stat(path, &st) != 0 || 1768 st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) || 1769 st.st_size > LINKER_HINTS_MAX || (fd = open(path, O_RDONLY)) < 0) { 1770 free(path); 1771 mdp->d_flags |= MDIR_NOHINTS; 1772 return; 1773 } 1774 free(path); 1775 size = read(fd, &version, sizeof(version)); 1776 if (size != sizeof(version) || version != LINKER_HINTS_VERSION) 1777 goto bad; 1778 size = st.st_size - size; 1779 mdp->d_hints = malloc(size); 1780 if (mdp->d_hints == NULL) 1781 goto bad; 1782 if (read(fd, mdp->d_hints, size) != size) 1783 goto bad; 1784 mdp->d_hintsz = size; 1785 close(fd); 1786 return; 1787 bad: 1788 close(fd); 1789 free(mdp->d_hints); 1790 mdp->d_hints = NULL; 1791 mdp->d_flags |= MDIR_NOHINTS; 1792 return; 1793 } 1794 1795 /* 1796 * Extract directories from the ';' separated list, remove duplicates. 1797 */ 1798 static void 1799 moduledir_rebuild(void) 1800 { 1801 struct moduledir *mdp, *mtmp; 1802 const char *path, *cp, *ep; 1803 size_t cplen; 1804 1805 path = getenv("module_path"); 1806 if (path == NULL) 1807 path = default_searchpath; 1808 /* 1809 * Rebuild list of module directories if it changed 1810 */ 1811 STAILQ_FOREACH(mdp, &moduledir_list, d_link) 1812 mdp->d_flags |= MDIR_REMOVED; 1813 1814 for (ep = path; *ep != 0; ep++) { 1815 cp = ep; 1816 for (; *ep != 0 && *ep != ';'; ep++) 1817 ; 1818 /* 1819 * Ignore trailing slashes 1820 */ 1821 for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--) 1822 ; 1823 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1824 if (strlen(mdp->d_path) != cplen || bcmp(cp, mdp->d_path, cplen) != 0) 1825 continue; 1826 mdp->d_flags &= ~MDIR_REMOVED; 1827 break; 1828 } 1829 if (mdp == NULL) { 1830 mdp = malloc(sizeof(*mdp) + cplen + 1); 1831 if (mdp == NULL) 1832 return; 1833 mdp->d_path = (char*)(mdp + 1); 1834 bcopy(cp, mdp->d_path, cplen); 1835 mdp->d_path[cplen] = 0; 1836 mdp->d_hints = NULL; 1837 mdp->d_flags = 0; 1838 STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link); 1839 } 1840 if (*ep == 0) 1841 break; 1842 } 1843 /* 1844 * Delete unused directories if any 1845 */ 1846 mdp = STAILQ_FIRST(&moduledir_list); 1847 while (mdp) { 1848 if ((mdp->d_flags & MDIR_REMOVED) == 0) { 1849 mdp = STAILQ_NEXT(mdp, d_link); 1850 } else { 1851 free(mdp->d_hints); 1852 mtmp = mdp; 1853 mdp = STAILQ_NEXT(mdp, d_link); 1854 STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link); 1855 free(mtmp); 1856 } 1857 } 1858 return; 1859 } 1860