sbin/fsck_hammer2: Add destroy.c to destroy ondisk inode/dirent
[dragonfly.git] / sys / kern / subr_module.c
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 $
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
37 caddr_t preload_metadata;
38
39 /*
40  * Search for the preloaded module (name)
41  */
42 caddr_t
43 preload_search_by_name(const char *name)
44 {
45     caddr_t     curp;
46     u_int32_t   *hdr;
47     int         next;
48     int         i;
49     char        *scanname;
50
51     if (preload_metadata == NULL)
52         return(NULL);
53
54     curp = preload_metadata;
55     for (;;) {
56         hdr = (u_int32_t *)curp;
57         if (hdr[0] == 0 && hdr[1] == 0)
58             break;
59
60         /*
61          * Search for a MODINFO_NAME field.  the boot loader really
62          * ought to strip the path names
63          */
64         if (hdr[0] == MODINFO_NAME) {
65             scanname = curp + sizeof(u_int32_t) * 2;
66             i = strlen(scanname);
67             while (i > 0 && scanname[i-1] != '/')
68                 --i;
69             if (strcmp(name, scanname) == 0)
70                 return(curp);
71             if (strcmp(name, scanname + i) == 0)
72                 return(curp);
73         }
74         /* skip to next field */
75         next = sizeof(u_int32_t) * 2 + hdr[1];
76         next = roundup(next, sizeof(u_long));
77         curp += next;
78     }
79     return(NULL);
80 }
81
82 /*
83  * Search for the first preloaded module of (type)
84  */
85 caddr_t
86 preload_search_by_type(const char *type)
87 {
88     caddr_t     curp, lname;
89     u_int32_t   *hdr;
90     int         next;
91
92     if (preload_metadata != NULL) {
93
94         curp = preload_metadata;
95         lname = NULL;
96         for (;;) {
97             hdr = (u_int32_t *)curp;
98             if (hdr[0] == 0 && hdr[1] == 0)
99                 break;
100
101             /* remember the start of each record */
102             if (hdr[0] == MODINFO_NAME)
103                 lname = curp;
104
105             /* Search for a MODINFO_TYPE field */
106             if ((hdr[0] == MODINFO_TYPE) &&
107                 !strcmp(type, curp + sizeof(u_int32_t) * 2))
108                 return(lname);
109
110             /* skip to next field */
111             next = sizeof(u_int32_t) * 2 + hdr[1];
112             next = roundup(next, sizeof(u_long));
113             curp += next;
114         }
115     }
116     return(NULL);
117 }
118
119 /*
120  * Walk through the preloaded module list
121  */
122 caddr_t
123 preload_search_next_name(caddr_t base)
124 {
125     caddr_t     curp;
126     u_int32_t   *hdr;
127     int         next;
128
129     if (preload_metadata != NULL) {
130
131         /* Pick up where we left off last time */
132         if (base) {
133             /* skip to next field */
134             curp = base;
135             hdr = (u_int32_t *)curp;
136             next = sizeof(u_int32_t) * 2 + hdr[1];
137             next = roundup(next, sizeof(u_long));
138             curp += next;
139         } else
140             curp = preload_metadata;
141
142         for (;;) {
143             hdr = (u_int32_t *)curp;
144             if (hdr[0] == 0 && hdr[1] == 0)
145                 break;
146
147             /* Found a new record? */
148             if (hdr[0] == MODINFO_NAME)
149                 return curp;
150
151             /* skip to next field */
152             next = sizeof(u_int32_t) * 2 + hdr[1];
153             next = roundup(next, sizeof(u_long));
154             curp += next;
155         }
156     }
157     return(NULL);
158 }
159
160 /*
161  * Given a preloaded module handle (mod), return a pointer
162  * to the data for the attribute (inf).
163  */
164 caddr_t
165 preload_search_info(caddr_t mod, int inf)
166 {
167     caddr_t     curp;
168     u_int32_t   *hdr;
169     u_int32_t   type = 0;
170     int         next;
171
172     curp = mod;
173     for (;;) {
174         hdr = (u_int32_t *)curp;
175         /* end of module data? */
176         if (hdr[0] == 0 && hdr[1] == 0)
177             break;
178         /*
179          * We give up once we've looped back to what we were looking at
180          * first - this should normally be a MODINFO_NAME field.
181          */
182         if (type == 0) {
183             type = hdr[0];
184         } else {
185             if (hdr[0] == type)
186                 break;
187         }
188
189         /*
190          * Attribute match? Return pointer to data.
191          * Consumer may safely assume that size value preceeds
192          * data.
193          */
194         if (hdr[0] == inf)
195             return(curp + (sizeof(u_int32_t) * 2));
196
197         /* skip to next field */
198         next = sizeof(u_int32_t) * 2 + hdr[1];
199         next = roundup(next, sizeof(u_long));
200         curp += next;
201     }
202     return(NULL);
203 }
204
205 /*
206  * Delete a preload record by name.
207  *
208  * XXX we should really pass the base of the preloaded module here and not
209  * require rematching of the name.  If the wrong module (or no module) is
210  * deleted, the original preloaded module might be loaded again, causing it's
211  * data to be relocated twice.
212  */
213 void
214 preload_delete_name(const char *name)
215 {
216     caddr_t     curp;
217     u_int32_t   *hdr;
218     int         next;
219     int         clearing;
220     int         i;
221     char        *scanname;
222
223     if (preload_metadata != NULL) {
224         clearing = 0;
225         curp = preload_metadata;
226         for (;;) {
227             hdr = (u_int32_t *)curp;
228             if (hdr[0] == 0 && hdr[1] == 0)
229                 break;
230
231             /* Search for a MODINFO_NAME field */
232             if (hdr[0] == MODINFO_NAME) {
233                 scanname = curp + sizeof(u_int32_t) * 2;
234                 i = strlen(scanname);
235                 while (i > 0 && scanname[i-1] != '/')
236                     --i;
237                 if (strcmp(name, scanname) == 0)
238                     clearing = 1;
239                 else if (strcmp(name, scanname + i) == 0)
240                     clearing = 1;
241                 else
242                     clearing = 0;       /* at next module now, stop clearing */
243             }
244             if (clearing)
245                 hdr[0] = MODINFO_EMPTY;
246
247             /* skip to next field */
248             next = sizeof(u_int32_t) * 2 + hdr[1];
249             next = roundup(next, sizeof(u_long));
250             curp += next;
251         }
252     }
253 }
254
255 /* Called from hammer_time() on pc64.  Convert physical pointers to kvm. Sigh. */
256 void
257 preload_bootstrap_relocate(vm_offset_t offset)
258 {
259     caddr_t     curp;
260     u_int32_t   *hdr;
261     vm_offset_t *ptr;
262     int         next;
263
264     if (preload_metadata != NULL) {
265
266         curp = preload_metadata;
267         for (;;) {
268             hdr = (u_int32_t *)curp;
269             if (hdr[0] == 0 && hdr[1] == 0)
270                 break;
271
272             /* Deal with the ones that we know we have to fix */
273             switch (hdr[0]) {
274             case MODINFO_ADDR:
275             case MODINFO_METADATA|MODINFOMD_SSYM:
276             case MODINFO_METADATA|MODINFOMD_ESYM:
277                 ptr = (vm_offset_t *)(curp + (sizeof(u_int32_t) * 2));
278                 *ptr += offset;
279                 break;
280             }
281             /* The rest is beyond us for now */
282
283             /* skip to next field */
284             next = sizeof(u_int32_t) * 2 + hdr[1];
285             next = roundup(next, sizeof(u_long));
286             curp += next;
287         }
288     }
289 }