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