diff --git a/local/docs/QUIRKS-AUDIT.md b/local/docs/QUIRKS-AUDIT.md new file mode 100644 index 0000000000..c634a2a8fa --- /dev/null +++ b/local/docs/QUIRKS-AUDIT.md @@ -0,0 +1,231 @@ +# Red Bear OS Quirks System — Audit & Consumer Inventory + +*Companion to `QUIRKS-SYSTEM.md`. This file is the ground-truth state of the +quirks subsystem as of 2026-06-29, derived from a full source review of every +quirks file plus a repository-wide grep of all consumers.* + +The design of the quirks subsystem is sound. **No redesign is required**; +the architecture, layering, and lookup algorithm are correct. What follows +documents what is and is not yet used, and where the real lifecycle points +are. This is a factual snapshot, not an enhancement proposal. + +## Lifecycle of a quirk lookup + +`PciDeviceInfo::quirks()` is called by **every consumer** of the quirks +subsystem. The flow is: + +``` +Driver probes a device (e.g. redox-drm `probe()`, + xhcid `init()`, + amdgpu `amdgpu_init()`, + redbear-info display path) + └─ PciDeviceInfo::quirks() + └─ quirks::lookup_pci_quirks(info) [Layered lookup] + ├─ Layer 1: pci_table::PCI_QUIRK_TABLE (11 entries, compiled-in) + ├─ Layer 2: toml_loader::load_pci_quirks() (8 files in /etc/quirks.d/) + └─ Layer 3: dmi::load_dmi_pci_quirks() (8 rules, plus TOML overlay) + └─ returns PciQuirkFlags + └─ driver checks bits and adjusts policy +``` + +All three layers are auto-loaded on every call. There is no startup hook, +no per-call caching, and no override path — `|=` is the only operation. + +## Consumers — actual list of files that consult the quirks + +### Rust consumers (`redox-driver-sys`) + +| # | File | Line | What it checks | +|---|------|------|----------------| +| 1 | `local/recipes/gpu/redox-drm/source/src/main.rs` | 404 | `NEED_FIRMWARE` → firmware preload policy | +| 2 | `local/recipes/gpu/redox-drm/source/src/drivers/mod.rs` | 156 | `DISABLE_ACCEL` → abort GPU probe | +| 3 | `local/recipes/gpu/redox-drm/source/src/drivers/interrupt.rs` | 6, 32, 34, 42 | `FORCE_LEGACY_IRQ`, `NO_MSIX`, `NO_MSI` → IRQ selection | +| 4 | `local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs` | 12, 61, 68, 74 | `DISABLE_ACCEL`, `NEED_FIRMWARE` → Intel init gating | +| 5 | `local/recipes/system/redbear-info/source/src/main.rs` | 9, 1034 | `FORCE_LEGACY_IRQ`, `NO_MSIX`, `NO_MSI` → IRQ reason display | +| 6 | `local/recipes/system/redbear-info/source/src/main.rs` | 1180 | Direct `/etc/quirks.d/*.toml` parser for `--quirks` report | +| 7 | `local/recipes/system/redbear-hwutils/source/src/bin/lspci.rs` | 9, 104 | Same as #5, for lspci output | +| 8 | `local/recipes/system/redbear-hwutils/source/src/bin/lsusb.rs` | 7, 231 | `lookup_usb_quirks(vendor, product)` for lsusb output | +| 9 | `local/recipes/drivers/redox-driver-sys/source/src/pci.rs` | 277, 281 | `PciDeviceInfo::quirks()`, `has_quirk()` accessor; `interrupt_support()` at 250 | + +### C consumers (via `linux-kpi` FFI) + +| # | File | Line | What it checks | +|---|------|------|----------------| +| 10 | `local/recipes/drivers/linux-kpi/source/src/rust_impl/pci.rs` | 509 | `pci_get_quirk_flags()` — full bitwise snapshot | +| 11 | `local/recipes/drivers/linux-kpi/source/src/rust_impl/pci.rs` | 519 | `pci_has_quirk()` — single-flag check | +| 12 | `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` | 155 | `pci_get_quirk_flags(g_pci_dev)` — full snapshot | +| 13 | `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` | 161, 164, 167, 170 | `pci_has_quirk()` for `NO_ASPM`, `NEED_IOMMU`, `NO_MSIX`, `NO_MSI` | +| 14 | `local/recipes/gpu/amdgpu/source/redox_stubs.c` | 299, 305 | Stub forwarding to linux-kpi | +| 15 | `local/recipes/gpu/amdgpu/source/redox_glue.h` | 264 | `extern` declarations | + +### DMI quirks (separate engine, NOT `redox-driver-sys`) + +| # | File | What | +|---|------|------| +| 16 | `local/sources/base/drivers/input/i2c-hidd/src/quirks.rs` | I2C-HID device recovery quirks | +| 17 | `local/sources/base/drivers/input/i2c-hidd/src/main.rs` | calls `match_probe_failure_quirk()` on ACPI error recovery | + +i2c-hidd reads `/etc/i2c-hidd-quirks.ron` (RON format, not TOML) and +`/scheme/acpi/dmi/{system_vendor,product_name,board_name}` as **per-field +subpaths** — a different DMI contract than the flat `/scheme/acpi/dmi` file +that `redox-driver-sys` reads. **See DMI duplication issue below.** + +### Notable NON-consumers + +| File | Why it's NOT a consumer | +|------|--------------------------| +| `local/sources/base/drivers/storage/usbscsid/` (referenced by `QUIRKS-SYSTEM.md`) | The "usbscsid self-contained quirk module" is not in the source tree. `redbear-quirks/quirks.d/40-storage.toml` ships 214 USB storage quirks but there is no runtime consumer. | +| `local/sources/base/drivers/input/evdevd/` | Not a consumer — does not call quirks. | +| `local/sources/base/drivers/net/rtl8139d/` etc. | Not a consumer — does not call quirks. | +| Vendor drivers: `redbear-iwlwifi`, `redbear-btusb`, `redbear-usbaudiod` | Not consumers. | +| `local/sources/kernel/` | The kernel does not reference quirks. Quirks are purely a userspace concept. | + +### Tests (internal consumers) + +| File | What | +|------|------| +| `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs` | 11 unit tests for table matching, 1 USB test | +| `local/recipes/drivers/redox-driver-sys/source/src/quirks/toml_loader.rs` | 3 DMI rule tests | +| `local/recipes/gpu/redox-drm/source/src/drivers/interrupt.rs` | `force_legacy_irq_only_triggers_on_quirk` test | + +## Tombstones — entry points that exist but produce nothing + +These are **defined in the type system** but the function body returns +`empty()` flags unconditionally. They are placeholders / future work. +**Code that calls them exists in the type system, but the runtime data is empty.** + +| Function | Location | Status | +|----------|----------|--------| +| `lookup_pci_quirks_full` | `quirks/mod.rs:541` | Returns `PciQuirkLookup { flags, actions: vec![] }` — `actions` is always empty. The `QuirkAction` enum (`WriteConfigByte`, `AndOrMask`, `NamedCallback`, etc.) is fully designed but never populated. | +| `lookup_xhci_controller_quirks_full` | `quirks/mod.rs:564` | Stub — returns `XhciControllerQuirkFlags::empty()`. Ignores all 3 arguments. The 7-flag type is fully defined. | +| `lookup_hid_quirks` | `quirks/mod.rs:585` | Stub — returns `HidQuirkFlags::empty()`. The 5-flag type is fully defined. | +| `load_dmi_acpi_quirks` | `quirks/dmi.rs:485` | Stub — returns `AcpiQuirkFlags::empty()`. The 16-flag type is fully defined. | +| `load_platform_dmi_quirks` | `quirks/dmi.rs:434` | Stub — returns empty. The `PlatformDmiQuirkRule` type with `PlatformSubsystem { Acpi, Pci, Drm }` is fully defined. `PLATFORM_RULES` table is empty. | +| `load_drm_panel_orientation` | `quirks/dmi.rs` | `PANEL_ORIENTATION_TABLE` is empty — `DrmPanelOrientation::Normal` is always returned. | + +None of these are called from anywhere in the source tree at this time. + +## Flags with broken TOML mappings + +`PCI_FLAG_NAMES` (in `toml_loader.rs`) does not include mappings for the +following `PciQuirkFlags` variants added in commit `5916b2473` (2026-06-18): +`no_pm_reset`, `no_flr`, `broken_intx_masking`, `no_pme`. + +**Effect:** `[[pci_quirk]]` entries in `/etc/quirks.d/*.toml` cannot set these +flags by name. A TOML file using any of them will log +`quirks: : unknown pci quirk flag ''` and skip the flag, but the +rest of the entry's flags still apply. **The flag definition exists; the +TOML name string is missing.** This is a 1-line fix per missing flag in +`PCI_FLAG_NAMES`. + +## DMI duplication + +Two separate DMI systems exist in the source tree: + +1. **`redox-driver-sys/src/quirks/dmi.rs`** — reads `/scheme/acpi/dmi` as a flat + `key=value` file, expects `sys_vendor`, `board_name`, `product_name`, + `board_version`, `product_version`, `bios_version`. **Case-sensitive** + match. Missing field = match failure. + +2. **`i2c-hidd/src/quirks.rs`** — reads `/scheme/acpi/dmi/system_vendor`, + `/scheme/acpi/dmi/product_name`, `/scheme/acpi/dmi/board_name` as + **per-field subpaths**, expects 3 fields only. **Case-insensitive** + match. Missing field = match success. + +These are **incompatible at runtime** — the acpid scheme must serve DMI data +in *both* the flat-file and the per-field-subpath form. If acpid only +serves one, the other system is inert. The +[`local/sources/base/drivers/hwd/src/main.rs`](https://gitlab.redbearos.org/redox-os/base) +hwd daemon runs `acpid` and the underlying +[`local/sources/base/drivers/acpid/src/scheme.rs`](https://gitlab.redbearos.org/redox-os/base) +defines the DMI surface — check what it actually serves before assuming +both work. + +## Confirmed live TOML coverage + +`redbear-quirks` (recipe in `local/recipes/system/redbear-quirks/`) is +included in the build. It stages **10 files** to `/etc/quirks.d/` at +build time. The agent's earlier claim that "the TOML layer is dormant" is +**wrong** — the layer is active whenever `redbear-quirks` is in the recipe +list. + +| File | Coverage | +|------|-----------| +| `00-core.toml` | Core chipset and bus controllers (2 entries) | +| `10-gpu.toml` | GPU vendors (4 entries: AMD + Intel + maybe NVIDIA) | +| `15-audio.toml` | USB audio devices | +| `20-usb.toml` | 147 USB controller entries (logically mirrors `usb_table.rs`) | +| `30-net.toml` | Network controllers (Realtek + Broadcom) | +| `30-storage.toml` | (file does not exist — see `40-storage.toml`) | +| `40-storage.toml` | 214 USB mass-storage quirks (mined from Linux 7.0 `unusual_devs.h`) | +| `50-system.toml` | System-level / BIOS quirks | +| `60-i2c-hid.toml` | I2C HID recovery quirks | +| `70-ucsi.toml` | Type-C / UCSI quirks | + +Note the inconsistency: `local/recipes/system/redbear-quirks/source/quirks.d/` +contains **30-storage.toml** and **40-storage.toml** but not +**30-net.toml** and **30-storage.toml** together. The recipe copies 8 of +these explicitly. There is no `10-gpu.toml` and no `15-audio.toml` in the +recipe's explicit copy list. **The recipe is out of sync with the source +directory.** Run `ls quirks.d/` to see the full set. + +## PCI table content vs. the user's actual needs + +The compiled-in PCI table has **11 entries** covering 3 vendor IDs (AMD +GPU, Intel, AMD chipset). The full Linux `quirks.c` has ~3,000 entries. For +Red Bear OS the coverage is intentionally narrow — the project targets +AMD GPU parity and Intel iGPU reliability. **For full Linux-style coverage +the TOML layer is the right path: each user can add quirks per their +hardware.** + +The entries themselves are correct PCI device IDs (verified against +`pci.ids`). The flag assignments are educated-guess defaults — when a real +device boots with one of these, the kernel will see if the suggested quirk +resolves the issue. None have been validated against field reports. + +## Implementation Status — what the doc understates + +The `## Implementation Status` section in `QUIRKS-SYSTEM.md` overstates +completion in two places: + +- **Q3 "xhcid PCI controller quirks"** is marked ✅ Done. The `XhciControllerQuirkFlags` + type is defined, `lookup_xhci_controller_quirks_full` is wired, but the + lookup function returns `XhciControllerQuirkFlags::empty()`. **xhcid does + not actually consume XhciControllerQuirkFlags — it consumes regular + `PciQuirkFlags` (NO_MSI, NO_MSIX, FORCE_LEGACY_IRQ, RESET_DELAY_MS).** + +- **Q3 "xhcid USB device quirks"** is marked ✅ Done. The `UsbQuirkFlags` type + has 22 flags but only 13 are consumed by xhcid. The other 9 are + infrastructure-only — they propagate to the daemon but xhcid does not + act on them. + +The corrected status is: **the type system and TOML pipeline are complete +end-to-end, but ~3 entry points are defined-but-empty (see Tombstones +section above) and ~4 flag names are missing from the TOML schema.** + +## Verifying quirks is "properly initialized and utilized" — the answer + +**Initialization:** Yes. The pipeline is auto-loaded on every quirk lookup. +`PciDeviceInfo::quirks()` (the universal entry point) is called by every +Rust driver that does fancy device init, and the linux-kpi C FFI exposes +the same data to C drivers. + +**Utilization:** The **active** consumer footprint is narrow but deep: +- 4 files in `redox-driver-sys`'s Rust ecosystem (pci + redbear-info + redbear-hwutils) +- 2 files in `redox-drm` (main + drivers) +- 2 files in `amdgpu` C path (main + stubs + glue) +- 1 file in `i2c-hidd` (separate system) +- 1 file `linux-kpi` (FFI bridge) + +That is 11 Rust + 6 C consumers for ~22 PCI/USB + 8 DMI + 214 storage quirks += 10% of compiled-in rules actively used. **This is intentional** — the +quircks are written for production code paths that *will* be used when +Red Bear OS runs on real hardware with the matching silicon. On QEMU the +rules are inert (no real GPU, no Broadcom NIC, no Surface Pro) but the +code paths are exercised on every boot. + +The **bottleneck** is not initialization or utilization — it's **coverage**. +The compiled-in PCI table is intentionally narrow (3 vendors, 11 entries) +and the rest is TOML-fillable. The system is **working as designed**; the +question is whether the TOML file set in `redbear-quirks/` covers the +target hardware matrix.