140090Smsmith/*- 240090Smsmith * Copyright (c) 1998 Michael Smith 340090Smsmith * All rights reserved. 440090Smsmith * 540090Smsmith * Redistribution and use in source and binary forms, with or without 640090Smsmith * modification, are permitted provided that the following conditions 740090Smsmith * are met: 840090Smsmith * 1. Redistributions of source code must retain the above copyright 940090Smsmith * notice, this list of conditions and the following disclaimer. 1040090Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1140090Smsmith * notice, this list of conditions and the following disclaimer in the 1240090Smsmith * documentation and/or other materials provided with the distribution. 1340090Smsmith * 1440090Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1540090Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1640090Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1740090Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1840090Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1940090Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2040090Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2140090Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2240090Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2340090Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2440090Smsmith * SUCH DAMAGE. 2540090Smsmith */ 2640090Smsmith 27116182Sobrien#include <sys/cdefs.h> 28116182Sobrien__FBSDID("$FreeBSD$"); 29116182Sobrien 3040090Smsmith#include <sys/param.h> 3140090Smsmith#include <sys/systm.h> 3240090Smsmith#include <sys/linker.h> 3340090Smsmith 3440090Smsmith/* 3540090Smsmith * Preloaded module support 3640090Smsmith */ 3740090Smsmith 38218494Smarcelvm_offset_t preload_addr_relocate = 0; 39218494Smarcelcaddr_t preload_metadata; 4040090Smsmith 4140090Smsmith/* 4240090Smsmith * Search for the preloaded module (name) 4340090Smsmith */ 4440090Smsmithcaddr_t 4540157Speterpreload_search_by_name(const char *name) 4640090Smsmith{ 4740090Smsmith caddr_t curp; 48209390Sed uint32_t *hdr; 4940157Speter int next; 5040090Smsmith 5140157Speter if (preload_metadata != NULL) { 5240090Smsmith 5340157Speter curp = preload_metadata; 5440090Smsmith for (;;) { 55209390Sed hdr = (uint32_t *)curp; 5640157Speter if (hdr[0] == 0 && hdr[1] == 0) 5740090Smsmith break; 5840090Smsmith 5940090Smsmith /* Search for a MODINFO_NAME field */ 6040090Smsmith if ((hdr[0] == MODINFO_NAME) && 61209390Sed !strcmp(name, curp + sizeof(uint32_t) * 2)) 6240090Smsmith return(curp); 6340090Smsmith 6440090Smsmith /* skip to next field */ 65209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 6640336Speter next = roundup(next, sizeof(u_long)); 6740157Speter curp += next; 6840090Smsmith } 6940090Smsmith } 7040090Smsmith return(NULL); 7140090Smsmith} 7240090Smsmith 7340090Smsmith/* 7440090Smsmith * Search for the first preloaded module of (type) 7540090Smsmith */ 7640090Smsmithcaddr_t 7740157Speterpreload_search_by_type(const char *type) 7840090Smsmith{ 7940090Smsmith caddr_t curp, lname; 80209390Sed uint32_t *hdr; 8140157Speter int next; 8240090Smsmith 8340157Speter if (preload_metadata != NULL) { 8440090Smsmith 8540157Speter curp = preload_metadata; 8640090Smsmith lname = NULL; 8740090Smsmith for (;;) { 88209390Sed hdr = (uint32_t *)curp; 8940157Speter if (hdr[0] == 0 && hdr[1] == 0) 9040090Smsmith break; 9140090Smsmith 9240090Smsmith /* remember the start of each record */ 9340090Smsmith if (hdr[0] == MODINFO_NAME) 9440090Smsmith lname = curp; 9540090Smsmith 9640090Smsmith /* Search for a MODINFO_TYPE field */ 9740090Smsmith if ((hdr[0] == MODINFO_TYPE) && 98209390Sed !strcmp(type, curp + sizeof(uint32_t) * 2)) 9940090Smsmith return(lname); 10040090Smsmith 10140090Smsmith /* skip to next field */ 102209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 10340336Speter next = roundup(next, sizeof(u_long)); 10440157Speter curp += next; 10540090Smsmith } 10640090Smsmith } 10740090Smsmith return(NULL); 10840090Smsmith} 10940090Smsmith 11040090Smsmith/* 11140157Speter * Walk through the preloaded module list 11240157Speter */ 11340157Spetercaddr_t 11440157Speterpreload_search_next_name(caddr_t base) 11540157Speter{ 11640157Speter caddr_t curp; 117209390Sed uint32_t *hdr; 11840157Speter int next; 11940157Speter 12040157Speter if (preload_metadata != NULL) { 12140157Speter 12240157Speter /* Pick up where we left off last time */ 12340157Speter if (base) { 12440157Speter /* skip to next field */ 12540157Speter curp = base; 126209390Sed hdr = (uint32_t *)curp; 127209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 12840336Speter next = roundup(next, sizeof(u_long)); 12940157Speter curp += next; 13040157Speter } else 13140157Speter curp = preload_metadata; 13240157Speter 13340157Speter for (;;) { 134209390Sed hdr = (uint32_t *)curp; 13540157Speter if (hdr[0] == 0 && hdr[1] == 0) 13640157Speter break; 13740157Speter 13840157Speter /* Found a new record? */ 13940157Speter if (hdr[0] == MODINFO_NAME) 14040157Speter return curp; 14140157Speter 14240157Speter /* skip to next field */ 143209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 14440336Speter next = roundup(next, sizeof(u_long)); 14540157Speter curp += next; 14640157Speter } 14740157Speter } 14840157Speter return(NULL); 14940157Speter} 15040157Speter 15140157Speter/* 15240090Smsmith * Given a preloaded module handle (mod), return a pointer 15340090Smsmith * to the data for the attribute (inf). 15440090Smsmith */ 15540090Smsmithcaddr_t 15640157Speterpreload_search_info(caddr_t mod, int inf) 15740090Smsmith{ 15840090Smsmith caddr_t curp; 159209390Sed uint32_t *hdr; 160209390Sed uint32_t type = 0; 16140157Speter int next; 16240090Smsmith 16340090Smsmith curp = mod; 16440090Smsmith for (;;) { 165209390Sed hdr = (uint32_t *)curp; 16640090Smsmith /* end of module data? */ 16740157Speter if (hdr[0] == 0 && hdr[1] == 0) 16840090Smsmith break; 16940090Smsmith /* 17040090Smsmith * We give up once we've looped back to what we were looking at 17140090Smsmith * first - this should normally be a MODINFO_NAME field. 17240090Smsmith */ 17340090Smsmith if (type == 0) { 17440090Smsmith type = hdr[0]; 17540090Smsmith } else { 17640090Smsmith if (hdr[0] == type) 17740090Smsmith break; 17840090Smsmith } 17940090Smsmith 18040090Smsmith /* 18140090Smsmith * Attribute match? Return pointer to data. 18272645Sasmodai * Consumer may safely assume that size value precedes 18340090Smsmith * data. 18440090Smsmith */ 18540090Smsmith if (hdr[0] == inf) 186209390Sed return(curp + (sizeof(uint32_t) * 2)); 18740090Smsmith 18840090Smsmith /* skip to next field */ 189209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 19040336Speter next = roundup(next, sizeof(u_long)); 19140157Speter curp += next; 19240090Smsmith } 19340090Smsmith return(NULL); 19440090Smsmith} 19540090Smsmith 19640157Speter/* 19740157Speter * Delete a preload record by name. 19840157Speter */ 19940157Spetervoid 20040157Speterpreload_delete_name(const char *name) 20140157Speter{ 20240157Speter caddr_t curp; 203209390Sed uint32_t *hdr; 20440157Speter int next; 20540157Speter int clearing; 20640157Speter 20740157Speter if (preload_metadata != NULL) { 20840157Speter 20940157Speter clearing = 0; 21040157Speter curp = preload_metadata; 21140157Speter for (;;) { 212209390Sed hdr = (uint32_t *)curp; 21340157Speter if (hdr[0] == 0 && hdr[1] == 0) 21440157Speter break; 21540157Speter 21640157Speter /* Search for a MODINFO_NAME field */ 21740157Speter if (hdr[0] == MODINFO_NAME) { 218209390Sed if (!strcmp(name, curp + sizeof(uint32_t) * 2)) 21940157Speter clearing = 1; /* got it, start clearing */ 22040157Speter else if (clearing) 22140157Speter clearing = 0; /* at next one now.. better stop */ 22240157Speter } 22340157Speter if (clearing) 22440157Speter hdr[0] = MODINFO_EMPTY; 22540157Speter 22640157Speter /* skip to next field */ 227209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 22840336Speter next = roundup(next, sizeof(u_long)); 22940157Speter curp += next; 23040157Speter } 23140157Speter } 23240157Speter} 23340157Speter 234218494Smarcelvoid * 235218494Smarcelpreload_fetch_addr(caddr_t mod) 236218494Smarcel{ 237218494Smarcel caddr_t *mdp; 238218494Smarcel 239218494Smarcel mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR); 240218494Smarcel if (mdp == NULL) 241218494Smarcel return (NULL); 242218494Smarcel return (*mdp + preload_addr_relocate); 243218494Smarcel} 244218494Smarcel 245218494Smarcelsize_t 246218494Smarcelpreload_fetch_size(caddr_t mod) 247218494Smarcel{ 248218494Smarcel size_t *mdp; 249218494Smarcel 250218494Smarcel mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE); 251218494Smarcel if (mdp == NULL) 252218494Smarcel return (0); 253218494Smarcel return (*mdp); 254218494Smarcel} 255218494Smarcel 25640157Speter/* Called from locore on i386. Convert physical pointers to kvm. Sigh. */ 25740157Spetervoid 25840157Speterpreload_bootstrap_relocate(vm_offset_t offset) 25940157Speter{ 26040157Speter caddr_t curp; 261209390Sed uint32_t *hdr; 26240157Speter vm_offset_t *ptr; 26340157Speter int next; 26440157Speter 26540157Speter if (preload_metadata != NULL) { 26640157Speter 26740157Speter curp = preload_metadata; 26840157Speter for (;;) { 269209390Sed hdr = (uint32_t *)curp; 27040157Speter if (hdr[0] == 0 && hdr[1] == 0) 27140157Speter break; 27240157Speter 27340252Speter /* Deal with the ones that we know we have to fix */ 27440252Speter switch (hdr[0]) { 27540252Speter case MODINFO_ADDR: 27640252Speter case MODINFO_METADATA|MODINFOMD_SSYM: 27740252Speter case MODINFO_METADATA|MODINFOMD_ESYM: 278209390Sed ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2)); 27940157Speter *ptr += offset; 28040252Speter break; 28140157Speter } 28240157Speter /* The rest is beyond us for now */ 28340157Speter 28440157Speter /* skip to next field */ 285209390Sed next = sizeof(uint32_t) * 2 + hdr[1]; 28640336Speter next = roundup(next, sizeof(u_long)); 28740157Speter curp += next; 28840157Speter } 28940157Speter } 29040157Speter} 291