xref: /freebsd-13.1/stand/common/module.c (revision 19d26be3)
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