Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144971298
D26687.id77939.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D26687.id77939.diff
View Options
Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -1853,6 +1853,15 @@
if (late_console)
cninit();
+ /*
+ * Dump the boot metadata. We have to wait for cninit() since console
+ * output is required. If it's grossly incorrect the kernel will never
+ * make it this far.
+ */
+ if ((boothowto & RB_VERBOSE) &&
+ getenv_is_true("debug.dump_modinfo_at_boot"))
+ preload_dump();
+
#ifdef DEV_ISA
#ifdef DEV_ATPIC
elcr_probe();
Index: sys/kern/subr_module.c
===================================================================
--- sys/kern/subr_module.c
+++ sys/kern/subr_module.c
@@ -3,6 +3,8 @@
*
* Copyright (c) 1998 Michael Smith
* All rights reserved.
+ * Copyright (c) 2020 NetApp Inc.
+ * Copyright (c) 2020 Klara Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,6 +34,10 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/linker.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+
+#include <machine/metadata.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -304,3 +310,249 @@
}
}
}
+
+/*
+ * Parse the modinfo type and append to the provided sbuf.
+ */
+static void
+preload_modinfo_type(struct sbuf *sbp, int type)
+{
+
+ if ((type & MODINFO_METADATA) == 0) {
+ switch (type) {
+ case MODINFO_END:
+ sbuf_cat(sbp, "MODINFO_END");
+ break;
+ case MODINFO_NAME:
+ sbuf_cat(sbp, "MODINFO_NAME");
+ break;
+ case MODINFO_TYPE:
+ sbuf_cat(sbp, "MODINFO_TYPE");
+ break;
+ case MODINFO_ADDR:
+ sbuf_cat(sbp, "MODINFO_ADDR");
+ break;
+ case MODINFO_SIZE:
+ sbuf_cat(sbp, "MODINFO_SIZE");
+ break;
+ case MODINFO_EMPTY:
+ sbuf_cat(sbp, "MODINFO_EMPTY");
+ break;
+ case MODINFO_ARGS:
+ sbuf_cat(sbp, "MODINFO_ARGS");
+ break;
+ default:
+ sbuf_cat(sbp, "unrecognized modinfo attribute");
+ }
+
+ return;
+ }
+
+ sbuf_cat(sbp, "MODINFO_METADATA | ");
+ switch (type & ~MODINFO_METADATA) {
+ case MODINFOMD_ELFHDR:
+ sbuf_cat(sbp, "MODINFOMD_ELFHDR");
+ break;
+ case MODINFOMD_SSYM:
+ sbuf_cat(sbp, "MODINFOMD_SSYM");
+ break;
+ case MODINFOMD_ESYM:
+ sbuf_cat(sbp, "MODINFOMD_ESYM");
+ break;
+ case MODINFOMD_DYNAMIC:
+ sbuf_cat(sbp, "MODINFOMD_DYNAMIC");
+ break;
+ case MODINFOMD_ENVP:
+ sbuf_cat(sbp, "MODINFOMD_ENVP");
+ break;
+ case MODINFOMD_HOWTO:
+ sbuf_cat(sbp, "MODINFOMD_HOWTO");
+ break;
+ case MODINFOMD_KERNEND:
+ sbuf_cat(sbp, "MODINFOMD_KERNEND");
+ break;
+ case MODINFOMD_SHDR:
+ sbuf_cat(sbp, "MODINFOMD_SHDR");
+ break;
+ case MODINFOMD_CTORS_ADDR:
+ sbuf_cat(sbp, "MODINFOMD_CTORS_ADDR");
+ break;
+ case MODINFOMD_CTORS_SIZE:
+ sbuf_cat(sbp, "MODINFOMD_CTORS_SIZE");
+ break;
+ case MODINFOMD_FW_HANDLE:
+ sbuf_cat(sbp, "MODINFOMD_FW_HANDLE");
+ break;
+ case MODINFOMD_KEYBUF:
+ sbuf_cat(sbp, "MODINFOMD_KEYBUF");
+ break;
+#ifdef MODINFOMD_SMAP
+ case MODINFOMD_SMAP:
+ sbuf_cat(sbp, "MODINFOMD_SMAP");
+ break;
+#endif
+#ifdef MODINFOMD_SMAP_XATTR
+ case MODINFOMD_SMAP_XATTR:
+ sbuf_cat(sbp, "MODINFOMD_SMAP_XATTR");
+ break;
+#endif
+#ifdef MODINFOMD_DTBP
+ case MODINFOMD_DTBP:
+ sbuf_cat(sbp, "MODINFOMD_DTBP");
+ break;
+#endif
+#ifdef MODINFOMD_EFI_MAP
+ case MODINFOMD_EFI_MAP:
+ sbuf_cat(sbp, "MODINFOMD_EFI_MAP");
+ break;
+#endif
+#ifdef MODINFOMD_EFI_FB
+ case MODINFOMD_EFI_FB:
+ sbuf_cat(sbp, "MODINFOMD_EFI_FB");
+ break;
+#endif
+#ifdef MODINFOMD_MODULEP
+ case MODINFOMD_MODULEP:
+ sbuf_cat(sbp, "MODINFOMD_MODULEP");
+ break;
+#endif
+ default:
+ sbuf_cat(sbp, "unrecognized metadata type");
+ }
+}
+
+/*
+ * Print the modinfo value, depending on type.
+ */
+static void
+preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len)
+{
+#ifdef __LP64__
+#define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%016lx", o);
+#else
+#define sbuf_print_vmoffset(sb, o) sbuf_printf(sb, "0x%08lx", o);
+#endif
+
+ switch (type) {
+ case MODINFO_NAME:
+ case MODINFO_TYPE:
+ case MODINFO_ARGS:
+ sbuf_printf(sbp, "%s", (char *)bptr);
+ break;
+ case MODINFO_SIZE:
+ case MODINFO_METADATA | MODINFOMD_CTORS_SIZE:
+ sbuf_printf(sbp, "%lu", *(u_long *)bptr);
+ break;
+ case MODINFO_ADDR:
+ case MODINFO_METADATA | MODINFOMD_SSYM:
+ case MODINFO_METADATA | MODINFOMD_ESYM:
+ case MODINFO_METADATA | MODINFOMD_DYNAMIC:
+ case MODINFO_METADATA | MODINFOMD_KERNEND:
+ case MODINFO_METADATA | MODINFOMD_ENVP:
+ case MODINFO_METADATA | MODINFOMD_CTORS_ADDR:
+#ifdef MODINFOMD_SMAP
+ case MODINFO_METADATA | MODINFOMD_SMAP:
+#endif
+#ifdef MODINFOMD_SMAP_XATTR
+ case MODINFO_METADATA | MODINFOMD_SMAP_XATTR:
+#endif
+#ifdef MODINFOMD_DTBP
+ case MODINFO_METADATA | MODINFOMD_DTBP:
+#endif
+#ifdef MODINFOMD_EFI_FB
+ case MODINFO_METADATA | MODINFOMD_EFI_FB:
+#endif
+ sbuf_print_vmoffset(sbp, *(vm_offset_t *)bptr);
+ break;
+ case MODINFO_METADATA | MODINFOMD_HOWTO:
+ sbuf_printf(sbp, "0x%08x", *bptr);
+ break;
+ case MODINFO_METADATA | MODINFOMD_SHDR:
+ case MODINFO_METADATA | MODINFOMD_ELFHDR:
+ case MODINFO_METADATA | MODINFOMD_FW_HANDLE:
+ case MODINFO_METADATA | MODINFOMD_KEYBUF:
+#ifdef MODINFOMD_EFI_MAP
+ case MODINFO_METADATA | MODINFOMD_EFI_MAP:
+#endif
+ /* Don't print data buffers. */
+ sbuf_cat(sbp, "buffer contents omitted");
+ break;
+ default:
+ break;
+ }
+#undef sbuf_print_vmoffset
+}
+
+static void
+preload_dump_internal(struct sbuf *sbp)
+{
+ uint32_t *bptr, type, len;
+
+ KASSERT(preload_metadata != NULL,
+ ("%s called without setting up preload_metadata", __func__));
+
+ /*
+ * Iterate through the TLV-encoded sections.
+ */
+ bptr = (uint32_t *)preload_metadata;
+ sbuf_putc(sbp, '\n');
+ while (bptr[0] != MODINFO_END || bptr[0] != MODINFO_END) {
+ sbuf_printf(sbp, " %p:\n", bptr);
+ type = *bptr++;
+ len = *bptr++;
+
+ sbuf_printf(sbp, "\ttype:\t(%#04x) ", type);
+ preload_modinfo_type(sbp, type);
+ sbuf_putc(sbp, '\n');
+ sbuf_printf(sbp, "\tlen:\t%u\n", len);
+ sbuf_cat(sbp, "\tvalue:\t");
+ preload_modinfo_value(sbp, bptr, type, len);
+ sbuf_putc(sbp, '\n');
+
+ bptr += roundup(len, sizeof(u_long)) / sizeof(uint32_t);
+ }
+}
+
+/*
+ * Print the preloaded data to the console. Called from the machine-dependent
+ * initialization routines, e.g. hammer_time().
+ */
+void
+preload_dump(void)
+{
+ char buf[512];
+ struct sbuf sb;
+
+ /*
+ * This function is expected to be called before malloc is available,
+ * so use a static buffer and struct sbuf.
+ */
+ sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
+ sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
+ preload_dump_internal(&sb);
+
+ sbuf_finish(&sb);
+ sbuf_delete(&sb);
+}
+
+static int
+sysctl_preload_dump(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf sb;
+ int error;
+
+ if (preload_metadata == NULL)
+ return (EINVAL);
+
+ sbuf_new_for_sysctl(&sb, NULL, 512, req);
+ preload_dump_internal(&sb);
+
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+
+ return (error);
+}
+SYSCTL_PROC(_debug, OID_AUTO, dump_modinfo,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, sysctl_preload_dump, "A",
+ "pretty-print the bootloader metadata");
Index: sys/sys/linker.h
===================================================================
--- sys/sys/linker.h
+++ sys/sys/linker.h
@@ -257,6 +257,7 @@
extern caddr_t preload_search_info(caddr_t _mod, int _inf);
extern void preload_delete_name(const char *_name);
extern void preload_bootstrap_relocate(vm_offset_t _offset);
+extern void preload_dump(void);
#ifdef KLD_DEBUG
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 3:13 PM (10 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28745834
Default Alt Text
D26687.id77939.diff (7 KB)
Attached To
Mode
D26687: Add a routine to dump the boot metadata
Attached
Detach File
Event Timeline
Log In to Comment