1 /* 2 * Copyright 2026 Edgecast Cloud LLC. 3 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 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/tem_impl.h> 42 #include <sys/font.h> 43 #include <sys/sha1.h> 44 #include <libcrypto.h> 45 46 #include "bootstrap.h" 47 48 #define MDIR_REMOVED 0x0001 49 #define MDIR_NOHINTS 0x0002 50 51 struct moduledir { 52 char *d_path; /* path of modules directory */ 53 uchar_t *d_hints; /* content of linker.hints file */ 54 int d_hintsz; /* size of hints data */ 55 int d_flags; 56 STAILQ_ENTRY(moduledir) d_link; 57 }; 58 59 static int file_load(char *, vm_offset_t, struct preloaded_file **); 60 static int file_load_dependencies(struct preloaded_file *); 61 static char *file_search(const char *, const char **); 62 static struct kernel_module *file_findmodule(struct preloaded_file *, char *, 63 struct mod_depend *); 64 static int file_havepath(const char *); 65 static char *mod_searchmodule(char *, struct mod_depend *); 66 static void file_insert_tail(struct preloaded_file *); 67 static void file_remove(struct preloaded_file *); 68 struct file_metadata *metadata_next(struct file_metadata *, int); 69 static void moduledir_readhints(struct moduledir *); 70 static void moduledir_rebuild(void); 71 72 /* load address should be tweaked by first module loaded (kernel) */ 73 static vm_offset_t loadaddr = 0; 74 75 #if defined(LOADER_FDT_SUPPORT) 76 static const char *default_searchpath = "/boot/kernel;/boot/modules;/boot/dtb"; 77 #else 78 static const char *default_searchpath = "/platform/i86pc"; 79 #endif 80 81 static STAILQ_HEAD(, moduledir) moduledir_list = 82 STAILQ_HEAD_INITIALIZER(moduledir_list); 83 84 struct preloaded_file *preloaded_files = NULL; 85 86 static const char *kld_ext_list[] = { 87 ".ko", 88 "", 89 ".debug", 90 NULL 91 }; 92 93 94 /* 95 * load an object, either a disk file or code module. 96 * 97 * To load a file, the syntax is: 98 * 99 * load -t <type> <path> 100 * 101 * code modules are loaded as: 102 * 103 * load <path> <options> 104 */ 105 106 COMMAND_SET(load, "load", "load a kernel or module", command_load); 107 108 static int 109 command_load(int argc, char *argv[]) 110 { 111 char *typestr; 112 int dofile, dokld, ch, error; 113 114 dokld = dofile = 0; 115 optind = 1; 116 optreset = 1; 117 typestr = NULL; 118 if (argc == 1) { 119 command_errmsg = "no filename specified"; 120 return (CMD_CRIT); 121 } 122 while ((ch = getopt(argc, argv, "kt:")) != -1) { 123 switch (ch) { 124 case 'k': 125 dokld = 1; 126 break; 127 case 't': 128 typestr = optarg; 129 dofile = 1; 130 break; 131 case '?': 132 default: 133 /* getopt has already reported an error */ 134 return (CMD_OK); 135 } 136 } 137 argv += (optind - 1); 138 argc -= (optind - 1); 139 140 printf("Loading %s...\n", argv[1]); 141 /* 142 * Request to load a raw file? 143 */ 144 if (dofile) { 145 struct preloaded_file *fp; 146 147 if ((typestr == NULL) || (*typestr == 0)) { 148 command_errmsg = "invalid load type"; 149 return (CMD_CRIT); 150 } 151 152 if (file_findfile(argv[1], typestr) != NULL) { 153 (void) snprintf(command_errbuf, sizeof (command_errbuf), 154 "warning: file '%s' already loaded", argv[1]); 155 return (CMD_WARN); 156 } 157 158 fp = file_loadraw(argv[1], typestr, argc - 2, argv + 2, 1); 159 if (fp != NULL) 160 return (CMD_OK); 161 162 /* Failing to load mfs_root is never going to end well! */ 163 if (strcmp("mfs_root", typestr) == 0) 164 return (CMD_FATAL); 165 166 return (CMD_ERROR); 167 } 168 /* 169 * Do we have explicit KLD load ? 170 */ 171 if (dokld || file_havepath(argv[1])) { 172 error = mod_loadkld(argv[1], argc - 2, argv + 2); 173 if (error == EEXIST) { 174 (void) snprintf(command_errbuf, sizeof (command_errbuf), 175 "warning: KLD '%s' already loaded", argv[1]); 176 return (CMD_WARN); 177 } 178 179 return (error == 0 ? CMD_OK : CMD_CRIT); 180 } 181 /* 182 * Looks like a request for a module. 183 */ 184 error = mod_load(argv[1], NULL, argc - 2, argv + 2); 185 if (error == EEXIST) { 186 (void) snprintf(command_errbuf, sizeof (command_errbuf), 187 "warning: module '%s' already loaded", argv[1]); 188 return (CMD_WARN); 189 } 190 191 return (error == 0 ? CMD_OK : CMD_CRIT); 192 } 193 194 void 195 unload(void) 196 { 197 struct preloaded_file *fp; 198 199 while (preloaded_files != NULL) { 200 fp = preloaded_files; 201 preloaded_files = preloaded_files->f_next; 202 file_discard(fp); 203 } 204 loadaddr = 0; 205 (void) unsetenv("kernelname"); 206 } 207 208 COMMAND_SET(unload, "unload", "unload all modules", command_unload); 209 210 static int 211 command_unload(int argc __unused, char *argv[] __unused) 212 { 213 unload(); 214 return (CMD_OK); 215 } 216 217 COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 218 219 static int 220 command_lsmod(int argc, char *argv[]) 221 { 222 struct preloaded_file *fp; 223 struct kernel_module *mp; 224 struct file_metadata *md; 225 char lbuf[80]; 226 int ch, verbose, hash, ret = 0; 227 228 verbose = 0; 229 hash = 0; 230 optind = 1; 231 optreset = 1; 232 while ((ch = getopt(argc, argv, "vs")) != -1) { 233 switch (ch) { 234 case 'v': 235 verbose = 1; 236 break; 237 case 's': 238 /* Compute and output hash when there is none */ 239 hash = 1; 240 break; 241 case '?': 242 default: 243 /* getopt has already reported an error */ 244 return (CMD_OK); 245 } 246 } 247 248 pager_open(); 249 for (fp = preloaded_files; fp; fp = fp->f_next) { 250 (void) snprintf(lbuf, sizeof (lbuf), " %p: ", 251 (void *) fp->f_addr); 252 (void) pager_output(lbuf); 253 (void) pager_output(fp->f_name); 254 (void) snprintf(lbuf, sizeof (lbuf), " (%s, 0x%lx)\n", 255 fp->f_type, (long)fp->f_size); 256 if (pager_output(lbuf)) 257 break; 258 if (fp->f_args != NULL) { 259 (void) pager_output(" args: "); 260 (void) pager_output(fp->f_args); 261 if (pager_output("\n")) 262 break; 263 if (strcmp(fp->f_type, "hash") == 0) { 264 size_t dsize; 265 266 (void) pager_output(" contents: "); 267 dsize = fp->f_size + 1; 268 if (sizeof (lbuf) < dsize) 269 dsize = sizeof (lbuf); 270 (void) strlcpy(lbuf, ptov(fp->f_addr), dsize); 271 if (pager_output(lbuf)) 272 break; 273 } 274 } 275 276 void *ptr = ptov(fp->f_addr); 277 char *hptr = strstr(fp->f_args, "hash="); 278 char digest[SHA1_DIGEST_LENGTH * 2 + 1]; 279 280 sha1(ptr, fp->f_size, (uint8_t *)lbuf); 281 for (int i = 0; i < SHA1_DIGEST_LENGTH; i++) { 282 (void) snprintf(digest + 2 * i, sizeof (digest) - 2 * i, 283 "%02x", (int)(lbuf[i] & 0xff)); 284 } 285 286 if (hptr != NULL) { 287 (void) pager_output(" hash: "); 288 if (strcmp(digest, hptr + 5) == 0) 289 (void) pager_output("match"); 290 else 291 (void) pager_output("mismatch"); 292 if (pager_output("\n")) 293 break; 294 } 295 296 if (hptr == NULL && hash == 1) { 297 (void) pager_output(" hash: "); 298 (void) pager_output(digest); 299 if (pager_output("\n")) 300 break; 301 } 302 303 if (fp->f_modules) { 304 (void) pager_output(" modules: "); 305 for (mp = fp->f_modules; mp; mp = mp->m_next) { 306 (void) snprintf(lbuf, sizeof (lbuf), "%s.%d ", 307 mp->m_name, mp->m_version); 308 (void) pager_output(lbuf); 309 } 310 if (pager_output("\n")) 311 break; 312 } 313 if (verbose) { 314 /* 315 * XXX could add some formatting smarts here to 316 * display some better 317 */ 318 for (md = fp->f_metadata; md != NULL; 319 md = md->md_next) { 320 (void) snprintf(lbuf, sizeof (lbuf), 321 " 0x%04x, 0x%lx\n", 322 md->md_type, (long)md->md_size); 323 if ((ret = pager_output(lbuf))) 324 break; 325 } 326 } 327 if (ret != 0) 328 break; 329 } 330 pager_close(); 331 return (CMD_OK); 332 } 333 334 /* 335 * File level interface, functions file_* 336 */ 337 int 338 file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) 339 { 340 static int last_file_format = 0; 341 struct preloaded_file *fp; 342 int error; 343 int i; 344 345 if (preloaded_files == NULL) 346 last_file_format = 0; 347 348 error = EFTYPE; 349 for (i = last_file_format, fp = NULL; 350 file_formats[i] && fp == NULL; i++) { 351 error = (file_formats[i]->l_load)(filename, dest, &fp); 352 if (error == 0) { 353 /* remember the loader */ 354 fp->f_loader = last_file_format = i; 355 *result = fp; 356 break; 357 } else if (last_file_format == i && i != 0) { 358 /* Restart from the beginning */ 359 i = -1; 360 last_file_format = 0; 361 fp = NULL; 362 continue; 363 } 364 if (error == EFTYPE) 365 continue; /* Unknown to this handler? */ 366 if (error) { 367 (void) snprintf(command_errbuf, sizeof (command_errbuf), 368 "can't load file '%s': %s", filename, 369 strerror(error)); 370 break; 371 } 372 } 373 return (error); 374 } 375 376 static int 377 file_load_dependencies(struct preloaded_file *base_file) 378 { 379 struct file_metadata *md; 380 struct preloaded_file *fp; 381 struct mod_depend *verinfo; 382 struct kernel_module *mp; 383 char *dmodname; 384 int error; 385 386 md = file_findmetadata(base_file, MODINFOMD_DEPLIST); 387 if (md == NULL) 388 return (0); 389 error = 0; 390 do { 391 verinfo = (struct mod_depend *)md->md_data; 392 dmodname = (char *)(verinfo + 1); 393 if (file_findmodule(NULL, dmodname, verinfo) == NULL) { 394 printf("loading required module '%s'\n", dmodname); 395 error = mod_load(dmodname, verinfo, 0, NULL); 396 if (error) 397 break; 398 /* 399 * If module loaded via kld name which isn't listed 400 * in the linker.hints file, we should check if it have 401 * required version. 402 */ 403 mp = file_findmodule(NULL, dmodname, verinfo); 404 if (mp == NULL) { 405 (void) snprintf(command_errbuf, 406 sizeof (command_errbuf), 407 "module '%s' exists but with wrong version", 408 dmodname); 409 error = ENOENT; 410 break; 411 } 412 } 413 md = metadata_next(md, MODINFOMD_DEPLIST); 414 } while (md); 415 if (!error) 416 return (0); 417 /* Load failed; discard everything */ 418 while (base_file != NULL) { 419 fp = base_file; 420 base_file = base_file->f_next; 421 file_discard(fp); 422 } 423 return (error); 424 } 425 426 /* 427 * Calculate the size of the environment module. 428 * The environment is list of name=value C strings, ending with a '\0' byte. 429 */ 430 static size_t 431 env_get_size(void) 432 { 433 size_t size = 0; 434 struct env_var *ep; 435 436 /* Traverse the environment. */ 437 for (ep = environ; ep != NULL; ep = ep->ev_next) { 438 size += strlen(ep->ev_name); 439 size++; /* "=" */ 440 if (ep->ev_value != NULL) 441 size += strlen(ep->ev_value); 442 size++; /* nul byte */ 443 } 444 size++; /* nul byte */ 445 return (size); 446 } 447 448 static void 449 module_hash(struct preloaded_file *fp, void *addr, size_t size) 450 { 451 uint8_t hash[SHA1_DIGEST_LENGTH]; 452 char ascii[2 * SHA1_DIGEST_LENGTH + 1]; 453 int i; 454 455 sha1(addr, size, hash); 456 for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { 457 (void) snprintf(ascii + 2 * i, sizeof (ascii) - 2 * i, "%02x", 458 hash[i] & 0xff); 459 } 460 /* Out of memory here is not fatal issue. */ 461 (void) asprintf(&fp->f_args, "hash=%s", ascii); 462 } 463 464 /* 465 * Create virtual module for environment variables. 466 * This module should be created as late as possible before executing 467 * the OS kernel, or we may miss some environment variable updates. 468 */ 469 void 470 build_environment_module(void) 471 { 472 struct preloaded_file *fp; 473 size_t size; 474 char *name = "environment"; 475 vm_offset_t laddr; 476 477 /* We can't load first */ 478 if (file_findfile(NULL, NULL) == NULL) { 479 printf("Can not load environment module: %s\n", 480 "the kernel is not loaded"); 481 return; 482 } 483 484 if (file_findfile(name, name) != NULL) { 485 printf("warning: '%s' is already loaded\n", name); 486 return; 487 } 488 489 tem_save_state(); /* Ask tem to save it's state in env. */ 490 size = env_get_size(); 491 492 fp = file_alloc(); 493 if (fp != NULL) { 494 fp->f_name = strdup(name); 495 fp->f_type = strdup(name); 496 } 497 498 if (fp == NULL || fp->f_name == NULL || fp->f_type == NULL) { 499 printf("Can not load environment module: %s\n", 500 "out of memory"); 501 file_discard(fp); 502 return; 503 } 504 505 506 if (archsw.arch_loadaddr != NULL) 507 loadaddr = archsw.arch_loadaddr(LOAD_MEM, &size, loadaddr); 508 509 if (loadaddr == 0) { 510 printf("Can not load environment module: %s\n", 511 "out of memory"); 512 file_discard(fp); 513 return; 514 } 515 516 laddr = bi_copyenv(loadaddr); 517 /* Looks OK so far; populate control structure */ 518 module_hash(fp, ptov(loadaddr), laddr - loadaddr); 519 fp->f_loader = -1; 520 fp->f_addr = loadaddr; 521 fp->f_size = laddr - loadaddr; 522 523 /* recognise space consumption */ 524 loadaddr = laddr; 525 526 file_insert_tail(fp); 527 } 528 529 void 530 build_font_module(void) 531 { 532 bitmap_data_t *bd; 533 struct font *fd; 534 struct preloaded_file *fp; 535 size_t size; 536 uint32_t checksum; 537 int i; 538 char *name = "console-font"; 539 vm_offset_t laddr; 540 struct font_info fi; 541 struct fontlist *fl; 542 543 if (STAILQ_EMPTY(&fonts)) 544 return; 545 546 /* We can't load first */ 547 if (file_findfile(NULL, NULL) == NULL) { 548 printf("Can not load font module: %s\n", 549 "the kernel is not loaded"); 550 return; 551 } 552 553 if (file_findfile(name, name) != NULL) { 554 printf("warning: '%s' is already loaded\n", name); 555 return; 556 } 557 558 /* helper pointers */ 559 bd = NULL; 560 STAILQ_FOREACH(fl, &fonts, font_next) { 561 if (tems.ts_font.vf_width == fl->font_data->width && 562 tems.ts_font.vf_height == fl->font_data->height) { 563 /* 564 * Kernel does have better built in font. 565 */ 566 if (fl->font_flags == FONT_BUILTIN) 567 return; 568 569 bd = fl->font_data; 570 break; 571 } 572 } 573 if (bd == NULL) 574 return; 575 fd = bd->font; 576 577 fi.fi_width = fd->vf_width; 578 checksum = fi.fi_width; 579 fi.fi_height = fd->vf_height; 580 checksum += fi.fi_height; 581 fi.fi_bitmap_size = bd->uncompressed_size; 582 checksum += fi.fi_bitmap_size; 583 584 size = roundup2(sizeof (struct font_info), 8); 585 for (i = 0; i < VFNT_MAPS; i++) { 586 fi.fi_map_count[i] = fd->vf_map_count[i]; 587 checksum += fi.fi_map_count[i]; 588 size += fd->vf_map_count[i] * sizeof (struct font_map); 589 size += roundup2(size, 8); 590 } 591 size += bd->uncompressed_size; 592 593 fi.fi_checksum = -checksum; 594 595 fp = file_alloc(); 596 if (fp != NULL) { 597 fp->f_name = strdup(name); 598 fp->f_type = strdup(name); 599 } 600 601 if (fp == NULL || fp->f_name == NULL || fp->f_type == NULL) { 602 printf("Can not load font module: %s\n", 603 "out of memory"); 604 file_discard(fp); 605 return; 606 } 607 608 if (archsw.arch_loadaddr != NULL) 609 loadaddr = archsw.arch_loadaddr(LOAD_MEM, &size, loadaddr); 610 611 if (loadaddr == 0) { 612 printf("Can not load font module: %s\n", 613 "out of memory"); 614 file_discard(fp); 615 return; 616 } 617 618 laddr = loadaddr; 619 laddr += archsw.arch_copyin(&fi, laddr, sizeof (struct font_info)); 620 laddr = roundup2(laddr, 8); 621 622 /* Copy maps. */ 623 for (i = 0; i < VFNT_MAPS; i++) { 624 if (fd->vf_map_count[i] != 0) { 625 laddr += archsw.arch_copyin(fd->vf_map[i], laddr, 626 fd->vf_map_count[i] * sizeof (struct font_map)); 627 laddr = roundup2(laddr, 8); 628 } 629 } 630 631 /* Copy the bitmap. */ 632 laddr += archsw.arch_copyin(fd->vf_bytes, laddr, fi.fi_bitmap_size); 633 634 /* Looks OK so far; populate control structure */ 635 module_hash(fp, ptov(loadaddr), laddr - loadaddr); 636 fp->f_loader = -1; 637 fp->f_addr = loadaddr; 638 fp->f_size = laddr - loadaddr; 639 640 /* recognise space consumption */ 641 loadaddr = laddr; 642 643 file_insert_tail(fp); 644 } 645 646 static struct preloaded_file * 647 file_assign_hash(int fd, size_t size, int argc, char **argv) 648 { 649 char *name = NULL; 650 struct preloaded_file *fp = NULL; 651 char *buf; 652 653 if (size < SHA1_DIGEST_LENGTH * 2) 654 return (fp); 655 656 size = SHA1_DIGEST_LENGTH * 2; 657 658 for (int i = 0; i < argc; i++) { 659 if (strncmp(argv[i], "name=", 5) == 0) { 660 name = argv[i] + 5; 661 break; 662 } 663 } 664 if (name == NULL) 665 return (fp); 666 667 buf = malloc(size + 1); 668 if (buf == NULL) 669 return (fp); 670 671 if (read(fd, buf, size) != (ssize_t)size) { 672 free(buf); 673 return (fp); 674 } 675 676 buf[size] = '\0'; 677 fp = file_findfile(name, NULL); 678 if (fp != NULL) { 679 char *tmp = fp->f_args; 680 681 if (tmp == NULL) { 682 (void) asprintf(&fp->f_args, "hash=%s", buf); 683 } else { 684 if (asprintf(&fp->f_args, "%s hash=%s", tmp, buf) < 0) { 685 fp->f_args = tmp; 686 fp = NULL; 687 } else { 688 free(tmp); 689 } 690 } 691 } 692 693 free(buf); 694 return (fp); 695 } 696 697 /* 698 * We've been asked to load (fname) as (type), so just suck it in, 699 * no arguments or anything. 700 */ 701 struct preloaded_file * 702 file_loadraw(const char *fname, char *type, int argc, char **argv, int insert) 703 { 704 struct preloaded_file *fp; 705 char *name; 706 int fd; 707 ssize_t got; 708 struct stat st; 709 710 /* We can't load first */ 711 if ((file_findfile(NULL, NULL)) == NULL) { 712 command_errmsg = "can't load file before kernel"; 713 return (NULL); 714 } 715 716 /* locate the file on the load path */ 717 name = file_search(fname, NULL); 718 if (name == NULL) { 719 (void) snprintf(command_errbuf, sizeof (command_errbuf), 720 "can't find '%s'", fname); 721 return (NULL); 722 } 723 724 if ((fd = open(name, O_RDONLY)) < 0) { 725 (void) snprintf(command_errbuf, sizeof (command_errbuf), 726 "can't open '%s': %s", name, strerror(errno)); 727 free(name); 728 return (NULL); 729 } 730 if (fstat(fd, &st) < 0) { 731 (void) close(fd); 732 (void) snprintf(command_errbuf, sizeof (command_errbuf), 733 "stat error '%s': %s", name, strerror(errno)); 734 free(name); 735 return (NULL); 736 } 737 738 /* 739 * hash module should have name=/path argument, pointing to 740 * file we are providing the hash. This is commonly used 741 * for boot archive (rootfs). 742 * Check if the file is already loaded, if so, attach the 743 * hash to it and skip this module. 744 */ 745 if (strcmp(type, "hash") == 0) { 746 fp = file_assign_hash(fd, st.st_size, argc, argv); 747 if (fp != NULL) { 748 (void) close(fd); 749 return (fp); 750 } 751 } 752 753 if (archsw.arch_loadaddr != NULL) 754 loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); 755 if (loadaddr == 0) { 756 (void) close(fd); 757 (void) snprintf(command_errbuf, sizeof (command_errbuf), 758 "no memory to load %s", name); 759 free(name); 760 return (NULL); 761 } 762 763 got = archsw.arch_readin(fd, loadaddr, st.st_size); 764 if ((size_t)got != st.st_size) { 765 (void) snprintf(command_errbuf, sizeof (command_errbuf), 766 "error reading '%s': %s", name, strerror(errno)); 767 free(name); 768 (void) close(fd); 769 if (archsw.arch_free_loadaddr != NULL && st.st_size != 0) { 770 archsw.arch_free_loadaddr(loadaddr, 771 (uint64_t)(roundup2(st.st_size, PAGE_SIZE) >> 12)); 772 } 773 return (NULL); 774 } 775 776 /* Looks OK so far; create & populate control structure */ 777 fp = file_alloc(); 778 if (fp == NULL) { 779 if (archsw.arch_free_loadaddr != NULL && st.st_size != 0) 780 archsw.arch_free_loadaddr(loadaddr, 781 (uint64_t)(roundup2(st.st_size, PAGE_SIZE) >> 12)); 782 (void) snprintf(command_errbuf, sizeof (command_errbuf), 783 "no memory to load %s", name); 784 free(name); 785 (void) close(fd); 786 return (NULL); 787 } 788 789 fp->f_name = name; 790 fp->f_args = unargv(argc, argv); 791 fp->f_type = strdup(type); 792 fp->f_metadata = NULL; 793 fp->f_loader = -1; 794 fp->f_addr = loadaddr; 795 fp->f_size = st.st_size; 796 797 if (fp->f_type == NULL || 798 (argc != 0 && fp->f_args == NULL)) { 799 (void) close(fd); 800 (void) snprintf(command_errbuf, sizeof (command_errbuf), 801 "no memory to load %s", name); 802 file_discard(fp); 803 return (NULL); 804 } 805 /* recognise space consumption */ 806 loadaddr += st.st_size; 807 808 /* Add to the list of loaded files */ 809 if (insert != 0) 810 file_insert_tail(fp); 811 (void) close(fd); 812 return (fp); 813 } 814 815 /* 816 * Load the module (name), pass it (argc),(argv), add container file 817 * to the list of loaded files. 818 * If module is already loaded just assign new argc/argv. 819 */ 820 int 821 mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[]) 822 { 823 struct kernel_module *mp; 824 int err; 825 char *filename; 826 827 if (file_havepath(modname)) { 828 printf("Warning: mod_load() called instead of mod_loadkld() " 829 "for module '%s'\n", modname); 830 return (mod_loadkld(modname, argc, argv)); 831 } 832 /* see if module is already loaded */ 833 mp = file_findmodule(NULL, modname, verinfo); 834 if (mp != NULL) { 835 free(mp->m_args); 836 mp->m_args = unargv(argc, argv); 837 (void) snprintf(command_errbuf, sizeof (command_errbuf), 838 "warning: module '%s' already loaded", mp->m_name); 839 return (0); 840 } 841 /* locate file with the module on the search path */ 842 filename = mod_searchmodule(modname, verinfo); 843 if (filename == NULL) { 844 (void) snprintf(command_errbuf, sizeof (command_errbuf), 845 "can't find '%s'", modname); 846 return (ENOENT); 847 } 848 err = mod_loadkld(filename, argc, argv); 849 free(filename); 850 return (err); 851 } 852 853 /* 854 * Load specified KLD. If path is omitted, then try to locate it via 855 * search path. 856 */ 857 int 858 mod_loadkld(const char *kldname, int argc, char *argv[]) 859 { 860 struct preloaded_file *fp; 861 int err; 862 char *filename; 863 vm_offset_t loadaddr_saved; 864 865 /* 866 * Get fully qualified KLD name 867 */ 868 filename = file_search(kldname, kld_ext_list); 869 if (filename == NULL) { 870 (void) snprintf(command_errbuf, sizeof (command_errbuf), 871 "can't find '%s'", kldname); 872 return (ENOENT); 873 } 874 /* 875 * Check if KLD already loaded 876 */ 877 fp = file_findfile(filename, NULL); 878 if (fp != NULL) { 879 (void) snprintf(command_errbuf, sizeof (command_errbuf), 880 "warning: KLD '%s' already loaded", filename); 881 free(filename); 882 return (0); 883 } 884 885 do { 886 err = file_load(filename, loadaddr, &fp); 887 if (err) 888 break; 889 fp->f_args = unargv(argc, argv); 890 loadaddr_saved = loadaddr; 891 loadaddr = fp->f_addr + fp->f_size; 892 file_insert_tail(fp); /* Add to the list of loaded files */ 893 if (file_load_dependencies(fp) != 0) { 894 err = ENOENT; 895 file_remove(fp); 896 loadaddr = loadaddr_saved; 897 fp = NULL; 898 break; 899 } 900 } while (0); 901 if (err == EFTYPE) { 902 (void) snprintf(command_errbuf, sizeof (command_errbuf), 903 "don't know how to load module '%s'", filename); 904 } 905 if (err) 906 file_discard(fp); 907 free(filename); 908 return (err); 909 } 910 911 /* 912 * Find a file matching (name) and (type). 913 * NULL may be passed as a wildcard to either. 914 */ 915 struct preloaded_file * 916 file_findfile(const char *name, const char *type) 917 { 918 struct preloaded_file *fp; 919 920 for (fp = preloaded_files; fp != NULL; fp = fp->f_next) { 921 if (((name == NULL) || strcmp(name, fp->f_name) == 0) && 922 ((type == NULL) || strcmp(type, fp->f_type) == 0)) 923 break; 924 } 925 return (fp); 926 } 927 928 /* 929 * Find a module matching (name) inside of given file. 930 * NULL may be passed as a wildcard. 931 */ 932 struct kernel_module * 933 file_findmodule(struct preloaded_file *fp, char *modname, 934 struct mod_depend *verinfo) 935 { 936 struct kernel_module *mp, *best; 937 int bestver, mver; 938 939 if (fp == NULL) { 940 for (fp = preloaded_files; fp; fp = fp->f_next) { 941 mp = file_findmodule(fp, modname, verinfo); 942 if (mp != NULL) 943 return (mp); 944 } 945 return (NULL); 946 } 947 best = NULL; 948 bestver = 0; 949 for (mp = fp->f_modules; mp; mp = mp->m_next) { 950 if (strcmp(modname, mp->m_name) == 0) { 951 if (verinfo == NULL) 952 return (mp); 953 mver = mp->m_version; 954 if (mver == verinfo->md_ver_preferred) 955 return (mp); 956 if (mver >= verinfo->md_ver_minimum && 957 mver <= verinfo->md_ver_maximum && 958 mver > bestver) { 959 best = mp; 960 bestver = mver; 961 } 962 } 963 } 964 return (best); 965 } 966 /* 967 * Make a copy of (size) bytes of data from (p), and associate them as 968 * metadata of (type) to the module (mp). 969 */ 970 void 971 file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p) 972 { 973 struct file_metadata *md; 974 975 md = malloc(sizeof (struct file_metadata) - sizeof (md->md_data) + 976 size); 977 if (md != NULL) { 978 md->md_size = size; 979 md->md_type = type; 980 bcopy(p, md->md_data, size); 981 md->md_next = fp->f_metadata; 982 } 983 fp->f_metadata = md; 984 } 985 986 /* 987 * Find a metadata object of (type) associated with the file (fp) 988 */ 989 struct file_metadata * 990 file_findmetadata(struct preloaded_file *fp, int type) 991 { 992 struct file_metadata *md; 993 994 for (md = fp->f_metadata; md != NULL; md = md->md_next) 995 if (md->md_type == type) 996 break; 997 return (md); 998 } 999 1000 struct file_metadata * 1001 metadata_next(struct file_metadata *md, int type) 1002 { 1003 1004 if (md == NULL) 1005 return (NULL); 1006 while ((md = md->md_next) != NULL) 1007 if (md->md_type == type) 1008 break; 1009 return (md); 1010 } 1011 1012 static const char *emptyextlist[] = { "", NULL }; 1013 1014 /* 1015 * Check if the given file is in place and return full path to it. 1016 */ 1017 static char * 1018 file_lookup(const char *path, const char *name, int namelen, 1019 const char **extlist) 1020 { 1021 struct stat st; 1022 char *result, *cp; 1023 const char **cpp; 1024 int pathlen, extlen, len; 1025 1026 pathlen = strlen(path); 1027 extlen = 0; 1028 if (extlist == NULL) 1029 extlist = emptyextlist; 1030 for (cpp = extlist; *cpp; cpp++) { 1031 len = strlen(*cpp); 1032 if (len > extlen) 1033 extlen = len; 1034 } 1035 result = malloc(pathlen + namelen + extlen + 2); 1036 if (result == NULL) 1037 return (NULL); 1038 bcopy(path, result, pathlen); 1039 if (pathlen > 0 && result[pathlen - 1] != '/') 1040 result[pathlen++] = '/'; 1041 cp = result + pathlen; 1042 bcopy(name, cp, namelen); 1043 cp += namelen; 1044 for (cpp = extlist; *cpp; cpp++) { 1045 (void) strcpy(cp, *cpp); 1046 if (stat(result, &st) == 0 && S_ISREG(st.st_mode)) 1047 return (result); 1048 } 1049 free(result); 1050 return (NULL); 1051 } 1052 1053 /* 1054 * Check if file name have any qualifiers 1055 */ 1056 static int 1057 file_havepath(const char *name) 1058 { 1059 const char *cp; 1060 1061 (void) archsw.arch_getdev(NULL, name, &cp); 1062 return (cp != name || strchr(name, '/') != NULL); 1063 } 1064 1065 /* 1066 * Attempt to find the file (name) on the module searchpath. 1067 * If (name) is qualified in any way, we simply check it and 1068 * return it or NULL. If it is not qualified, then we attempt 1069 * to construct a path using entries in the environment variable 1070 * module_path. 1071 * 1072 * The path we return a pointer to need never be freed, as we manage 1073 * it internally. 1074 */ 1075 static char * 1076 file_search(const char *name, const char **extlist) 1077 { 1078 struct moduledir *mdp; 1079 struct stat sb; 1080 char *result; 1081 int namelen; 1082 1083 /* Don't look for nothing */ 1084 if (name == NULL) 1085 return (NULL); 1086 1087 if (*name == '\0') 1088 return (strdup(name)); 1089 1090 if (file_havepath(name)) { 1091 /* Qualified, so just see if it exists */ 1092 if (stat(name, &sb) == 0) 1093 return (strdup(name)); 1094 return (NULL); 1095 } 1096 moduledir_rebuild(); 1097 result = NULL; 1098 namelen = strlen(name); 1099 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1100 result = file_lookup(mdp->d_path, name, namelen, extlist); 1101 if (result != NULL) 1102 break; 1103 } 1104 return (result); 1105 } 1106 1107 #define INT_ALIGN(base, ptr) ptr = \ 1108 (base) + (((ptr) - (base) + sizeof (int) - 1) & ~(sizeof (int) - 1)) 1109 1110 static char * 1111 mod_search_hints(struct moduledir *mdp, const char *modname, 1112 struct mod_depend *verinfo) 1113 { 1114 uchar_t *cp, *recptr, *bufend, *best; 1115 char *result; 1116 int *intp, bestver, blen, clen, ival, modnamelen, reclen; 1117 bool found; 1118 1119 moduledir_readhints(mdp); 1120 modnamelen = strlen(modname); 1121 found = false; 1122 result = NULL; 1123 bestver = 0; 1124 if (mdp->d_hints == NULL) 1125 goto bad; 1126 recptr = mdp->d_hints; 1127 bufend = recptr + mdp->d_hintsz; 1128 clen = blen = 0; 1129 best = cp = NULL; 1130 while (recptr < bufend && !found) { 1131 intp = (int *)recptr; 1132 reclen = *intp++; 1133 ival = *intp++; 1134 cp = (uchar_t *)intp; 1135 switch (ival) { 1136 case MDT_VERSION: 1137 clen = *cp++; 1138 if (clen != modnamelen || bcmp(cp, modname, clen) != 0) 1139 break; 1140 cp += clen; 1141 INT_ALIGN(mdp->d_hints, cp); 1142 ival = *(int *)cp; 1143 cp += sizeof (int); 1144 clen = *cp++; 1145 if (verinfo == NULL || 1146 ival == verinfo->md_ver_preferred) { 1147 found = true; 1148 break; 1149 } 1150 if (ival >= verinfo->md_ver_minimum && 1151 ival <= verinfo->md_ver_maximum && 1152 ival > bestver) { 1153 bestver = ival; 1154 best = cp; 1155 blen = clen; 1156 } 1157 break; 1158 default: 1159 break; 1160 } 1161 recptr += reclen + sizeof (int); 1162 } 1163 /* 1164 * Finally check if KLD is in the place 1165 */ 1166 if (found) 1167 result = file_lookup(mdp->d_path, (char *)cp, clen, NULL); 1168 else if (best) 1169 result = file_lookup(mdp->d_path, (char *)best, blen, NULL); 1170 bad: 1171 /* 1172 * If nothing found or hints is absent - fallback to the old way 1173 * by using "kldname[.ko]" as module name. 1174 */ 1175 if (!found && bestver == 0 && result == NULL) { 1176 result = file_lookup(mdp->d_path, modname, modnamelen, 1177 kld_ext_list); 1178 } 1179 return (result); 1180 } 1181 1182 /* 1183 * Attempt to locate the file containing the module (name) 1184 */ 1185 static char * 1186 mod_searchmodule(char *name, struct mod_depend *verinfo) 1187 { 1188 struct moduledir *mdp; 1189 char *result; 1190 1191 moduledir_rebuild(); 1192 /* 1193 * Now we ready to lookup module in the given directories 1194 */ 1195 result = NULL; 1196 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1197 result = mod_search_hints(mdp, name, verinfo); 1198 if (result != NULL) 1199 break; 1200 } 1201 1202 return (result); 1203 } 1204 1205 int 1206 file_addmodule(struct preloaded_file *fp, char *modname, int version, 1207 struct kernel_module **newmp) 1208 { 1209 struct kernel_module *mp; 1210 struct mod_depend mdepend; 1211 1212 bzero(&mdepend, sizeof (mdepend)); 1213 mdepend.md_ver_preferred = version; 1214 mp = file_findmodule(fp, modname, &mdepend); 1215 if (mp != NULL) 1216 return (EEXIST); 1217 mp = calloc(1, sizeof (struct kernel_module)); 1218 if (mp == NULL) 1219 return (ENOMEM); 1220 mp->m_name = strdup(modname); 1221 if (mp->m_name == NULL) { 1222 free(mp); 1223 return (ENOMEM); 1224 } 1225 mp->m_version = version; 1226 mp->m_fp = fp; 1227 mp->m_next = fp->f_modules; 1228 fp->f_modules = mp; 1229 if (newmp) 1230 *newmp = mp; 1231 return (0); 1232 } 1233 1234 /* 1235 * Throw a file away 1236 */ 1237 void 1238 file_discard(struct preloaded_file *fp) 1239 { 1240 struct file_metadata *md, *md1; 1241 struct kernel_module *mp, *mp1; 1242 1243 if (fp == NULL) 1244 return; 1245 1246 if (archsw.arch_free_loadaddr != NULL && fp->f_addr && 1247 fp->f_size != 0) { 1248 archsw.arch_free_loadaddr(fp->f_addr, 1249 (uint64_t)(roundup2(fp->f_size, PAGE_SIZE) >> 12)); 1250 } 1251 1252 md = fp->f_metadata; 1253 while (md != NULL) { 1254 md1 = md; 1255 md = md->md_next; 1256 free(md1); 1257 } 1258 mp = fp->f_modules; 1259 while (mp != NULL) { 1260 free(mp->m_name); 1261 mp1 = mp; 1262 mp = mp->m_next; 1263 free(mp1); 1264 } 1265 free(fp->f_name); 1266 free(fp->f_type); 1267 free(fp->f_args); 1268 free(fp); 1269 } 1270 1271 /* 1272 * Allocate a new file; must be used instead of malloc() 1273 * to ensure safe initialisation. 1274 */ 1275 struct preloaded_file * 1276 file_alloc(void) 1277 { 1278 1279 return (calloc(1, sizeof (struct preloaded_file))); 1280 } 1281 1282 /* 1283 * Add a module to the chain 1284 */ 1285 static void 1286 file_insert_tail(struct preloaded_file *fp) 1287 { 1288 struct preloaded_file *cm; 1289 1290 /* Append to list of loaded file */ 1291 fp->f_next = NULL; 1292 if (preloaded_files == NULL) { 1293 preloaded_files = fp; 1294 } else { 1295 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) 1296 ; 1297 cm->f_next = fp; 1298 } 1299 } 1300 1301 /* 1302 * Remove module from the chain 1303 */ 1304 static void 1305 file_remove(struct preloaded_file *fp) 1306 { 1307 struct preloaded_file *cm; 1308 1309 if (preloaded_files == NULL) 1310 return; 1311 1312 if (preloaded_files == fp) { 1313 preloaded_files = fp->f_next; 1314 return; 1315 } 1316 for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) { 1317 if (cm->f_next == fp) { 1318 cm->f_next = fp->f_next; 1319 return; 1320 } 1321 } 1322 } 1323 1324 static char * 1325 moduledir_fullpath(struct moduledir *mdp, const char *fname) 1326 { 1327 char *cp; 1328 1329 if (asprintf(&cp, "%s/%s", mdp->d_path, fname) > 0) 1330 return (cp); 1331 1332 return (NULL); 1333 } 1334 1335 /* 1336 * Read linker.hints file into memory performing some sanity checks. 1337 */ 1338 static void 1339 moduledir_readhints(struct moduledir *mdp) 1340 { 1341 struct stat st; 1342 char *path; 1343 int fd, size, version; 1344 1345 if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS)) 1346 return; 1347 path = moduledir_fullpath(mdp, "linker.hints"); 1348 if (stat(path, &st) != 0 || 1349 st.st_size < (ssize_t)(sizeof (version) + sizeof (int)) || 1350 st.st_size > LINKER_HINTS_MAX || 1351 (fd = open(path, O_RDONLY)) < 0) { 1352 free(path); 1353 mdp->d_flags |= MDIR_NOHINTS; 1354 return; 1355 } 1356 free(path); 1357 size = read(fd, &version, sizeof (version)); 1358 if (size != sizeof (version) || version != LINKER_HINTS_VERSION) 1359 goto bad; 1360 size = st.st_size - size; 1361 mdp->d_hints = malloc(size); 1362 if (mdp->d_hints == NULL) 1363 goto bad; 1364 if (read(fd, mdp->d_hints, size) != size) 1365 goto bad; 1366 mdp->d_hintsz = size; 1367 (void) close(fd); 1368 return; 1369 bad: 1370 (void) close(fd); 1371 free(mdp->d_hints); 1372 mdp->d_hints = NULL; 1373 mdp->d_flags |= MDIR_NOHINTS; 1374 } 1375 1376 /* 1377 * Extract directories from the ';' separated list, remove duplicates. 1378 */ 1379 static void 1380 moduledir_rebuild(void) 1381 { 1382 struct moduledir *mdp, *mtmp; 1383 const char *path, *cp, *ep; 1384 size_t cplen; 1385 1386 path = getenv("module_path"); 1387 if (path == NULL) 1388 path = default_searchpath; 1389 /* 1390 * Rebuild list of module directories if it changed 1391 */ 1392 STAILQ_FOREACH(mdp, &moduledir_list, d_link) 1393 mdp->d_flags |= MDIR_REMOVED; 1394 1395 for (ep = path; *ep != 0; ep++) { 1396 cp = ep; 1397 for (; *ep != 0 && *ep != ';'; ep++) 1398 ; 1399 /* 1400 * Ignore trailing slashes 1401 */ 1402 for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; 1403 cplen--) 1404 ; 1405 STAILQ_FOREACH(mdp, &moduledir_list, d_link) { 1406 if (strlen(mdp->d_path) != cplen || 1407 bcmp(cp, mdp->d_path, cplen) != 0) 1408 continue; 1409 mdp->d_flags &= ~MDIR_REMOVED; 1410 break; 1411 } 1412 if (mdp == NULL) { 1413 mdp = malloc(sizeof (*mdp) + cplen + 1); 1414 if (mdp == NULL) 1415 return; 1416 mdp->d_path = (char *)(mdp + 1); 1417 bcopy(cp, mdp->d_path, cplen); 1418 mdp->d_path[cplen] = 0; 1419 mdp->d_hints = NULL; 1420 mdp->d_flags = 0; 1421 STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link); 1422 } 1423 if (*ep == '\0') 1424 break; 1425 } 1426 /* 1427 * Delete unused directories if any 1428 */ 1429 mdp = STAILQ_FIRST(&moduledir_list); 1430 while (mdp) { 1431 if ((mdp->d_flags & MDIR_REMOVED) == 0) { 1432 mdp = STAILQ_NEXT(mdp, d_link); 1433 } else { 1434 free(mdp->d_hints); 1435 mtmp = mdp; 1436 mdp = STAILQ_NEXT(mdp, d_link); 1437 STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link); 1438 free(mtmp); 1439 } 1440 } 1441 } 1442