An honest comparison of how this project's kmodloader stacks up against the GPU/driver autodetection mechanisms in GhostBSD, NomadBSD, the xlibre X server, and Linux's udev+modprobe stack. Includes the failure-mode analysis: what happens when a DRM kmod loads but doesn't recognize your GPU.
test_x rolls back on Xorg failure; we don't verify the kmod actually attached.kldunload cleanup pass for kmods that loaded but didn't bind./dev/devctl watcher).i915kms loads but the chip isn't in its supported table, the LinuxKPI shim returns ENXIO from pci_probe. The kmod stays resident (~10MB RAM), no drmn child attaches, vgapci0 keeps owning the slot, vt_efifb keeps owning the console, and Xorg falls back to scfb (UEFI) or vesa (BIOS). No crash, no console disruption.intel/modesetting/amdgpu), not kmod names. Doesn't tell us which kmods to load or skip.MODULE_PNP_INFO. Upstream PR to drm-kmod adding it would let our GPU pass collapse into devmatch.kextcache prelink optimization remains an interesting Phase 4+ idea.Eight axes that matter for GPU autodetection on FreeBSD.
| Axis | kmodloader (this project) | GhostBSD xconfig |
NomadBSD initgfx |
xlibre | Linux udev+modprobe | macOS kextd / IOKit |
|---|---|---|---|---|---|---|
| Implementation language | Objective-C (Foundation) under launchd | POSIX shell (1411 LOC) | POSIX shell (467 LOC) + sourced DB (1782 LOC) | C, inside Xorg server | C (libkmod) inside udevd | C++ (kextd, IOKit), launchd-supervised |
| Cadence | One-shot at boot (RunAtLoad); Phase 2 will add hot-plug |
Boot via rc.d, every boot unconditionally | Boot via rc.d, but PCI-hash short-circuit if hardware unchanged | Server start; not autoload-related | Hot-plug + boot, event-driven | Boot (kextcache prelink) + hot-plug (IOKit matching notifications) |
| Detection input | pciconf -l (class 0x0300xx) + devmatch(8) |
pciconf -lv grep + kern.vm_guest + dmesg |
pciconf -lv awk-parsed + hw.pci.default_vgapci_unit |
libpciaccess + udev DRM enum + drmGetVersion |
kernel MODALIAS uevent → pattern match |
IOKit IORegistry walk; IOService::probe per matching kext |
| (vendor:device) → driver source | 3 vendor IDs in code; for AMD split, 699-ID frozen list sourced from drm-kmod's drm_pciids.h |
701-ID inline regex sourced from drm-kmod's drm_pciids.h; NVIDIA branches by marketing-name string |
~507 AMD IDs + ~56 legacy Intel IDs in sourced DB; NVIDIA branches by marketing-name string | Inline switch(vendor) in C; modern Intel falls through to modesetting |
MODULE_DEVICE_TABLE in each .ko; depmod emits modules.alias |
IOKitPersonalities dict in each .kext/Info.plist with IOPCIMatch arrays |
| Validation that the driver actually works | No — load and trust | No — load and trust | Yes — test_x runs xinit with the proposed config; rollback on failure |
n/a (post-kmod) | No at module level (PCI probe is the validation) | Yes — IOService::probe returns IOProbeScore; highest-scoring kext wins; non-matching kexts never attach |
| Fallback to scfb/vesa/efifb | Implicit: vt_efifb stays in console if no DRM attaches; user/Xorg picks scfb |
Explicit scfb default; vesa manual subcommand |
Explicit, picks vesa on BIOS / scfb on EFI from machdep.bootmethod |
Falls back through fbdev/scfb/vesa in compile-time order |
n/a (kmod stays loaded; userspace X handles fallback) | n/a — Apple ships hardware + drivers as a unit; "no matching driver" effectively can't happen |
| "Kmod loaded but didn't attach" cleanup | No — ~10MB stuck per stale kmod | No | Indirect — test_x failure rolls back next-boot config but doesn't kldunload |
n/a | No — same shape: probe-fail leaves module resident | Yes — kexts that don't pass probe never load; kextcache only fuses kexts whose match succeeds |
| Hot-plug coverage | Phase 2 — planned but not shipped | No | Non-DRM only via dsbdriverd (DRM kmods explicitly excluded) |
n/a | Yes — udev rules trigger libkmod on every uevent | Yes — IOKit matching notifications fire on every IORegistry change |
| Multi-GPU / Optimus | Both vendors load (Intel + NVIDIA), each driver attaches to its own card | First vendor wins (Intel → AMD → NVIDIA); single GPU loaded | Walks each vgapci device and tries handlers; default vgapci first | Iterates platform devices, multi-card supported | All matching modules load; kernel binds each to its card | IOService probe scores per device; multiple GPUs each get their best-scoring kext |
| NVIDIA driver-version selection | One package only (current). Gap: no 340/390/470 legacy support | Marketing-name pattern picks nvidia-driver/-470/-390/-340 at runtime via pkg install |
All four NVIDIA branches pre-staged at image-build time; runtime symlinks the right one | Lists nvidia as one option; selection is xorg.conf-side |
Per-distro packaging picks one branch | n/a since 10.13 (NVIDIA support dropped); historically Apple shipped the kext, no version selection |
| Scope | Whole-system: GPU + NICs + WiFi + storage + USB classes + VM guest additions | GPU + Xorg config only | GPU + Xorg config only (non-GPU via separate dsbdriverd) |
X server only | All hardware classes | All hardware classes (IOKit owns everything driver-shaped) |
| Pre-link / boot speedup | No — load on demand at boot | No | No | n/a | No at the module-load layer (initramfs is a separate concept) | Yes — kextcache fuses kernel + matched kexts into a single boot image |
An ObjC daemon at /usr/libexec/kmodloader, started by launchd's org.freebsd.kmodloader.plist with RunAtLoad=true, KeepAlive=false. Three match paths run sequentially in a single runOneShot:
kmodloader/src/KMDaemon.m (~250 LOC) plus RadeonPCIIDs.h (the frozen 699-entry uint16_t array generated from upstream).PNP_INFO — if_em, if_iwlwifi, if_iwm, if_rtw88/89, ahci, nvme, umass, ACPI HID drivers, etc. GhostBSD and NomadBSD don't have an equivalent — they handle only GPU and rely on either base-kernel auto-attach (anything in GENERIC) or a separate tool (NomadBSD's dsbdriverd) for the rest.0x8086, AMD 0x1002, NVIDIA 0x10de) instead of hundreds. The AMD split uses the upstream-frozen radeon list (sourced from drm-kmod's include/drm/drm_pciids.h — same source GhostBSD uses), then defaults to amdgpu for everything else. New AMD silicon picks up amdgpu with no code change.kern.vm_guest and kldloaded VBox/VMware additions; removed because guest additions are services (loaded by their own launchd plist), not hardware drivers.xconfigSingle shell script bin/xconfig (1411 lines) plus an rc.d wrapper. Runs every boot via rc.d (logged to /var/log/xconfig_boot.log), persists choices in /etc/rc.conf's kld_list.
kern.vm_guest + dmesg grep for hypervisor type.pciconf -lv | grep -B4 VGA | grep -qi Intel|AMD|ATI|NVIDIA for vendor.RADEON_DEVICE at bin/xconfig:33) determines radeonkms vs amdgpu. Comment cites drm-kmod's drm_pciids.h as source.detect_nvidia_driver_version matches the GPU's pretty-print description against five marketing-name pipe-strings (latest / 580 / 470 / 390 / 340) checked newest-first. No PCI IDs for NVIDIA at all.kldload, persists via sysrc -f /etc/rc.conf kld_list+=.... Generates X config: deletes xorg.conf for Intel/AMD (modesetting handles it); uses X -configure + sed for NVIDIA.XF86Config.scfb template pinning Driver "scfb". vesa only via manual subcommand.Calls pkg install nvidia-driver-NNN at runtime, or pulls from offline /xdrivers/drivers-list for live ISOs. Means a live boot may need network for NVIDIA support unless the offline pkg cache is staged.
initgfxShell script config/etc/rc.d/initgfx (467 lines) plus sourced DB config/etc/initgfx_device.db (1782 lines) and Xorg templates. Runs at boot; persists via initgfx_kmods= in /etc/rc.conf; smart-skip on PCI hash unchanged.
The standout: test_x at initgfx:120-137. After loading the candidate kmod and writing the proposed Xorg config:
xinit session against the proposed config (xmessage -timeout 3).xinit exits non-zero, call __reset: revert config, try the next handler.test_x failure fall through to setup_nv (basic nv driver) before going to vesa/scfb.This catches the "kmod loaded but didn't attach" case indirectly via Xorg failing to start. None of the other systems do this.
Build-time, NomadBSD packs every NVIDIA branch (340 / 390 / 470 / latest per build.cfg:NVIDIA_DRIVERS) into /usr/local/nvidia/<ver>/. At boot, setup_nvidia picks the right version from marketing-name match, then symlinks the version's libGL / Xorg modules into place, runs ldconfig -m, installs libmap.d/nvidia.conf. Trades image size (~150MB extra) for offline reliability.
get_fallback_driver() {
case "$(sysctl -n machdep.bootmethod)" in
BIOS) echo vesa ;;
UEFI) echo scfb ;;
esac
}
Cleaner than GhostBSD's "always scfb." Matches the FreeBSD Handbook's Xorg recommendation exactly.
NomadBSD ships dsbdriverd for non-GPU drivers (NICs, sound, etc.). Its config explicitly excludes DRM kmods: exclude_kmods = { "radeonkms", "amdgpu", "i915kms" }. Two daemons, clean split. kmodloader collapses these into one process via the two-path scan.
xlibre is a fork of Xorg. Its detection runs at server start, after the DRM kmod is loaded. The vendor-switch table at hw/xfree86/common/xf86pciBus.c:1046-1264 maps PCI vendor → X driver name, not kmod:
| Vendor | X driver(s) tried |
|---|---|
0x1002 (AMD) | ati (a metadriver dispatching to radeon/amdgpu/r128/mach64 in userspace) |
0x8086 (Intel) | intel for pre-Gen3 only; modern Intel falls through to modesetting |
0x10de (NVIDIA) | nouveau (Linux/NetBSD) → modesetting → nvidia → nv |
/dev/dri/cardN exists. It consumes the result of kmod loading; it doesn't produce guidance for it.ati driver covers all AMD generations and dispatches based on drmGetVersion output — there's no "skip radeonkms because xlibre would never use it" signal.xf86LoadKernelModule exists but is a legacy DRI1 hook (dri.c:823) that's effectively dead on modern KMS systems. xlibre does NOT autoload i915kms/amdgpu/etc.xf86MatchDriverFromFiles() at xf86pciBus.c:1266 reads a directory of <driver>.ids files at compile-time-configured path. Disabled by default; only meaningful on Linux. Lets external X drivers advertise (vendor:device) support without source patches. Not a model we'd benefit from copying for kmod loading.
The reference design. Five steps:
MODULE_DEVICE_TABLE(pci, ...); emitted into the .ko's .modinfo ELF section as strings like pci:v00008086d00009A49sv*sd*bc03sc*i*.depmod -a reads .modinfo from every .ko and writes /lib/modules/$(uname -r)/modules.alias.MODALIAS=pci:..../lib/udev/rules.d/80-drivers.rules contains RUN{builtin}+="kmod load $env{MODALIAS}".kmod builtin (linked into udevd) calls libkmod in-process; libkmod fnmatch-globs MODALIAS against modules.alias, finds i915, calls init_module(2).This is exactly what FreeBSD already implements:
| Concept | Linux | FreeBSD |
|---|---|---|
| Per-module device table embedded in .ko | MODULE_DEVICE_TABLE | MODULE_PNP_INFO |
| Tool that grovels device tables out of modules | depmod → modules.alias | kldxref → linker.hints |
| Hotplug dispatcher | udev + libkmod | devd → devmatch → kldload |
| Boot enumeration | kernel uevents on init | devmatch -a reads device tree at boot |
Linux's drm modules (i915.ko, amdgpu.ko, nouveau.ko) all declare MODULE_DEVICE_TABLE. FreeBSD's drm-kmod (a LinuxKPI port of the same code) doesn't — the LinuxKPI shim doesn't translate MODULE_DEVICE_TABLE into MODULE_PNP_INFO. That single missing translation is why we need a GPU PCI scan at all. Devmatch handles every other driver in tree.
If the .ko loads but the live device ID isn't in the module's pci_ids: the driver's .probe() is never called, the device sits unbound. Modern kernels expose i915.force_probe=, amdgpu.force_probe= etc. for users with too-new hardware. There is no userspace "fall back to a different kernel module" mechanism — udev hands MODALIAS to libkmod, gets a hit or miss, and that's it.
The original kmodloader plan was modeled directly on Apple's kextd + IOKit personality matching. Phase 1a-c shipped a literal port of that idea (.kext bundles in /System/Library/Extensions/, IOKitPersonalities dicts, integer probe scores, highest-scoring kext wins). Phase 1d ripped it out in favor of devmatch for FreeBSD-specific reasons. Worth showing the reference architecture both for design provenance and to answer "why don't you just do what Apple does?"
kextd is a launchd-supervised daemon (com.apple.kextd.plist). On startup it:
/System/Library/Extensions/*.kext/ and /Library/Extensions/*.kext/.Contents/Info.plist, extracts the IOKitPersonalities dict.kextload(8)-equivalent.kAppleEventLoopMessage-style notifications: when a new device appears in IOKit's IORegistry, kextd is told and re-runs matching for that device.The kernel keeps a personality registry indexed by match category ("PCI", "USB", "USBClass", etc.). When IOKit sees a new device, it walks the registry, calls IOService::probe on every personality whose match dict could apply, and binds the device to the highest-scoring service.
An IOKit personality looks like this (Apple's actual i915 driver, simplified):
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.driver.AppleIntelKBLGraphicsFramebuffer</string>
<key>IOClass</key> <string>AppleIntelKBLFramebuffer</string>
<key>IOMatchCategory</key> <string>IOFramebuffer</string>
<key>IOPCIMatch</key>
<array>
<string>0x59168086</string> <!-- HD Graphics 620 -->
<string>0x591B8086</string> <!-- HD Graphics 630 -->
<!-- ... -->
</array>
<key>IOProbeScore</key> <integer>90000</integer>
</dict>
The probe call returns either 0 (don't match, skip) or a positive score. Higher score wins; ties broken by personality registration order. Non-matching personalities never get a probe call — the match dict is the gate.
This is what kmodloader Phase 1a-c implemented in kmodloader/personalities/*.kext/Contents/Info.plist with our own probe-score algorithm. Worked correctly for hardware we hand-curated; failed scaling because FreeBSD's drm-kmod doesn't ship Info.plists with IOPCIMatch arrays, so we'd be hand-curating ~2000 device IDs ourselves — without Apple's full-time staff to maintain them.
Apple's optimization for boot speed: kextcache fuses the kernel binary plus every kext that matched at last-boot into a single signed boot image (/System/Library/PrelinkedKernels/prelinkedkernel). At boot the loader maps the prelinked kernel directly — no per-boot scan of /System/Library/Extensions/, no per-kext load decisions, no probe loop. The matching work happened once at install time.
Plan §11 Phase 4 flagged this as a future optimization for kmodloader; it remains a Phase-4 idea. The Apple-shape parallel is roughly: at install time, run kmodloader's two-path scan, write the result to a manifest, have /boot/loader consume the manifest and pre-load on next boot. Defers all the "vendor scan + devmatch" work from boot to install.
Since macOS 10.15 / iOS 14, Apple has been moving drivers out of the kernel and into sandboxed userspace processes called .dext bundles (DriverExtension). Each dext is a launchd-launched signed binary that talks to a small in-kernel "personality" stub via IOKit's DriverKit framework. Match logic stays the same (IOPCIMatch in the dext's Info.plist); the actual driver code runs in userspace.
Genuinely interesting as a long-term direction but not on kmodloader's roadmap. FreeBSD has no equivalent to DriverKit's userspace-driver kernel infrastructure today, and porting one is a project comparable to launchd itself.
We started here (Phase 1a-c) and reached a different place (Phase 1d-1g) for three reasons:
linker.hints built from MODULE_PNP_INFO macros gives us the same (vendor:device → kld) map for every in-tree driver. devmatch(8) is the canonical reader. We don't need to reinvent the registry; we need to use the one FreeBSD already has.The Apple-shape design we kept: launchd supervision, ObjC implementation, plist-based config, the conceptual model of "a daemon that owns kernel-extension loading." The Apple-shape design we dropped: the per-driver IOPCIMatch personality plist as the load-decision data structure.
The user's specific concern: what happens in our case when the device is too new for the latest drm-kmods? Detailed answer with FreeBSD source citations.
drm-kmod's i915kms registers as a pci_driver via LinuxKPI. Newbus calls linux_pci_probe() at sys/compat/linuxkpi/common/src/linux_pci.c:506:
if ((pdrv = linux_pci_find(dev, &id)) == NULL)
return (ENXIO);
linux_pci_find() walks the driver's id_table matching on vendor/device/subvendor/subdevice. If the chip isn't in the table, probe returns ENXIO. Newbus tries the next driver in priority order; vgapci(4) wins by default at BUS_PROBE_GENERIC.
If the chip is in the table but flagged require_force_probe, drm-kmod's i915_pci.c emits the canonical "too-new" dmesg line:
Your graphics device 0xNNNN is not properly supported by i915 in this
kernel version. To force driver probe anyway, use i915.force_probe=NNNN
module parameter or CONFIG_DRM_I915_FORCE_PROBE=NNNN configuration option,
or (recommended) check for kernel updates.
And returns -ENODEV. Same outcome: no drmn child attaches.
| Layer | State after probe failure |
|---|---|
| kmod | Stays loaded. kldstat shows i915kms.ko resident (~10MB). No CPU, no IRQ, no /dev/dri/cardN. |
vgapci0 | Stays attached to the GPU's PCI slot. No regression. |
| Console (UEFI boot) | vt_efifb stays in charge. Full-resolution framebuffer, unaccelerated. Works. |
| Console (BIOS boot) | vt_vga stays in charge. Text mode. Works. |
| Xorg (any boot) | Falls through modesetting (no DRM, fails) → scfb (UEFI) or vesa (BIOS). Native res on UEFI, low VESA modes on BIOS. No crash. |
nvidia.ko + nvidia-modeset.ko + nvidia-drm.ko behave differently:
hw.nvidiadrm.modeset is unset (or 0), nvidia-drm loads but skips DRM device creation. Kmod resident, no /dev/dri/cardN. Set in /boot/loader.conf; kmodloader does this.NVRM: The NVIDIA <chip> GPU installed in this system is not supported by the <ver> NVIDIA driver and refuses. Same end state — no /dev/dri/cardN, no crash.vt_efifb framebuffer is the universal fallback and stays in place exactly because no DRM driver attached to take it over.
DISPATCH_SOURCE_TYPE_READ on /dev/devctl, structured logging, optional kldunload cleanup pass).
drm_pciids.h), but baked into RadeonPCIIDs.h at build time so we can iterate the array directly in C without shell regex. amdgpu becomes the open default — no maintenance for new AMD silicon.
kern.vm_guest → vbox/vmware kld lists). Pulled out: guest additions are services, not hardware drivers; they belong in their own launchd plist (org.freebsd.vboxservice.plist Phase 2+) which kldloads its supporting kmods before launching the userspace daemon.
test_x runs a real xinit after loading the kmod and rolls back the choice if Xorg can't start. We don't. If our vendor map is wrong (shouldn't happen for the three vendors but possible if drm-kmod renames a kld), the user discovers it when X doesn't come up. Mitigation path: add an optional Phase 2+ check that dev.drmn.0.%pnpinfo exists after kmod load; if not, log warning. Doesn't replicate test_x's full smoke test but catches the obvious case.
amdgpu on a system whose AMD GPU is in the radeonkms-frozen list (so our split routed correctly to radeonkms), amdgpu doesn't get loaded — fine. But if we load all four GPU kmods speculatively and only one binds, the others sit at ~10MB each. Phase 2+ enhancement: post-load, check for drmn children under each vgapci; kldunload the unbound ones. Current behavior is correct (we only load per-vendor, not all four), so this is a future polish, not a fix.
nvidia-driver-470, -390, or -340 instead of current. We ship one nvidia-drm-latest-kmod. NomadBSD bakes all four branches at build time and picks at boot via marketing-name match; GhostBSD pkg installs the right one at runtime. Fix: add the three legacy nvidia-driver packages to pkglist.txt and extend the GPU-vendor scan to map NVIDIA marketing-name strings to specific kmod names. Cost: ~200MB on the ISO (NomadBSD's penalty for the same coverage).
DISPATCH_SOURCE_TYPE_READ on /dev/devctl, parse +/? events (attach / nomatch), re-run the appropriate match path.
vt_efifb keeps the console on UEFI systems — works correctly without us doing anything. But we don't verify this; we don't generate an Xorg fallback config. Acceptable today (Xorg autoconfig handles scfb fallback); becomes a policy question if we ship an X server with strict driver requirements.
The user's prompt asked specifically about xlibre's devmatch detection so kmodloader doesn't load too aggressively. Conclusion after deep-reading xlibre source:
/dev/dri/cardN and falls through to scfb/vesa/fbdev if none does. This is graceful but not a guidance signal.
The right framing is: don't expect xlibre to filter our kmod-load decisions. Filtering belongs to the kmod-load layer (us). What xlibre does provide is a clean fallback through its listPossibleVideoDrivers() chain (modesetting → fbdev/scfb → vesa) that handles "no DRM kmod attached" without panic — confirming that loading drm-kmod kmods speculatively is safe.
| Priority | Item | Effort |
|---|---|---|
| High | Phase 2 hot-plug (devctl source). Closes the biggest functional gap vs Linux. | ~300 LOC ObjC + plist KeepAlive=true. |
| Medium | NVIDIA legacy driver-version selection. Add nvidia-driver-{470,390,340}-kmod to pkglist; extend GPU-vendor scan with marketing-name → kmod map. | ~50 LOC + ~200MB pkglist. |
| Medium | Optional kldunload cleanup pass for unbound kmods. Check dev.drmn.* after load; unload if no children. | ~30 LOC. |
| Low | Live validation lite: log warning if a loaded GPU kmod has no drmn child after a brief settle delay. | ~20 LOC. |
| Long-term | Upstream PR to drm-kmod adding MODULE_PNP_INFO declarations from each driver's compiled-in supported list. Would let our GPU PCI scan collapse into devmatch. | Out of our control; coordinate with drm-kmod maintainers. |
drm-kmod is the canonical case kmodloader's GPU PCI scan addresses. But it isn't the only ports kld package that may have the same problem — "the kld ships from ports without MODULE_PNP_INFO, so devmatch can't see it, so we'd need a vendor-scan-style fallback or speculative load." Each of these needs a one-shot investigation: install the package, run kldxref -d /boot/modules/linker.hints | grep <name>, and see whether devmatch picks it up. If yes, no kmodloader change — just add the package to pkglist.txt. If no, we need the same kind of targeted handling we do for GPUs.
For any ports kld package that ships an if_* / wmt_* / similar driver kmod:
# 1. Install on a test system
pkg install <package>
# 2. Re-build hints (pkg post-install does this, but be explicit)
kldxref /boot/modules
# 3. Look for the driver in the hints database
kldxref -d /boot/modules/linker.hints | grep -i <driver>
# 4. Look for PNP_INFO sections in the .ko binary
strings /boot/modules/<driver>.ko | grep -i pnp_info
# 5. Try devmatch directly (after kldunload to make the device unattached)
devmatch | grep -i <driver>
Outcomes:
pkglist.txt, devmatch handles the rest. Zero kmodloader code change.MODULE_PNP_INFO. Same problem we have for drm-kmod. Two choices:
MODULE_PNP_INFO declarations from the driver's compiled-in supported table. Best long-term answer; works for everyone.| Package | What it ships | Why it might need help | Investigation status |
|---|---|---|---|
net/realtek-re-kmod |
Newer Realtek 2.5G/5G ethernet driver (if_re) from Realtek's upstream source — supersedes the base if_re for RTL8125/8126 etc. |
Ports build of a vendor-supplied tarball; PNP_INFO presence is upstream-source-dependent. Common on motherboards with 2.5GbE NICs (most boards 2022+). | TODO: install on a test system with an RTL8125 NIC, run the procedure above. Likely outcome: has PNP_INFO (Realtek's source declares device IDs); just needs adding to pkglist. |
net/rtl8821au-kmod /net/rtl88xxau-kmod /net/rtw88-kmod |
Realtek USB WiFi drivers (LinuxKPI ports of out-of-tree Linux drivers). | LinuxKPI ports — the same drm-kmod issue applies. Linux's MODULE_DEVICE_TABLE doesn't auto-translate to FreeBSD's MODULE_PNP_INFO through the LinuxKPI shim. Almost certainly have the same gap as drm-kmod. |
TODO: confirm gap. If confirmed, options are: (a) speculative load — add to pkglist, kmodloader kldloads on USB-class match for known Realtek vendor IDs, similar to GPU pass; (b) extend devmatch's source data to include LinuxKPI's id-tables (upstream effort). |
x11-drivers/xf86-input-evdev+ kernel evdev support |
Userspace X input driver consuming kernel evdev events. Touchscreens, multitouch trackpads, advanced HID devices. | The kernel side (evdev, wmt, iichid) is in base and has PNP_INFO via standard USB/IIC class match. The Xorg driver loads on top. Likely no kmodloader work needed. |
Verify: run devmatch on a system with a Precision Touchpad — should suggest iichid/wmt. If yes, fine. |
"utouch" family (USB touch controllers via uhid+hidraw) |
Various USB touchscreens, touch-bar-like devices, drawing tablets. Driven by uhid/ums/wmt in base; ports versions extend or supersede. |
Mostly works via base USB class drivers (uhid matches USB HID class generically). The "ports needed" cases are usually graphics tablets with proprietary protocols (Wacom etc.). Some have FreeBSD support via x11-drivers/xf86-input-wacom + evdev. |
TODO: list specific devices that don't work via base USB classes; investigate per-device. |
graphics/drm-kmod-experimental /future drm-kmod-next |
Bleeding-edge drm-kmod for hardware too new for the stable release (e.g., Intel Battlemage, latest RDNA). | Same shape as drm-kmod (no PNP_INFO via LinuxKPI). Our GPU PCI scan would route Intel/AMD GPUs to i915kms/amdgpu regardless — so users who install drm-kmod-experimental and uninstall drm-kmod get the right kld name; just a swap. Conflict if both installed. |
Trivial: document that experimental and stable are mutually exclusive; the kld name doesn't change so kmodloader's PCI scan handles either. |
NVIDIA legacy nvidia-driver-{340,390,470}-kmod |
Older NVIDIA branches for Kepler / Fermi / Tesla generations. | Already flagged as a gap in §9. NomadBSD bakes all four branches; we ship one. Solving this needs a marketing-name → kmod-name map at the GPU pass. | Open; tracked in §11 Recommendations as medium priority. |
sysutils/xen-kmod |
Xen guest extensions kld for newer Xen versions than base supports. | Xen guest base support is in GENERIC kernel. Ports kld is for newer features (PCI passthrough, etc.). Probably not auto-load territory; user-driven. | Defer: not a common live-ISO scenario. |
net/wireguard-kmod |
WireGuard VPN as a kld (when not built into kernel). | Already in GENERIC kernel as of 13.x. Kld package is for older releases. Not relevant on 14.x/15.x targets. | n/a on our target. |
multimedia/v4l_compat /multimedia/webcamd |
Video4Linux compat for webcams + USB webcam daemon. | webcamd is a userspace daemon that talks to USB devices; not a kld. v4l_compat is a header-only port. Neither is a kmodloader concern; they're launchd-service-shaped. |
n/a for kmodloader; relevant for a future "media services" plan. |
For each port-shipped kld package we want on the ISO, the decision tree is:
pkglist.txt with a comment citing the test result. Done. devmatch handles it on every boot via the existing path.MODULE_PNP_INFO. Upstream maintainer reviews, ships, FreeBSD pkg rebuilds, problem disappears for everyone using FreeBSD.KMDaemon.m, similar to the GPU PCI scan but for the relevant device class (USB vendor:device for Realtek WiFi adapters; PCI vendor:device for Realtek 2.5G ethernet; etc.). Cost: per-driver code, but small.kldload <name> manually after pkg install. Acceptable for low-priority hardware where the user is already in setup-mode.None of these candidates are blocking Phase 1 functionality; they're TODOs to work through as users surface needs. The shape of the answer is the same for each: investigate empirically, then either pkglist-only or pkglist+code.
kmodloader/src/RadeonPCIIDs.h (generated from drm-kmod's drm_pciids.h)bin/xconfig:374-403 (vendor probes), :456-462 (radeon split), :641-672 (NVIDIA branch)cardDetect/XF86Config.{scfb,vesa,safe}config/etc/rc.d/initgfx:140-219 (PCI parser), :240-345 (handlers), :374-390 (fallback)config/etc/rc.d/initgfx:120-137 (test_x)config/etc/initgfx_device.dbconfig/usr/local/etc/dsbdriverd/config.lua:7hw/xfree86/common/xf86AutoConfig.c:166-225 (top-level), xf86pciBus.c:1046-1264 (vendor → driver table)hw/xfree86/common/xf86platformBus.c:206, os-support/shared/drm_platform.c:24MODULE_DEVICE_TABLE macro: kernel include/linux/module.hdepmod / modules.alias: kernel.org kmod/lib/udev/rules.d/80-drivers.rules (RUN{builtin}+="kmod load $env{MODALIAS}")linux_pci.c:506 — LinuxKPI probe returning ENXIO on id_table missvga_pci.c:344 — vgapci probe at BUS_PROBE_GENERICvt_core.c:3275 — vt_replace_backend() only fires when DRM attacheskextd source: github.com/apple-oss-distributions/IOKitTools (referenced for design — not vendored)kextcache(8) man page (prelinked-kernel construction): macOS man pages — search kextcache