subr_module.c revision 52128
1/*-
2 * Copyright (c) 1998 Michael Smith
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 * $FreeBSD: head/sys/kern/subr_module.c 52128 1999-10-11 15:19:12Z peter $
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/linker.h>
32
33/*
34 * Preloaded module support
35 */
36
37caddr_t	preload_metadata;
38
39/*
40 * Search for the preloaded module (name)
41 */
42caddr_t
43preload_search_by_name(const char *name)
44{
45    caddr_t	curp;
46    u_int32_t	*hdr;
47    int		next;
48
49    if (preload_metadata != NULL) {
50
51	curp = preload_metadata;
52	for (;;) {
53	    hdr = (u_int32_t *)curp;
54	    if (hdr[0] == 0 && hdr[1] == 0)
55		break;
56
57	    /* Search for a MODINFO_NAME field */
58	    if ((hdr[0] == MODINFO_NAME) &&
59		!strcmp(name, curp + sizeof(u_int32_t) * 2))
60		return(curp);
61
62	    /* skip to next field */
63	    next = sizeof(u_int32_t) * 2 + hdr[1];
64	    next = roundup(next, sizeof(u_long));
65	    curp += next;
66	}
67    }
68    return(NULL);
69}
70
71/*
72 * Search for the first preloaded module of (type)
73 */
74caddr_t
75preload_search_by_type(const char *type)
76{
77    caddr_t	curp, lname;
78    u_int32_t	*hdr;
79    int		next;
80
81    if (preload_metadata != NULL) {
82
83	curp = preload_metadata;
84	lname = NULL;
85	for (;;) {
86	    hdr = (u_int32_t *)curp;
87	    if (hdr[0] == 0 && hdr[1] == 0)
88		break;
89
90	    /* remember the start of each record */
91	    if (hdr[0] == MODINFO_NAME)
92		lname = curp;
93
94	    /* Search for a MODINFO_TYPE field */
95	    if ((hdr[0] == MODINFO_TYPE) &&
96		!strcmp(type, curp + sizeof(u_int32_t) * 2))
97		return(lname);
98
99	    /* skip to next field */
100	    next = sizeof(u_int32_t) * 2 + hdr[1];
101	    next = roundup(next, sizeof(u_long));
102	    curp += next;
103	}
104    }
105    return(NULL);
106}
107
108/*
109 * Walk through the preloaded module list
110 */
111caddr_t
112preload_search_next_name(caddr_t base)
113{
114    caddr_t	curp;
115    u_int32_t	*hdr;
116    int		next;
117
118    if (preload_metadata != NULL) {
119
120	/* Pick up where we left off last time */
121	if (base) {
122	    /* skip to next field */
123	    curp = base;
124	    hdr = (u_int32_t *)curp;
125	    next = sizeof(u_int32_t) * 2 + hdr[1];
126	    next = roundup(next, sizeof(u_long));
127	    curp += next;
128	} else
129	    curp = preload_metadata;
130
131	for (;;) {
132	    hdr = (u_int32_t *)curp;
133	    if (hdr[0] == 0 && hdr[1] == 0)
134		break;
135
136	    /* Found a new record? */
137	    if (hdr[0] == MODINFO_NAME)
138		return curp;
139
140	    /* skip to next field */
141	    next = sizeof(u_int32_t) * 2 + hdr[1];
142	    next = roundup(next, sizeof(u_long));
143	    curp += next;
144	}
145    }
146    return(NULL);
147}
148
149/*
150 * Given a preloaded module handle (mod), return a pointer
151 * to the data for the attribute (inf).
152 */
153caddr_t
154preload_search_info(caddr_t mod, int inf)
155{
156    caddr_t	curp;
157    u_int32_t	*hdr;
158    u_int32_t	type = 0;
159    int		next;
160
161    curp = mod;
162    for (;;) {
163	hdr = (u_int32_t *)curp;
164	/* end of module data? */
165	if (hdr[0] == 0 && hdr[1] == 0)
166	    break;
167	/*
168	 * We give up once we've looped back to what we were looking at
169	 * first - this should normally be a MODINFO_NAME field.
170	 */
171	if (type == 0) {
172	    type = hdr[0];
173	} else {
174	    if (hdr[0] == type)
175		break;
176	}
177
178	/*
179	 * Attribute match? Return pointer to data.
180	 * Consumer may safely assume that size value preceeds
181	 * data.
182	 */
183	if (hdr[0] == inf)
184	    return(curp + (sizeof(u_int32_t) * 2));
185
186	/* skip to next field */
187	next = sizeof(u_int32_t) * 2 + hdr[1];
188	next = roundup(next, sizeof(u_long));
189	curp += next;
190    }
191    return(NULL);
192}
193
194/*
195 * Delete a preload record by name.
196 */
197void
198preload_delete_name(const char *name)
199{
200    caddr_t	curp;
201    u_int32_t	*hdr;
202    int		next;
203    int		clearing;
204
205    if (preload_metadata != NULL) {
206
207	clearing = 0;
208	curp = preload_metadata;
209	for (;;) {
210	    hdr = (u_int32_t *)curp;
211	    if (hdr[0] == 0 && hdr[1] == 0)
212		break;
213
214	    /* Search for a MODINFO_NAME field */
215	    if (hdr[0] == MODINFO_NAME) {
216		if (!strcmp(name, curp + sizeof(u_int32_t) * 2))
217		    clearing = 1;	/* got it, start clearing */
218		else if (clearing)
219		    clearing = 0;	/* at next one now.. better stop */
220	    }
221	    if (clearing)
222		hdr[0] = MODINFO_EMPTY;
223
224	    /* skip to next field */
225	    next = sizeof(u_int32_t) * 2 + hdr[1];
226	    next = roundup(next, sizeof(u_long));
227	    curp += next;
228	}
229    }
230}
231
232/* Called from locore on i386.  Convert physical pointers to kvm. Sigh. */
233void
234preload_bootstrap_relocate(vm_offset_t offset)
235{
236    caddr_t	curp;
237    u_int32_t	*hdr;
238    vm_offset_t	*ptr;
239    int		next;
240
241    if (preload_metadata != NULL) {
242
243	curp = preload_metadata;
244	for (;;) {
245	    hdr = (u_int32_t *)curp;
246	    if (hdr[0] == 0 && hdr[1] == 0)
247		break;
248
249	    /* Deal with the ones that we know we have to fix */
250	    switch (hdr[0]) {
251	    case MODINFO_ADDR:
252	    case MODINFO_METADATA|MODINFOMD_SSYM:
253	    case MODINFO_METADATA|MODINFOMD_ESYM:
254		ptr = (vm_offset_t *)(curp + (sizeof(u_int32_t) * 2));
255		*ptr += offset;
256		break;
257	    }
258	    /* The rest is beyond us for now */
259
260	    /* skip to next field */
261	    next = sizeof(u_int32_t) * 2 + hdr[1];
262	    next = roundup(next, sizeof(u_long));
263	    curp += next;
264	}
265    }
266}
267