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