Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sys / kern / subr_module.c
blob344b008c65de0fdcf813b6666744376f270aebdb
1 /*-
2 * Copyright (c) 1998 Michael Smith
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/sys/kern/subr_module.c,v 1.6 1999/10/11 15:19:10 peter Exp $
27 * $DragonFly: src/sys/kern/subr_module.c,v 1.4 2004/05/26 08:32:41 dillon Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/linker.h>
35 * Preloaded module support
38 caddr_t preload_metadata;
41 * Search for the preloaded module (name)
43 caddr_t
44 preload_search_by_name(const char *name)
46 caddr_t curp;
47 u_int32_t *hdr;
48 int next;
49 int i;
50 char *scanname;
52 if (preload_metadata == NULL)
53 return(NULL);
55 curp = preload_metadata;
56 for (;;) {
57 hdr = (u_int32_t *)curp;
58 if (hdr[0] == 0 && hdr[1] == 0)
59 break;
62 * Search for a MODINFO_NAME field. the boot loader really
63 * ought to strip the path names
65 if (hdr[0] == MODINFO_NAME) {
66 scanname = curp + sizeof(u_int32_t) * 2;
67 i = strlen(scanname);
68 while (i > 0 && scanname[i-1] != '/')
69 --i;
70 if (strcmp(name, scanname) == 0)
71 return(curp);
72 if (strcmp(name, scanname + i) == 0)
73 return(curp);
75 /* skip to next field */
76 next = sizeof(u_int32_t) * 2 + hdr[1];
77 next = roundup(next, sizeof(u_long));
78 curp += next;
80 return(NULL);
84 * Search for the first preloaded module of (type)
86 caddr_t
87 preload_search_by_type(const char *type)
89 caddr_t curp, lname;
90 u_int32_t *hdr;
91 int next;
93 if (preload_metadata != NULL) {
95 curp = preload_metadata;
96 lname = NULL;
97 for (;;) {
98 hdr = (u_int32_t *)curp;
99 if (hdr[0] == 0 && hdr[1] == 0)
100 break;
102 /* remember the start of each record */
103 if (hdr[0] == MODINFO_NAME)
104 lname = curp;
106 /* Search for a MODINFO_TYPE field */
107 if ((hdr[0] == MODINFO_TYPE) &&
108 !strcmp(type, curp + sizeof(u_int32_t) * 2))
109 return(lname);
111 /* skip to next field */
112 next = sizeof(u_int32_t) * 2 + hdr[1];
113 next = roundup(next, sizeof(u_long));
114 curp += next;
117 return(NULL);
121 * Walk through the preloaded module list
123 caddr_t
124 preload_search_next_name(caddr_t base)
126 caddr_t curp;
127 u_int32_t *hdr;
128 int next;
130 if (preload_metadata != NULL) {
132 /* Pick up where we left off last time */
133 if (base) {
134 /* skip to next field */
135 curp = base;
136 hdr = (u_int32_t *)curp;
137 next = sizeof(u_int32_t) * 2 + hdr[1];
138 next = roundup(next, sizeof(u_long));
139 curp += next;
140 } else
141 curp = preload_metadata;
143 for (;;) {
144 hdr = (u_int32_t *)curp;
145 if (hdr[0] == 0 && hdr[1] == 0)
146 break;
148 /* Found a new record? */
149 if (hdr[0] == MODINFO_NAME)
150 return curp;
152 /* skip to next field */
153 next = sizeof(u_int32_t) * 2 + hdr[1];
154 next = roundup(next, sizeof(u_long));
155 curp += next;
158 return(NULL);
162 * Given a preloaded module handle (mod), return a pointer
163 * to the data for the attribute (inf).
165 caddr_t
166 preload_search_info(caddr_t mod, int inf)
168 caddr_t curp;
169 u_int32_t *hdr;
170 u_int32_t type = 0;
171 int next;
173 curp = mod;
174 for (;;) {
175 hdr = (u_int32_t *)curp;
176 /* end of module data? */
177 if (hdr[0] == 0 && hdr[1] == 0)
178 break;
180 * We give up once we've looped back to what we were looking at
181 * first - this should normally be a MODINFO_NAME field.
183 if (type == 0) {
184 type = hdr[0];
185 } else {
186 if (hdr[0] == type)
187 break;
191 * Attribute match? Return pointer to data.
192 * Consumer may safely assume that size value preceeds
193 * data.
195 if (hdr[0] == inf)
196 return(curp + (sizeof(u_int32_t) * 2));
198 /* skip to next field */
199 next = sizeof(u_int32_t) * 2 + hdr[1];
200 next = roundup(next, sizeof(u_long));
201 curp += next;
203 return(NULL);
207 * Delete a preload record by name.
209 * XXX we should really pass the base of the preloaded module here and not
210 * require rematching of the name. If the wrong module (or no module) is
211 * deleted, the original preloaded module might be loaded again, causing it's
212 * data to be relocated twice.
214 void
215 preload_delete_name(const char *name)
217 caddr_t curp;
218 u_int32_t *hdr;
219 int next;
220 int clearing;
221 int i;
222 char *scanname;
224 if (preload_metadata != NULL) {
225 clearing = 0;
226 curp = preload_metadata;
227 for (;;) {
228 hdr = (u_int32_t *)curp;
229 if (hdr[0] == 0 && hdr[1] == 0)
230 break;
232 /* Search for a MODINFO_NAME field */
233 if (hdr[0] == MODINFO_NAME) {
234 scanname = curp + sizeof(u_int32_t) * 2;
235 i = strlen(scanname);
236 while (i > 0 && scanname[i-1] != '/')
237 --i;
238 if (strcmp(name, scanname) == 0)
239 clearing = 1;
240 else if (strcmp(name, scanname + i) == 0)
241 clearing = 1;
242 else
243 clearing = 0; /* at next module now, stop clearing */
245 if (clearing)
246 hdr[0] = MODINFO_EMPTY;
248 /* skip to next field */
249 next = sizeof(u_int32_t) * 2 + hdr[1];
250 next = roundup(next, sizeof(u_long));
251 curp += next;
256 /* Called from locore on i386. Convert physical pointers to kvm. Sigh. */
257 void
258 preload_bootstrap_relocate(vm_offset_t offset)
260 caddr_t curp;
261 u_int32_t *hdr;
262 vm_offset_t *ptr;
263 int next;
265 if (preload_metadata != NULL) {
267 curp = preload_metadata;
268 for (;;) {
269 hdr = (u_int32_t *)curp;
270 if (hdr[0] == 0 && hdr[1] == 0)
271 break;
273 /* Deal with the ones that we know we have to fix */
274 switch (hdr[0]) {
275 case MODINFO_ADDR:
276 case MODINFO_METADATA|MODINFOMD_SSYM:
277 case MODINFO_METADATA|MODINFOMD_ESYM:
278 ptr = (vm_offset_t *)(curp + (sizeof(u_int32_t) * 2));
279 *ptr += offset;
280 break;
282 /* The rest is beyond us for now */
284 /* skip to next field */
285 next = sizeof(u_int32_t) * 2 + hdr[1];
286 next = roundup(next, sizeof(u_long));
287 curp += next;