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