xref: /freebsd/sys/kern/subr_module.c (revision 4d213c595ac3247a85cea5d3ea521db14151a427)
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