Page MenuHomeFreeBSD

D26687.id77939.diff
No OneTemporary

D26687.id77939.diff

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

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)

Event Timeline