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