16ba9413bSMike Smith /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 38a36da99SPedro F. Giffuni * 46ba9413bSMike Smith * Copyright (c) 1998 Michael Smith 56ba9413bSMike Smith * All rights reserved. 622e6a670SMitchell Horne * Copyright (c) 2020 NetApp Inc. 722e6a670SMitchell Horne * Copyright (c) 2020 Klara Inc. 86ba9413bSMike Smith * 96ba9413bSMike Smith * Redistribution and use in source and binary forms, with or without 106ba9413bSMike Smith * modification, are permitted provided that the following conditions 116ba9413bSMike Smith * are met: 126ba9413bSMike Smith * 1. Redistributions of source code must retain the above copyright 136ba9413bSMike Smith * notice, this list of conditions and the following disclaimer. 146ba9413bSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 156ba9413bSMike Smith * notice, this list of conditions and the following disclaimer in the 166ba9413bSMike Smith * documentation and/or other materials provided with the distribution. 176ba9413bSMike Smith * 186ba9413bSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 196ba9413bSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 206ba9413bSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 216ba9413bSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 226ba9413bSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 236ba9413bSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 246ba9413bSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 256ba9413bSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 266ba9413bSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 276ba9413bSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 286ba9413bSMike Smith * SUCH DAMAGE. 296ba9413bSMike Smith */ 306ba9413bSMike Smith 316ba9413bSMike Smith #include <sys/param.h> 326ba9413bSMike Smith #include <sys/systm.h> 336ba9413bSMike Smith #include <sys/linker.h> 3422e6a670SMitchell Horne #include <sys/sbuf.h> 3522e6a670SMitchell Horne #include <sys/sysctl.h> 3622e6a670SMitchell Horne 3722e6a670SMitchell Horne #include <machine/metadata.h> 386ba9413bSMike Smith 39483f692eSMark Johnston #include <vm/vm.h> 40483f692eSMark Johnston #include <vm/vm_extern.h> 41483f692eSMark Johnston 426ba9413bSMike Smith /* 436ba9413bSMike Smith * Preloaded module support 446ba9413bSMike Smith */ 456ba9413bSMike Smith 46278e7970SMarcel Moolenaar vm_offset_t preload_addr_relocate = 0; 47e4f1a52fSPeter Wemm caddr_t preload_metadata; 486ba9413bSMike Smith 496ba9413bSMike Smith /* 506ba9413bSMike Smith * Search for the preloaded module (name) 516ba9413bSMike Smith */ 526ba9413bSMike Smith caddr_t 53e4f1a52fSPeter Wemm preload_search_by_name(const char *name) 546ba9413bSMike Smith { 556ba9413bSMike Smith caddr_t curp; 5660ae52f7SEd Schouten uint32_t *hdr; 57e4f1a52fSPeter Wemm int next; 586ba9413bSMike Smith 59e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 60e4f1a52fSPeter Wemm curp = preload_metadata; 616ba9413bSMike Smith for (;;) { 6260ae52f7SEd Schouten hdr = (uint32_t *)curp; 63e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 646ba9413bSMike Smith break; 656ba9413bSMike Smith 666ba9413bSMike Smith /* Search for a MODINFO_NAME field */ 676ba9413bSMike Smith if ((hdr[0] == MODINFO_NAME) && 6860ae52f7SEd Schouten !strcmp(name, curp + sizeof(uint32_t) * 2)) 696ba9413bSMike Smith return(curp); 706ba9413bSMike Smith 716ba9413bSMike Smith /* skip to next field */ 7260ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 732a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 74e4f1a52fSPeter Wemm curp += next; 756ba9413bSMike Smith } 766ba9413bSMike Smith } 776ba9413bSMike Smith return(NULL); 786ba9413bSMike Smith } 796ba9413bSMike Smith 806ba9413bSMike Smith /* 816ba9413bSMike Smith * Search for the first preloaded module of (type) 826ba9413bSMike Smith */ 836ba9413bSMike Smith caddr_t 84e4f1a52fSPeter Wemm preload_search_by_type(const char *type) 856ba9413bSMike Smith { 866ba9413bSMike Smith caddr_t curp, lname; 8760ae52f7SEd Schouten uint32_t *hdr; 88e4f1a52fSPeter Wemm int next; 896ba9413bSMike Smith 90e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 91e4f1a52fSPeter Wemm curp = preload_metadata; 926ba9413bSMike Smith lname = NULL; 936ba9413bSMike Smith for (;;) { 9460ae52f7SEd Schouten hdr = (uint32_t *)curp; 95e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 966ba9413bSMike Smith break; 976ba9413bSMike Smith 986ba9413bSMike Smith /* remember the start of each record */ 996ba9413bSMike Smith if (hdr[0] == MODINFO_NAME) 1006ba9413bSMike Smith lname = curp; 1016ba9413bSMike Smith 1026ba9413bSMike Smith /* Search for a MODINFO_TYPE field */ 1036ba9413bSMike Smith if ((hdr[0] == MODINFO_TYPE) && 10460ae52f7SEd Schouten !strcmp(type, curp + sizeof(uint32_t) * 2)) 1056ba9413bSMike Smith return(lname); 1066ba9413bSMike Smith 1076ba9413bSMike Smith /* skip to next field */ 10860ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1092a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 110e4f1a52fSPeter Wemm curp += next; 111e4f1a52fSPeter Wemm } 112e4f1a52fSPeter Wemm } 113e4f1a52fSPeter Wemm return(NULL); 114e4f1a52fSPeter Wemm } 115e4f1a52fSPeter Wemm 116e4f1a52fSPeter Wemm /* 117e4f1a52fSPeter Wemm * Walk through the preloaded module list 118e4f1a52fSPeter Wemm */ 119e4f1a52fSPeter Wemm caddr_t 120e4f1a52fSPeter Wemm preload_search_next_name(caddr_t base) 121e4f1a52fSPeter Wemm { 122e4f1a52fSPeter Wemm caddr_t curp; 12360ae52f7SEd Schouten uint32_t *hdr; 124e4f1a52fSPeter Wemm int next; 125e4f1a52fSPeter Wemm 126e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 127e4f1a52fSPeter Wemm /* Pick up where we left off last time */ 128e4f1a52fSPeter Wemm if (base) { 129e4f1a52fSPeter Wemm /* skip to next field */ 130e4f1a52fSPeter Wemm curp = base; 13160ae52f7SEd Schouten hdr = (uint32_t *)curp; 13260ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1332a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 134e4f1a52fSPeter Wemm curp += next; 135e4f1a52fSPeter Wemm } else 136e4f1a52fSPeter Wemm curp = preload_metadata; 137e4f1a52fSPeter Wemm 138e4f1a52fSPeter Wemm for (;;) { 13960ae52f7SEd Schouten hdr = (uint32_t *)curp; 140e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 141e4f1a52fSPeter Wemm break; 142e4f1a52fSPeter Wemm 143e4f1a52fSPeter Wemm /* Found a new record? */ 144e4f1a52fSPeter Wemm if (hdr[0] == MODINFO_NAME) 145e4f1a52fSPeter Wemm return curp; 146e4f1a52fSPeter Wemm 147e4f1a52fSPeter Wemm /* skip to next field */ 14860ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1492a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 150e4f1a52fSPeter Wemm curp += next; 1516ba9413bSMike Smith } 1526ba9413bSMike Smith } 1536ba9413bSMike Smith return(NULL); 1546ba9413bSMike Smith } 1556ba9413bSMike Smith 1566ba9413bSMike Smith /* 1576ba9413bSMike Smith * Given a preloaded module handle (mod), return a pointer 1586ba9413bSMike Smith * to the data for the attribute (inf). 1596ba9413bSMike Smith */ 1606ba9413bSMike Smith caddr_t 161e4f1a52fSPeter Wemm preload_search_info(caddr_t mod, int inf) 1626ba9413bSMike Smith { 1636ba9413bSMike Smith caddr_t curp; 16460ae52f7SEd Schouten uint32_t *hdr; 16560ae52f7SEd Schouten uint32_t type = 0; 166e4f1a52fSPeter Wemm int next; 1676ba9413bSMike Smith 168e8234cfeSRoger Pau Monné if (mod == NULL) 169e8234cfeSRoger Pau Monné return (NULL); 170e8234cfeSRoger Pau Monné 1716ba9413bSMike Smith curp = mod; 1726ba9413bSMike Smith for (;;) { 17360ae52f7SEd Schouten hdr = (uint32_t *)curp; 1746ba9413bSMike Smith /* end of module data? */ 175e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 1766ba9413bSMike Smith break; 1776ba9413bSMike Smith /* 1786ba9413bSMike Smith * We give up once we've looped back to what we were looking at 1796ba9413bSMike Smith * first - this should normally be a MODINFO_NAME field. 1806ba9413bSMike Smith */ 1816ba9413bSMike Smith if (type == 0) { 1826ba9413bSMike Smith type = hdr[0]; 1836ba9413bSMike Smith } else { 1846ba9413bSMike Smith if (hdr[0] == type) 1856ba9413bSMike Smith break; 1866ba9413bSMike Smith } 1876ba9413bSMike Smith 1886ba9413bSMike Smith /* 1896ba9413bSMike Smith * Attribute match? Return pointer to data. 190d7d97eb0SJeroen Ruigrok van der Werven * Consumer may safely assume that size value precedes 1916ba9413bSMike Smith * data. 1926ba9413bSMike Smith */ 1936ba9413bSMike Smith if (hdr[0] == inf) 19460ae52f7SEd Schouten return(curp + (sizeof(uint32_t) * 2)); 1956ba9413bSMike Smith 1966ba9413bSMike Smith /* skip to next field */ 19760ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1982a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 199e4f1a52fSPeter Wemm curp += next; 2006ba9413bSMike Smith } 2016ba9413bSMike Smith return(NULL); 2026ba9413bSMike Smith } 2036ba9413bSMike Smith 204e4f1a52fSPeter Wemm /* 205e4f1a52fSPeter Wemm * Delete a preload record by name. 206e4f1a52fSPeter Wemm */ 207e4f1a52fSPeter Wemm void 208e4f1a52fSPeter Wemm preload_delete_name(const char *name) 209e4f1a52fSPeter Wemm { 210483f692eSMark Johnston caddr_t addr, curp; 211483f692eSMark Johnston uint32_t *hdr, sz; 212e4f1a52fSPeter Wemm int next; 213e4f1a52fSPeter Wemm int clearing; 214e4f1a52fSPeter Wemm 215483f692eSMark Johnston addr = 0; 216483f692eSMark Johnston sz = 0; 217483f692eSMark Johnston 218e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 219e4f1a52fSPeter Wemm clearing = 0; 220e4f1a52fSPeter Wemm curp = preload_metadata; 221e4f1a52fSPeter Wemm for (;;) { 22260ae52f7SEd Schouten hdr = (uint32_t *)curp; 223483f692eSMark Johnston if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) { 224483f692eSMark Johnston /* Free memory used to store the file. */ 225483f692eSMark Johnston if (addr != 0 && sz != 0) 226483f692eSMark Johnston kmem_bootstrap_free((vm_offset_t)addr, sz); 227483f692eSMark Johnston addr = 0; 228483f692eSMark Johnston sz = 0; 229e4f1a52fSPeter Wemm 230483f692eSMark Johnston if (hdr[0] == 0) 231483f692eSMark Johnston break; 23260ae52f7SEd Schouten if (!strcmp(name, curp + sizeof(uint32_t) * 2)) 233e4f1a52fSPeter Wemm clearing = 1; /* got it, start clearing */ 234483f692eSMark Johnston else if (clearing) { 235e4f1a52fSPeter Wemm clearing = 0; /* at next one now.. better stop */ 236e4f1a52fSPeter Wemm } 237483f692eSMark Johnston } 238483f692eSMark Johnston if (clearing) { 239483f692eSMark Johnston if (hdr[0] == MODINFO_ADDR) 240483f692eSMark Johnston addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2); 241483f692eSMark Johnston else if (hdr[0] == MODINFO_SIZE) 242483f692eSMark Johnston sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2); 243e4f1a52fSPeter Wemm hdr[0] = MODINFO_EMPTY; 244483f692eSMark Johnston } 245e4f1a52fSPeter Wemm 246e4f1a52fSPeter Wemm /* skip to next field */ 24760ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 2482a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 249e4f1a52fSPeter Wemm curp += next; 250e4f1a52fSPeter Wemm } 251e4f1a52fSPeter Wemm } 252e4f1a52fSPeter Wemm } 253e4f1a52fSPeter Wemm 254278e7970SMarcel Moolenaar void * 255278e7970SMarcel Moolenaar preload_fetch_addr(caddr_t mod) 256278e7970SMarcel Moolenaar { 257278e7970SMarcel Moolenaar caddr_t *mdp; 258278e7970SMarcel Moolenaar 259278e7970SMarcel Moolenaar mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR); 260278e7970SMarcel Moolenaar if (mdp == NULL) 261278e7970SMarcel Moolenaar return (NULL); 262278e7970SMarcel Moolenaar return (*mdp + preload_addr_relocate); 263278e7970SMarcel Moolenaar } 264278e7970SMarcel Moolenaar 265278e7970SMarcel Moolenaar size_t 266278e7970SMarcel Moolenaar preload_fetch_size(caddr_t mod) 267278e7970SMarcel Moolenaar { 268278e7970SMarcel Moolenaar size_t *mdp; 269278e7970SMarcel Moolenaar 270278e7970SMarcel Moolenaar mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE); 271278e7970SMarcel Moolenaar if (mdp == NULL) 272278e7970SMarcel Moolenaar return (0); 273278e7970SMarcel Moolenaar return (*mdp); 274278e7970SMarcel Moolenaar } 275278e7970SMarcel Moolenaar 27612d7eaa0SWarner Losh /* Called from locore. Convert physical pointers to kvm. Sigh. */ 277e4f1a52fSPeter Wemm void 278e4f1a52fSPeter Wemm preload_bootstrap_relocate(vm_offset_t offset) 279e4f1a52fSPeter Wemm { 280e4f1a52fSPeter Wemm caddr_t curp; 28160ae52f7SEd Schouten uint32_t *hdr; 282e4f1a52fSPeter Wemm vm_offset_t *ptr; 283e4f1a52fSPeter Wemm int next; 284e4f1a52fSPeter Wemm 285e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 286e4f1a52fSPeter Wemm curp = preload_metadata; 287e4f1a52fSPeter Wemm for (;;) { 28860ae52f7SEd Schouten hdr = (uint32_t *)curp; 289e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 290e4f1a52fSPeter Wemm break; 291e4f1a52fSPeter Wemm 2922da2eeacSPeter Wemm /* Deal with the ones that we know we have to fix */ 2932da2eeacSPeter Wemm switch (hdr[0]) { 2942da2eeacSPeter Wemm case MODINFO_ADDR: 29593b18e37SToomas Soome case MODINFO_METADATA|MODINFOMD_FONT: 296*966e53a4SEmmanuel Vadot case MODINFO_METADATA|MODINFOMD_SPLASH: 2972da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_SSYM: 2982da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_ESYM: 29960ae52f7SEd Schouten ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2)); 300e4f1a52fSPeter Wemm *ptr += offset; 3012da2eeacSPeter Wemm break; 302e4f1a52fSPeter Wemm } 303e4f1a52fSPeter Wemm /* The rest is beyond us for now */ 304e4f1a52fSPeter Wemm 305e4f1a52fSPeter Wemm /* skip to next field */ 30660ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 3072a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 308e4f1a52fSPeter Wemm curp += next; 309e4f1a52fSPeter Wemm } 310e4f1a52fSPeter Wemm } 311e4f1a52fSPeter Wemm } 31222e6a670SMitchell Horne 31322e6a670SMitchell Horne /* 31422e6a670SMitchell Horne * Parse the modinfo type and append to the provided sbuf. 31522e6a670SMitchell Horne */ 31622e6a670SMitchell Horne static void 31722e6a670SMitchell Horne preload_modinfo_type(struct sbuf *sbp, int type) 31822e6a670SMitchell Horne { 31922e6a670SMitchell Horne 32022e6a670SMitchell Horne if ((type & MODINFO_METADATA) == 0) { 32122e6a670SMitchell Horne switch (type) { 32222e6a670SMitchell Horne case MODINFO_END: 32322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_END"); 32422e6a670SMitchell Horne break; 32522e6a670SMitchell Horne case MODINFO_NAME: 32622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_NAME"); 32722e6a670SMitchell Horne break; 32822e6a670SMitchell Horne case MODINFO_TYPE: 32922e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_TYPE"); 33022e6a670SMitchell Horne break; 33122e6a670SMitchell Horne case MODINFO_ADDR: 33222e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ADDR"); 33322e6a670SMitchell Horne break; 33422e6a670SMitchell Horne case MODINFO_SIZE: 33522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_SIZE"); 33622e6a670SMitchell Horne break; 33722e6a670SMitchell Horne case MODINFO_EMPTY: 33822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_EMPTY"); 33922e6a670SMitchell Horne break; 34022e6a670SMitchell Horne case MODINFO_ARGS: 34122e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ARGS"); 34222e6a670SMitchell Horne break; 34322e6a670SMitchell Horne default: 34422e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized modinfo attribute"); 34522e6a670SMitchell Horne } 34622e6a670SMitchell Horne 34722e6a670SMitchell Horne return; 34822e6a670SMitchell Horne } 34922e6a670SMitchell Horne 35022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_METADATA | "); 35122e6a670SMitchell Horne switch (type & ~MODINFO_METADATA) { 35222e6a670SMitchell Horne case MODINFOMD_ELFHDR: 35322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ELFHDR"); 35422e6a670SMitchell Horne break; 35522e6a670SMitchell Horne case MODINFOMD_SSYM: 35622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SSYM"); 35722e6a670SMitchell Horne break; 35822e6a670SMitchell Horne case MODINFOMD_ESYM: 35922e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ESYM"); 36022e6a670SMitchell Horne break; 36122e6a670SMitchell Horne case MODINFOMD_DYNAMIC: 36222e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DYNAMIC"); 36322e6a670SMitchell Horne break; 36422e6a670SMitchell Horne case MODINFOMD_ENVP: 36522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ENVP"); 36622e6a670SMitchell Horne break; 36722e6a670SMitchell Horne case MODINFOMD_HOWTO: 36822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_HOWTO"); 36922e6a670SMitchell Horne break; 37022e6a670SMitchell Horne case MODINFOMD_KERNEND: 37122e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KERNEND"); 37222e6a670SMitchell Horne break; 37322e6a670SMitchell Horne case MODINFOMD_SHDR: 37422e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SHDR"); 37522e6a670SMitchell Horne break; 37622e6a670SMitchell Horne case MODINFOMD_CTORS_ADDR: 37722e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR"); 37822e6a670SMitchell Horne break; 37922e6a670SMitchell Horne case MODINFOMD_CTORS_SIZE: 38022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE"); 38122e6a670SMitchell Horne break; 38222e6a670SMitchell Horne case MODINFOMD_FW_HANDLE: 38322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_FW_HANDLE"); 38422e6a670SMitchell Horne break; 38522e6a670SMitchell Horne case MODINFOMD_KEYBUF: 38622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KEYBUF"); 38722e6a670SMitchell Horne break; 38822e6a670SMitchell Horne #ifdef MODINFOMD_SMAP 38922e6a670SMitchell Horne case MODINFOMD_SMAP: 39022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP"); 39122e6a670SMitchell Horne break; 39222e6a670SMitchell Horne #endif 39322e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR 39422e6a670SMitchell Horne case MODINFOMD_SMAP_XATTR: 39522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR"); 39622e6a670SMitchell Horne break; 39722e6a670SMitchell Horne #endif 39822e6a670SMitchell Horne #ifdef MODINFOMD_DTBP 39922e6a670SMitchell Horne case MODINFOMD_DTBP: 40022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DTBP"); 40122e6a670SMitchell Horne break; 40222e6a670SMitchell Horne #endif 40322e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP 40422e6a670SMitchell Horne case MODINFOMD_EFI_MAP: 40522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_MAP"); 40622e6a670SMitchell Horne break; 40722e6a670SMitchell Horne #endif 40822e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB 40922e6a670SMitchell Horne case MODINFOMD_EFI_FB: 41022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_FB"); 41122e6a670SMitchell Horne break; 41222e6a670SMitchell Horne #endif 41322e6a670SMitchell Horne #ifdef MODINFOMD_MODULEP 41422e6a670SMitchell Horne case MODINFOMD_MODULEP: 41522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_MODULEP"); 41622e6a670SMitchell Horne break; 41722e6a670SMitchell Horne #endif 418a4a10b37SToomas Soome #ifdef MODINFOMD_VBE_FB 419a4a10b37SToomas Soome case MODINFOMD_VBE_FB: 420a4a10b37SToomas Soome sbuf_cat(sbp, "MODINFOMD_VBE_FB"); 421a4a10b37SToomas Soome break; 422a4a10b37SToomas Soome #endif 423742653ebSToomas Soome #ifdef MODINFOMD_FONT 424742653ebSToomas Soome case MODINFOMD_FONT: 425742653ebSToomas Soome sbuf_cat(sbp, "MODINFOMD_FONT"); 426742653ebSToomas Soome break; 427742653ebSToomas Soome #endif 428*966e53a4SEmmanuel Vadot #ifdef MODINFOMD_SPLASH 429*966e53a4SEmmanuel Vadot case MODINFOMD_SPLASH: 430*966e53a4SEmmanuel Vadot sbuf_cat(sbp, "MODINFOMD_SPLASH"); 431*966e53a4SEmmanuel Vadot break; 432*966e53a4SEmmanuel Vadot #endif 43322e6a670SMitchell Horne default: 43422e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized metadata type"); 43522e6a670SMitchell Horne } 43622e6a670SMitchell Horne } 43722e6a670SMitchell Horne 43822e6a670SMitchell Horne /* 43922e6a670SMitchell Horne * Print the modinfo value, depending on type. 44022e6a670SMitchell Horne */ 44122e6a670SMitchell Horne static void 44222e6a670SMitchell Horne preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len) 44322e6a670SMitchell Horne { 44422e6a670SMitchell Horne #ifdef __LP64__ 44522e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o); 44622e6a670SMitchell Horne #else 44722e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08x", o); 44822e6a670SMitchell Horne #endif 44922e6a670SMitchell Horne 45022e6a670SMitchell Horne switch (type) { 45122e6a670SMitchell Horne case MODINFO_NAME: 45222e6a670SMitchell Horne case MODINFO_TYPE: 45322e6a670SMitchell Horne case MODINFO_ARGS: 45422e6a670SMitchell Horne sbuf_printf(sbp, "%s", (char *)bptr); 45522e6a670SMitchell Horne break; 45622e6a670SMitchell Horne case MODINFO_SIZE: 45722e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_SIZE: 45822e6a670SMitchell Horne sbuf_printf(sbp, "%lu", *(u_long *)bptr); 45922e6a670SMitchell Horne break; 46022e6a670SMitchell Horne case MODINFO_ADDR: 46122e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SSYM: 46222e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ESYM: 46322e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DYNAMIC: 46422e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KERNEND: 46522e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ENVP: 46622e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_ADDR: 46722e6a670SMitchell Horne #ifdef MODINFOMD_SMAP 46822e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP: 46922e6a670SMitchell Horne #endif 47022e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR 47122e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP_XATTR: 47222e6a670SMitchell Horne #endif 47322e6a670SMitchell Horne #ifdef MODINFOMD_DTBP 47422e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DTBP: 47522e6a670SMitchell Horne #endif 47622e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB 47722e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_FB: 47822e6a670SMitchell Horne #endif 479a4a10b37SToomas Soome #ifdef MODINFOMD_VBE_FB 480a4a10b37SToomas Soome case MODINFO_METADATA | MODINFOMD_VBE_FB: 481a4a10b37SToomas Soome #endif 482742653ebSToomas Soome #ifdef MODINFOMD_FONT 483742653ebSToomas Soome case MODINFO_METADATA | MODINFOMD_FONT: 484742653ebSToomas Soome #endif 485*966e53a4SEmmanuel Vadot #ifdef MODINFOMD_SPLASH 486*966e53a4SEmmanuel Vadot case MODINFO_METADATA | MODINFOMD_SPLASH: 487*966e53a4SEmmanuel Vadot #endif 48822e6a670SMitchell Horne sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr); 48922e6a670SMitchell Horne break; 49022e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_HOWTO: 49122e6a670SMitchell Horne sbuf_printf(sbp, "0x%08x", *bptr); 49222e6a670SMitchell Horne break; 49322e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SHDR: 49422e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ELFHDR: 49522e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_FW_HANDLE: 49622e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KEYBUF: 49722e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP 49822e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_MAP: 49922e6a670SMitchell Horne #endif 50022e6a670SMitchell Horne /* Don't print data buffers. */ 50122e6a670SMitchell Horne sbuf_cat(sbp, "buffer contents omitted"); 50222e6a670SMitchell Horne break; 50322e6a670SMitchell Horne default: 50422e6a670SMitchell Horne break; 50522e6a670SMitchell Horne } 50622e6a670SMitchell Horne #undef sbuf_print_vmoffset 50722e6a670SMitchell Horne } 50822e6a670SMitchell Horne 50922e6a670SMitchell Horne static void 51022e6a670SMitchell Horne preload_dump_internal(struct sbuf *sbp) 51122e6a670SMitchell Horne { 51222e6a670SMitchell Horne uint32_t *bptr, type, len; 51322e6a670SMitchell Horne 51422e6a670SMitchell Horne KASSERT(preload_metadata != NULL, 51522e6a670SMitchell Horne ("%s called without setting up preload_metadata", __func__)); 51622e6a670SMitchell Horne 51722e6a670SMitchell Horne /* 51822e6a670SMitchell Horne * Iterate through the TLV-encoded sections. 51922e6a670SMitchell Horne */ 52022e6a670SMitchell Horne bptr = (uint32_t *)preload_metadata; 52122e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 522841dad02SMitchell Horne while (bptr[0] != MODINFO_END || bptr[1] != MODINFO_END) { 52322e6a670SMitchell Horne sbuf_printf(sbp, " %p:\n", bptr); 52422e6a670SMitchell Horne type = *bptr++; 52522e6a670SMitchell Horne len = *bptr++; 52622e6a670SMitchell Horne 52722e6a670SMitchell Horne sbuf_printf(sbp, "\ttype:\t(%#04x) ", type); 52822e6a670SMitchell Horne preload_modinfo_type(sbp, type); 52922e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 53022e6a670SMitchell Horne sbuf_printf(sbp, "\tlen:\t%u\n", len); 53122e6a670SMitchell Horne sbuf_cat(sbp, "\tvalue:\t"); 53222e6a670SMitchell Horne preload_modinfo_value(sbp, bptr, type, len); 53322e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 53422e6a670SMitchell Horne 53522e6a670SMitchell Horne bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t); 53622e6a670SMitchell Horne } 53722e6a670SMitchell Horne } 53822e6a670SMitchell Horne 53922e6a670SMitchell Horne /* 54022e6a670SMitchell Horne * Print the preloaded data to the console. Called from the machine-dependent 54122e6a670SMitchell Horne * initialization routines, e.g. hammer_time(). 54222e6a670SMitchell Horne */ 54322e6a670SMitchell Horne void 54422e6a670SMitchell Horne preload_dump(void) 54522e6a670SMitchell Horne { 54622e6a670SMitchell Horne char buf[512]; 54722e6a670SMitchell Horne struct sbuf sb; 54822e6a670SMitchell Horne 54922e6a670SMitchell Horne /* 55022e6a670SMitchell Horne * This function is expected to be called before malloc is available, 55122e6a670SMitchell Horne * so use a static buffer and struct sbuf. 55222e6a670SMitchell Horne */ 55322e6a670SMitchell Horne sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 55422e6a670SMitchell Horne sbuf_set_drain(&sb, sbuf_printf_drain, NULL); 55522e6a670SMitchell Horne preload_dump_internal(&sb); 55622e6a670SMitchell Horne 55722e6a670SMitchell Horne sbuf_finish(&sb); 55822e6a670SMitchell Horne sbuf_delete(&sb); 55922e6a670SMitchell Horne } 56022e6a670SMitchell Horne 56122e6a670SMitchell Horne static int 56222e6a670SMitchell Horne sysctl_preload_dump(SYSCTL_HANDLER_ARGS) 56322e6a670SMitchell Horne { 56422e6a670SMitchell Horne struct sbuf sb; 56522e6a670SMitchell Horne int error; 56622e6a670SMitchell Horne 56722e6a670SMitchell Horne if (preload_metadata == NULL) 56822e6a670SMitchell Horne return (EINVAL); 56922e6a670SMitchell Horne 57022e6a670SMitchell Horne sbuf_new_for_sysctl(&sb, NULL, 512, req); 57122e6a670SMitchell Horne preload_dump_internal(&sb); 57222e6a670SMitchell Horne 57322e6a670SMitchell Horne error = sbuf_finish(&sb); 57422e6a670SMitchell Horne sbuf_delete(&sb); 57522e6a670SMitchell Horne 57622e6a670SMitchell Horne return (error); 57722e6a670SMitchell Horne } 57822e6a670SMitchell Horne SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo, 57922e6a670SMitchell Horne CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 58022e6a670SMitchell Horne NULL, 0, sysctl_preload_dump, "A", 58122e6a670SMitchell Horne "pretty-print the bootloader metadata"); 582