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