16ba9413bSMike Smith /*- 26ba9413bSMike Smith * Copyright (c) 1998 Michael Smith 36ba9413bSMike Smith * All rights reserved. 46ba9413bSMike Smith * 56ba9413bSMike Smith * Redistribution and use in source and binary forms, with or without 66ba9413bSMike Smith * modification, are permitted provided that the following conditions 76ba9413bSMike Smith * are met: 86ba9413bSMike Smith * 1. Redistributions of source code must retain the above copyright 96ba9413bSMike Smith * notice, this list of conditions and the following disclaimer. 106ba9413bSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 116ba9413bSMike Smith * notice, this list of conditions and the following disclaimer in the 126ba9413bSMike Smith * documentation and/or other materials provided with the distribution. 136ba9413bSMike Smith * 146ba9413bSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 156ba9413bSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 166ba9413bSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 176ba9413bSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 186ba9413bSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 196ba9413bSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 206ba9413bSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 216ba9413bSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 226ba9413bSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 236ba9413bSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 246ba9413bSMike Smith * SUCH DAMAGE. 256ba9413bSMike Smith */ 266ba9413bSMike Smith 27677b542eSDavid E. O'Brien #include <sys/cdefs.h> 28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29677b542eSDavid E. O'Brien 306ba9413bSMike Smith #include <sys/param.h> 316ba9413bSMike Smith #include <sys/systm.h> 326ba9413bSMike Smith #include <sys/linker.h> 336ba9413bSMike Smith 346ba9413bSMike Smith /* 356ba9413bSMike Smith * Preloaded module support 366ba9413bSMike Smith */ 376ba9413bSMike Smith 38e4f1a52fSPeter Wemm caddr_t preload_metadata; 396ba9413bSMike Smith 406ba9413bSMike Smith /* 416ba9413bSMike Smith * Search for the preloaded module (name) 426ba9413bSMike Smith */ 436ba9413bSMike Smith caddr_t 44e4f1a52fSPeter Wemm preload_search_by_name(const char *name) 456ba9413bSMike Smith { 466ba9413bSMike Smith caddr_t curp; 47*60ae52f7SEd Schouten uint32_t *hdr; 48e4f1a52fSPeter Wemm int next; 496ba9413bSMike Smith 50e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 516ba9413bSMike Smith 52e4f1a52fSPeter Wemm curp = preload_metadata; 536ba9413bSMike Smith for (;;) { 54*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 55e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 566ba9413bSMike Smith break; 576ba9413bSMike Smith 586ba9413bSMike Smith /* Search for a MODINFO_NAME field */ 596ba9413bSMike Smith if ((hdr[0] == MODINFO_NAME) && 60*60ae52f7SEd Schouten !strcmp(name, curp + sizeof(uint32_t) * 2)) 616ba9413bSMike Smith return(curp); 626ba9413bSMike Smith 636ba9413bSMike Smith /* skip to next field */ 64*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 652a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 66e4f1a52fSPeter Wemm curp += next; 676ba9413bSMike Smith } 686ba9413bSMike Smith } 696ba9413bSMike Smith return(NULL); 706ba9413bSMike Smith } 716ba9413bSMike Smith 726ba9413bSMike Smith /* 736ba9413bSMike Smith * Search for the first preloaded module of (type) 746ba9413bSMike Smith */ 756ba9413bSMike Smith caddr_t 76e4f1a52fSPeter Wemm preload_search_by_type(const char *type) 776ba9413bSMike Smith { 786ba9413bSMike Smith caddr_t curp, lname; 79*60ae52f7SEd Schouten uint32_t *hdr; 80e4f1a52fSPeter Wemm int next; 816ba9413bSMike Smith 82e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 836ba9413bSMike Smith 84e4f1a52fSPeter Wemm curp = preload_metadata; 856ba9413bSMike Smith lname = NULL; 866ba9413bSMike Smith for (;;) { 87*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 88e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 896ba9413bSMike Smith break; 906ba9413bSMike Smith 916ba9413bSMike Smith /* remember the start of each record */ 926ba9413bSMike Smith if (hdr[0] == MODINFO_NAME) 936ba9413bSMike Smith lname = curp; 946ba9413bSMike Smith 956ba9413bSMike Smith /* Search for a MODINFO_TYPE field */ 966ba9413bSMike Smith if ((hdr[0] == MODINFO_TYPE) && 97*60ae52f7SEd Schouten !strcmp(type, curp + sizeof(uint32_t) * 2)) 986ba9413bSMike Smith return(lname); 996ba9413bSMike Smith 1006ba9413bSMike Smith /* skip to next field */ 101*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1022a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 103e4f1a52fSPeter Wemm curp += next; 104e4f1a52fSPeter Wemm } 105e4f1a52fSPeter Wemm } 106e4f1a52fSPeter Wemm return(NULL); 107e4f1a52fSPeter Wemm } 108e4f1a52fSPeter Wemm 109e4f1a52fSPeter Wemm /* 110e4f1a52fSPeter Wemm * Walk through the preloaded module list 111e4f1a52fSPeter Wemm */ 112e4f1a52fSPeter Wemm caddr_t 113e4f1a52fSPeter Wemm preload_search_next_name(caddr_t base) 114e4f1a52fSPeter Wemm { 115e4f1a52fSPeter Wemm caddr_t curp; 116*60ae52f7SEd Schouten uint32_t *hdr; 117e4f1a52fSPeter Wemm int next; 118e4f1a52fSPeter Wemm 119e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 120e4f1a52fSPeter Wemm 121e4f1a52fSPeter Wemm /* Pick up where we left off last time */ 122e4f1a52fSPeter Wemm if (base) { 123e4f1a52fSPeter Wemm /* skip to next field */ 124e4f1a52fSPeter Wemm curp = base; 125*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 126*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1272a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 128e4f1a52fSPeter Wemm curp += next; 129e4f1a52fSPeter Wemm } else 130e4f1a52fSPeter Wemm curp = preload_metadata; 131e4f1a52fSPeter Wemm 132e4f1a52fSPeter Wemm for (;;) { 133*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 134e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 135e4f1a52fSPeter Wemm break; 136e4f1a52fSPeter Wemm 137e4f1a52fSPeter Wemm /* Found a new record? */ 138e4f1a52fSPeter Wemm if (hdr[0] == MODINFO_NAME) 139e4f1a52fSPeter Wemm return curp; 140e4f1a52fSPeter Wemm 141e4f1a52fSPeter Wemm /* skip to next field */ 142*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1432a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 144e4f1a52fSPeter Wemm curp += next; 1456ba9413bSMike Smith } 1466ba9413bSMike Smith } 1476ba9413bSMike Smith return(NULL); 1486ba9413bSMike Smith } 1496ba9413bSMike Smith 1506ba9413bSMike Smith /* 1516ba9413bSMike Smith * Given a preloaded module handle (mod), return a pointer 1526ba9413bSMike Smith * to the data for the attribute (inf). 1536ba9413bSMike Smith */ 1546ba9413bSMike Smith caddr_t 155e4f1a52fSPeter Wemm preload_search_info(caddr_t mod, int inf) 1566ba9413bSMike Smith { 1576ba9413bSMike Smith caddr_t curp; 158*60ae52f7SEd Schouten uint32_t *hdr; 159*60ae52f7SEd Schouten uint32_t type = 0; 160e4f1a52fSPeter Wemm int next; 1616ba9413bSMike Smith 1626ba9413bSMike Smith curp = mod; 1636ba9413bSMike Smith for (;;) { 164*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 1656ba9413bSMike Smith /* end of module data? */ 166e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 1676ba9413bSMike Smith break; 1686ba9413bSMike Smith /* 1696ba9413bSMike Smith * We give up once we've looped back to what we were looking at 1706ba9413bSMike Smith * first - this should normally be a MODINFO_NAME field. 1716ba9413bSMike Smith */ 1726ba9413bSMike Smith if (type == 0) { 1736ba9413bSMike Smith type = hdr[0]; 1746ba9413bSMike Smith } else { 1756ba9413bSMike Smith if (hdr[0] == type) 1766ba9413bSMike Smith break; 1776ba9413bSMike Smith } 1786ba9413bSMike Smith 1796ba9413bSMike Smith /* 1806ba9413bSMike Smith * Attribute match? Return pointer to data. 181d7d97eb0SJeroen Ruigrok van der Werven * Consumer may safely assume that size value precedes 1826ba9413bSMike Smith * data. 1836ba9413bSMike Smith */ 1846ba9413bSMike Smith if (hdr[0] == inf) 185*60ae52f7SEd Schouten return(curp + (sizeof(uint32_t) * 2)); 1866ba9413bSMike Smith 1876ba9413bSMike Smith /* skip to next field */ 188*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1892a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 190e4f1a52fSPeter Wemm curp += next; 1916ba9413bSMike Smith } 1926ba9413bSMike Smith return(NULL); 1936ba9413bSMike Smith } 1946ba9413bSMike Smith 195e4f1a52fSPeter Wemm /* 196e4f1a52fSPeter Wemm * Delete a preload record by name. 197e4f1a52fSPeter Wemm */ 198e4f1a52fSPeter Wemm void 199e4f1a52fSPeter Wemm preload_delete_name(const char *name) 200e4f1a52fSPeter Wemm { 201e4f1a52fSPeter Wemm caddr_t curp; 202*60ae52f7SEd Schouten uint32_t *hdr; 203e4f1a52fSPeter Wemm int next; 204e4f1a52fSPeter Wemm int clearing; 205e4f1a52fSPeter Wemm 206e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 207e4f1a52fSPeter Wemm 208e4f1a52fSPeter Wemm clearing = 0; 209e4f1a52fSPeter Wemm curp = preload_metadata; 210e4f1a52fSPeter Wemm for (;;) { 211*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 212e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 213e4f1a52fSPeter Wemm break; 214e4f1a52fSPeter Wemm 215e4f1a52fSPeter Wemm /* Search for a MODINFO_NAME field */ 216e4f1a52fSPeter Wemm if (hdr[0] == MODINFO_NAME) { 217*60ae52f7SEd Schouten if (!strcmp(name, curp + sizeof(uint32_t) * 2)) 218e4f1a52fSPeter Wemm clearing = 1; /* got it, start clearing */ 219e4f1a52fSPeter Wemm else if (clearing) 220e4f1a52fSPeter Wemm clearing = 0; /* at next one now.. better stop */ 221e4f1a52fSPeter Wemm } 222e4f1a52fSPeter Wemm if (clearing) 223e4f1a52fSPeter Wemm hdr[0] = MODINFO_EMPTY; 224e4f1a52fSPeter Wemm 225e4f1a52fSPeter Wemm /* skip to next field */ 226*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 2272a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 228e4f1a52fSPeter Wemm curp += next; 229e4f1a52fSPeter Wemm } 230e4f1a52fSPeter Wemm } 231e4f1a52fSPeter Wemm } 232e4f1a52fSPeter Wemm 233e4f1a52fSPeter Wemm /* Called from locore on i386. Convert physical pointers to kvm. Sigh. */ 234e4f1a52fSPeter Wemm void 235e4f1a52fSPeter Wemm preload_bootstrap_relocate(vm_offset_t offset) 236e4f1a52fSPeter Wemm { 237e4f1a52fSPeter Wemm caddr_t curp; 238*60ae52f7SEd Schouten uint32_t *hdr; 239e4f1a52fSPeter Wemm vm_offset_t *ptr; 240e4f1a52fSPeter Wemm int next; 241e4f1a52fSPeter Wemm 242e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 243e4f1a52fSPeter Wemm 244e4f1a52fSPeter Wemm curp = preload_metadata; 245e4f1a52fSPeter Wemm for (;;) { 246*60ae52f7SEd Schouten hdr = (uint32_t *)curp; 247e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 248e4f1a52fSPeter Wemm break; 249e4f1a52fSPeter Wemm 2502da2eeacSPeter Wemm /* Deal with the ones that we know we have to fix */ 2512da2eeacSPeter Wemm switch (hdr[0]) { 2522da2eeacSPeter Wemm case MODINFO_ADDR: 2532da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_SSYM: 2542da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_ESYM: 255*60ae52f7SEd Schouten ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2)); 256e4f1a52fSPeter Wemm *ptr += offset; 2572da2eeacSPeter Wemm break; 258e4f1a52fSPeter Wemm } 259e4f1a52fSPeter Wemm /* The rest is beyond us for now */ 260e4f1a52fSPeter Wemm 261e4f1a52fSPeter Wemm /* skip to next field */ 262*60ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 2632a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 264e4f1a52fSPeter Wemm curp += next; 265e4f1a52fSPeter Wemm } 266e4f1a52fSPeter Wemm } 267e4f1a52fSPeter Wemm } 268