]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/subr_module.c
vn_copy_file_range(): find write vnodes on which to call the VOP
[FreeBSD/FreeBSD.git] / sys / kern / subr_module.c
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 <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/linker.h>
35 #include <sys/sbuf.h>
36 #include <sys/sysctl.h>
37
38 #include <machine/metadata.h>
39
40 #include <vm/vm.h>
41 #include <vm/vm_extern.h>
42
43 /*
44  * Preloaded module support
45  */
46
47 vm_offset_t preload_addr_relocate = 0;
48 caddr_t preload_metadata;
49
50 /*
51  * Search for the preloaded module (name)
52  */
53 caddr_t
54 preload_search_by_name(const char *name)
55 {
56     caddr_t     curp;
57     uint32_t    *hdr;
58     int         next;
59     
60     if (preload_metadata != NULL) {
61         curp = preload_metadata;
62         for (;;) {
63             hdr = (uint32_t *)curp;
64             if (hdr[0] == 0 && hdr[1] == 0)
65                 break;
66
67             /* Search for a MODINFO_NAME field */
68             if ((hdr[0] == MODINFO_NAME) &&
69                 !strcmp(name, curp + sizeof(uint32_t) * 2))
70                 return(curp);
71
72             /* skip to next field */
73             next = sizeof(uint32_t) * 2 + hdr[1];
74             next = roundup(next, sizeof(u_long));
75             curp += next;
76         }
77     }
78     return(NULL);
79 }
80
81 /*
82  * Search for the first preloaded module of (type)
83  */
84 caddr_t
85 preload_search_by_type(const char *type)
86 {
87     caddr_t     curp, lname;
88     uint32_t    *hdr;
89     int         next;
90
91     if (preload_metadata != NULL) {
92         curp = preload_metadata;
93         lname = NULL;
94         for (;;) {
95             hdr = (uint32_t *)curp;
96             if (hdr[0] == 0 && hdr[1] == 0)
97                 break;
98
99             /* remember the start of each record */
100             if (hdr[0] == MODINFO_NAME)
101                 lname = curp;
102
103             /* Search for a MODINFO_TYPE field */
104             if ((hdr[0] == MODINFO_TYPE) &&
105                 !strcmp(type, curp + sizeof(uint32_t) * 2))
106                 return(lname);
107
108             /* skip to next field */
109             next = sizeof(uint32_t) * 2 + hdr[1];
110             next = roundup(next, sizeof(u_long));
111             curp += next;
112         }
113     }
114     return(NULL);
115 }
116
117 /*
118  * Walk through the preloaded module list
119  */
120 caddr_t
121 preload_search_next_name(caddr_t base)
122 {
123     caddr_t     curp;
124     uint32_t    *hdr;
125     int         next;
126     
127     if (preload_metadata != NULL) {
128         /* Pick up where we left off last time */
129         if (base) {
130             /* skip to next field */
131             curp = base;
132             hdr = (uint32_t *)curp;
133             next = sizeof(uint32_t) * 2 + hdr[1];
134             next = roundup(next, sizeof(u_long));
135             curp += next;
136         } else
137             curp = preload_metadata;
138
139         for (;;) {
140             hdr = (uint32_t *)curp;
141             if (hdr[0] == 0 && hdr[1] == 0)
142                 break;
143
144             /* Found a new record? */
145             if (hdr[0] == MODINFO_NAME)
146                 return curp;
147
148             /* skip to next field */
149             next = sizeof(uint32_t) * 2 + hdr[1];
150             next = roundup(next, sizeof(u_long));
151             curp += next;
152         }
153     }
154     return(NULL);
155 }
156
157 /*
158  * Given a preloaded module handle (mod), return a pointer
159  * to the data for the attribute (inf).
160  */
161 caddr_t
162 preload_search_info(caddr_t mod, int inf)
163 {
164     caddr_t     curp;
165     uint32_t    *hdr;
166     uint32_t    type = 0;
167     int         next;
168
169     if (mod == NULL)
170         return (NULL);
171
172     curp = mod;
173     for (;;) {
174         hdr = (uint32_t *)curp;
175         /* end of module data? */
176         if (hdr[0] == 0 && hdr[1] == 0)
177             break;
178         /* 
179          * We give up once we've looped back to what we were looking at 
180          * first - this should normally be a MODINFO_NAME field.
181          */
182         if (type == 0) {
183             type = hdr[0];
184         } else {
185             if (hdr[0] == type)
186                 break;
187         }
188
189         /* 
190          * Attribute match? Return pointer to data.
191          * Consumer may safely assume that size value precedes  
192          * data.
193          */
194         if (hdr[0] == inf)
195             return(curp + (sizeof(uint32_t) * 2));
196
197         /* skip to next field */
198         next = sizeof(uint32_t) * 2 + hdr[1];
199         next = roundup(next, sizeof(u_long));
200         curp += next;
201     }
202     return(NULL);
203 }
204
205 /*
206  * Delete a preload record by name.
207  */
208 void
209 preload_delete_name(const char *name)
210 {
211     caddr_t     addr, curp;
212     uint32_t    *hdr, sz;
213     int         next;
214     int         clearing;
215
216     addr = 0;
217     sz = 0;
218     
219     if (preload_metadata != NULL) {
220         clearing = 0;
221         curp = preload_metadata;
222         for (;;) {
223             hdr = (uint32_t *)curp;
224             if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) {
225                 /* Free memory used to store the file. */
226                 if (addr != 0 && sz != 0)
227                     kmem_bootstrap_free((vm_offset_t)addr, sz);
228                 addr = 0;
229                 sz = 0;
230
231                 if (hdr[0] == 0)
232                     break;
233                 if (!strcmp(name, curp + sizeof(uint32_t) * 2))
234                     clearing = 1;       /* got it, start clearing */
235                 else if (clearing) {
236                     clearing = 0;       /* at next one now.. better stop */
237                 }
238             }
239             if (clearing) {
240                 if (hdr[0] == MODINFO_ADDR)
241                     addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2);
242                 else if (hdr[0] == MODINFO_SIZE)
243                     sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2);
244                 hdr[0] = MODINFO_EMPTY;
245             }
246
247             /* skip to next field */
248             next = sizeof(uint32_t) * 2 + hdr[1];
249             next = roundup(next, sizeof(u_long));
250             curp += next;
251         }
252     }
253 }
254
255 void *
256 preload_fetch_addr(caddr_t mod)
257 {
258         caddr_t *mdp;
259
260         mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR);
261         if (mdp == NULL)
262                 return (NULL);
263         return (*mdp + preload_addr_relocate);
264 }
265
266 size_t
267 preload_fetch_size(caddr_t mod)
268 {
269         size_t *mdp;
270
271         mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE);
272         if (mdp == NULL)
273                 return (0);
274         return (*mdp);
275 }
276
277 /* Called from locore.  Convert physical pointers to kvm. Sigh. */
278 void
279 preload_bootstrap_relocate(vm_offset_t offset)
280 {
281     caddr_t     curp;
282     uint32_t    *hdr;
283     vm_offset_t *ptr;
284     int         next;
285     
286     if (preload_metadata != NULL) {
287         curp = preload_metadata;
288         for (;;) {
289             hdr = (uint32_t *)curp;
290             if (hdr[0] == 0 && hdr[1] == 0)
291                 break;
292
293             /* Deal with the ones that we know we have to fix */
294             switch (hdr[0]) {
295             case MODINFO_ADDR:
296             case MODINFO_METADATA|MODINFOMD_FONT:
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         default:
429                 sbuf_cat(sbp, "unrecognized metadata type");
430         }
431 }
432
433 /*
434  * Print the modinfo value, depending on type.
435  */
436 static void
437 preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len)
438 {
439 #ifdef __LP64__
440 #define sbuf_print_vmoffset(sb, o)      sbuf_printf(sb, "0x%016lx", o);
441 #else
442 #define sbuf_print_vmoffset(sb, o)      sbuf_printf(sb, "0x%08x", o);
443 #endif
444
445         switch (type) {
446         case MODINFO_NAME:
447         case MODINFO_TYPE:
448         case MODINFO_ARGS:
449                 sbuf_printf(sbp, "%s", (char *)bptr);
450                 break;
451         case MODINFO_SIZE:
452         case MODINFO_METADATA | MODINFOMD_CTORS_SIZE:
453                 sbuf_printf(sbp, "%lu", *(u_long *)bptr);
454                 break;
455         case MODINFO_ADDR:
456         case MODINFO_METADATA | MODINFOMD_SSYM:
457         case MODINFO_METADATA | MODINFOMD_ESYM:
458         case MODINFO_METADATA | MODINFOMD_DYNAMIC:
459         case MODINFO_METADATA | MODINFOMD_KERNEND:
460         case MODINFO_METADATA | MODINFOMD_ENVP:
461         case MODINFO_METADATA | MODINFOMD_CTORS_ADDR:
462 #ifdef MODINFOMD_SMAP
463         case MODINFO_METADATA | MODINFOMD_SMAP:
464 #endif
465 #ifdef MODINFOMD_SMAP_XATTR
466         case MODINFO_METADATA | MODINFOMD_SMAP_XATTR:
467 #endif
468 #ifdef MODINFOMD_DTBP
469         case MODINFO_METADATA | MODINFOMD_DTBP:
470 #endif
471 #ifdef MODINFOMD_EFI_FB
472         case MODINFO_METADATA | MODINFOMD_EFI_FB:
473 #endif
474 #ifdef MODINFOMD_VBE_FB
475         case MODINFO_METADATA | MODINFOMD_VBE_FB:
476 #endif
477 #ifdef MODINFOMD_FONT
478         case MODINFO_METADATA | MODINFOMD_FONT:
479 #endif
480                 sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr);
481                 break;
482         case MODINFO_METADATA | MODINFOMD_HOWTO:
483                 sbuf_printf(sbp, "0x%08x", *bptr);
484                 break;
485         case MODINFO_METADATA | MODINFOMD_SHDR:
486         case MODINFO_METADATA | MODINFOMD_ELFHDR:
487         case MODINFO_METADATA | MODINFOMD_FW_HANDLE:
488         case MODINFO_METADATA | MODINFOMD_KEYBUF:
489 #ifdef MODINFOMD_EFI_MAP
490         case MODINFO_METADATA | MODINFOMD_EFI_MAP:
491 #endif
492                 /* Don't print data buffers. */
493                 sbuf_cat(sbp, "buffer contents omitted");
494                 break;
495         default:
496                 break;
497         }
498 #undef sbuf_print_vmoffset
499 }
500
501 static void
502 preload_dump_internal(struct sbuf *sbp)
503 {
504         uint32_t *bptr, type, len;
505
506         KASSERT(preload_metadata != NULL,
507             ("%s called without setting up preload_metadata", __func__));
508
509         /*
510          * Iterate through the TLV-encoded sections.
511          */
512         bptr = (uint32_t *)preload_metadata;
513         sbuf_putc(sbp, '\n');
514         while (bptr[0] != MODINFO_END || bptr[1] != MODINFO_END) {
515                 sbuf_printf(sbp, " %p:\n", bptr);
516                 type = *bptr++;
517                 len = *bptr++;
518
519                 sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
520                 preload_modinfo_type(sbp, type);
521                 sbuf_putc(sbp, '\n');
522                 sbuf_printf(sbp, "\tlen:\t%u\n", len);
523                 sbuf_cat(sbp, "\tvalue:\t");
524                 preload_modinfo_value(sbp, bptr, type, len);
525                 sbuf_putc(sbp, '\n');
526
527                 bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
528         }
529 }
530
531 /*
532  * Print the preloaded data to the console. Called from the machine-dependent
533  * initialization routines, e.g. hammer_time().
534  */
535 void
536 preload_dump(void)
537 {
538         char buf[512];
539         struct sbuf sb;
540
541         /*
542          * This function is expected to be called before malloc is available,
543          * so use a static buffer and struct sbuf.
544          */
545         sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
546         sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
547         preload_dump_internal(&sb);
548
549         sbuf_finish(&sb);
550         sbuf_delete(&sb);
551 }
552
553 static int
554 sysctl_preload_dump(SYSCTL_HANDLER_ARGS)
555 {
556         struct sbuf sb;
557         int error;
558
559         if (preload_metadata == NULL)
560                 return (EINVAL);
561
562         sbuf_new_for_sysctl(&sb, NULL, 512, req);
563         preload_dump_internal(&sb);
564
565         error = sbuf_finish(&sb);
566         sbuf_delete(&sb);
567
568         return (error);
569 }
570 SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo,
571     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
572     NULL, 0, sysctl_preload_dump, "A",
573     "pretty-print the bootloader metadata");