16ba9413bSMike Smith /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni *
46ba9413bSMike Smith * Copyright (c) 1998 Michael Smith
56ba9413bSMike Smith * All rights reserved.
622e6a670SMitchell Horne * Copyright (c) 2020 NetApp Inc.
722e6a670SMitchell Horne * Copyright (c) 2020 Klara Inc.
86ba9413bSMike Smith *
96ba9413bSMike Smith * Redistribution and use in source and binary forms, with or without
106ba9413bSMike Smith * modification, are permitted provided that the following conditions
116ba9413bSMike Smith * are met:
126ba9413bSMike Smith * 1. Redistributions of source code must retain the above copyright
136ba9413bSMike Smith * notice, this list of conditions and the following disclaimer.
146ba9413bSMike Smith * 2. Redistributions in binary form must reproduce the above copyright
156ba9413bSMike Smith * notice, this list of conditions and the following disclaimer in the
166ba9413bSMike Smith * documentation and/or other materials provided with the distribution.
176ba9413bSMike Smith *
186ba9413bSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
196ba9413bSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
206ba9413bSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
216ba9413bSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
226ba9413bSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
236ba9413bSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
246ba9413bSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
256ba9413bSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
266ba9413bSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
276ba9413bSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
286ba9413bSMike Smith * SUCH DAMAGE.
296ba9413bSMike Smith */
306ba9413bSMike Smith
316ba9413bSMike Smith #include <sys/param.h>
326ba9413bSMike Smith #include <sys/systm.h>
336ba9413bSMike Smith #include <sys/linker.h>
3422e6a670SMitchell Horne #include <sys/sbuf.h>
3522e6a670SMitchell Horne #include <sys/sysctl.h>
3622e6a670SMitchell Horne
3722e6a670SMitchell Horne #include <machine/metadata.h>
386ba9413bSMike Smith
39483f692eSMark Johnston #include <vm/vm.h>
40483f692eSMark Johnston #include <vm/vm_extern.h>
41483f692eSMark Johnston
426ba9413bSMike Smith /*
436ba9413bSMike Smith * Preloaded module support
446ba9413bSMike Smith */
456ba9413bSMike Smith
46278e7970SMarcel Moolenaar vm_offset_t preload_addr_relocate = 0;
47b72ae900SAhmad Khalifa caddr_t preload_metadata, preload_kmdp;
48b72ae900SAhmad Khalifa
494d213c59SAhmad Khalifa const char preload_modtype[] = MODTYPE;
504d213c59SAhmad Khalifa const char preload_kerntype[] = KERNTYPE;
514d213c59SAhmad Khalifa const char preload_modtype_obj[] = MODTYPE_OBJ;
524d213c59SAhmad Khalifa
53b72ae900SAhmad Khalifa void
preload_initkmdp(bool fatal)54b72ae900SAhmad Khalifa preload_initkmdp(bool fatal)
55b72ae900SAhmad Khalifa {
564d213c59SAhmad Khalifa preload_kmdp = preload_search_by_type(preload_kerntype);
57b72ae900SAhmad Khalifa
58b72ae900SAhmad Khalifa if (preload_kmdp == NULL && fatal)
59b72ae900SAhmad Khalifa panic("unable to find kernel metadata");
60b72ae900SAhmad Khalifa }
616ba9413bSMike Smith
626ba9413bSMike Smith /*
636ba9413bSMike Smith * Search for the preloaded module (name)
646ba9413bSMike Smith */
656ba9413bSMike Smith caddr_t
preload_search_by_name(const char * name)66e4f1a52fSPeter Wemm preload_search_by_name(const char *name)
676ba9413bSMike Smith {
686ba9413bSMike Smith caddr_t curp;
6960ae52f7SEd Schouten uint32_t *hdr;
70e4f1a52fSPeter Wemm int next;
716ba9413bSMike Smith
72e4f1a52fSPeter Wemm if (preload_metadata != NULL) {
73e4f1a52fSPeter Wemm curp = preload_metadata;
746ba9413bSMike Smith for (;;) {
7560ae52f7SEd Schouten hdr = (uint32_t *)curp;
76e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0)
776ba9413bSMike Smith break;
786ba9413bSMike Smith
796ba9413bSMike Smith /* Search for a MODINFO_NAME field */
806ba9413bSMike Smith if ((hdr[0] == MODINFO_NAME) &&
8160ae52f7SEd Schouten !strcmp(name, curp + sizeof(uint32_t) * 2))
826ba9413bSMike Smith return(curp);
836ba9413bSMike Smith
846ba9413bSMike Smith /* skip to next field */
8560ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
862a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
87e4f1a52fSPeter Wemm curp += next;
886ba9413bSMike Smith }
896ba9413bSMike Smith }
906ba9413bSMike Smith return(NULL);
916ba9413bSMike Smith }
926ba9413bSMike Smith
936ba9413bSMike Smith /*
946ba9413bSMike Smith * Search for the first preloaded module of (type)
956ba9413bSMike Smith */
966ba9413bSMike Smith caddr_t
preload_search_by_type(const char * type)97e4f1a52fSPeter Wemm preload_search_by_type(const char *type)
986ba9413bSMike Smith {
996ba9413bSMike Smith caddr_t curp, lname;
10060ae52f7SEd Schouten uint32_t *hdr;
101e4f1a52fSPeter Wemm int next;
1026ba9413bSMike Smith
103e4f1a52fSPeter Wemm if (preload_metadata != NULL) {
104e4f1a52fSPeter Wemm curp = preload_metadata;
1056ba9413bSMike Smith lname = NULL;
1066ba9413bSMike Smith for (;;) {
10760ae52f7SEd Schouten hdr = (uint32_t *)curp;
108e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0)
1096ba9413bSMike Smith break;
1106ba9413bSMike Smith
1116ba9413bSMike Smith /* remember the start of each record */
1126ba9413bSMike Smith if (hdr[0] == MODINFO_NAME)
1136ba9413bSMike Smith lname = curp;
1146ba9413bSMike Smith
1156ba9413bSMike Smith /* Search for a MODINFO_TYPE field */
1166ba9413bSMike Smith if ((hdr[0] == MODINFO_TYPE) &&
11760ae52f7SEd Schouten !strcmp(type, curp + sizeof(uint32_t) * 2))
1186ba9413bSMike Smith return(lname);
1196ba9413bSMike Smith
1206ba9413bSMike Smith /* skip to next field */
12160ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
1222a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
123e4f1a52fSPeter Wemm curp += next;
124e4f1a52fSPeter Wemm }
125e4f1a52fSPeter Wemm }
126e4f1a52fSPeter Wemm return(NULL);
127e4f1a52fSPeter Wemm }
128e4f1a52fSPeter Wemm
129e4f1a52fSPeter Wemm /*
130e4f1a52fSPeter Wemm * Walk through the preloaded module list
131e4f1a52fSPeter Wemm */
132e4f1a52fSPeter Wemm caddr_t
preload_search_next_name(caddr_t base)133e4f1a52fSPeter Wemm preload_search_next_name(caddr_t base)
134e4f1a52fSPeter Wemm {
135e4f1a52fSPeter Wemm caddr_t curp;
13660ae52f7SEd Schouten uint32_t *hdr;
137e4f1a52fSPeter Wemm int next;
138e4f1a52fSPeter Wemm
139e4f1a52fSPeter Wemm if (preload_metadata != NULL) {
140e4f1a52fSPeter Wemm /* Pick up where we left off last time */
141e4f1a52fSPeter Wemm if (base) {
142e4f1a52fSPeter Wemm /* skip to next field */
143e4f1a52fSPeter Wemm curp = base;
14460ae52f7SEd Schouten hdr = (uint32_t *)curp;
14560ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
1462a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
147e4f1a52fSPeter Wemm curp += next;
148e4f1a52fSPeter Wemm } else
149e4f1a52fSPeter Wemm curp = preload_metadata;
150e4f1a52fSPeter Wemm
151e4f1a52fSPeter Wemm for (;;) {
15260ae52f7SEd Schouten hdr = (uint32_t *)curp;
153e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0)
154e4f1a52fSPeter Wemm break;
155e4f1a52fSPeter Wemm
156e4f1a52fSPeter Wemm /* Found a new record? */
157e4f1a52fSPeter Wemm if (hdr[0] == MODINFO_NAME)
158e4f1a52fSPeter Wemm return curp;
159e4f1a52fSPeter Wemm
160e4f1a52fSPeter Wemm /* skip to next field */
16160ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
1622a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
163e4f1a52fSPeter Wemm curp += next;
1646ba9413bSMike Smith }
1656ba9413bSMike Smith }
1666ba9413bSMike Smith return(NULL);
1676ba9413bSMike Smith }
1686ba9413bSMike Smith
1696ba9413bSMike Smith /*
1706ba9413bSMike Smith * Given a preloaded module handle (mod), return a pointer
1716ba9413bSMike Smith * to the data for the attribute (inf).
1726ba9413bSMike Smith */
1736ba9413bSMike Smith caddr_t
preload_search_info(caddr_t mod,int inf)174e4f1a52fSPeter Wemm preload_search_info(caddr_t mod, int inf)
1756ba9413bSMike Smith {
1766ba9413bSMike Smith caddr_t curp;
17760ae52f7SEd Schouten uint32_t *hdr;
17860ae52f7SEd Schouten uint32_t type = 0;
179e4f1a52fSPeter Wemm int next;
1806ba9413bSMike Smith
181e8234cfeSRoger Pau Monné if (mod == NULL)
182e8234cfeSRoger Pau Monné return (NULL);
183e8234cfeSRoger Pau Monné
1846ba9413bSMike Smith curp = mod;
1856ba9413bSMike Smith for (;;) {
18660ae52f7SEd Schouten hdr = (uint32_t *)curp;
1876ba9413bSMike Smith /* end of module data? */
188e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0)
1896ba9413bSMike Smith break;
1906ba9413bSMike Smith /*
1916ba9413bSMike Smith * We give up once we've looped back to what we were looking at
1926ba9413bSMike Smith * first - this should normally be a MODINFO_NAME field.
1936ba9413bSMike Smith */
1946ba9413bSMike Smith if (type == 0) {
1956ba9413bSMike Smith type = hdr[0];
1966ba9413bSMike Smith } else {
1976ba9413bSMike Smith if (hdr[0] == type)
1986ba9413bSMike Smith break;
1996ba9413bSMike Smith }
2006ba9413bSMike Smith
2016ba9413bSMike Smith /*
2026ba9413bSMike Smith * Attribute match? Return pointer to data.
203d7d97eb0SJeroen Ruigrok van der Werven * Consumer may safely assume that size value precedes
2046ba9413bSMike Smith * data.
2056ba9413bSMike Smith */
2066ba9413bSMike Smith if (hdr[0] == inf)
20760ae52f7SEd Schouten return(curp + (sizeof(uint32_t) * 2));
2086ba9413bSMike Smith
2096ba9413bSMike Smith /* skip to next field */
21060ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
2112a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
212e4f1a52fSPeter Wemm curp += next;
2136ba9413bSMike Smith }
2146ba9413bSMike Smith return(NULL);
2156ba9413bSMike Smith }
2166ba9413bSMike Smith
217e4f1a52fSPeter Wemm /*
218e4f1a52fSPeter Wemm * Delete a preload record by name.
219e4f1a52fSPeter Wemm */
220e4f1a52fSPeter Wemm void
preload_delete_name(const char * name)221e4f1a52fSPeter Wemm preload_delete_name(const char *name)
222e4f1a52fSPeter Wemm {
223483f692eSMark Johnston caddr_t addr, curp;
224483f692eSMark Johnston uint32_t *hdr, sz;
225e4f1a52fSPeter Wemm int next;
226e4f1a52fSPeter Wemm int clearing;
227e4f1a52fSPeter Wemm
228483f692eSMark Johnston addr = 0;
229483f692eSMark Johnston sz = 0;
230483f692eSMark Johnston
231e4f1a52fSPeter Wemm if (preload_metadata != NULL) {
232e4f1a52fSPeter Wemm clearing = 0;
233e4f1a52fSPeter Wemm curp = preload_metadata;
234e4f1a52fSPeter Wemm for (;;) {
23560ae52f7SEd Schouten hdr = (uint32_t *)curp;
236483f692eSMark Johnston if (hdr[0] == MODINFO_NAME || (hdr[0] == 0 && hdr[1] == 0)) {
237483f692eSMark Johnston /* Free memory used to store the file. */
238483f692eSMark Johnston if (addr != 0 && sz != 0)
239483f692eSMark Johnston kmem_bootstrap_free((vm_offset_t)addr, sz);
240483f692eSMark Johnston addr = 0;
241483f692eSMark Johnston sz = 0;
242e4f1a52fSPeter Wemm
243483f692eSMark Johnston if (hdr[0] == 0)
244483f692eSMark Johnston break;
24560ae52f7SEd Schouten if (!strcmp(name, curp + sizeof(uint32_t) * 2))
246e4f1a52fSPeter Wemm clearing = 1; /* got it, start clearing */
247483f692eSMark Johnston else if (clearing) {
248e4f1a52fSPeter Wemm clearing = 0; /* at next one now.. better stop */
249e4f1a52fSPeter Wemm }
250483f692eSMark Johnston }
251483f692eSMark Johnston if (clearing) {
252483f692eSMark Johnston if (hdr[0] == MODINFO_ADDR)
253483f692eSMark Johnston addr = *(caddr_t *)(curp + sizeof(uint32_t) * 2);
254483f692eSMark Johnston else if (hdr[0] == MODINFO_SIZE)
255483f692eSMark Johnston sz = *(uint32_t *)(curp + sizeof(uint32_t) * 2);
256e4f1a52fSPeter Wemm hdr[0] = MODINFO_EMPTY;
257483f692eSMark Johnston }
258e4f1a52fSPeter Wemm
259e4f1a52fSPeter Wemm /* skip to next field */
26060ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
2612a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
262e4f1a52fSPeter Wemm curp += next;
263e4f1a52fSPeter Wemm }
264e4f1a52fSPeter Wemm }
265e4f1a52fSPeter Wemm }
266e4f1a52fSPeter Wemm
267278e7970SMarcel Moolenaar void *
preload_fetch_addr(caddr_t mod)268278e7970SMarcel Moolenaar preload_fetch_addr(caddr_t mod)
269278e7970SMarcel Moolenaar {
270278e7970SMarcel Moolenaar caddr_t *mdp;
271278e7970SMarcel Moolenaar
272278e7970SMarcel Moolenaar mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR);
273278e7970SMarcel Moolenaar if (mdp == NULL)
274278e7970SMarcel Moolenaar return (NULL);
275278e7970SMarcel Moolenaar return (*mdp + preload_addr_relocate);
276278e7970SMarcel Moolenaar }
277278e7970SMarcel Moolenaar
278278e7970SMarcel Moolenaar size_t
preload_fetch_size(caddr_t mod)279278e7970SMarcel Moolenaar preload_fetch_size(caddr_t mod)
280278e7970SMarcel Moolenaar {
281278e7970SMarcel Moolenaar size_t *mdp;
282278e7970SMarcel Moolenaar
283278e7970SMarcel Moolenaar mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE);
284278e7970SMarcel Moolenaar if (mdp == NULL)
285278e7970SMarcel Moolenaar return (0);
286278e7970SMarcel Moolenaar return (*mdp);
287278e7970SMarcel Moolenaar }
288278e7970SMarcel Moolenaar
28912d7eaa0SWarner Losh /* Called from locore. Convert physical pointers to kvm. Sigh. */
290e4f1a52fSPeter Wemm void
preload_bootstrap_relocate(vm_offset_t offset)291e4f1a52fSPeter Wemm preload_bootstrap_relocate(vm_offset_t offset)
292e4f1a52fSPeter Wemm {
293e4f1a52fSPeter Wemm caddr_t curp;
29460ae52f7SEd Schouten uint32_t *hdr;
295e4f1a52fSPeter Wemm vm_offset_t *ptr;
296e4f1a52fSPeter Wemm int next;
297e4f1a52fSPeter Wemm
298e4f1a52fSPeter Wemm if (preload_metadata != NULL) {
299e4f1a52fSPeter Wemm curp = preload_metadata;
300e4f1a52fSPeter Wemm for (;;) {
30160ae52f7SEd Schouten hdr = (uint32_t *)curp;
302e4f1a52fSPeter Wemm if (hdr[0] == 0 && hdr[1] == 0)
303e4f1a52fSPeter Wemm break;
304e4f1a52fSPeter Wemm
3052da2eeacSPeter Wemm /* Deal with the ones that we know we have to fix */
3062da2eeacSPeter Wemm switch (hdr[0]) {
3072da2eeacSPeter Wemm case MODINFO_ADDR:
30893b18e37SToomas Soome case MODINFO_METADATA|MODINFOMD_FONT:
309966e53a4SEmmanuel Vadot case MODINFO_METADATA|MODINFOMD_SPLASH:
3102da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_SSYM:
3112da2eeacSPeter Wemm case MODINFO_METADATA|MODINFOMD_ESYM:
31260ae52f7SEd Schouten ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2));
313e4f1a52fSPeter Wemm *ptr += offset;
3142da2eeacSPeter Wemm break;
315e4f1a52fSPeter Wemm }
316e4f1a52fSPeter Wemm /* The rest is beyond us for now */
317e4f1a52fSPeter Wemm
318e4f1a52fSPeter Wemm /* skip to next field */
31960ae52f7SEd Schouten next = sizeof(uint32_t) * 2 + hdr[1];
3202a26e9eaSPeter Wemm next = roundup(next, sizeof(u_long));
321e4f1a52fSPeter Wemm curp += next;
322e4f1a52fSPeter Wemm }
323e4f1a52fSPeter Wemm }
324e4f1a52fSPeter Wemm }
32522e6a670SMitchell Horne
32622e6a670SMitchell Horne /*
32722e6a670SMitchell Horne * Parse the modinfo type and append to the provided sbuf.
32822e6a670SMitchell Horne */
32922e6a670SMitchell Horne static void
preload_modinfo_type(struct sbuf * sbp,int type)33022e6a670SMitchell Horne preload_modinfo_type(struct sbuf *sbp, int type)
33122e6a670SMitchell Horne {
33222e6a670SMitchell Horne
33322e6a670SMitchell Horne if ((type & MODINFO_METADATA) == 0) {
33422e6a670SMitchell Horne switch (type) {
33522e6a670SMitchell Horne case MODINFO_END:
33622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_END");
33722e6a670SMitchell Horne break;
33822e6a670SMitchell Horne case MODINFO_NAME:
33922e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_NAME");
34022e6a670SMitchell Horne break;
34122e6a670SMitchell Horne case MODINFO_TYPE:
34222e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_TYPE");
34322e6a670SMitchell Horne break;
34422e6a670SMitchell Horne case MODINFO_ADDR:
34522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ADDR");
34622e6a670SMitchell Horne break;
34722e6a670SMitchell Horne case MODINFO_SIZE:
34822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_SIZE");
34922e6a670SMitchell Horne break;
35022e6a670SMitchell Horne case MODINFO_EMPTY:
35122e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_EMPTY");
35222e6a670SMitchell Horne break;
35322e6a670SMitchell Horne case MODINFO_ARGS:
35422e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_ARGS");
35522e6a670SMitchell Horne break;
35622e6a670SMitchell Horne default:
35722e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized modinfo attribute");
35822e6a670SMitchell Horne }
35922e6a670SMitchell Horne
36022e6a670SMitchell Horne return;
36122e6a670SMitchell Horne }
36222e6a670SMitchell Horne
36322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFO_METADATA | ");
36422e6a670SMitchell Horne switch (type & ~MODINFO_METADATA) {
36522e6a670SMitchell Horne case MODINFOMD_ELFHDR:
36622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ELFHDR");
36722e6a670SMitchell Horne break;
36822e6a670SMitchell Horne case MODINFOMD_SSYM:
36922e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SSYM");
37022e6a670SMitchell Horne break;
37122e6a670SMitchell Horne case MODINFOMD_ESYM:
37222e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ESYM");
37322e6a670SMitchell Horne break;
37422e6a670SMitchell Horne case MODINFOMD_DYNAMIC:
37522e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DYNAMIC");
37622e6a670SMitchell Horne break;
37722e6a670SMitchell Horne case MODINFOMD_ENVP:
37822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_ENVP");
37922e6a670SMitchell Horne break;
38022e6a670SMitchell Horne case MODINFOMD_HOWTO:
38122e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_HOWTO");
38222e6a670SMitchell Horne break;
38322e6a670SMitchell Horne case MODINFOMD_KERNEND:
38422e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KERNEND");
38522e6a670SMitchell Horne break;
38622e6a670SMitchell Horne case MODINFOMD_SHDR:
38722e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SHDR");
38822e6a670SMitchell Horne break;
38922e6a670SMitchell Horne case MODINFOMD_CTORS_ADDR:
39022e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR");
39122e6a670SMitchell Horne break;
39222e6a670SMitchell Horne case MODINFOMD_CTORS_SIZE:
39322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE");
39422e6a670SMitchell Horne break;
39522e6a670SMitchell Horne case MODINFOMD_FW_HANDLE:
39622e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_FW_HANDLE");
39722e6a670SMitchell Horne break;
39822e6a670SMitchell Horne case MODINFOMD_KEYBUF:
39922e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_KEYBUF");
40022e6a670SMitchell Horne break;
40122e6a670SMitchell Horne #ifdef MODINFOMD_SMAP
40222e6a670SMitchell Horne case MODINFOMD_SMAP:
40322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP");
40422e6a670SMitchell Horne break;
40522e6a670SMitchell Horne #endif
40622e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR
40722e6a670SMitchell Horne case MODINFOMD_SMAP_XATTR:
40822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR");
40922e6a670SMitchell Horne break;
41022e6a670SMitchell Horne #endif
41122e6a670SMitchell Horne #ifdef MODINFOMD_DTBP
41222e6a670SMitchell Horne case MODINFOMD_DTBP:
41322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_DTBP");
41422e6a670SMitchell Horne break;
41522e6a670SMitchell Horne #endif
41622e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP
41722e6a670SMitchell Horne case MODINFOMD_EFI_MAP:
41822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_MAP");
41922e6a670SMitchell Horne break;
42022e6a670SMitchell Horne #endif
42122e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB
42222e6a670SMitchell Horne case MODINFOMD_EFI_FB:
42322e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_EFI_FB");
42422e6a670SMitchell Horne break;
42522e6a670SMitchell Horne #endif
42622e6a670SMitchell Horne #ifdef MODINFOMD_MODULEP
42722e6a670SMitchell Horne case MODINFOMD_MODULEP:
42822e6a670SMitchell Horne sbuf_cat(sbp, "MODINFOMD_MODULEP");
42922e6a670SMitchell Horne break;
43022e6a670SMitchell Horne #endif
431a4a10b37SToomas Soome #ifdef MODINFOMD_VBE_FB
432a4a10b37SToomas Soome case MODINFOMD_VBE_FB:
433a4a10b37SToomas Soome sbuf_cat(sbp, "MODINFOMD_VBE_FB");
434a4a10b37SToomas Soome break;
435a4a10b37SToomas Soome #endif
436742653ebSToomas Soome #ifdef MODINFOMD_FONT
437742653ebSToomas Soome case MODINFOMD_FONT:
438742653ebSToomas Soome sbuf_cat(sbp, "MODINFOMD_FONT");
439742653ebSToomas Soome break;
440742653ebSToomas Soome #endif
441966e53a4SEmmanuel Vadot #ifdef MODINFOMD_SPLASH
442966e53a4SEmmanuel Vadot case MODINFOMD_SPLASH:
443966e53a4SEmmanuel Vadot sbuf_cat(sbp, "MODINFOMD_SPLASH");
444966e53a4SEmmanuel Vadot break;
445966e53a4SEmmanuel Vadot #endif
446*04a812aeSMitchell Horne #ifdef MODINFOMD_BOOT_HARTID
447*04a812aeSMitchell Horne case MODINFOMD_BOOT_HARTID:
448*04a812aeSMitchell Horne sbuf_cat(sbp, "MODINFOMD_BOOT_HARTID");
449*04a812aeSMitchell Horne break;
450*04a812aeSMitchell Horne #endif
45122e6a670SMitchell Horne default:
45222e6a670SMitchell Horne sbuf_cat(sbp, "unrecognized metadata type");
45322e6a670SMitchell Horne }
45422e6a670SMitchell Horne }
45522e6a670SMitchell Horne
45622e6a670SMitchell Horne /*
45722e6a670SMitchell Horne * Print the modinfo value, depending on type.
45822e6a670SMitchell Horne */
45922e6a670SMitchell Horne static void
preload_modinfo_value(struct sbuf * sbp,uint32_t * bptr,int type,int len)46022e6a670SMitchell Horne preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len)
46122e6a670SMitchell Horne {
46222e6a670SMitchell Horne #ifdef __LP64__
46322e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o);
46422e6a670SMitchell Horne #else
46522e6a670SMitchell Horne #define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08x", o);
46622e6a670SMitchell Horne #endif
46722e6a670SMitchell Horne
46822e6a670SMitchell Horne switch (type) {
46922e6a670SMitchell Horne case MODINFO_NAME:
47022e6a670SMitchell Horne case MODINFO_TYPE:
47122e6a670SMitchell Horne case MODINFO_ARGS:
47222e6a670SMitchell Horne sbuf_printf(sbp, "%s", (char *)bptr);
47322e6a670SMitchell Horne break;
47422e6a670SMitchell Horne case MODINFO_SIZE:
47522e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_SIZE:
47622e6a670SMitchell Horne sbuf_printf(sbp, "%lu", *(u_long *)bptr);
47722e6a670SMitchell Horne break;
47822e6a670SMitchell Horne case MODINFO_ADDR:
47922e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SSYM:
48022e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ESYM:
48122e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DYNAMIC:
48222e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KERNEND:
48322e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ENVP:
48422e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_CTORS_ADDR:
48522e6a670SMitchell Horne #ifdef MODINFOMD_SMAP
48622e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP:
48722e6a670SMitchell Horne #endif
48822e6a670SMitchell Horne #ifdef MODINFOMD_SMAP_XATTR
48922e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SMAP_XATTR:
49022e6a670SMitchell Horne #endif
49122e6a670SMitchell Horne #ifdef MODINFOMD_DTBP
49222e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_DTBP:
49322e6a670SMitchell Horne #endif
49422e6a670SMitchell Horne #ifdef MODINFOMD_EFI_FB
49522e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_FB:
49622e6a670SMitchell Horne #endif
497a4a10b37SToomas Soome #ifdef MODINFOMD_VBE_FB
498a4a10b37SToomas Soome case MODINFO_METADATA | MODINFOMD_VBE_FB:
499a4a10b37SToomas Soome #endif
500742653ebSToomas Soome #ifdef MODINFOMD_FONT
501742653ebSToomas Soome case MODINFO_METADATA | MODINFOMD_FONT:
502742653ebSToomas Soome #endif
503966e53a4SEmmanuel Vadot #ifdef MODINFOMD_SPLASH
504966e53a4SEmmanuel Vadot case MODINFO_METADATA | MODINFOMD_SPLASH:
505966e53a4SEmmanuel Vadot #endif
50622e6a670SMitchell Horne sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr);
50722e6a670SMitchell Horne break;
50822e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_HOWTO:
50922e6a670SMitchell Horne sbuf_printf(sbp, "0x%08x", *bptr);
51022e6a670SMitchell Horne break;
511*04a812aeSMitchell Horne #ifdef MODINFOMD_BOOT_HARTID
512*04a812aeSMitchell Horne case MODINFO_METADATA | MODINFOMD_BOOT_HARTID:
513*04a812aeSMitchell Horne sbuf_printf(sbp, "0x%lu", *(uint64_t *)bptr);
514*04a812aeSMitchell Horne break;
515*04a812aeSMitchell Horne #endif
51622e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_SHDR:
51722e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_ELFHDR:
51822e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_FW_HANDLE:
51922e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_KEYBUF:
52022e6a670SMitchell Horne #ifdef MODINFOMD_EFI_MAP
52122e6a670SMitchell Horne case MODINFO_METADATA | MODINFOMD_EFI_MAP:
52222e6a670SMitchell Horne #endif
52322e6a670SMitchell Horne /* Don't print data buffers. */
52422e6a670SMitchell Horne sbuf_cat(sbp, "buffer contents omitted");
52522e6a670SMitchell Horne break;
52622e6a670SMitchell Horne default:
52722e6a670SMitchell Horne break;
52822e6a670SMitchell Horne }
52922e6a670SMitchell Horne #undef sbuf_print_vmoffset
53022e6a670SMitchell Horne }
53122e6a670SMitchell Horne
53222e6a670SMitchell Horne static void
preload_dump_internal(struct sbuf * sbp)53322e6a670SMitchell Horne preload_dump_internal(struct sbuf *sbp)
53422e6a670SMitchell Horne {
53522e6a670SMitchell Horne uint32_t *bptr, type, len;
53622e6a670SMitchell Horne
53722e6a670SMitchell Horne KASSERT(preload_metadata != NULL,
53822e6a670SMitchell Horne ("%s called without setting up preload_metadata", __func__));
53922e6a670SMitchell Horne
54022e6a670SMitchell Horne /*
54122e6a670SMitchell Horne * Iterate through the TLV-encoded sections.
54222e6a670SMitchell Horne */
54322e6a670SMitchell Horne bptr = (uint32_t *)preload_metadata;
54422e6a670SMitchell Horne sbuf_putc(sbp, '\n');
545841dad02SMitchell Horne while (bptr[0] != MODINFO_END || bptr[1] != MODINFO_END) {
54622e6a670SMitchell Horne sbuf_printf(sbp, " %p:\n", bptr);
54722e6a670SMitchell Horne type = *bptr++;
54822e6a670SMitchell Horne len = *bptr++;
54922e6a670SMitchell Horne
55022e6a670SMitchell Horne sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
55122e6a670SMitchell Horne preload_modinfo_type(sbp, type);
55222e6a670SMitchell Horne sbuf_putc(sbp, '\n');
55322e6a670SMitchell Horne sbuf_printf(sbp, "\tlen:\t%u\n", len);
55422e6a670SMitchell Horne sbuf_cat(sbp, "\tvalue:\t");
55522e6a670SMitchell Horne preload_modinfo_value(sbp, bptr, type, len);
55622e6a670SMitchell Horne sbuf_putc(sbp, '\n');
55722e6a670SMitchell Horne
55822e6a670SMitchell Horne bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
55922e6a670SMitchell Horne }
56022e6a670SMitchell Horne }
56122e6a670SMitchell Horne
56222e6a670SMitchell Horne /*
56322e6a670SMitchell Horne * Print the preloaded data to the console. Called from the machine-dependent
56422e6a670SMitchell Horne * initialization routines, e.g. hammer_time().
56522e6a670SMitchell Horne */
56622e6a670SMitchell Horne void
preload_dump(void)56722e6a670SMitchell Horne preload_dump(void)
56822e6a670SMitchell Horne {
56922e6a670SMitchell Horne char buf[512];
57022e6a670SMitchell Horne struct sbuf sb;
57122e6a670SMitchell Horne
57222e6a670SMitchell Horne /*
57322e6a670SMitchell Horne * This function is expected to be called before malloc is available,
57422e6a670SMitchell Horne * so use a static buffer and struct sbuf.
57522e6a670SMitchell Horne */
57622e6a670SMitchell Horne sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
57722e6a670SMitchell Horne sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
57822e6a670SMitchell Horne preload_dump_internal(&sb);
57922e6a670SMitchell Horne
58022e6a670SMitchell Horne sbuf_finish(&sb);
58122e6a670SMitchell Horne sbuf_delete(&sb);
58222e6a670SMitchell Horne }
58322e6a670SMitchell Horne
58422e6a670SMitchell Horne static int
sysctl_preload_dump(SYSCTL_HANDLER_ARGS)58522e6a670SMitchell Horne sysctl_preload_dump(SYSCTL_HANDLER_ARGS)
58622e6a670SMitchell Horne {
58722e6a670SMitchell Horne struct sbuf sb;
58822e6a670SMitchell Horne int error;
58922e6a670SMitchell Horne
59022e6a670SMitchell Horne if (preload_metadata == NULL)
59122e6a670SMitchell Horne return (EINVAL);
59222e6a670SMitchell Horne
59322e6a670SMitchell Horne sbuf_new_for_sysctl(&sb, NULL, 512, req);
59422e6a670SMitchell Horne preload_dump_internal(&sb);
59522e6a670SMitchell Horne
59622e6a670SMitchell Horne error = sbuf_finish(&sb);
59722e6a670SMitchell Horne sbuf_delete(&sb);
59822e6a670SMitchell Horne
59922e6a670SMitchell Horne return (error);
60022e6a670SMitchell Horne }
60122e6a670SMitchell Horne SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo,
60222e6a670SMitchell Horne CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
60322e6a670SMitchell Horne NULL, 0, sysctl_preload_dump, "A",
60422e6a670SMitchell Horne "pretty-print the bootloader metadata");
605