FreeBSD kernel kern code
subr_module.c
Go to the documentation of this file.
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("$BSDSUniX$");
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;
40 
41 /*
42  * Search for the preloaded module (name)
43  */
44 caddr_t
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
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
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  curp = mod;
164  for (;;) {
165  hdr = (uint32_t *)curp;
166  /* end of module data? */
167  if (hdr[0] == 0 && hdr[1] == 0)
168  break;
169  /*
170  * We give up once we've looped back to what we were looking at
171  * first - this should normally be a MODINFO_NAME field.
172  */
173  if (type == 0) {
174  type = hdr[0];
175  } else {
176  if (hdr[0] == type)
177  break;
178  }
179 
180  /*
181  * Attribute match? Return pointer to data.
182  * Consumer may safely assume that size value precedes
183  * data.
184  */
185  if (hdr[0] == inf)
186  return(curp + (sizeof(uint32_t) * 2));
187 
188  /* skip to next field */
189  next = sizeof(uint32_t) * 2 + hdr[1];
190  next = roundup(next, sizeof(u_long));
191  curp += next;
192  }
193  return(NULL);
194 }
195 
196 /*
197  * Delete a preload record by name.
198  */
199 void
201 {
202  caddr_t curp;
203  uint32_t *hdr;
204  int next;
205  int clearing;
206 
207  if (preload_metadata != NULL) {
208 
209  clearing = 0;
210  curp = preload_metadata;
211  for (;;) {
212  hdr = (uint32_t *)curp;
213  if (hdr[0] == 0 && hdr[1] == 0)
214  break;
215 
216  /* Search for a MODINFO_NAME field */
217  if (hdr[0] == MODINFO_NAME) {
218  if (!strcmp(name, curp + sizeof(uint32_t) * 2))
219  clearing = 1; /* got it, start clearing */
220  else if (clearing)
221  clearing = 0; /* at next one now.. better stop */
222  }
223  if (clearing)
224  hdr[0] = MODINFO_EMPTY;
225 
226  /* skip to next field */
227  next = sizeof(uint32_t) * 2 + hdr[1];
228  next = roundup(next, sizeof(u_long));
229  curp += next;
230  }
231  }
232 }
233 
234 void *
235 preload_fetch_addr(caddr_t mod)
236 {
237  caddr_t *mdp;
238 
239  mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR);
240  if (mdp == NULL)
241  return (NULL);
242  return (*mdp + preload_addr_relocate);
243 }
244 
245 size_t
246 preload_fetch_size(caddr_t mod)
247 {
248  size_t *mdp;
249 
250  mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE);
251  if (mdp == NULL)
252  return (0);
253  return (*mdp);
254 }
255 
256 /* Called from locore on i386. Convert physical pointers to kvm. Sigh. */
257 void
258 preload_bootstrap_relocate(vm_offset_t offset)
259 {
260  caddr_t curp;
261  uint32_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 = (uint32_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(uint32_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(uint32_t) * 2 + hdr[1];
286  next = roundup(next, sizeof(u_long));
287  curp += next;
288  }
289  }
290 }
void preload_bootstrap_relocate(vm_offset_t offset)
Definition: subr_module.c:258
void preload_delete_name(const char *name)
Definition: subr_module.c:200
caddr_t preload_search_by_type(const char *type)
Definition: subr_module.c:77
const char * name
Definition: kern_fail.c:97
caddr_t preload_metadata
Definition: subr_module.c:39
size_t preload_fetch_size(caddr_t mod)
Definition: subr_module.c:246
int * type
Definition: cpufreq_if.m:98
caddr_t preload_search_next_name(caddr_t base)
Definition: subr_module.c:114
__FBSDID("$BSDSUniX$")
caddr_t preload_search_by_name(const char *name)
Definition: subr_module.c:45
void * preload_fetch_addr(caddr_t mod)
Definition: subr_module.c:235
caddr_t preload_search_info(caddr_t mod, int inf)
Definition: subr_module.c:156
vm_offset_t preload_addr_relocate
Definition: subr_module.c:38