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