Disallow writes to filesystems mounted read-only via NULLFS. In this case
[dragonfly.git] / sys / kern / subr_module.c
CommitLineData
984263bc
MD
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: src/sys/kern/subr_module.c,v 1.6 1999/10/11 15:19:10 peter Exp $
2bc3312a 27 * $DragonFly: src/sys/kern/subr_module.c,v 1.4 2004/05/26 08:32:41 dillon Exp $
984263bc
MD
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/linker.h>
33
34/*
35 * Preloaded module support
36 */
37
38caddr_t preload_metadata;
39
40/*
41 * Search for the preloaded module (name)
42 */
43caddr_t
44preload_search_by_name(const char *name)
45{
46 caddr_t curp;
47 u_int32_t *hdr;
48 int next;
32832096
MD
49 int i;
50 char *scanname;
984263bc 51
32832096
MD
52 if (preload_metadata == NULL)
53 return(NULL);
54
55 curp = preload_metadata;
56 for (;;) {
57 hdr = (u_int32_t *)curp;
58 if (hdr[0] == 0 && hdr[1] == 0)
59 break;
984263bc 60
32832096
MD
61 /*
62 * Search for a MODINFO_NAME field. the boot loader really
63 * ought to strip the path names
64 */
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);
984263bc 74 }
32832096
MD
75 /* skip to next field */
76 next = sizeof(u_int32_t) * 2 + hdr[1];
77 next = roundup(next, sizeof(u_long));
78 curp += next;
984263bc
MD
79 }
80 return(NULL);
81}
82
83/*
84 * Search for the first preloaded module of (type)
85 */
86caddr_t
87preload_search_by_type(const char *type)
88{
89 caddr_t curp, lname;
90 u_int32_t *hdr;
91 int next;
92
93 if (preload_metadata != NULL) {
94
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;
101
102 /* remember the start of each record */
103 if (hdr[0] == MODINFO_NAME)
104 lname = curp;
105
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);
110
111 /* skip to next field */
112 next = sizeof(u_int32_t) * 2 + hdr[1];
113 next = roundup(next, sizeof(u_long));
114 curp += next;
115 }
116 }
117 return(NULL);
118}
119
120/*
121 * Walk through the preloaded module list
122 */
123caddr_t
124preload_search_next_name(caddr_t base)
125{
126 caddr_t curp;
127 u_int32_t *hdr;
128 int next;
129
130 if (preload_metadata != NULL) {
131
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;
142
143 for (;;) {
144 hdr = (u_int32_t *)curp;
145 if (hdr[0] == 0 && hdr[1] == 0)
146 break;
147
148 /* Found a new record? */
149 if (hdr[0] == MODINFO_NAME)
150 return curp;
151
152 /* skip to next field */
153 next = sizeof(u_int32_t) * 2 + hdr[1];
154 next = roundup(next, sizeof(u_long));
155 curp += next;
156 }
157 }
158 return(NULL);
159}
160
161/*
162 * Given a preloaded module handle (mod), return a pointer
163 * to the data for the attribute (inf).
164 */
165caddr_t
166preload_search_info(caddr_t mod, int inf)
167{
168 caddr_t curp;
169 u_int32_t *hdr;
170 u_int32_t type = 0;
171 int next;
172
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;
179 /*
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.
182 */
183 if (type == 0) {
184 type = hdr[0];
185 } else {
186 if (hdr[0] == type)
187 break;
188 }
189
190 /*
191 * Attribute match? Return pointer to data.
192 * Consumer may safely assume that size value preceeds
193 * data.
194 */
195 if (hdr[0] == inf)
196 return(curp + (sizeof(u_int32_t) * 2));
197
198 /* skip to next field */
199 next = sizeof(u_int32_t) * 2 + hdr[1];
200 next = roundup(next, sizeof(u_long));
201 curp += next;
202 }
203 return(NULL);
204}
205
206/*
207 * Delete a preload record by name.
2bc3312a
MD
208 *
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.
984263bc
MD
213 */
214void
215preload_delete_name(const char *name)
216{
217 caddr_t curp;
218 u_int32_t *hdr;
219 int next;
220 int clearing;
2bc3312a
MD
221 int i;
222 char *scanname;
984263bc
MD
223
224 if (preload_metadata != NULL) {
984263bc
MD
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;
231
232 /* Search for a MODINFO_NAME field */
233 if (hdr[0] == MODINFO_NAME) {
2bc3312a
MD
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 */
984263bc
MD
244 }
245 if (clearing)
246 hdr[0] = MODINFO_EMPTY;
247
248 /* skip to next field */
249 next = sizeof(u_int32_t) * 2 + hdr[1];
250 next = roundup(next, sizeof(u_long));
251 curp += next;
252 }
253 }
254}
255
256/* Called from locore on i386. Convert physical pointers to kvm. Sigh. */
257void
258preload_bootstrap_relocate(vm_offset_t offset)
259{
260 caddr_t curp;
261 u_int32_t *hdr;
262 vm_offset_t *ptr;
263 int next;
264
265 if (preload_metadata != NULL) {
266
267 curp = preload_metadata;
268 for (;;) {
269 hdr = (u_int32_t *)curp;
270 if (hdr[0] == 0 && hdr[1] == 0)
271 break;
272
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;
281 }
282 /* The rest is beyond us for now */
283
284 /* skip to next field */
285 next = sizeof(u_int32_t) * 2 + hdr[1];
286 next = roundup(next, sizeof(u_long));
287 curp += next;
288 }
289 }
290}