subr_module.c revision 40157
140090Smsmith/*-
240090Smsmith * Copyright (c) 1998 Michael Smith
340090Smsmith * All rights reserved.
440090Smsmith *
540090Smsmith * Redistribution and use in source and binary forms, with or without
640090Smsmith * modification, are permitted provided that the following conditions
740090Smsmith * are met:
840090Smsmith * 1. Redistributions of source code must retain the above copyright
940090Smsmith *    notice, this list of conditions and the following disclaimer.
1040090Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1140090Smsmith *    notice, this list of conditions and the following disclaimer in the
1240090Smsmith *    documentation and/or other materials provided with the distribution.
1340090Smsmith *
1440090Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1540090Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1640090Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1740090Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1840090Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1940090Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2040090Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2140090Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2240090Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2340090Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2440090Smsmith * SUCH DAMAGE.
2540090Smsmith *
2640157Speter *	$Id: subr_module.c,v 1.1 1998/10/09 00:31:29 msmith Exp $
2740090Smsmith */
2840090Smsmith
2940090Smsmith#include <sys/param.h>
3040090Smsmith#include <sys/kernel.h>
3140090Smsmith#include <sys/systm.h>
3240090Smsmith#include <sys/linker.h>
3340090Smsmith
3440090Smsmith/*
3540090Smsmith * Preloaded module support
3640090Smsmith */
3740090Smsmith
3840157Spetercaddr_t	preload_metadata;
3940090Smsmith
4040090Smsmith/*
4140090Smsmith * Search for the preloaded module (name)
4240090Smsmith */
4340090Smsmithcaddr_t
4440157Speterpreload_search_by_name(const char *name)
4540090Smsmith{
4640090Smsmith    caddr_t	curp;
4740090Smsmith    u_int32_t	*hdr;
4840157Speter    int		next;
4940090Smsmith
5040157Speter    if (preload_metadata != NULL) {
5140090Smsmith
5240157Speter	curp = preload_metadata;
5340090Smsmith	for (;;) {
5440090Smsmith	    hdr = (u_int32_t *)curp;
5540157Speter	    if (hdr[0] == 0 && hdr[1] == 0)
5640090Smsmith		break;
5740090Smsmith
5840090Smsmith	    /* Search for a MODINFO_NAME field */
5940090Smsmith	    if ((hdr[0] == MODINFO_NAME) &&
6040090Smsmith		!strcmp(name, curp + sizeof(u_int32_t) * 2))
6140090Smsmith		return(curp);
6240090Smsmith
6340090Smsmith	    /* skip to next field */
6440157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
6540157Speter	    next = roundup(next, sizeof(u_int32_t));
6640157Speter	    curp += next;
6740090Smsmith	}
6840090Smsmith    }
6940090Smsmith    return(NULL);
7040090Smsmith}
7140090Smsmith
7240090Smsmith/*
7340090Smsmith * Search for the first preloaded module of (type)
7440090Smsmith */
7540090Smsmithcaddr_t
7640157Speterpreload_search_by_type(const char *type)
7740090Smsmith{
7840090Smsmith    caddr_t	curp, lname;
7940090Smsmith    u_int32_t	*hdr;
8040157Speter    int		next;
8140090Smsmith
8240157Speter    if (preload_metadata != NULL) {
8340090Smsmith
8440157Speter	curp = preload_metadata;
8540090Smsmith	lname = NULL;
8640090Smsmith	for (;;) {
8740090Smsmith	    hdr = (u_int32_t *)curp;
8840157Speter	    if (hdr[0] == 0 && hdr[1] == 0)
8940090Smsmith		break;
9040090Smsmith
9140090Smsmith	    /* remember the start of each record */
9240090Smsmith	    if (hdr[0] == MODINFO_NAME)
9340090Smsmith		lname = curp;
9440090Smsmith
9540090Smsmith	    /* Search for a MODINFO_TYPE field */
9640090Smsmith	    if ((hdr[0] == MODINFO_TYPE) &&
9740090Smsmith		!strcmp(type, curp + sizeof(u_int32_t) * 2))
9840090Smsmith		return(lname);
9940090Smsmith
10040090Smsmith	    /* skip to next field */
10140157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
10240157Speter	    next = roundup(next, sizeof(u_int32_t));
10340157Speter	    curp += next;
10440090Smsmith	}
10540090Smsmith    }
10640090Smsmith    return(NULL);
10740090Smsmith}
10840090Smsmith
10940090Smsmith/*
11040157Speter * Walk through the preloaded module list
11140157Speter */
11240157Spetercaddr_t
11340157Speterpreload_search_next_name(caddr_t base)
11440157Speter{
11540157Speter    caddr_t	curp;
11640157Speter    u_int32_t	*hdr;
11740157Speter    int		next;
11840157Speter
11940157Speter    if (preload_metadata != NULL) {
12040157Speter
12140157Speter	/* Pick up where we left off last time */
12240157Speter	if (base) {
12340157Speter	    /* skip to next field */
12440157Speter	    curp = base;
12540157Speter	    hdr = (u_int32_t *)curp;
12640157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
12740157Speter	    next = roundup(next, sizeof(u_int32_t));
12840157Speter	    curp += next;
12940157Speter	} else
13040157Speter	    curp = preload_metadata;
13140157Speter
13240157Speter	for (;;) {
13340157Speter	    hdr = (u_int32_t *)curp;
13440157Speter	    if (hdr[0] == 0 && hdr[1] == 0)
13540157Speter		break;
13640157Speter
13740157Speter	    /* Found a new record? */
13840157Speter	    if (hdr[0] == MODINFO_NAME)
13940157Speter		return curp;
14040157Speter
14140157Speter	    /* skip to next field */
14240157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
14340157Speter	    next = roundup(next, sizeof(u_int32_t));
14440157Speter	    curp += next;
14540157Speter	}
14640157Speter    }
14740157Speter    return(NULL);
14840157Speter}
14940157Speter
15040157Speter/*
15140090Smsmith * Given a preloaded module handle (mod), return a pointer
15240090Smsmith * to the data for the attribute (inf).
15340090Smsmith */
15440090Smsmithcaddr_t
15540157Speterpreload_search_info(caddr_t mod, int inf)
15640090Smsmith{
15740090Smsmith    caddr_t	curp;
15840090Smsmith    u_int32_t	*hdr;
15940090Smsmith    u_int32_t	type = 0;
16040157Speter    int		next;
16140090Smsmith
16240090Smsmith    curp = mod;
16340090Smsmith    for (;;) {
16440090Smsmith	hdr = (u_int32_t *)curp;
16540090Smsmith	/* end of module data? */
16640157Speter	if (hdr[0] == 0 && hdr[1] == 0)
16740090Smsmith	    break;
16840090Smsmith	/*
16940090Smsmith	 * We give up once we've looped back to what we were looking at
17040090Smsmith	 * first - this should normally be a MODINFO_NAME field.
17140090Smsmith	 */
17240090Smsmith	if (type == 0) {
17340090Smsmith	    type = hdr[0];
17440090Smsmith	} else {
17540090Smsmith	    if (hdr[0] == type)
17640090Smsmith		break;
17740090Smsmith	}
17840090Smsmith
17940090Smsmith	/*
18040090Smsmith	 * Attribute match? Return pointer to data.
18140090Smsmith	 * Consumer may safely assume that size value preceeds
18240090Smsmith	 * data.
18340090Smsmith	 */
18440090Smsmith	if (hdr[0] == inf)
18540090Smsmith	    return(curp + (sizeof(u_int32_t) * 2));
18640090Smsmith
18740090Smsmith	/* skip to next field */
18840157Speter	next = sizeof(u_int32_t) * 2 + hdr[1];
18940157Speter	next = roundup(next, sizeof(u_int32_t));
19040157Speter	curp += next;
19140090Smsmith    }
19240090Smsmith    return(NULL);
19340090Smsmith}
19440090Smsmith
19540157Speter/*
19640157Speter * Delete a preload record by name.
19740157Speter */
19840157Spetervoid
19940157Speterpreload_delete_name(const char *name)
20040157Speter{
20140157Speter    caddr_t	curp;
20240157Speter    u_int32_t	*hdr;
20340157Speter    int		next;
20440157Speter    int		clearing;
20540157Speter
20640157Speter    if (preload_metadata != NULL) {
20740157Speter
20840157Speter	clearing = 0;
20940157Speter	curp = preload_metadata;
21040157Speter	for (;;) {
21140157Speter	    hdr = (u_int32_t *)curp;
21240157Speter	    if (hdr[0] == 0 && hdr[1] == 0)
21340157Speter		break;
21440157Speter
21540157Speter	    /* Search for a MODINFO_NAME field */
21640157Speter	    if (hdr[0] == MODINFO_NAME) {
21740157Speter		if (!strcmp(name, curp + sizeof(u_int32_t) * 2))
21840157Speter		    clearing = 1;	/* got it, start clearing */
21940157Speter		else if (clearing)
22040157Speter		    clearing = 0;	/* at next one now.. better stop */
22140157Speter	    }
22240157Speter	    if (clearing)
22340157Speter		hdr[0] = MODINFO_EMPTY;
22440157Speter
22540157Speter	    /* skip to next field */
22640157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
22740157Speter	    next = roundup(next, sizeof(u_int32_t));
22840157Speter	    curp += next;
22940157Speter	}
23040157Speter    }
23140157Speter}
23240157Speter
23340157Speter/* Called from locore on i386.  Convert physical pointers to kvm. Sigh. */
23440157Spetervoid
23540157Speterpreload_bootstrap_relocate(vm_offset_t offset)
23640157Speter{
23740157Speter    caddr_t	curp;
23840157Speter    u_int32_t	*hdr;
23940157Speter    vm_offset_t	*ptr;
24040157Speter    int		next;
24140157Speter
24240157Speter    if (preload_metadata != NULL) {
24340157Speter
24440157Speter	curp = preload_metadata;
24540157Speter	for (;;) {
24640157Speter	    hdr = (u_int32_t *)curp;
24740157Speter	    if (hdr[0] == 0 && hdr[1] == 0)
24840157Speter		break;
24940157Speter
25040157Speter	    /* Look for a MODINFO_ADDR field */
25140157Speter	    if (hdr[0] == MODINFO_ADDR) {
25240157Speter		ptr = (vm_offset_t *)(curp + (sizeof(u_int32_t) * 2));
25340157Speter		*ptr += offset;
25440157Speter	    }
25540157Speter	    /* The rest is beyond us for now */
25640157Speter
25740157Speter	    /* skip to next field */
25840157Speter	    next = sizeof(u_int32_t) * 2 + hdr[1];
25940157Speter	    next = roundup(next, sizeof(u_int32_t));
26040157Speter	    curp += next;
26140157Speter	}
26240157Speter    }
26340157Speter}
264