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