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