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