DF-5015 / offmod2.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* * offmod2 v2 -- DF-5015 in-kernel evidence probe (crash-safe). * sysctl hw.df5015: live syscons history state of the ACTIVE scp + * count of Z-cells (0x075a) in the page BEFORE the history buffer. */ #include <sys/param.h> #include <sys/stdint.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/module.h> #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/bus.h> #include <sys/consio.h> #include <sys/fbio.h> #include <vm/pmap.h> #include <dev/misc/syscons/syscons.h> static char report[4096]; static int df5015_state(SYSCTL_HANDLER_ARGS) { devclass_t dc; device_t dev; sc_softc_t *sc; scr_stat *scp; sc_vtb_t *vtb; int n = 0; dc = devclass_find("sc"); if (dc == NULL) { n = ksnprintf(report, sizeof(report), "no sc devclass"); goto out; } dev = devclass_get_device(dc, 0); if (dev == NULL) { n = ksnprintf(report, sizeof(report), "no sc0 device"); goto out; } sc = device_get_softc(dev); if (sc == NULL || sc->cur_scp == NULL) { n = ksnprintf(report, sizeof(report), "no softc/cur_scp"); goto out; } scp = sc->cur_scp; if (scp->history == NULL) { ksnprintf(report, sizeof(report), "scp=%p history=NULL xsize=%d ysize=%d", scp, scp->xsize, scp->ysize); goto out; } vtb = scp->history; n = ksnprintf(report, sizeof(report), "scp=%p vtb=%p cols=%d rows=%d size=%d buf=%p tail=%d " "xsize=%d ysize=%d", scp, vtb, vtb->vtb_cols, vtb->vtb_rows, vtb->vtb_size, vtb->vtb_buffer, vtb->vtb_tail, scp->xsize, scp->ysize); if (vtb->vtb_buffer != NULL) { uint16_t *prev = (uint16_t *)((char *)vtb->vtb_buffer - 4096); vm_paddr_t pa = pmap_kextract((vm_offset_t)prev); int zprev = -1, zin = -1, i; if (pa != 0 && pmap_kextract((vm_offset_t)(prev + 2047)) != 0) { zprev = 0; for (i = 0; i < 2048; i++) if (prev[i] == 0x075a) zprev++; } if (vtb->vtb_size > 0 && vtb->vtb_size <= 65536) { zin = 0; for (i = 0; i < vtb->vtb_size; i++) if (vtb->vtb_buffer[i] == 0x075a) zin++; } if (n < (int)sizeof(report) - 1) ksnprintf(report + n, sizeof(report) - n, " prevphys=%#llx zprev=%d zin=%d", (unsigned long long)pa, zprev, zin); } out: return SYSCTL_OUT(req, report, strlen(report) + 1); } SYSCTL_PROC(_hw, OID_AUTO, df5015, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, df5015_state, "A", "DF-5015 syscons history probe"); static int offmod2_load(module_t mod, int what, void *arg) { switch (what) { case MOD_LOAD: kprintf("DF5015OFF2 loaded\n"); return 0; case MOD_UNLOAD: return 0; default: return 0; } } static moduledata_t offmod2_mod = { "offmod2", offmod2_load, NULL }; DECLARE_MODULE(offmod2, offmod2_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |