DF-5789 / walker.c
/* * DF-5789 walker — dump the flat device tree via hw.bus.devices exactly * the way libdevctl/devd does, and flag zombie devices: still parented * (present in the tree) but with state < DS_ATTACHED and no driver. * This is what an UNPRIVILEGED user can observe. */ #include <sys/types.h> #include <sys/sysctl.h> #include <err.h> #include <stdio.h> #include <string.h> #include <stdlib.h> struct u_businfo { int ub_version; int ub_generation; }; struct u_device { uintptr_t dv_handle; uintptr_t dv_parent; char dv_name[32]; char dv_desc[32]; char dv_drivername[32]; char dv_pnpinfo[128]; char dv_location[128]; uint32_t dv_devflags; uint16_t dv_flags; int dv_state; }; #define DS_NOTPRESENT 0 #define DS_ALIVE 1 #define DS_INPROGRESS 2 #define DS_ATTACHED 3 #define DS_BUSY 4 static const char *statename[] = { "NOTPRESENT", "ALIVE", "INPROGRESS", "ATTACHED", "BUSY" }; int main(void) { struct u_businfo ubus; struct u_device udev; int mib[16], genmib[16], gmib[16]; size_t len, glen; int gen, idx, nz; len = sizeof(genmib); if (sysctlnametomib("hw.bus.info", genmib, &len) < 0) err(1, "sysctlnametomib(hw.bus.info)"); glen = sizeof(ubus); if (sysctl(genmib, len, &ubus, &glen, NULL, 0) < 0) err(1, "sysctl(hw.bus.info)"); gen = ubus.ub_generation; printf("generation %d (version %d)\n", gen, ubus.ub_version); len = sizeof(mib); if (sysctlnametomib("hw.bus.devices", mib, &len) < 0) err(1, "sysctlnametomib(hw.bus.devices)"); memcpy(gmib, mib, (len + 2) * sizeof(int)); gmib[len] = gen; nz = 0; for (idx = 0; idx < 4096; idx++) { size_t sz = sizeof(udev); gmib[len + 1] = idx; if (sysctl(gmib, len + 2, &udev, &sz, NULL, 0) < 0) break; if (idx < 3 || udev.dv_state < DS_ATTACHED || strcmp(udev.dv_drivername, "") == 0) { printf("[%3d] %-12s drv=%-10s state=%-11s parent=%#lx\n", idx, udev.dv_name, udev.dv_drivername, udev.dv_state <= DS_BUSY ? statename[udev.dv_state] : "?", (unsigned long)udev.dv_parent); if (udev.dv_state < DS_ATTACHED && strcmp(udev.dv_drivername, "") == 0) nz++; } } printf("total listed (capped 4096): %d; ZOMBIES (no driver, state<ATTACHED): %d\n", idx, nz); return (0); } |