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