16ba9413bSMike Smith /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 38a36da99SPedro F. Giffuni * 46ba9413bSMike Smith * Copyright (c) 1998 Michael Smith 56ba9413bSMike Smith * All rights reserved. 6*22e6a670SMitchell Horne * Copyright (c) 2020 NetApp Inc. 7*22e6a670SMitchell 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 31677b542eSDavid E. O'Brien #include <sys/cdefs.h> 32677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 33677b542eSDavid E. O'Brien 346ba9413bSMike Smith #include <sys/param.h> 356ba9413bSMike Smith #include <sys/systm.h> 366ba9413bSMike Smith #include <sys/linker.h> 37*22e6a670SMitchell Horne #include <sys/sbuf.h> 38*22e6a670SMitchell Horne #include <sys/sysctl.h> 39*22e6a670SMitchell Horne 40*22e6a670SMitchell Horne #include <machine/metadata.h> 416ba9413bSMike Smith 42483f692eSMark Johnston #include <vm/vm.h> 43483f692eSMark Johnston #include <vm/vm_extern.h> 44483f692eSMark Johnston 456ba9413bSMike Smith /* 466ba9413bSMike Smith * Preloaded module support 476ba9413bSMike Smith */ 486ba9413bSMike Smith 49278e7970SMarcel Moolenaar vm_offset_t preload_addr_relocate = 0; 50e4f1a52fSPeter Wemm caddr_t preload_metadata; 516ba9413bSMike Smith 526ba9413bSMike Smith /* 536ba9413bSMike Smith * Search for the preloaded module (name) 546ba9413bSMike Smith */ 556ba9413bSMike Smith caddr_t 56e4f1a52fSPeter Wemm preload_search_by_name(const char *name) 576ba9413bSMike Smith { 586ba9413bSMike Smith caddr_t curp; 5960ae52f7SEd Schouten uint32_t *hdr; 60e4f1a52fSPeter Wemm int next; 616ba9413bSMike Smith 62e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 63e4f1a52fSPeter Wemm curp = preload_metadata; 646ba9413bSMike Smith for (;;) { 6560ae52f7SEd Schouten hdr = (uint32_t *)curp; 66e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 676ba9413bSMike Smith break; 686ba9413bSMike Smith 696ba9413bSMike Smith /* Search for a MODINFO_NAME field */ 706ba9413bSMike Smith if ((hdr[0] == MODINFO_NAME) && 7160ae52f7SEd Schouten !strcmp(name, curp + sizeof(uint32_t) * 2)) 726ba9413bSMike Smith return(curp); 736ba9413bSMike Smith 746ba9413bSMike Smith /* skip to next field */ 7560ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 762a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 77e4f1a52fSPeter Wemm curp += next; 786ba9413bSMike Smith } 796ba9413bSMike Smith } 806ba9413bSMike Smith return(NULL); 816ba9413bSMike Smith } 826ba9413bSMike Smith 836ba9413bSMike Smith /* 846ba9413bSMike Smith * Search for the first preloaded module of (type) 856ba9413bSMike Smith */ 866ba9413bSMike Smith caddr_t 87e4f1a52fSPeter Wemm preload_search_by_type(const char *type) 886ba9413bSMike Smith { 896ba9413bSMike Smith caddr_t curp, lname; 9060ae52f7SEd Schouten uint32_t *hdr; 91e4f1a52fSPeter Wemm int next; 926ba9413bSMike Smith 93e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 94e4f1a52fSPeter Wemm curp = preload_metadata; 956ba9413bSMike Smith lname = NULL; 966ba9413bSMike Smith for (;;) { 9760ae52f7SEd Schouten hdr = (uint32_t *)curp; 98e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 996ba9413bSMike Smith break; 1006ba9413bSMike Smith 1016ba9413bSMike Smith /* remember the start of each record */ 1026ba9413bSMike Smith if (hdr[0] == MODINFO_NAME) 1036ba9413bSMike Smith lname = curp; 1046ba9413bSMike Smith 1056ba9413bSMike Smith /* Search for a MODINFO_TYPE field */ 1066ba9413bSMike Smith if ((hdr[0] == MODINFO_TYPE) && 10760ae52f7SEd Schouten !strcmp(type, curp + sizeof(uint32_t) * 2)) 1086ba9413bSMike Smith return(lname); 1096ba9413bSMike Smith 1106ba9413bSMike Smith /* skip to next field */ 11160ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1122a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 113e4f1a52fSPeter Wemm curp += next; 114e4f1a52fSPeter Wemm } 115e4f1a52fSPeter Wemm } 116e4f1a52fSPeter Wemm return(NULL); 117e4f1a52fSPeter Wemm } 118e4f1a52fSPeter Wemm 119e4f1a52fSPeter Wemm /* 120e4f1a52fSPeter Wemm * Walk through the preloaded module list 121e4f1a52fSPeter Wemm */ 122e4f1a52fSPeter Wemm caddr_t 123e4f1a52fSPeter Wemm preload_search_next_name(caddr_t base) 124e4f1a52fSPeter Wemm { 125e4f1a52fSPeter Wemm caddr_t curp; 12660ae52f7SEd Schouten uint32_t *hdr; 127e4f1a52fSPeter Wemm int next; 128e4f1a52fSPeter Wemm 129e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 130e4f1a52fSPeter Wemm /* Pick up where we left off last time */ 131e4f1a52fSPeter Wemm if (base) { 132e4f1a52fSPeter Wemm /* skip to next field */ 133e4f1a52fSPeter Wemm curp = base; 13460ae52f7SEd Schouten hdr = (uint32_t *)curp; 13560ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1362a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 137e4f1a52fSPeter Wemm curp += next; 138e4f1a52fSPeter Wemm } else 139e4f1a52fSPeter Wemm curp = preload_metadata; 140e4f1a52fSPeter Wemm 141e4f1a52fSPeter Wemm for (;;) { 14260ae52f7SEd Schouten hdr = (uint32_t *)curp; 143e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 144e4f1a52fSPeter Wemm break; 145e4f1a52fSPeter Wemm 146e4f1a52fSPeter Wemm /* Found a new record? */ 147e4f1a52fSPeter Wemm if (hdr[0] == MODINFO_NAME) 148e4f1a52fSPeter Wemm return curp; 149e4f1a52fSPeter Wemm 150e4f1a52fSPeter Wemm /* skip to next field */ 15160ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 1522a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 153e4f1a52fSPeter Wemm curp += next; 1546ba9413bSMike Smith } 1556ba9413bSMike Smith } 1566ba9413bSMike Smith return(NULL); 1576ba9413bSMike Smith } 1586ba9413bSMike Smith 1596ba9413bSMike Smith /* 1606ba9413bSMike Smith * Given a preloaded module handle (mod), return a pointer 1616ba9413bSMike Smith * to the data for the attribute (inf). 1626ba9413bSMike Smith */ 1636ba9413bSMike Smith caddr_t 164e4f1a52fSPeter Wemm preload_search_info(caddr_t mod, int inf) 1656ba9413bSMike Smith { 1666ba9413bSMike Smith caddr_t curp; 16760ae52f7SEd Schouten uint32_t *hdr; 16860ae52f7SEd Schouten uint32_t type = 0; 169e4f1a52fSPeter Wemm int next; 1706ba9413bSMike Smith 171e8234cfeSRoger Pau Monné if (mod == NULL) 172e8234cfeSRoger Pau Monné return (NULL); 173e8234cfeSRoger Pau Monné 1746ba9413bSMike Smith curp = mod; 1756ba9413bSMike Smith for (;;) { 17660ae52f7SEd Schouten hdr = (uint32_t *)curp; 1776ba9413bSMike Smith /* end of module data? */ 178e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 1796ba9413bSMike Smith break; 1806ba9413bSMike Smith /* 1816ba9413bSMike Smith * We give up once we've looped back to what we were looking at 1826ba9413bSMike Smith * first - this should normally be a MODINFO_NAME field. 1836ba9413bSMike Smith */ 1846ba9413bSMike Smith if (type == 0) { 1856ba9413bSMike Smith type = hdr[0]; 1866ba9413bSMike Smith } else { 1876ba9413bSMike Smith if (hdr[0] == type) 1886ba9413bSMike Smith break; 1896ba9413bSMike Smith } 1906ba9413bSMike Smith 1916ba9413bSMike Smith /* 1926ba9413bSMike Smith * Attribute match? Return pointer to data. 193d7d97eb0SJeroen Ruigrok van der Werven * Consumer may safely assume that size value precedes 1946ba9413bSMike Smith * data. 1956ba9413bSMike Smith */ 1966ba9413bSMike Smith if (hdr[0] == inf) 19760ae52f7SEd Schouten return(curp + (sizeof(uint32_t) * 2)); 1986ba9413bSMike Smith 1996ba9413bSMike Smith /* skip to next field */ 20060ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 2012a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 202e4f1a52fSPeter Wemm curp += next; 2036ba9413bSMike Smith } 2046ba9413bSMike Smith return(NULL); 2056ba9413bSMike Smith } 2066ba9413bSMike Smith 207e4f1a52fSPeter Wemm /* 208e4f1a52fSPeter Wemm * Delete a preload record by name. 209e4f1a52fSPeter Wemm */ 210e4f1a52fSPeter Wemm void 211e4f1a52fSPeter Wemm preload_delete_name(const char *name) 212e4f1a52fSPeter Wemm { 213483f692eSMark Johnston caddr_t addr, curp; 214483f692eSMark Johnston uint32_t *hdr, sz; 215e4f1a52fSPeter Wemm int next; 216e4f1a52fSPeter Wemm int clearing; 217e4f1a52fSPeter Wemm 218483f692eSMark Johnston addr = 0; 219483f692eSMark Johnston sz = 0; 220483f692eSMark Johnston 221e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 222e4f1a52fSPeter Wemm clearing = 0; 223e4f1a52fSPeter Wemm curp = preload_metadata; 224e4f1a52fSPeter Wemm for (;;) { 22560ae52f7SEd Schouten hdr = (uint32_t *)curp; 226483f692eSMark Johnston if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) { 227483f692eSMark Johnston /* Free memory used to store the file. */ 228483f692eSMark Johnston if (addr != 0 && sz != 0) 229483f692eSMark Johnston kmem_bootstrap_free((vm_offset_t)addr, sz); 230483f692eSMark Johnston addr = 0; 231483f692eSMark Johnston sz = 0; 232e4f1a52fSPeter Wemm 233483f692eSMark Johnston if (hdr[0] == 0) 234483f692eSMark Johnston break; 23560ae52f7SEd Schouten if (!strcmp(name, curp + sizeof(uint32_t) * 2)) 236e4f1a52fSPeter Wemm clearing = 1; /* got it, start clearing */ 237483f692eSMark Johnston else if (clearing) { 238e4f1a52fSPeter Wemm clearing = 0; /* at next one now.. better stop */ 239e4f1a52fSPeter Wemm } 240483f692eSMark Johnston } 241483f692eSMark Johnston if (clearing) { 242483f692eSMark Johnston if (hdr[0] == MODINFO_ADDR) 243483f692eSMark Johnston addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2); 244483f692eSMark Johnston else if (hdr[0] == MODINFO_SIZE) 245483f692eSMark Johnston sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2); 246e4f1a52fSPeter Wemm hdr[0] = MODINFO_EMPTY; 247483f692eSMark Johnston } 248e4f1a52fSPeter Wemm 249e4f1a52fSPeter Wemm /* skip to next field */ 25060ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 2512a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 252e4f1a52fSPeter Wemm curp += next; 253e4f1a52fSPeter Wemm } 254e4f1a52fSPeter Wemm } 255e4f1a52fSPeter Wemm } 256e4f1a52fSPeter Wemm 257278e7970SMarcel Moolenaar void * 258278e7970SMarcel Moolenaar preload_fetch_addr(caddr_t mod) 259278e7970SMarcel Moolenaar { 260278e7970SMarcel Moolenaar caddr_t *mdp; 261278e7970SMarcel Moolenaar 262278e7970SMarcel Moolenaar mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR); 263278e7970SMarcel Moolenaar if (mdp == NULL) 264278e7970SMarcel Moolenaar return (NULL); 265278e7970SMarcel Moolenaar return (*mdp + preload_addr_relocate); 266278e7970SMarcel Moolenaar } 267278e7970SMarcel Moolenaar 268278e7970SMarcel Moolenaar size_t 269278e7970SMarcel Moolenaar preload_fetch_size(caddr_t mod) 270278e7970SMarcel Moolenaar { 271278e7970SMarcel Moolenaar size_t *mdp; 272278e7970SMarcel Moolenaar 273278e7970SMarcel Moolenaar mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE); 274278e7970SMarcel Moolenaar if (mdp == NULL) 275278e7970SMarcel Moolenaar return (0); 276278e7970SMarcel Moolenaar return (*mdp); 277278e7970SMarcel Moolenaar } 278278e7970SMarcel Moolenaar 27912d7eaa0SWarner Losh /* Called from locore. Convert physical pointers to kvm. Sigh. */ 280e4f1a52fSPeter Wemm void 281e4f1a52fSPeter Wemm preload_bootstrap_relocate(vm_offset_t offset) 282e4f1a52fSPeter Wemm { 283e4f1a52fSPeter Wemm caddr_t curp; 28460ae52f7SEd Schouten uint32_t *hdr; 285e4f1a52fSPeter Wemm vm_offset_t *ptr; 286e4f1a52fSPeter Wemm int next; 287e4f1a52fSPeter Wemm 288e4f1a52fSPeter Wemm if (preload_metadata != NULL) { 289e4f1a52fSPeter Wemm curp = preload_metadata; 290e4f1a52fSPeter Wemm for (;;) { 29160ae52f7SEd Schouten hdr = (uint32_t *)curp; 292e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0) 293e4f1a52fSPeter Wemm break; 294e4f1a52fSPeter Wemm 2952da2eeacSPeter Wemm /* Deal with the ones that we know we have to fix */ 2962da2eeacSPeter Wemm switch (hdr[0]) { 2972da2eeacSPeter Wemm case MODINFO_ADDR: 2982da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_SSYM: 2992da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_ESYM: 30060ae52f7SEd Schouten ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2)); 301e4f1a52fSPeter Wemm *ptr += offset; 3022da2eeacSPeter Wemm break; 303e4f1a52fSPeter Wemm } 304e4f1a52fSPeter Wemm /* The rest is beyond us for now */ 305e4f1a52fSPeter Wemm 306e4f1a52fSPeter Wemm /* skip to next field */ 30760ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1]; 3082a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long)); 309e4f1a52fSPeter Wemm curp += next; 310e4f1a52fSPeter Wemm } 311e4f1a52fSPeter Wemm } 312e4f1a52fSPeter Wemm } 313*22e6a670SMitchell Horne 314*22e6a670SMitchell Horne /* 315*22e6a670SMitchell Horne * Parse the modinfo type and append to the provided sbuf. 316*22e6a670SMitchell Horne */ 317*22e6a670SMitchell Horne static void 318*22e6a670SMitchell Horne preload_modinfo_type(struct sbuf *sbp, int type) 319*22e6a670SMitchell Horne { 320*22e6a670SMitchell Horne 321*22e6a670SMitchell Horne if ((type & MODINFO_METADATA) == 0) { 322*22e6a670SMitchell Horne switch (type) { 323*22e6a670SMitchell Horne case MODINFO_END: 324*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_END"); 325*22e6a670SMitchell Horne break; 326*22e6a670SMitchell Horne case MODINFO_NAME: 327*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_NAME"); 328*22e6a670SMitchell Horne break; 329*22e6a670SMitchell Horne case MODINFO_TYPE: 330*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_TYPE"); 331*22e6a670SMitchell Horne break; 332*22e6a670SMitchell Horne case MODINFO_ADDR: 333*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ADDR"); 334*22e6a670SMitchell Horne break; 335*22e6a670SMitchell Horne case MODINFO_SIZE: 336*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_SIZE"); 337*22e6a670SMitchell Horne break; 338*22e6a670SMitchell Horne case MODINFO_EMPTY: 339*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_EMPTY"); 340*22e6a670SMitchell Horne break; 341*22e6a670SMitchell Horne case MODINFO_ARGS: 342*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ARGS"); 343*22e6a670SMitchell Horne break; 344*22e6a670SMitchell Horne default: 345*22e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized modinfo attribute"); 346*22e6a670SMitchell Horne } 347*22e6a670SMitchell Horne 348*22e6a670SMitchell Horne return; 349*22e6a670SMitchell Horne } 350*22e6a670SMitchell Horne 351*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_METADATA | "); 352*22e6a670SMitchell Horne switch (type & ~MODINFO_METADATA) { 353*22e6a670SMitchell Horne case MODINFOMD_ELFHDR: 354*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ELFHDR"); 355*22e6a670SMitchell Horne break; 356*22e6a670SMitchell Horne case MODINFOMD_SSYM: 357*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SSYM"); 358*22e6a670SMitchell Horne break; 359*22e6a670SMitchell Horne case MODINFOMD_ESYM: 360*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ESYM"); 361*22e6a670SMitchell Horne break; 362*22e6a670SMitchell Horne case MODINFOMD_DYNAMIC: 363*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DYNAMIC"); 364*22e6a670SMitchell Horne break; 365*22e6a670SMitchell Horne case MODINFOMD_ENVP: 366*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ENVP"); 367*22e6a670SMitchell Horne break; 368*22e6a670SMitchell Horne case MODINFOMD_HOWTO: 369*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_HOWTO"); 370*22e6a670SMitchell Horne break; 371*22e6a670SMitchell Horne case MODINFOMD_KERNEND: 372*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KERNEND"); 373*22e6a670SMitchell Horne break; 374*22e6a670SMitchell Horne case MODINFOMD_SHDR: 375*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SHDR"); 376*22e6a670SMitchell Horne break; 377*22e6a670SMitchell Horne case MODINFOMD_CTORS_ADDR: 378*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR"); 379*22e6a670SMitchell Horne break; 380*22e6a670SMitchell Horne case MODINFOMD_CTORS_SIZE: 381*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE"); 382*22e6a670SMitchell Horne break; 383*22e6a670SMitchell Horne case MODINFOMD_FW_HANDLE: 384*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_FW_HANDLE"); 385*22e6a670SMitchell Horne break; 386*22e6a670SMitchell Horne case MODINFOMD_KEYBUF: 387*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KEYBUF"); 388*22e6a670SMitchell Horne break; 389*22e6a670SMitchell Horne #ifdef MODINFOMD_SMAP 390*22e6a670SMitchell Horne case MODINFOMD_SMAP: 391*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP"); 392*22e6a670SMitchell Horne break; 393*22e6a670SMitchell Horne #endif 394*22e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR 395*22e6a670SMitchell Horne case MODINFOMD_SMAP_XATTR: 396*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR"); 397*22e6a670SMitchell Horne break; 398*22e6a670SMitchell Horne #endif 399*22e6a670SMitchell Horne #ifdef MODINFOMD_DTBP 400*22e6a670SMitchell Horne case MODINFOMD_DTBP: 401*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DTBP"); 402*22e6a670SMitchell Horne break; 403*22e6a670SMitchell Horne #endif 404*22e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP 405*22e6a670SMitchell Horne case MODINFOMD_EFI_MAP: 406*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_MAP"); 407*22e6a670SMitchell Horne break; 408*22e6a670SMitchell Horne #endif 409*22e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB 410*22e6a670SMitchell Horne case MODINFOMD_EFI_FB: 411*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_FB"); 412*22e6a670SMitchell Horne break; 413*22e6a670SMitchell Horne #endif 414*22e6a670SMitchell Horne #ifdef MODINFOMD_MODULEP 415*22e6a670SMitchell Horne case MODINFOMD_MODULEP: 416*22e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_MODULEP"); 417*22e6a670SMitchell Horne break; 418*22e6a670SMitchell Horne #endif 419*22e6a670SMitchell Horne default: 420*22e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized metadata type"); 421*22e6a670SMitchell Horne } 422*22e6a670SMitchell Horne } 423*22e6a670SMitchell Horne 424*22e6a670SMitchell Horne /* 425*22e6a670SMitchell Horne * Print the modinfo value, depending on type. 426*22e6a670SMitchell Horne */ 427*22e6a670SMitchell Horne static void 428*22e6a670SMitchell Horne preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len) 429*22e6a670SMitchell Horne { 430*22e6a670SMitchell Horne #ifdef __LP64__ 431*22e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o); 432*22e6a670SMitchell Horne #else 433*22e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08x", o); 434*22e6a670SMitchell Horne #endif 435*22e6a670SMitchell Horne 436*22e6a670SMitchell Horne switch (type) { 437*22e6a670SMitchell Horne case MODINFO_NAME: 438*22e6a670SMitchell Horne case MODINFO_TYPE: 439*22e6a670SMitchell Horne case MODINFO_ARGS: 440*22e6a670SMitchell Horne sbuf_printf(sbp, "%s", (char *)bptr); 441*22e6a670SMitchell Horne break; 442*22e6a670SMitchell Horne case MODINFO_SIZE: 443*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_SIZE: 444*22e6a670SMitchell Horne sbuf_printf(sbp, "%lu", *(u_long *)bptr); 445*22e6a670SMitchell Horne break; 446*22e6a670SMitchell Horne case MODINFO_ADDR: 447*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SSYM: 448*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ESYM: 449*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DYNAMIC: 450*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KERNEND: 451*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ENVP: 452*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_ADDR: 453*22e6a670SMitchell Horne #ifdef MODINFOMD_SMAP 454*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP: 455*22e6a670SMitchell Horne #endif 456*22e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR 457*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP_XATTR: 458*22e6a670SMitchell Horne #endif 459*22e6a670SMitchell Horne #ifdef MODINFOMD_DTBP 460*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DTBP: 461*22e6a670SMitchell Horne #endif 462*22e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB 463*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_FB: 464*22e6a670SMitchell Horne #endif 465*22e6a670SMitchell Horne sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr); 466*22e6a670SMitchell Horne break; 467*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_HOWTO: 468*22e6a670SMitchell Horne sbuf_printf(sbp, "0x%08x", *bptr); 469*22e6a670SMitchell Horne break; 470*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SHDR: 471*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ELFHDR: 472*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_FW_HANDLE: 473*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KEYBUF: 474*22e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP 475*22e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_MAP: 476*22e6a670SMitchell Horne #endif 477*22e6a670SMitchell Horne /* Don't print data buffers. */ 478*22e6a670SMitchell Horne sbuf_cat(sbp, "buffer contents omitted"); 479*22e6a670SMitchell Horne break; 480*22e6a670SMitchell Horne default: 481*22e6a670SMitchell Horne break; 482*22e6a670SMitchell Horne } 483*22e6a670SMitchell Horne #undef sbuf_print_vmoffset 484*22e6a670SMitchell Horne } 485*22e6a670SMitchell Horne 486*22e6a670SMitchell Horne static void 487*22e6a670SMitchell Horne preload_dump_internal(struct sbuf *sbp) 488*22e6a670SMitchell Horne { 489*22e6a670SMitchell Horne uint32_t *bptr, type, len; 490*22e6a670SMitchell Horne 491*22e6a670SMitchell Horne KASSERT(preload_metadata != NULL, 492*22e6a670SMitchell Horne ("%s called without setting up preload_metadata", __func__)); 493*22e6a670SMitchell Horne 494*22e6a670SMitchell Horne /* 495*22e6a670SMitchell Horne * Iterate through the TLV-encoded sections. 496*22e6a670SMitchell Horne */ 497*22e6a670SMitchell Horne bptr = (uint32_t *)preload_metadata; 498*22e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 499*22e6a670SMitchell Horne while (bptr[0] != MODINFO_END || bptr[0] != MODINFO_END) { 500*22e6a670SMitchell Horne sbuf_printf(sbp, " %p:\n", bptr); 501*22e6a670SMitchell Horne type = *bptr++; 502*22e6a670SMitchell Horne len = *bptr++; 503*22e6a670SMitchell Horne 504*22e6a670SMitchell Horne sbuf_printf(sbp, "\ttype:\t(%#04x) ", type); 505*22e6a670SMitchell Horne preload_modinfo_type(sbp, type); 506*22e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 507*22e6a670SMitchell Horne sbuf_printf(sbp, "\tlen:\t%u\n", len); 508*22e6a670SMitchell Horne sbuf_cat(sbp, "\tvalue:\t"); 509*22e6a670SMitchell Horne preload_modinfo_value(sbp, bptr, type, len); 510*22e6a670SMitchell Horne sbuf_putc(sbp, '\n'); 511*22e6a670SMitchell Horne 512*22e6a670SMitchell Horne bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t); 513*22e6a670SMitchell Horne } 514*22e6a670SMitchell Horne } 515*22e6a670SMitchell Horne 516*22e6a670SMitchell Horne /* 517*22e6a670SMitchell Horne * Print the preloaded data to the console. Called from the machine-dependent 518*22e6a670SMitchell Horne * initialization routines, e.g. hammer_time(). 519*22e6a670SMitchell Horne */ 520*22e6a670SMitchell Horne void 521*22e6a670SMitchell Horne preload_dump(void) 522*22e6a670SMitchell Horne { 523*22e6a670SMitchell Horne char buf[512]; 524*22e6a670SMitchell Horne struct sbuf sb; 525*22e6a670SMitchell Horne 526*22e6a670SMitchell Horne /* 527*22e6a670SMitchell Horne * This function is expected to be called before malloc is available, 528*22e6a670SMitchell Horne * so use a static buffer and struct sbuf. 529*22e6a670SMitchell Horne */ 530*22e6a670SMitchell Horne sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 531*22e6a670SMitchell Horne sbuf_set_drain(&sb, sbuf_printf_drain, NULL); 532*22e6a670SMitchell Horne preload_dump_internal(&sb); 533*22e6a670SMitchell Horne 534*22e6a670SMitchell Horne sbuf_finish(&sb); 535*22e6a670SMitchell Horne sbuf_delete(&sb); 536*22e6a670SMitchell Horne } 537*22e6a670SMitchell Horne 538*22e6a670SMitchell Horne static int 539*22e6a670SMitchell Horne sysctl_preload_dump(SYSCTL_HANDLER_ARGS) 540*22e6a670SMitchell Horne { 541*22e6a670SMitchell Horne struct sbuf sb; 542*22e6a670SMitchell Horne int error; 543*22e6a670SMitchell Horne 544*22e6a670SMitchell Horne if (preload_metadata == NULL) 545*22e6a670SMitchell Horne return (EINVAL); 546*22e6a670SMitchell Horne 547*22e6a670SMitchell Horne sbuf_new_for_sysctl(&sb, NULL, 512, req); 548*22e6a670SMitchell Horne preload_dump_internal(&sb); 549*22e6a670SMitchell Horne 550*22e6a670SMitchell Horne error = sbuf_finish(&sb); 551*22e6a670SMitchell Horne sbuf_delete(&sb); 552*22e6a670SMitchell Horne 553*22e6a670SMitchell Horne return (error); 554*22e6a670SMitchell Horne } 555*22e6a670SMitchell Horne SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo, 556*22e6a670SMitchell Horne CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 557*22e6a670SMitchell Horne NULL, 0, sysctl_preload_dump, "A", 558*22e6a670SMitchell Horne "pretty-print the bootloader metadata"); 559