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