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