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