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