kern_linker.c revision 40906
1/*-
2 * Copyright (c) 1997 Doug Rabson
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 *	$Id: kern_linker.c,v 1.13 1998/11/03 14:27:05 peter Exp $
27 */
28
29#include "opt_ddb.h"
30
31#include <sys/param.h>
32#include <sys/kernel.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/sysproto.h>
36#include <sys/sysent.h>
37#include <sys/proc.h>
38#include <sys/lock.h>
39#include <machine/cpu.h>
40#include <machine/bootinfo.h>
41#include <sys/module.h>
42#include <sys/linker.h>
43#include <sys/unistd.h>
44#include <sys/fcntl.h>
45#include <sys/libkern.h>
46#include <sys/namei.h>
47#include <sys/vnode.h>
48#include <sys/sysctl.h>
49
50MALLOC_DEFINE(M_LINKER, "kld", "kernel linker");
51linker_file_t linker_current_file;
52linker_file_t linker_kernel_file;
53
54static struct lock lock;	/* lock for the file list */
55static linker_class_list_t classes;
56static linker_file_list_t files;
57static int next_file_id = 1;
58
59static void
60linker_init(void* arg)
61{
62    lockinit(&lock, PVM, "klink", 0, 0);
63    TAILQ_INIT(&classes);
64    TAILQ_INIT(&files);
65}
66
67SYSINIT(linker, SI_SUB_KLD, SI_ORDER_FIRST, linker_init, 0);
68
69int
70linker_add_class(const char* desc, void* priv,
71		 struct linker_class_ops* ops)
72{
73    linker_class_t lc;
74
75    lc = malloc(sizeof(struct linker_class), M_LINKER, M_NOWAIT);
76    if (!lc)
77	return ENOMEM;
78    bzero(lc, sizeof(*lc));
79
80    lc->desc = desc;
81    lc->priv = priv;
82    lc->ops = ops;
83    TAILQ_INSERT_HEAD(&classes, lc, link);
84
85    return 0;
86}
87
88static void
89linker_file_sysinit(linker_file_t lf)
90{
91    struct linker_set* sysinits;
92    struct sysinit** sipp;
93    struct sysinit** xipp;
94    struct sysinit* save;
95    moduledata_t *moddata;
96
97    KLD_DPF(FILE, ("linker_file_sysinit: calling SYSINITs for %s\n",
98		   lf->filename));
99
100    sysinits = (struct linker_set*)
101	linker_file_lookup_symbol(lf, "sysinit_set", 0);
102
103    KLD_DPF(FILE, ("linker_file_sysinit: SYSINITs %p\n", sysinits));
104    if (!sysinits)
105	return;
106
107    /* HACK ALERT! */
108    for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
109	if ((*sipp)->func == module_register_init) {
110	    moddata = (*sipp)->udata;
111	    moddata->_file = lf;
112	}
113    }
114
115    /*
116     * Perform a bubble sort of the system initialization objects by
117     * their subsystem (primary key) and order (secondary key).
118     *
119     * Since some things care about execution order, this is the
120     * operation which ensures continued function.
121     */
122    for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
123	for( xipp = sipp + 1; *xipp; xipp++) {
124	    if( (*sipp)->subsystem < (*xipp)->subsystem ||
125		( (*sipp)->subsystem == (*xipp)->subsystem &&
126		  (*sipp)->order < (*xipp)->order))
127		continue;	/* skip*/
128	    save = *sipp;
129	    *sipp = *xipp;
130	    *xipp = save;
131	}
132    }
133
134
135    /*
136     * Traverse the (now) ordered list of system initialization tasks.
137     * Perform each task, and continue on to the next task.
138     *
139     * The last item on the list is expected to be the scheduler,
140     * which will not return.
141     */
142    for( sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
143	if( (*sipp)->subsystem == SI_SUB_DUMMY)
144	    continue;	/* skip dummy task(s)*/
145
146	switch( (*sipp)->type) {
147	case SI_TYPE_DEFAULT:
148	    /* no special processing*/
149	    (*((*sipp)->func))( (*sipp)->udata);
150	    break;
151
152	case SI_TYPE_KTHREAD:
153#if !defined(SMP)
154	    /* kernel thread*/
155	    if (fork1(&proc0, RFFDG|RFPROC|RFMEM))
156		panic("fork kernel thread");
157	    cpu_set_fork_handler(pfind(proc0.p_retval[0]),
158		(*sipp)->func, (*sipp)->udata);
159	    break;
160#endif
161
162	case SI_TYPE_KPROCESS:
163	    /* kernel thread*/
164	    if (fork1(&proc0, RFFDG|RFPROC))
165		panic("fork kernel process");
166	    cpu_set_fork_handler(pfind(proc0.p_retval[0]),
167		(*sipp)->func, (*sipp)->udata);
168	    break;
169
170	default:
171	    panic( "linker_file_sysinit: unrecognized init type");
172	}
173    }
174}
175
176int
177linker_load_file(const char* filename, linker_file_t* result)
178{
179    linker_class_t lc;
180    linker_file_t lf;
181    int error = 0;
182    char *koname = NULL;
183
184    lf = linker_find_file_by_name(filename);
185    if (lf) {
186	KLD_DPF(FILE, ("linker_load_file: file %s is already loaded, incrementing refs\n", filename));
187	*result = lf;
188	lf->refs++;
189	goto out;
190    }
191
192    koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
193    if (koname == NULL) {
194	error = ENOMEM;
195	goto out;
196    }
197    sprintf(koname, "%s.ko", filename);
198    lf = NULL;
199    for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) {
200	KLD_DPF(FILE, ("linker_load_file: trying to load %s as %s\n",
201		       filename, lc->desc));
202	error = lc->ops->load_file(koname, &lf);
203	if (lf == NULL && error && error != ENOENT)
204	    goto out;
205	if (lf == NULL)
206	    error = lc->ops->load_file(filename, &lf);
207	if (lf == NULL && error && error != ENOENT)
208	    goto out;
209	if (lf) {
210	    linker_file_sysinit(lf);
211
212	    *result = lf;
213	    error = 0;
214	    goto out;
215	}
216    }
217    error = ENOEXEC;		/* format not recognised */
218
219out:
220    if (koname)
221	free(koname, M_LINKER);
222    return error;
223}
224
225linker_file_t
226linker_find_file_by_name(const char* filename)
227{
228    linker_file_t lf = 0;
229    char *koname;
230
231    koname = malloc(strlen(filename) + 4, M_LINKER, M_WAITOK);
232    if (koname == NULL)
233	goto out;
234    sprintf(koname, "%s.ko", filename);
235
236    lockmgr(&lock, LK_SHARED, 0, curproc);
237    for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) {
238	if (!strcmp(lf->filename, koname))
239	    break;
240	if (!strcmp(lf->filename, filename))
241	    break;
242    }
243    lockmgr(&lock, LK_RELEASE, 0, curproc);
244
245out:
246    if (koname)
247	free(koname, M_LINKER);
248    return lf;
249}
250
251linker_file_t
252linker_find_file_by_id(int fileid)
253{
254    linker_file_t lf = 0;
255
256    lockmgr(&lock, LK_SHARED, 0, curproc);
257    for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link))
258	if (lf->id == fileid)
259	    break;
260    lockmgr(&lock, LK_RELEASE, 0, curproc);
261
262    return lf;
263}
264
265linker_file_t
266linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops)
267{
268    linker_file_t lf = 0;
269    int namelen;
270    const char *filename;
271
272    filename = rindex(pathname, '/');
273    if (filename && filename[1])
274	filename++;
275    else
276	filename = pathname;
277
278    KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
279    lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc);
280    namelen = strlen(filename) + 1;
281    lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK);
282    if (!lf)
283	goto out;
284    bzero(lf, sizeof(*lf));
285
286    lf->refs = 1;
287    lf->userrefs = 0;
288    lf->filename = (char*) (lf + 1);
289    strcpy(lf->filename, filename);
290    lf->id = next_file_id++;
291    lf->ndeps = 0;
292    lf->deps = NULL;
293    STAILQ_INIT(&lf->common);
294    TAILQ_INIT(&lf->modules);
295
296    lf->priv = priv;
297    lf->ops = ops;
298    TAILQ_INSERT_TAIL(&files, lf, link);
299
300out:
301    lockmgr(&lock, LK_RELEASE, 0, curproc);
302    return lf;
303}
304
305int
306linker_file_unload(linker_file_t file)
307{
308    module_t mod, next;
309    struct common_symbol* cp;
310    int error = 0;
311    int i;
312
313    KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
314    lockmgr(&lock, LK_EXCLUSIVE|LK_RETRY, 0, curproc);
315    if (file->refs == 1) {
316	KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
317	/*
318	 * Inform any modules associated with this file.
319	 */
320	for (mod = TAILQ_FIRST(&file->modules); mod; mod = next) {
321	    next = module_getfnext(mod);
322
323	    /*
324	     * Give the module a chance to veto the unload.
325	     */
326	    if (error = module_unload(mod)) {
327		KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
328			       mod));
329		lockmgr(&lock, LK_RELEASE, 0, curproc);
330		goto out;
331	    }
332
333	    module_release(mod);
334	}
335    }
336
337    file->refs--;
338    if (file->refs > 0) {
339	lockmgr(&lock, LK_RELEASE, 0, curproc);
340	goto out;
341    }
342
343    TAILQ_REMOVE(&files, file, link);
344    lockmgr(&lock, LK_RELEASE, 0, curproc);
345
346    for (i = 0; i < file->ndeps; i++)
347	linker_file_unload(file->deps[i]);
348    free(file->deps, M_LINKER);
349
350    for (cp = STAILQ_FIRST(&file->common); cp;
351	 cp = STAILQ_FIRST(&file->common)) {
352	STAILQ_REMOVE(&file->common, cp, common_symbol, link);
353	free(cp, M_LINKER);
354    }
355
356    file->ops->unload(file);
357    free(file, M_LINKER);
358
359out:
360    return error;
361}
362
363int
364linker_file_add_dependancy(linker_file_t file, linker_file_t dep)
365{
366    linker_file_t* newdeps;
367
368    newdeps = malloc((file->ndeps + 1) * sizeof(linker_file_t*),
369		     M_LINKER, M_WAITOK);
370    if (newdeps == NULL)
371	return ENOMEM;
372    bzero(newdeps, (file->ndeps + 1) * sizeof(linker_file_t*));
373
374    if (file->deps) {
375	bcopy(file->deps, newdeps, file->ndeps * sizeof(linker_file_t*));
376	free(file->deps, M_LINKER);
377    }
378    file->deps = newdeps;
379    file->deps[file->ndeps] = dep;
380    file->ndeps++;
381
382    return 0;
383}
384
385caddr_t
386linker_file_lookup_symbol(linker_file_t file, const char* name, int deps)
387{
388    linker_sym_t sym;
389    linker_symval_t symval;
390    caddr_t address;
391    size_t common_size = 0;
392    int i;
393
394    KLD_DPF(SYM, ("linker_file_lookup_symbol: file=%x, name=%s, deps=%d\n",
395		  file, name, deps));
396
397    if (file->ops->lookup_symbol(file, name, &sym) == 0) {
398	file->ops->symbol_values(file, sym, &symval);
399	if (symval.value == 0)
400	    /*
401	     * For commons, first look them up in the dependancies and
402	     * only allocate space if not found there.
403	     */
404	    common_size = symval.size;
405	else {
406	    KLD_DPF(SYM, ("linker_file_lookup_symbol: symbol.value=%x\n", symval.value));
407	    return symval.value;
408	}
409    }
410
411    if (deps)
412	for (i = 0; i < file->ndeps; i++) {
413	    address = linker_file_lookup_symbol(file->deps[i], name, 0);
414	    if (address) {
415		KLD_DPF(SYM, ("linker_file_lookup_symbol: deps value=%x\n", address));
416		return address;
417	    }
418	}
419
420    if (common_size > 0) {
421	/*
422	 * This is a common symbol which was not found in the
423	 * dependancies.  We maintain a simple common symbol table in
424	 * the file object.
425	 */
426	struct common_symbol* cp;
427
428	for (cp = STAILQ_FIRST(&file->common); cp;
429	     cp = STAILQ_NEXT(cp, link))
430	    if (!strcmp(cp->name, name)) {
431		KLD_DPF(SYM, ("linker_file_lookup_symbol: old common value=%x\n", cp->address));
432		return cp->address;
433	    }
434
435	/*
436	 * Round the symbol size up to align.
437	 */
438	common_size = (common_size + sizeof(int) - 1) & -sizeof(int);
439	cp = malloc(sizeof(struct common_symbol)
440		    + common_size
441		    + strlen(name) + 1,
442		    M_LINKER, M_WAITOK);
443	if (!cp) {
444	    KLD_DPF(SYM, ("linker_file_lookup_symbol: nomem\n"));
445	    return 0;
446	}
447	bzero(cp, sizeof(struct common_symbol) + common_size + strlen(name)+ 1);
448
449	cp->address = (caddr_t) (cp + 1);
450	cp->name = cp->address + common_size;
451	strcpy(cp->name, name);
452	bzero(cp->address, common_size);
453	STAILQ_INSERT_TAIL(&file->common, cp, link);
454
455	KLD_DPF(SYM, ("linker_file_lookup_symbol: new common value=%x\n", cp->address));
456	return cp->address;
457    }
458
459    KLD_DPF(SYM, ("linker_file_lookup_symbol: fail\n"));
460    return 0;
461}
462
463#ifdef DDB
464/*
465 * DDB Helpers.  DDB has to look across multiple files with their own
466 * symbol tables and string tables.
467 *
468 * Note that we do not obey list locking protocols here.  We really don't
469 * need DDB to hang because somebody's got the lock held.  We'll take the
470 * chance that the files list is inconsistant instead.
471 */
472
473int
474linker_ddb_lookup(char *symstr, linker_sym_t *sym)
475{
476    linker_file_t lf;
477
478    for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) {
479	if (lf->ops->lookup_symbol(lf, symstr, sym) == 0)
480	    return 0;
481    }
482    return ENOENT;
483}
484
485int
486linker_ddb_search_symbol(caddr_t value, linker_sym_t *sym, long *diffp)
487{
488    linker_file_t lf;
489    u_long off = (u_long)value;
490    u_long diff, bestdiff;
491    linker_sym_t best;
492    linker_sym_t es;
493
494    best = 0;
495    bestdiff = off;
496    for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) {
497	if (lf->ops->search_symbol(lf, value, &es, &diff) != 0)
498	    continue;
499	if (es != 0 && diff < bestdiff) {
500	    best = es;
501	    bestdiff = diff;
502	}
503	if (bestdiff == 0)
504	    break;
505    }
506    if (best) {
507	*sym = best;
508	*diffp = bestdiff;
509	return 0;
510    } else {
511	*sym = 0;
512	*diffp = off;
513	return ENOENT;
514    }
515}
516
517int
518linker_ddb_symbol_values(linker_sym_t sym, linker_symval_t *symval)
519{
520    linker_file_t lf;
521
522    for (lf = TAILQ_FIRST(&files); lf; lf = TAILQ_NEXT(lf, link)) {
523	if (lf->ops->symbol_values(lf, sym, symval) == 0)
524	    return 0;
525    }
526    return ENOENT;
527}
528
529#endif
530
531/*
532 * Syscalls.
533 */
534
535int
536kldload(struct proc* p, struct kldload_args* uap)
537{
538    char* filename = NULL;
539    linker_file_t lf;
540    int error = 0;
541
542    p->p_retval[0] = -1;
543
544    if (securelevel > 0)
545	return EPERM;
546
547    if (error = suser(p->p_ucred, &p->p_acflag))
548	return error;
549
550    filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
551    if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
552	goto out;
553
554    if (error = linker_load_file(filename, &lf))
555	goto out;
556
557    lf->userrefs++;
558    p->p_retval[0] = lf->id;
559
560out:
561    if (filename)
562	free(filename, M_TEMP);
563    return error;
564}
565
566int
567kldunload(struct proc* p, struct kldunload_args* uap)
568{
569    linker_file_t lf;
570    int error = 0;
571
572    if (securelevel > 0)
573	return EPERM;
574
575    if (error = suser(p->p_ucred, &p->p_acflag))
576	return error;
577
578    lf = linker_find_file_by_id(SCARG(uap, fileid));
579    if (lf) {
580	KLD_DPF(FILE, ("kldunload: lf->userrefs=%d\n", lf->userrefs));
581	if (lf->userrefs == 0) {
582	    printf("linkerunload: attempt to unload file which was not loaded by user\n");
583	    error = EBUSY;
584	    goto out;
585	}
586	lf->userrefs--;
587	error = linker_file_unload(lf);
588    } else
589	error = ENOENT;
590
591out:
592    return error;
593}
594
595int
596kldfind(struct proc* p, struct kldfind_args* uap)
597{
598    char* filename = NULL;
599    linker_file_t lf;
600    int error = 0;
601
602    p->p_retval[0] = -1;
603
604    filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
605    if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
606	goto out;
607
608    lf = linker_find_file_by_name(filename);
609    if (lf)
610	p->p_retval[0] = lf->id;
611    else
612	error = ENOENT;
613
614out:
615    if (filename)
616	free(filename, M_TEMP);
617    return error;
618}
619
620int
621kldnext(struct proc* p, struct kldnext_args* uap)
622{
623    linker_file_t lf;
624    int error = 0;
625
626    if (SCARG(uap, fileid) == 0) {
627	if (TAILQ_FIRST(&files))
628	    p->p_retval[0] = TAILQ_FIRST(&files)->id;
629	else
630	    p->p_retval[0] = 0;
631	return 0;
632    }
633
634    lf = linker_find_file_by_id(SCARG(uap, fileid));
635    if (lf) {
636	if (TAILQ_NEXT(lf, link))
637	    p->p_retval[0] = TAILQ_NEXT(lf, link)->id;
638	else
639	    p->p_retval[0] = 0;
640    } else
641	error = ENOENT;
642
643    return error;
644}
645
646int
647kldstat(struct proc* p, struct kldstat_args* uap)
648{
649    linker_file_t lf;
650    int error = 0;
651    int version;
652    struct kld_file_stat* stat;
653    int namelen;
654
655    lf = linker_find_file_by_id(SCARG(uap, fileid));
656    if (!lf) {
657	error = ENOENT;
658	goto out;
659    }
660
661    stat = SCARG(uap, stat);
662
663    /*
664     * Check the version of the user's structure.
665     */
666    if (error = copyin(&stat->version, &version, sizeof(version)))
667	goto out;
668    if (version != sizeof(struct kld_file_stat)) {
669	error = EINVAL;
670	goto out;
671    }
672
673    namelen = strlen(lf->filename) + 1;
674    if (namelen > MAXPATHLEN)
675	namelen = MAXPATHLEN;
676    if (error = copyout(lf->filename, &stat->name[0], namelen))
677	goto out;
678    if (error = copyout(&lf->refs, &stat->refs, sizeof(int)))
679	goto out;
680    if (error = copyout(&lf->id, &stat->id, sizeof(int)))
681	goto out;
682    if (error = copyout(&lf->address, &stat->address, sizeof(caddr_t)))
683	goto out;
684    if (error = copyout(&lf->size, &stat->size, sizeof(size_t)))
685	goto out;
686
687    p->p_retval[0] = 0;
688
689out:
690    return error;
691}
692
693int
694kldfirstmod(struct proc* p, struct kldfirstmod_args* uap)
695{
696    linker_file_t lf;
697    int error = 0;
698
699    lf = linker_find_file_by_id(SCARG(uap, fileid));
700    if (lf) {
701	if (TAILQ_FIRST(&lf->modules))
702	    p->p_retval[0] = module_getid(TAILQ_FIRST(&lf->modules));
703	else
704	    p->p_retval[0] = 0;
705    } else
706	error = ENOENT;
707
708    return error;
709}
710
711/*
712 * Preloaded module support
713 */
714
715static void
716linker_preload(void* arg)
717{
718    caddr_t		modptr;
719    char		*modname;
720    char		*modtype;
721    linker_file_t	lf;
722    linker_class_t	lc;
723    int			error;
724    struct linker_set	*sysinits;
725    struct sysinit	**sipp;
726    moduledata_t	*moddata;
727
728    modptr = NULL;
729    while ((modptr = preload_search_next_name(modptr)) != NULL) {
730	modname = (char *)preload_search_info(modptr, MODINFO_NAME);
731	modtype = (char *)preload_search_info(modptr, MODINFO_TYPE);
732	if (modname == NULL) {
733	    printf("Preloaded module at %p does not have a name!\n", modptr);
734	    continue;
735	}
736	if (modtype == NULL) {
737	    printf("Preloaded module at %p does not have a type!\n", modptr);
738	    continue;
739	}
740	printf("Preloaded %s \"%s\" at %p.\n", modtype, modname, modptr);
741	lf = linker_find_file_by_name(modname);
742	if (lf) {
743	    lf->userrefs++;
744	    continue;
745	}
746	lf = NULL;
747	for (lc = TAILQ_FIRST(&classes); lc; lc = TAILQ_NEXT(lc, link)) {
748	    error = lc->ops->load_file(modname, &lf);
749	    if (error) {
750		lf = NULL;
751		break;
752	    }
753	}
754	if (lf) {
755	    lf->userrefs++;
756
757	    sysinits = (struct linker_set*)
758		linker_file_lookup_symbol(lf, "sysinit_set", 0);
759	    if (sysinits) {
760		/* HACK ALERT!
761		 * This is to set the sysinit moduledata so that the module
762		 * can attach itself to the correct containing file.
763		 * The sysinit could be run at *any* time.
764		 */
765		for (sipp = (struct sysinit **)sysinits->ls_items; *sipp; sipp++) {
766		    if ((*sipp)->func == module_register_init) {
767			moddata = (*sipp)->udata;
768			moddata->_file = lf;
769		    }
770		}
771		sysinit_add((struct sysinit **)sysinits->ls_items);
772	    }
773	}
774    }
775}
776
777SYSINIT(preload, SI_SUB_KLD, SI_ORDER_MIDDLE, linker_preload, 0);
778
779/*
780 * Search for a not-loaded module by name.
781 *
782 * Modules may be found in the following locations:
783 *
784 * - preloaded (result is just the module name)
785 * - on disk (result is full path to module)
786 *
787 * If the module name is qualified in any way (contains path, etc.)
788 * the we simply return a copy of it.
789 *
790 * The search path can be manipulated via sysctl.  Note that we use the ';'
791 * character as a separator to be consistent with the bootloader.
792 */
793
794static char linker_path[MAXPATHLEN + 1] = "/;/boot/;/modules/";
795
796SYSCTL_STRING(_kern, OID_AUTO, module_path, CTLFLAG_RW, linker_path,
797	      sizeof(linker_path), "module load search path");
798
799static char *
800linker_strdup(const char *str)
801{
802    char	*result;
803
804    if ((result = malloc((strlen(str) + 1), M_LINKER, M_WAITOK)) != NULL)
805	strcpy(result, str);
806    return(result);
807}
808
809char *
810linker_search_path(const char *name)
811{
812    struct nameidata	nd;
813    struct proc		*p = curproc;	/* XXX */
814    char		*cp, *ep, *result;
815    int			error;
816    enum vtype		type;
817
818    /* qualified at all? */
819    if (index(name, '/'))
820	return(linker_strdup(name));
821
822    /* traverse the linker path */
823    cp = linker_path;
824    for (;;) {
825
826	/* find the end of this component */
827	for (ep = cp; (*ep != 0) && (*ep != ';'); ep++)
828	    ;
829	result = malloc((strlen(name) + (ep - cp) + 1), M_LINKER, M_WAITOK);
830	if (result == NULL)	/* actually ENOMEM */
831	    return(NULL);
832
833	strncpy(result, cp, ep - cp);
834	strcpy(result + (ep - cp), name);
835
836	/*
837	 * Attempt to open the file, and return the path if we succeed and it's
838	 * a regular file.
839	 */
840	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, p);
841	error = vn_open(&nd, FREAD, 0);
842	if (error == 0) {
843	    type = nd.ni_vp->v_type;
844	    VOP_UNLOCK(nd.ni_vp, 0, p);
845	    vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
846	    if (type == VREG)
847		return(result);
848	}
849	free(result, M_LINKER);
850
851	if (*ep == 0)
852	    break;
853	cp = ep + 1;
854    }
855    return(NULL);
856}
857