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