module.c revision 294981
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: stable/10/sys/boot/common/module.c 294981 2016-01-28 12:11:42Z smh $");
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
41#include "bootstrap.h"
42
43#define	MDIR_REMOVED	0x0001
44#define	MDIR_NOHINTS	0x0002
45
46struct moduledir {
47	char	*d_path;	/* path of modules directory */
48	u_char	*d_hints;	/* content of linker.hints file */
49	int	d_hintsz;	/* size of hints data */
50	int	d_flags;
51	STAILQ_ENTRY(moduledir) d_link;
52};
53
54static int			file_load(char *filename, vm_offset_t dest, struct preloaded_file **result);
55static int			file_load_dependencies(struct preloaded_file *base_mod);
56static char *			file_search(const char *name, char **extlist);
57static struct kernel_module *	file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo);
58static int			file_havepath(const char *name);
59static char			*mod_searchmodule(char *name, struct mod_depend *verinfo);
60static void			file_insert_tail(struct preloaded_file *mp);
61struct file_metadata*		metadata_next(struct file_metadata *base_mp, int type);
62static void			moduledir_readhints(struct moduledir *mdp);
63static void			moduledir_rebuild(void);
64
65/* load address should be tweaked by first module loaded (kernel) */
66static vm_offset_t	loadaddr = 0;
67
68#if defined(LOADER_FDT_SUPPORT)
69static const char	*default_searchpath =
70    "/boot/kernel;/boot/modules;/boot/dtb";
71#else
72static const char	*default_searchpath ="/boot/kernel;/boot/modules";
73#endif
74
75static STAILQ_HEAD(, moduledir) moduledir_list = STAILQ_HEAD_INITIALIZER(moduledir_list);
76
77struct preloaded_file *preloaded_files = NULL;
78
79static char *kld_ext_list[] = {
80    ".ko",
81    "",
82    ".debug",
83    NULL
84};
85
86
87/*
88 * load an object, either a disk file or code module.
89 *
90 * To load a file, the syntax is:
91 *
92 * load -t <type> <path>
93 *
94 * code modules are loaded as:
95 *
96 * load <path> <options>
97 */
98
99COMMAND_SET(load, "load", "load a kernel or module", command_load);
100
101static int
102command_load(int argc, char *argv[])
103{
104    char	*typestr;
105    int		dofile, dokld, ch, error;
106
107    dokld = dofile = 0;
108    optind = 1;
109    optreset = 1;
110    typestr = NULL;
111    if (argc == 1) {
112	command_errmsg = "no filename specified";
113	return(CMD_ERROR);
114    }
115    while ((ch = getopt(argc, argv, "kt:")) != -1) {
116	switch(ch) {
117	case 'k':
118	    dokld = 1;
119	    break;
120	case 't':
121	    typestr = optarg;
122	    dofile = 1;
123	    break;
124	case '?':
125	default:
126	    /* getopt has already reported an error */
127	    return(CMD_OK);
128	}
129    }
130    argv += (optind - 1);
131    argc -= (optind - 1);
132
133    /*
134     * Request to load a raw file?
135     */
136    if (dofile) {
137	if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) {
138	    command_errmsg = "invalid load type";
139	    return(CMD_ERROR);
140	}
141	return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR);
142    }
143    /*
144     * Do we have explicit KLD load ?
145     */
146    if (dokld || file_havepath(argv[1])) {
147	error = mod_loadkld(argv[1], argc - 2, argv + 2);
148	if (error == EEXIST)
149	    sprintf(command_errbuf, "warning: KLD '%s' already loaded", argv[1]);
150	return (error == 0 ? CMD_OK : CMD_ERROR);
151    }
152    /*
153     * Looks like a request for a module.
154     */
155    error = mod_load(argv[1], NULL, argc - 2, argv + 2);
156    if (error == EEXIST)
157	sprintf(command_errbuf, "warning: module '%s' already loaded", argv[1]);
158    return (error == 0 ? CMD_OK : CMD_ERROR);
159}
160
161COMMAND_SET(load_geli, "load_geli", "load a geli key", command_load_geli);
162
163static int
164command_load_geli(int argc, char *argv[])
165{
166    char	typestr[80];
167    char	*cp;
168    int		ch, num;
169
170    if (argc < 3) {
171	    command_errmsg = "usage is [-n key#] <prov> <file>";
172	    return(CMD_ERROR);
173    }
174
175    num = 0;
176    optind = 1;
177    optreset = 1;
178    while ((ch = getopt(argc, argv, "n:")) != -1) {
179	switch(ch) {
180	case 'n':
181	    num = strtol(optarg, &cp, 0);
182	    if (cp == optarg) {
183		    sprintf(command_errbuf, "bad key index '%s'", optarg);
184		    return(CMD_ERROR);
185	    }
186	    break;
187	case '?':
188	default:
189	    /* getopt has already reported an error */
190	    return(CMD_OK);
191	}
192    }
193    argv += (optind - 1);
194    argc -= (optind - 1);
195    sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
196    return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
197}
198
199COMMAND_SET(unload, "unload", "unload all modules", command_unload);
200
201static int
202command_unload(int argc, char *argv[])
203{
204    struct preloaded_file	*fp;
205
206    while (preloaded_files != NULL) {
207	fp = preloaded_files;
208	preloaded_files = preloaded_files->f_next;
209	file_discard(fp);
210    }
211    loadaddr = 0;
212    unsetenv("kernelname");
213    return(CMD_OK);
214}
215
216COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod);
217
218static int
219command_lsmod(int argc, char *argv[])
220{
221    struct preloaded_file	*fp;
222    struct kernel_module	*mp;
223    struct file_metadata	*md;
224    char			lbuf[80];
225    int				ch, verbose;
226
227    verbose = 0;
228    optind = 1;
229    optreset = 1;
230    while ((ch = getopt(argc, argv, "v")) != -1) {
231	switch(ch) {
232	case 'v':
233	    verbose = 1;
234	    break;
235	case '?':
236	default:
237	    /* getopt has already reported an error */
238	    return(CMD_OK);
239	}
240    }
241
242    pager_open();
243    for (fp = preloaded_files; fp; fp = fp->f_next) {
244	sprintf(lbuf, " %p: %s (%s, 0x%lx)\n",
245		(void *) fp->f_addr, fp->f_name, fp->f_type, (long) fp->f_size);
246	pager_output(lbuf);
247	if (fp->f_args != NULL) {
248	    pager_output("    args: ");
249	    pager_output(fp->f_args);
250	    pager_output("\n");
251	}
252	if (fp->f_modules) {
253	    pager_output("  modules: ");
254	    for (mp = fp->f_modules; mp; mp = mp->m_next) {
255		sprintf(lbuf, "%s.%d ", mp->m_name, mp->m_version);
256		pager_output(lbuf);
257	    }
258	    pager_output("\n");
259	}
260	if (verbose) {
261	    /* XXX could add some formatting smarts here to display some better */
262	    for (md = fp->f_metadata; md != NULL; md = md->md_next) {
263		sprintf(lbuf, "      0x%04x, 0x%lx\n", md->md_type, (long) md->md_size);
264		pager_output(lbuf);
265	    }
266	}
267    }
268    pager_close();
269    return(CMD_OK);
270}
271
272/*
273 * File level interface, functions file_*
274 */
275int
276file_load(char *filename, vm_offset_t dest, struct preloaded_file **result)
277{
278    static int last_file_format = 0;
279    struct preloaded_file *fp;
280    int error;
281    int i;
282
283    if (archsw.arch_loadaddr != NULL)
284	dest = archsw.arch_loadaddr(LOAD_RAW, filename, dest);
285
286    error = EFTYPE;
287    for (i = last_file_format, fp = NULL;
288	file_formats[i] && fp == NULL; i++) {
289	error = (file_formats[i]->l_load)(filename, dest, &fp);
290	if (error == 0) {
291	    fp->f_loader = last_file_format = i; /* remember the loader */
292	    *result = fp;
293	    break;
294	} else if (last_file_format == i && i != 0) {
295	    /* Restart from the beginning */
296	    i = -1;
297	    last_file_format = 0;
298	    fp = NULL;
299	    continue;
300	}
301	if (error == EFTYPE)
302	    continue;		/* Unknown to this handler? */
303	if (error) {
304	    sprintf(command_errbuf, "can't load file '%s': %s",
305		filename, strerror(error));
306	    break;
307	}
308    }
309    return (error);
310}
311
312static int
313file_load_dependencies(struct preloaded_file *base_file)
314{
315    struct file_metadata *md;
316    struct preloaded_file *fp;
317    struct mod_depend *verinfo;
318    struct kernel_module *mp;
319    char *dmodname;
320    int error;
321
322    md = file_findmetadata(base_file, MODINFOMD_DEPLIST);
323    if (md == NULL)
324	return (0);
325    error = 0;
326    do {
327	verinfo = (struct mod_depend*)md->md_data;
328	dmodname = (char *)(verinfo + 1);
329	if (file_findmodule(NULL, dmodname, verinfo) == NULL) {
330	    printf("loading required module '%s'\n", dmodname);
331	    error = mod_load(dmodname, verinfo, 0, NULL);
332	    if (error)
333		break;
334	    /*
335	     * If module loaded via kld name which isn't listed
336	     * in the linker.hints file, we should check if it have
337	     * required version.
338	     */
339	    mp = file_findmodule(NULL, dmodname, verinfo);
340	    if (mp == NULL) {
341		sprintf(command_errbuf, "module '%s' exists but with wrong version",
342		    dmodname);
343		error = ENOENT;
344		break;
345	    }
346	}
347	md = metadata_next(md, MODINFOMD_DEPLIST);
348    } while (md);
349    if (!error)
350	return (0);
351    /* Load failed; discard everything */
352    while (base_file != NULL) {
353        fp = base_file;
354        base_file = base_file->f_next;
355        file_discard(fp);
356    }
357    return (error);
358}
359
360/*
361 * We've been asked to load (fname) as (type), so just suck it in,
362 * no arguments or anything.
363 */
364struct preloaded_file *
365file_loadraw(const char *fname, char *type, int insert)
366{
367    struct preloaded_file	*fp;
368    char			*name;
369    int				fd, got;
370    vm_offset_t			laddr;
371
372    /* We can't load first */
373    if ((file_findfile(NULL, NULL)) == NULL) {
374	command_errmsg = "can't load file before kernel";
375	return(NULL);
376    }
377
378    /* locate the file on the load path */
379    name = file_search(fname, NULL);
380    if (name == NULL) {
381	sprintf(command_errbuf, "can't find '%s'", fname);
382	return(NULL);
383    }
384
385    if ((fd = open(name, O_RDONLY)) < 0) {
386	sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
387	free(name);
388	return(NULL);
389    }
390
391    if (archsw.arch_loadaddr != NULL)
392	loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
393
394    laddr = loadaddr;
395    for (;;) {
396	/* read in 4k chunks; size is not really important */
397	got = archsw.arch_readin(fd, laddr, 4096);
398	if (got == 0)				/* end of file */
399	    break;
400	if (got < 0) {				/* error */
401	    sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno));
402	    free(name);
403	    close(fd);
404	    return(NULL);
405	}
406	laddr += got;
407    }
408
409    /* Looks OK so far; create & populate control structure */
410    fp = file_alloc();
411    fp->f_name = strdup(name);
412    fp->f_type = strdup(type);
413    fp->f_args = NULL;
414    fp->f_metadata = NULL;
415    fp->f_loader = -1;
416    fp->f_addr = loadaddr;
417    fp->f_size = laddr - loadaddr;
418
419    /* recognise space consumption */
420    loadaddr = laddr;
421
422    /* Add to the list of loaded files */
423    if (insert != 0)
424    	file_insert_tail(fp);
425    close(fd);
426    return(fp);
427}
428
429/*
430 * Load the module (name), pass it (argc),(argv), add container file
431 * to the list of loaded files.
432 * If module is already loaded just assign new argc/argv.
433 */
434int
435mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[])
436{
437    struct kernel_module	*mp;
438    int				err;
439    char			*filename;
440
441    if (file_havepath(modname)) {
442	printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname);
443	return (mod_loadkld(modname, argc, argv));
444    }
445    /* see if module is already loaded */
446    mp = file_findmodule(NULL, modname, verinfo);
447    if (mp) {
448#ifdef moduleargs
449	if (mp->m_args)
450	    free(mp->m_args);
451	mp->m_args = unargv(argc, argv);
452#endif
453	sprintf(command_errbuf, "warning: module '%s' already loaded", mp->m_name);
454	return (0);
455    }
456    /* locate file with the module on the search path */
457    filename = mod_searchmodule(modname, verinfo);
458    if (filename == NULL) {
459	sprintf(command_errbuf, "can't find '%s'", modname);
460	return (ENOENT);
461    }
462    err = mod_loadkld(filename, argc, argv);
463    return (err);
464}
465
466/*
467 * Load specified KLD. If path is omitted, then try to locate it via
468 * search path.
469 */
470int
471mod_loadkld(const char *kldname, int argc, char *argv[])
472{
473    struct preloaded_file	*fp, *last_file;
474    int				err;
475    char			*filename;
476
477    /*
478     * Get fully qualified KLD name
479     */
480    filename = file_search(kldname, kld_ext_list);
481    if (filename == NULL) {
482	sprintf(command_errbuf, "can't find '%s'", kldname);
483	return (ENOENT);
484    }
485    /*
486     * Check if KLD already loaded
487     */
488    fp = file_findfile(filename, NULL);
489    if (fp) {
490	sprintf(command_errbuf, "warning: KLD '%s' already loaded", filename);
491	free(filename);
492	return (0);
493    }
494    for (last_file = preloaded_files;
495	 last_file != NULL && last_file->f_next != NULL;
496	 last_file = last_file->f_next)
497	;
498
499    do {
500	err = file_load(filename, loadaddr, &fp);
501	if (err)
502	    break;
503	fp->f_args = unargv(argc, argv);
504	loadaddr = fp->f_addr + fp->f_size;
505	file_insert_tail(fp);		/* Add to the list of loaded files */
506	if (file_load_dependencies(fp) != 0) {
507	    err = ENOENT;
508	    last_file->f_next = NULL;
509	    loadaddr = last_file->f_addr + last_file->f_size;
510	    fp = NULL;
511	    break;
512	}
513    } while(0);
514    if (err == EFTYPE)
515	sprintf(command_errbuf, "don't know how to load module '%s'", filename);
516    if (err && fp)
517	file_discard(fp);
518    free(filename);
519    return (err);
520}
521
522/*
523 * Find a file matching (name) and (type).
524 * NULL may be passed as a wildcard to either.
525 */
526struct preloaded_file *
527file_findfile(const char *name, const char *type)
528{
529    struct preloaded_file *fp;
530
531    for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
532	if (((name == NULL) || !strcmp(name, fp->f_name)) &&
533	    ((type == NULL) || !strcmp(type, fp->f_type)))
534	    break;
535    }
536    return (fp);
537}
538
539/*
540 * Find a module matching (name) inside of given file.
541 * NULL may be passed as a wildcard.
542 */
543struct kernel_module *
544file_findmodule(struct preloaded_file *fp, char *modname,
545	struct mod_depend *verinfo)
546{
547    struct kernel_module *mp, *best;
548    int bestver, mver;
549
550    if (fp == NULL) {
551	for (fp = preloaded_files; fp; fp = fp->f_next) {
552	    mp = file_findmodule(fp, modname, verinfo);
553    	    if (mp)
554		return (mp);
555	}
556	return (NULL);
557    }
558    best = NULL;
559    bestver = 0;
560    for (mp = fp->f_modules; mp; mp = mp->m_next) {
561        if (strcmp(modname, mp->m_name) == 0) {
562	    if (verinfo == NULL)
563		return (mp);
564	    mver = mp->m_version;
565	    if (mver == verinfo->md_ver_preferred)
566		return (mp);
567	    if (mver >= verinfo->md_ver_minimum &&
568		mver <= verinfo->md_ver_maximum &&
569		mver > bestver) {
570		best = mp;
571		bestver = mver;
572	    }
573	}
574    }
575    return (best);
576}
577/*
578 * Make a copy of (size) bytes of data from (p), and associate them as
579 * metadata of (type) to the module (mp).
580 */
581void
582file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p)
583{
584    struct file_metadata	*md;
585
586    md = malloc(sizeof(struct file_metadata) - sizeof(md->md_data) + size);
587    md->md_size = size;
588    md->md_type = type;
589    bcopy(p, md->md_data, size);
590    md->md_next = fp->f_metadata;
591    fp->f_metadata = md;
592}
593
594/*
595 * Find a metadata object of (type) associated with the file (fp)
596 */
597struct file_metadata *
598file_findmetadata(struct preloaded_file *fp, int type)
599{
600    struct file_metadata *md;
601
602    for (md = fp->f_metadata; md != NULL; md = md->md_next)
603	if (md->md_type == type)
604	    break;
605    return(md);
606}
607
608struct file_metadata *
609metadata_next(struct file_metadata *md, int type)
610{
611    if (md == NULL)
612	return (NULL);
613    while((md = md->md_next) != NULL)
614	if (md->md_type == type)
615	    break;
616    return (md);
617}
618
619static char *emptyextlist[] = { "", NULL };
620
621/*
622 * Check if the given file is in place and return full path to it.
623 */
624static char *
625file_lookup(const char *path, const char *name, int namelen, char **extlist)
626{
627    struct stat	st;
628    char	*result, *cp, **cpp;
629    int		pathlen, extlen, len;
630
631    pathlen = strlen(path);
632    extlen = 0;
633    if (extlist == NULL)
634	extlist = emptyextlist;
635    for (cpp = extlist; *cpp; cpp++) {
636	len = strlen(*cpp);
637	if (len > extlen)
638	    extlen = len;
639    }
640    result = malloc(pathlen + namelen + extlen + 2);
641    if (result == NULL)
642	return (NULL);
643    bcopy(path, result, pathlen);
644    if (pathlen > 0 && result[pathlen - 1] != '/')
645	result[pathlen++] = '/';
646    cp = result + pathlen;
647    bcopy(name, cp, namelen);
648    cp += namelen;
649    for (cpp = extlist; *cpp; cpp++) {
650	strcpy(cp, *cpp);
651	if (stat(result, &st) == 0 && S_ISREG(st.st_mode))
652	    return result;
653    }
654    free(result);
655    return NULL;
656}
657
658/*
659 * Check if file name have any qualifiers
660 */
661static int
662file_havepath(const char *name)
663{
664    const char		*cp;
665
666    archsw.arch_getdev(NULL, name, &cp);
667    return (cp != name || strchr(name, '/') != NULL);
668}
669
670/*
671 * Attempt to find the file (name) on the module searchpath.
672 * If (name) is qualified in any way, we simply check it and
673 * return it or NULL.  If it is not qualified, then we attempt
674 * to construct a path using entries in the environment variable
675 * module_path.
676 *
677 * The path we return a pointer to need never be freed, as we manage
678 * it internally.
679 */
680static char *
681file_search(const char *name, char **extlist)
682{
683    struct moduledir	*mdp;
684    struct stat		sb;
685    char		*result;
686    int			namelen;
687
688    /* Don't look for nothing */
689    if (name == NULL)
690	return(NULL);
691
692    if (*name == 0)
693	return(strdup(name));
694
695    if (file_havepath(name)) {
696	/* Qualified, so just see if it exists */
697	if (stat(name, &sb) == 0)
698	    return(strdup(name));
699	return(NULL);
700    }
701    moduledir_rebuild();
702    result = NULL;
703    namelen = strlen(name);
704    STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
705	result = file_lookup(mdp->d_path, name, namelen, extlist);
706	if (result)
707	    break;
708    }
709    return(result);
710}
711
712#define	INT_ALIGN(base, ptr)	ptr = \
713	(base) + (((ptr) - (base) + sizeof(int) - 1) & ~(sizeof(int) - 1))
714
715static char *
716mod_search_hints(struct moduledir *mdp, const char *modname,
717	struct mod_depend *verinfo)
718{
719    u_char	*cp, *recptr, *bufend, *best;
720    char	*result;
721    int		*intp, bestver, blen, clen, found, ival, modnamelen, reclen;
722
723    moduledir_readhints(mdp);
724    modnamelen = strlen(modname);
725    found = 0;
726    result = NULL;
727    bestver = 0;
728    if (mdp->d_hints == NULL)
729	goto bad;
730    recptr = mdp->d_hints;
731    bufend = recptr + mdp->d_hintsz;
732    clen = blen = 0;
733    best = cp = NULL;
734    while (recptr < bufend && !found) {
735	intp = (int*)recptr;
736	reclen = *intp++;
737	ival = *intp++;
738	cp = (char*)intp;
739	switch (ival) {
740	case MDT_VERSION:
741	    clen = *cp++;
742	    if (clen != modnamelen || bcmp(cp, modname, clen) != 0)
743		break;
744	    cp += clen;
745	    INT_ALIGN(mdp->d_hints, cp);
746	    ival = *(int*)cp;
747	    cp += sizeof(int);
748	    clen = *cp++;
749	    if (verinfo == NULL || ival == verinfo->md_ver_preferred) {
750		found = 1;
751		break;
752	    }
753	    if (ival >= verinfo->md_ver_minimum &&
754		ival <= verinfo->md_ver_maximum &&
755		ival > bestver) {
756		bestver = ival;
757		best = cp;
758		blen = clen;
759	    }
760	    break;
761	default:
762	    break;
763	}
764	recptr += reclen + sizeof(int);
765    }
766    /*
767     * Finally check if KLD is in the place
768     */
769    if (found)
770	result = file_lookup(mdp->d_path, cp, clen, NULL);
771    else if (best)
772	result = file_lookup(mdp->d_path, best, blen, NULL);
773bad:
774    /*
775     * If nothing found or hints is absent - fallback to the old way
776     * by using "kldname[.ko]" as module name.
777     */
778    if (!found && !bestver && result == NULL)
779	result = file_lookup(mdp->d_path, modname, modnamelen, kld_ext_list);
780    return result;
781}
782
783/*
784 * Attempt to locate the file containing the module (name)
785 */
786static char *
787mod_searchmodule(char *name, struct mod_depend *verinfo)
788{
789    struct	moduledir *mdp;
790    char	*result;
791
792    moduledir_rebuild();
793    /*
794     * Now we ready to lookup module in the given directories
795     */
796    result = NULL;
797    STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
798	result = mod_search_hints(mdp, name, verinfo);
799	if (result)
800	    break;
801    }
802
803    return(result);
804}
805
806int
807file_addmodule(struct preloaded_file *fp, char *modname, int version,
808	struct kernel_module **newmp)
809{
810    struct kernel_module *mp;
811    struct mod_depend mdepend;
812
813    bzero(&mdepend, sizeof(mdepend));
814    mdepend.md_ver_preferred = version;
815    mp = file_findmodule(fp, modname, &mdepend);
816    if (mp)
817	return (EEXIST);
818    mp = malloc(sizeof(struct kernel_module));
819    if (mp == NULL)
820	return (ENOMEM);
821    bzero(mp, sizeof(struct kernel_module));
822    mp->m_name = strdup(modname);
823    mp->m_version = version;
824    mp->m_fp = fp;
825    mp->m_next = fp->f_modules;
826    fp->f_modules = mp;
827    if (newmp)
828	*newmp = mp;
829    return (0);
830}
831
832/*
833 * Throw a file away
834 */
835void
836file_discard(struct preloaded_file *fp)
837{
838    struct file_metadata	*md, *md1;
839    struct kernel_module	*mp, *mp1;
840    if (fp == NULL)
841	return;
842    md = fp->f_metadata;
843    while (md) {
844	md1 = md;
845	md = md->md_next;
846	free(md1);
847    }
848    mp = fp->f_modules;
849    while (mp) {
850	if (mp->m_name)
851	    free(mp->m_name);
852	mp1 = mp;
853	mp = mp->m_next;
854	free(mp1);
855    }
856    if (fp->f_name != NULL)
857	free(fp->f_name);
858    if (fp->f_type != NULL)
859        free(fp->f_type);
860    if (fp->f_args != NULL)
861        free(fp->f_args);
862    free(fp);
863}
864
865/*
866 * Allocate a new file; must be used instead of malloc()
867 * to ensure safe initialisation.
868 */
869struct preloaded_file *
870file_alloc(void)
871{
872    struct preloaded_file	*fp;
873
874    if ((fp = malloc(sizeof(struct preloaded_file))) != NULL) {
875	bzero(fp, sizeof(struct preloaded_file));
876    }
877    return (fp);
878}
879
880/*
881 * Add a module to the chain
882 */
883static void
884file_insert_tail(struct preloaded_file *fp)
885{
886    struct preloaded_file	*cm;
887
888    /* Append to list of loaded file */
889    fp->f_next = NULL;
890    if (preloaded_files == NULL) {
891	preloaded_files = fp;
892    } else {
893	for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
894	    ;
895	cm->f_next = fp;
896    }
897}
898
899static char *
900moduledir_fullpath(struct moduledir *mdp, const char *fname)
901{
902    char *cp;
903
904    cp = malloc(strlen(mdp->d_path) + strlen(fname) + 2);
905    if (cp == NULL)
906	return NULL;
907    strcpy(cp, mdp->d_path);
908    strcat(cp, "/");
909    strcat(cp, fname);
910    return (cp);
911}
912
913/*
914 * Read linker.hints file into memory performing some sanity checks.
915 */
916static void
917moduledir_readhints(struct moduledir *mdp)
918{
919    struct stat	st;
920    char	*path;
921    int		fd, size, version;
922
923    if (mdp->d_hints != NULL || (mdp->d_flags & MDIR_NOHINTS))
924	return;
925    path = moduledir_fullpath(mdp, "linker.hints");
926    if (stat(path, &st) != 0 ||
927	st.st_size < (ssize_t)(sizeof(version) + sizeof(int)) ||
928	st.st_size > 100 * 1024 || (fd = open(path, O_RDONLY)) < 0) {
929	free(path);
930	mdp->d_flags |= MDIR_NOHINTS;
931	return;
932    }
933    free(path);
934    size = read(fd, &version, sizeof(version));
935    if (size != sizeof(version) || version != LINKER_HINTS_VERSION)
936	goto bad;
937    size = st.st_size - size;
938    mdp->d_hints = malloc(size);
939    if (mdp->d_hints == NULL)
940	goto bad;
941    if (read(fd, mdp->d_hints, size) != size)
942	goto bad;
943    mdp->d_hintsz = size;
944    close(fd);
945    return;
946bad:
947    close(fd);
948    if (mdp->d_hints) {
949	free(mdp->d_hints);
950	mdp->d_hints = NULL;
951    }
952    mdp->d_flags |= MDIR_NOHINTS;
953    return;
954}
955
956/*
957 * Extract directories from the ';' separated list, remove duplicates.
958 */
959static void
960moduledir_rebuild(void)
961{
962    struct	moduledir *mdp, *mtmp;
963    const char	*path, *cp, *ep;
964    size_t	cplen;
965
966    path = getenv("module_path");
967    if (path == NULL)
968	path = default_searchpath;
969    /*
970     * Rebuild list of module directories if it changed
971     */
972    STAILQ_FOREACH(mdp, &moduledir_list, d_link)
973	mdp->d_flags |= MDIR_REMOVED;
974
975    for (ep = path; *ep != 0;  ep++) {
976	cp = ep;
977	for (; *ep != 0 && *ep != ';'; ep++)
978	    ;
979	/*
980	 * Ignore trailing slashes
981	 */
982	for (cplen = ep - cp; cplen > 1 && cp[cplen - 1] == '/'; cplen--)
983	    ;
984	STAILQ_FOREACH(mdp, &moduledir_list, d_link) {
985	    if (strlen(mdp->d_path) != cplen ||	bcmp(cp, mdp->d_path, cplen) != 0)
986		continue;
987	    mdp->d_flags &= ~MDIR_REMOVED;
988	    break;
989	}
990	if (mdp == NULL) {
991	    mdp = malloc(sizeof(*mdp) + cplen + 1);
992	    if (mdp == NULL)
993		return;
994	    mdp->d_path = (char*)(mdp + 1);
995	    bcopy(cp, mdp->d_path, cplen);
996	    mdp->d_path[cplen] = 0;
997	    mdp->d_hints = NULL;
998	    mdp->d_flags = 0;
999	    STAILQ_INSERT_TAIL(&moduledir_list, mdp, d_link);
1000	}
1001	if (*ep == 0)
1002	    break;
1003    }
1004    /*
1005     * Delete unused directories if any
1006     */
1007    mdp = STAILQ_FIRST(&moduledir_list);
1008    while (mdp) {
1009	if ((mdp->d_flags & MDIR_REMOVED) == 0) {
1010	    mdp = STAILQ_NEXT(mdp, d_link);
1011	} else {
1012	    if (mdp->d_hints)
1013		free(mdp->d_hints);
1014	    mtmp = mdp;
1015	    mdp = STAILQ_NEXT(mdp, d_link);
1016	    STAILQ_REMOVE(&moduledir_list, mtmp, moduledir, d_link);
1017	    free(mtmp);
1018	}
1019    }
1020    return;
1021}
1022