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