1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 1998 Michael Smith 5 * All rights reserved. 6 * Copyright (c) 2020 NetApp Inc. 7 * Copyright (c) 2020 Klara Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/linker.h> 35 #include <sys/sbuf.h> 36 #include <sys/sysctl.h> 37 38 #include <machine/metadata.h> 39 40 #include <vm/vm.h> 41 #include <vm/vm_extern.h> 42 43 /* 44 * Preloaded module support 45 */ 46 47 vm_offset_t preload_addr_relocate = 0; 48 caddr_t preload_metadata; 49 50 /* 51 * Search for the preloaded module (name) 52 */ 53 caddr_t 54 preload_search_by_name(const char *name) 55 { 56 caddr_t curp; 57 uint32_t *hdr; 58 int next; 59 60 if (preload_metadata != NULL) { 61 curp = preload_metadata; 62 for (;;) { 63 hdr = (uint32_t *)curp; 64 if (hdr[0] == 0 && hdr[1] == 0) 65 break; 66 67 /* Search for a MODINFO_NAME field */ 68 if ((hdr[0] == MODINFO_NAME) && 69 !strcmp(name, curp + sizeof(uint32_t) * 2)) 70 return(curp); 71 72 /* skip to next field */ 73 next = sizeof(uint32_t) * 2 + hdr[1]; 74 next = roundup(next, sizeof(u_long)); 75 curp += next; 76 } 77 } 78 return(NULL); 79 } 80 81 /* 82 * Search for the first preloaded module of (type) 83 */ 84 caddr_t 85 preload_search_by_type(const char *type) 86 { 87 caddr_t curp, lname; 88 uint32_t *hdr; 89 int next; 90 91 if (preload_metadata != NULL) { 92 curp = preload_metadata; 93 lname = NULL; 94 for (;;) { 95 hdr = (uint32_t *)curp; 96 if (hdr[0] == 0 && hdr[1] == 0) 97 break; 98 99 /* remember the start of each record */ 100 if (hdr[0] == MODINFO_NAME) 101 lname = curp; 102 103 /* Search for a MODINFO_TYPE field */ 104 if ((hdr[0] == MODINFO_TYPE) && 105 !strcmp(type, curp + sizeof(uint32_t) * 2)) 106 return(lname); 107 108 /* skip to next field */ 109 next = sizeof(uint32_t) * 2 + hdr[1]; 110 next = roundup(next, sizeof(u_long)); 111 curp += next; 112 } 113 } 114 return(NULL); 115 } 116 117 /* 118 * Walk through the preloaded module list 119 */ 120 caddr_t 121 preload_search_next_name(caddr_t base) 122 { 123 caddr_t curp; 124 uint32_t *hdr; 125 int next; 126 127 if (preload_metadata != NULL) { 128 /* Pick up where we left off last time */ 129 if (base) { 130 /* skip to next field */ 131 curp = base; 132 hdr = (uint32_t *)curp; 133 next = sizeof(uint32_t) * 2 + hdr[1]; 134 next = roundup(next, sizeof(u_long)); 135 curp += next; 136 } else 137 curp = preload_metadata; 138 139 for (;;) { 140 hdr = (uint32_t *)curp; 141 if (hdr[0] == 0 && hdr[1] == 0) 142 break; 143 144 /* Found a new record? */ 145 if (hdr[0] == MODINFO_NAME) 146 return curp; 147 148 /* skip to next field */ 149 next = sizeof(uint32_t) * 2 + hdr[1]; 150 next = roundup(next, sizeof(u_long)); 151 curp += next; 152 } 153 } 154 return(NULL); 155 } 156 157 /* 158 * Given a preloaded module handle (mod), return a pointer 159 * to the data for the attribute (inf). 160 */ 161 caddr_t 162 preload_search_info(caddr_t mod, int inf) 163 { 164 caddr_t curp; 165 uint32_t *hdr; 166 uint32_t type = 0; 167 int next; 168 169 if (mod == NULL) 170 return (NULL); 171 172 curp = mod; 173 for (;;) { 174 hdr = (uint32_t *)curp; 175 /* end of module data? */ 176 if (hdr[0] == 0 && hdr[1] == 0) 177 break; 178 /* 179 * We give up once we've looped back to what we were looking at 180 * first - this should normally be a MODINFO_NAME field. 181 */ 182 if (type == 0) { 183 type = hdr[0]; 184 } else { 185 if (hdr[0] == type) 186 break; 187 } 188 189 /* 190 * Attribute match? Return pointer to data. 191 * Consumer may safely assume that size value precedes 192 * data. 193 */ 194 if (hdr[0] == inf) 195 return(curp + (sizeof(uint32_t) * 2)); 196 197 /* skip to next field */ 198 next = sizeof(uint32_t) * 2 + hdr[1]; 199 next = roundup(next, sizeof(u_long)); 200 curp += next; 201 } 202 return(NULL); 203 } 204 205 /* 206 * Delete a preload record by name. 207 */ 208 void 209 preload_delete_name(const char *name) 210 { 211 caddr_t addr, curp; 212 uint32_t *hdr, sz; 213 int next; 214 int clearing; 215 216 addr = 0; 217 sz = 0; 218 219 if (preload_metadata != NULL) { 220 clearing = 0; 221 curp = preload_metadata; 222 for (;;) { 223 hdr = (uint32_t *)curp; 224 if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) { 225 /* Free memory used to store the file. */ 226 if (addr != 0 && sz != 0) 227 kmem_bootstrap_free((vm_offset_t)addr, sz); 228 addr = 0; 229 sz = 0; 230 231 if (hdr[0] == 0) 232 break; 233 if (!strcmp(name, curp + sizeof(uint32_t) * 2)) 234 clearing = 1; /* got it, start clearing */ 235 else if (clearing) { 236 clearing = 0; /* at next one now.. better stop */ 237 } 238 } 239 if (clearing) { 240 if (hdr[0] == MODINFO_ADDR) 241 addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2); 242 else if (hdr[0] == MODINFO_SIZE) 243 sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2); 244 hdr[0] = MODINFO_EMPTY; 245 } 246 247 /* skip to next field */ 248 next = sizeof(uint32_t) * 2 + hdr[1]; 249 next = roundup(next, sizeof(u_long)); 250 curp += next; 251 } 252 } 253 } 254 255 void * 256 preload_fetch_addr(caddr_t mod) 257 { 258 caddr_t *mdp; 259 260 mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR); 261 if (mdp == NULL) 262 return (NULL); 263 return (*mdp + preload_addr_relocate); 264 } 265 266 size_t 267 preload_fetch_size(caddr_t mod) 268 { 269 size_t *mdp; 270 271 mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE); 272 if (mdp == NULL) 273 return (0); 274 return (*mdp); 275 } 276 277 /* Called from locore. Convert physical pointers to kvm. Sigh. */ 278 void 279 preload_bootstrap_relocate(vm_offset_t offset) 280 { 281 caddr_t curp; 282 uint32_t *hdr; 283 vm_offset_t *ptr; 284 int next; 285 286 if (preload_metadata != NULL) { 287 curp = preload_metadata; 288 for (;;) { 289 hdr = (uint32_t *)curp; 290 if (hdr[0] == 0 && hdr[1] == 0) 291 break; 292 293 /* Deal with the ones that we know we have to fix */ 294 switch (hdr[0]) { 295 case MODINFO_ADDR: 296 case MODINFO_METADATA|MODINFOMD_FONT: 297 case MODINFO_METADATA|MODINFOMD_SPLASH: 298 case MODINFO_METADATA|MODINFOMD_SSYM: 299 case MODINFO_METADATA|MODINFOMD_ESYM: 300 ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2)); 301 *ptr += offset; 302 break; 303 } 304 /* The rest is beyond us for now */ 305 306 /* skip to next field */ 307 next = sizeof(uint32_t) * 2 + hdr[1]; 308 next = roundup(next, sizeof(u_long)); 309 curp += next; 310 } 311 } 312 } 313 314 /* 315 * Parse the modinfo type and append to the provided sbuf. 316 */ 317 static void 318 preload_modinfo_type(struct sbuf *sbp, int type) 319 { 320 321 if ((type & MODINFO_METADATA) == 0) { 322 switch (type) { 323 case MODINFO_END: 324 sbuf_cat(sbp, "MODINFO_END"); 325 break; 326 case MODINFO_NAME: 327 sbuf_cat(sbp, "MODINFO_NAME"); 328 break; 329 case MODINFO_TYPE: 330 sbuf_cat(sbp, "MODINFO_TYPE"); 331 break; 332 case MODINFO_ADDR: 333 sbuf_cat(sbp, "MODINFO_ADDR"); 334 break; 335 case MODINFO_SIZE: 336 sbuf_cat(sbp, "MODINFO_SIZE"); 337 break; 338 case MODINFO_EMPTY: 339 sbuf_cat(sbp, "MODINFO_EMPTY"); 340 break; 341 case MODINFO_ARGS: 342 sbuf_cat(sbp, "MODINFO_ARGS"); 343 break; 344 default: 345 sbuf_cat(sbp, "unrecognized modinfo attribute"); 346 } 347 348 return; 349 } 350 351 sbuf_cat(sbp, "MODINFO_METADATA | "); 352 switch (type & ~MODINFO_METADATA) { 353 case MODINFOMD_ELFHDR: 354 sbuf_cat(sbp, "MODINFOMD_ELFHDR"); 355 break; 356 case MODINFOMD_SSYM: 357 sbuf_cat(sbp, "MODINFOMD_SSYM"); 358 break; 359 case MODINFOMD_ESYM: 360 sbuf_cat(sbp, "MODINFOMD_ESYM"); 361 break; 362 case MODINFOMD_DYNAMIC: 363 sbuf_cat(sbp, "MODINFOMD_DYNAMIC"); 364 break; 365 case MODINFOMD_ENVP: 366 sbuf_cat(sbp, "MODINFOMD_ENVP"); 367 break; 368 case MODINFOMD_HOWTO: 369 sbuf_cat(sbp, "MODINFOMD_HOWTO"); 370 break; 371 case MODINFOMD_KERNEND: 372 sbuf_cat(sbp, "MODINFOMD_KERNEND"); 373 break; 374 case MODINFOMD_SHDR: 375 sbuf_cat(sbp, "MODINFOMD_SHDR"); 376 break; 377 case MODINFOMD_CTORS_ADDR: 378 sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR"); 379 break; 380 case MODINFOMD_CTORS_SIZE: 381 sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE"); 382 break; 383 case MODINFOMD_FW_HANDLE: 384 sbuf_cat(sbp, "MODINFOMD_FW_HANDLE"); 385 break; 386 case MODINFOMD_KEYBUF: 387 sbuf_cat(sbp, "MODINFOMD_KEYBUF"); 388 break; 389 #ifdef MODINFOMD_SMAP 390 case MODINFOMD_SMAP: 391 sbuf_cat(sbp, "MODINFOMD_SMAP"); 392 break; 393 #endif 394 #ifdef MODINFOMD_SMAP_XATTR 395 case MODINFOMD_SMAP_XATTR: 396 sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR"); 397 break; 398 #endif 399 #ifdef MODINFOMD_DTBP 400 case MODINFOMD_DTBP: 401 sbuf_cat(sbp, "MODINFOMD_DTBP"); 402 break; 403 #endif 404 #ifdef MODINFOMD_EFI_MAP 405 case MODINFOMD_EFI_MAP: 406 sbuf_cat(sbp, "MODINFOMD_EFI_MAP"); 407 break; 408 #endif 409 #ifdef MODINFOMD_EFI_FB 410 case MODINFOMD_EFI_FB: 411 sbuf_cat(sbp, "MODINFOMD_EFI_FB"); 412 break; 413 #endif 414 #ifdef MODINFOMD_MODULEP 415 case MODINFOMD_MODULEP: 416 sbuf_cat(sbp, "MODINFOMD_MODULEP"); 417 break; 418 #endif 419 #ifdef MODINFOMD_VBE_FB 420 case MODINFOMD_VBE_FB: 421 sbuf_cat(sbp, "MODINFOMD_VBE_FB"); 422 break; 423 #endif 424 #ifdef MODINFOMD_FONT 425 case MODINFOMD_FONT: 426 sbuf_cat(sbp, "MODINFOMD_FONT"); 427 break; 428 #endif 429 #ifdef MODINFOMD_SPLASH 430 case MODINFOMD_SPLASH: 431 sbuf_cat(sbp, "MODINFOMD_SPLASH"); 432 break; 433 #endif 434 default: 435 sbuf_cat(sbp, "unrecognized metadata type"); 436 } 437 } 438 439 /* 440 * Print the modinfo value, depending on type. 441 */ 442 static void 443 preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len) 444 { 445 #ifdef __LP64__ 446 #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o); 447 #else 448 #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08x", o); 449 #endif 450 451 switch (type) { 452 case MODINFO_NAME: 453 case MODINFO_TYPE: 454 case MODINFO_ARGS: 455 sbuf_printf(sbp, "%s", (char *)bptr); 456 break; 457 case MODINFO_SIZE: 458 case MODINFO_METADATA | MODINFOMD_CTORS_SIZE: 459 sbuf_printf(sbp, "%lu", *(u_long *)bptr); 460 break; 461 case MODINFO_ADDR: 462 case MODINFO_METADATA | MODINFOMD_SSYM: 463 case MODINFO_METADATA | MODINFOMD_ESYM: 464 case MODINFO_METADATA | MODINFOMD_DYNAMIC: 465 case MODINFO_METADATA | MODINFOMD_KERNEND: 466 case MODINFO_METADATA | MODINFOMD_ENVP: 467 case MODINFO_METADATA | MODINFOMD_CTORS_ADDR: 468 #ifdef MODINFOMD_SMAP 469 case MODINFO_METADATA | MODINFOMD_SMAP: 470 #endif 471 #ifdef MODINFOMD_SMAP_XATTR 472 case MODINFO_METADATA | MODINFOMD_SMAP_XATTR: 473 #endif 474 #ifdef MODINFOMD_DTBP 475 case MODINFO_METADATA | MODINFOMD_DTBP: 476 #endif 477 #ifdef MODINFOMD_EFI_FB 478 case MODINFO_METADATA | MODINFOMD_EFI_FB: 479 #endif 480 #ifdef MODINFOMD_VBE_FB 481 case MODINFO_METADATA | MODINFOMD_VBE_FB: 482 #endif 483 #ifdef MODINFOMD_FONT 484 case MODINFO_METADATA | MODINFOMD_FONT: 485 #endif 486 #ifdef MODINFOMD_SPLASH 487 case MODINFO_METADATA | MODINFOMD_SPLASH: 488 #endif 489 sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr); 490 break; 491 case MODINFO_METADATA | MODINFOMD_HOWTO: 492 sbuf_printf(sbp, "0x%08x", *bptr); 493 break; 494 case MODINFO_METADATA | MODINFOMD_SHDR: 495 case MODINFO_METADATA | MODINFOMD_ELFHDR: 496 case MODINFO_METADATA | MODINFOMD_FW_HANDLE: 497 case MODINFO_METADATA | MODINFOMD_KEYBUF: 498 #ifdef MODINFOMD_EFI_MAP 499 case MODINFO_METADATA | MODINFOMD_EFI_MAP: 500 #endif 501 /* Don't print data buffers. */ 502 sbuf_cat(sbp, "buffer contents omitted"); 503 break; 504 default: 505 break; 506 } 507 #undef sbuf_print_vmoffset 508 } 509 510 static void 511 preload_dump_internal(struct sbuf *sbp) 512 { 513 uint32_t *bptr, type, len; 514 515 KASSERT(preload_metadata != NULL, 516 ("%s called without setting up preload_metadata", __func__)); 517 518 /* 519 * Iterate through the TLV-encoded sections. 520 */ 521 bptr = (uint32_t *)preload_metadata; 522 sbuf_putc(sbp, '\n'); 523 while (bptr[0] != MODINFO_END || bptr[1] != MODINFO_END) { 524 sbuf_printf(sbp, " %p:\n", bptr); 525 type = *bptr++; 526 len = *bptr++; 527 528 sbuf_printf(sbp, "\ttype:\t(%#04x) ", type); 529 preload_modinfo_type(sbp, type); 530 sbuf_putc(sbp, '\n'); 531 sbuf_printf(sbp, "\tlen:\t%u\n", len); 532 sbuf_cat(sbp, "\tvalue:\t"); 533 preload_modinfo_value(sbp, bptr, type, len); 534 sbuf_putc(sbp, '\n'); 535 536 bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t); 537 } 538 } 539 540 /* 541 * Print the preloaded data to the console. Called from the machine-dependent 542 * initialization routines, e.g. hammer_time(). 543 */ 544 void 545 preload_dump(void) 546 { 547 char buf[512]; 548 struct sbuf sb; 549 550 /* 551 * This function is expected to be called before malloc is available, 552 * so use a static buffer and struct sbuf. 553 */ 554 sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN); 555 sbuf_set_drain(&sb, sbuf_printf_drain, NULL); 556 preload_dump_internal(&sb); 557 558 sbuf_finish(&sb); 559 sbuf_delete(&sb); 560 } 561 562 static int 563 sysctl_preload_dump(SYSCTL_HANDLER_ARGS) 564 { 565 struct sbuf sb; 566 int error; 567 568 if (preload_metadata == NULL) 569 return (EINVAL); 570 571 sbuf_new_for_sysctl(&sb, NULL, 512, req); 572 preload_dump_internal(&sb); 573 574 error = sbuf_finish(&sb); 575 sbuf_delete(&sb); 576 577 return (error); 578 } 579 SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo, 580 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 581 NULL, 0, sysctl_preload_dump, "A", 582 "pretty-print the bootloader metadata"); 583