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 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 precedes 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 } 268