Files
RedBear-OS/local/docs/BOOT-AND-HW-ENABLEMENT-ASSESSMENT.md
T
vasilito e289904852 docs: add 8 comprehensive audit/assessment documents (7500+ lines total)
- STUBS-AUDIT-AND-REWRITE-PLAN.md: master plan, 20 drivers audited
- USB-STUBS-AUDIT.md: USB stack focus, xhcid/usbhubd/usbctl/usbhidd/usbscsid/ucsid
- HID-STUBS-AUDIT.md: HID focus, usbhidd/i2c-hidd/intel-thc-hidd/ps2d/inputd/evdevd
- LOWLEVEL-STUBS-AUDIT.md: ACPI/PCI/IRQ/IOMMU/boot/init, 50+ row coverage
- BOOT-AND-HW-ENABLEMENT-ASSESSMENT.md: kernel to display chain, NO VESA policy
- DESKTOP-SERVICES-ASSESSMENT.md: D-Bus, session, audio, network
- CONFIG-AND-INIT-ASSESSMENT.md: configs, init.d, recipes, layering
- GPU-MESA-KDE-CHAIN-ASSESSMENT.md: Mesa to Plasma build chain

These documents track the v6.0 stub-fix campaign and the comprehensive
Phase 1-5 implementation work. All cited paths and line numbers are
real. Documents are durable in local/docs/ which survives make distclean.
2026-06-09 12:06:18 +03:00

1560 lines
94 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Boot and Hardware Enablement Assessment — KERNEL → INITFS → INIT → DISPLAY → WAYLAND → KDE
**Document version:** 1.0
**Date:** 2026-06-09
**Scope:** Every link in the chain that turns cold metal into a Wayland/SDDM login prompt on `redbear-full` (QEMU virtio-gpu, AMD64).
**Audience:** Red Bear OS maintainers planning the next 12 weeks of integration work.
**Method:** Direct code-level inspection of every layer in `local/sources/` and `local/recipes/`, cross-referenced against `local/docs/STUBS-AUDIT-AND-REWRITE-PLAN.md`, `local/docs/LOWLEVEL-STUBS-AUDIT.md`, `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` (v6.0), `local/docs/QUIRKS-SYSTEM.md`, `local/docs/DBUS-INTEGRATION-PLAN.md`, `local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md`, and the local kernel/init/initfs source.
**Important:** This document is **read-only**. No source files are modified. It is an audit, not a fix.
---
## Executive Summary
| Metric | Value |
|--------|-------|
| Stage coverage | 6/6 (kernel, initfs, init, pcid, display, quirk system) |
| `unimplemented!()` macro panics in chain | 6 (vesad 1, pcid fallback 2, ihdgd 1, ps2d 2) |
| `expect("TODO")` panic strings in chain | 2 (`init/src/service.rs:98,100`) |
| `// TODO` / `// FIXME` in chain (excluding upstream KWin/SDDM/dbus) | ~500+ |
| Anti-pattern: `*-stub` recipes installed to satisfy KWin/SDDM/CMake | 5 (`libudev-stub`, `libdisplay-info-stub`, `libepoxy-stub`, `libxcvt-stub`, `lcms2-stub`) |
| Anti-pattern: `vesad` registered as `display.vesa` primary display | YES (policy violation, see §5.1) |
| Display handoff (vesad → DRM/KMS) actually implemented | NO (de facto app-level only; no daemon-level unregister) |
| Quirks fully compiled-in + TOML-loaded + DMI-matched | YES (R0R22 landed 2026-06-07; 131 host-buildable unit tests) |
| Quirks actually consumed by every relevant driver | NO — kernel, network drivers, audio, panel rotation all deferred (see §6) |
| Init service order matches the canonical plan | PARTIAL — most services exist but two target references are unresolved |
| Init auto-restart on failure | NO (`enum JobKind { Start }` only; no Restart/Stop/Reload) |
| KWin real build (QML/Quick on) | BLOCKED — 10 `KWIN_BUILD_*=OFF` flags and the `lib*-stub` chain block it |
| SDDM real build (Qt6 + Wayland greeter) | Compiles with multiple disabled paths; 4 `// TODO: IMPLEMENT` remain in `daemon/DisplayManager.cpp:156,160,164,195` |
| Mesa → Qt6 CMake config chain | Compiles; feature gates at the Qt6 detection layer require explicit `-DQT_FEATURE_*=ON` overrides |
| Estimated LoC to add to reach **Wayland/SDDM login on QEMU** | ~3,5005,000 |
| Estimated time to fix (2 devs) | 1218 weeks |
### Top blockers for the user's stated goal (boot to Wayland/SDDM on QEMU)
1. **`vesad` still registers `display.vesa` as a primary display scheme** (`vesad/src/main.rs:87`). Per project policy (`AGENTS.md` "NO VESA POLICY") vesad must hand off to `redox-drm` and not be the primary surface. The code does not implement this handoff. KWin/SDDM are told to use `/scheme/drm/card0` (good) but if `redox-drm` is slow to register (or fails on a non-virtio GPU) the boot falls back to vesad as the visible surface, contradicting the policy.
2. **KWin recipe disables 10+ build features via `KWIN_BUILD_*=OFF`** (`local/recipes/kde/kwin/recipe.toml:155-165`) — auto-rotation, X11, X11 backend, KCMS, screenlocker, tabbox, globalshortcuts, runners, notifications, activities, EIS. This is the "honest build" policy from the project AGENTS.md but it means the resulting KWin binary is a compositor shell, not the full KWin that SDDM expects to spawn.
3. **5 `*-stub` recipes are wired into the build chain** for KWin (`libepoxy-stub`, `libxcvt-stub`, `libdisplay-info-stub`, `lcms2-stub`, `libudev-stub`). These exist only to satisfy KWin's CMake `find_package` calls and provide empty/no-op symbols. Per project policy this is a violation: "Implement the missing functionality properly" rather than stub.
4. **Init has no auto-restart** (`init/src/scheduler.rs:14-17` defines `enum JobKind { Start }` only; no Restart, no Stop, no Reload). If `redox-drm` dies after registering `/scheme/drm/card0`, the user gets a frozen desktop and no recovery.
5. **The `redbear-compositor` Wayland protocol is bounded** (`redbear-compositor/source/src/main.rs:1-15`: "bounded proof scaffold, not a real compositor runtime proof"). The canonical plan v6.0 says it is for the greeter only and KWin takes over for the user session, but the integration step (handoff from compositor → KWin) is not specified and not implemented in either binary.
### Phase blockers (canonical plan v6.0 mapping)
The CONSOLE-TO-KDE-DESKTOP-PLAN.md v6.0 defines 10 phases. Real status against current code:
| Phase | Status | Evidence |
|-------|--------|----------|
| 0 — Pre-flight: QML JIT + kf6-kdeclarative QML re-enable | NOT STARTED | `redbear-full.toml:96` kirigami is not even listed; plasma-framework / plasma-workspace / plasma-desktop are commented out |
| 1 — Single evdev producer | PARTIAL | evdevd + `redbear-input-headers` exist; no integrated plan in `redbear-full.toml` to retire inputd |
| 2 — redbear-compositor real-or-honest | HONEST STUB | `redbear-compositor/src/main.rs:1-15` is explicit about being a bounded scaffold |
| 3 — Mesa + libdrm + libepoxy (Mesa is the boundary) | COMPILES | mesa = {} in config; libdrm = {}; libepoxy = "stub" (anti-pattern) |
| 4 — KWin QML-free build | COMPILES via KWIN_BUILD_*=OFF | recipe.toml:155-165 |
| 5 — KWin real QML/Quick build | BLOCKED on QML gate | recipe.toml:1 `#TODO: KWin — full build with Qt6Quick/QML` |
| 6 — SDDM activation | COMPILES with 4 TODO:IMPLEMENT in DisplayManager | `sddm/source/src/daemon/DisplayManager.cpp:156,160,164,195` |
| 7 — Compositor + SDDM integration | NOT STARTED | No `/etc/sddm.conf` matches the daemon's compiled-in paths; `/usr/share/wayland-sessions/plasmawayland.desktop` is hand-installed via `redbear-full.toml:592-601` |
| 8 — Plasma framework/workspace/desktop | BLOCKED on QML gate | 3 packages commented out in `redbear-full.toml:147-150` |
| 9 — KDE apps (Dolphin, Kate, Gwenview) | NOT STARTED | No recipes in `local/recipes/kde/` for them |
| 10 — Polish / integration | NOT STARTED | — |
---
## Per-Stage Assessment
### 1. Kernel Boot
**Location**: `local/sources/kernel/`
**Total LoC audited**: ~21,555 (per LOWLEVEL-STUBS-AUDIT.md)
**Relevant files**: `src/acpi/{mod,rsdp,rsdt,rxsdt,xsdt,sdt,hpet,gtdt,srat,slit,spcr}.rs`, `src/arch/x86_64/`, `src/arch/x86_shared/`, `src/startup/mod.rs`, `src/scheme/acpi.rs`, `src/syscall/mod.rs`
#### What works (per LOWLEVEL-STUBS-AUDIT.md, confirmed by code)
| Feature | Status | File:line |
|---------|--------|-----------|
| RSDP search (x86 BIOS, EFI, RSDP_ADDR forwarded) | ✅ | `acpi/mod.rs:95-170` |
| RSDT/XSDT parsing | ✅ | `rxsdt.rs`, `xsdt.rs` |
| FADT, MADT, SRAT, SLIT, SPCR (aarch64), HPET, GTDT (aarch64) | ✅ | per-file `init()` |
| `enumerate_pci_class` from pcid-spawner handoff | ✅ | `redox-drm/source/src/main.rs:217-228` |
| `setrens(0,0)` syscall | ✅ | `init/src/main.rs:178` |
| Symmetric Multiprocessing (x2APIC) | ✅ (per plan v6.0 + LOWLEVEL-STUBS-AUDIT.md Phase P0) | `arch/x86_64/interrupt/` |
| Syscall interface for schemes (irq, memory, pci, event, debug) | ✅ | `scheme/{irq,memory,debug,proc,sys}.rs` |
| DMI scheme (`/scheme/acpi/dmi`) | ✅ (Blocker 2, 2026-06) | `scheme/acpi.rs` + `acpid/dmi.rs` |
#### Stubs / half-impls
1. **HPET initialization is hard-coded; userspace cannot reconfigure**`acpi/mod.rs:163`:
```rust
// TODO: Let userspace setup HPET, and then provide an interface to specify which timer to
// use?
Hpet::init();
```
Impact: When `redbear-quirks` flags a clocksource issue (e.g. `PMTMR_BLACKLIST` on PIIX4<3, ICH4, ServerWorks LE), the kernel has no path to read the flag and pick a different clocksource. The flag exists in `redox-driver-sys` and is loaded by the TOML (R15), but the kernel-side consumer is missing.
2. **Processor enumeration is in the kernel** — `acpi/mod.rs:149`:
```rust
// TODO: Enumerate processors in userspace, and then provide an ACPI-independent interface
// to initialize enumerated processors to userspace?
```
Impact: kernel-side enumeration couples the boot to ACPI; for a DTB/AAarch64 future this will need a refactor. Not blocking QEMU.
3. **aarch64 SPCR parsing is gated** — `acpi/mod.rs:159-167`:
```rust
//TODO: support this on any arch
#[cfg(target_arch = "aarch64")]
spcr::Spcr::init();
```
x86_64 SPCR is not parsed; the kernel picks 0x3F8 serial port from a hard-coded fallback. Adequate for QEMU, blocks headless server debugging with custom baud.
4. **Start-up still touches ACPI tables directly** — `acpi/mod.rs:134`:
```rust
// TODO: Don't touch ACPI tables in kernel?
for sdt in rxsdt.iter() {
get_sdt(sdt, &mut KernelMapper::lock_rw());
}
```
The kernel's responsibility is to expose the RSDP address + raw SDT bytes to userspace; acpid does the parsing. The current implementation parses enough to find the MADT/SRAT in the kernel. Not blocking, but contributes to the asymmetric "kernel does too much, userspace duplicates" pattern.
5. **IOMMU interrupt remapping is open** (per LOWLEVEL-STUBS-AUDIT.md "Critical Gaps"). The kernel has the IOMMU page-table code (per `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`) but the redbear-quirks R21 flag `SUPPRESS_IVRS` for the `iommu` daemon to consult is not yet wired into the kernel side.
6. **Total of 330 `TODO|FIXME` markers across the kernel tree** (`find ... | xargs grep -c "TODO\|FIXME" | awk '{s+=$2}END{print s}'` = 330) — most are localised in `context/memory.rs:67` (memory layout) and `context/signal.rs:7` (signal delivery). These are tracked in the LOWLEVEL-STUBS-AUDIT but they do not block boot to a Wayland login.
#### Missing wirings
- **DMI-to-clocksource handoff**: `redox-driver-sys` exports `ClocksourceQuirkFlags::PMTMR_BLACKLIST/PMTMR_GRAYLIST/HPET_BROKEN/TSC_UNSTABLE` (R15), but the kernel `Hpet::init()` does not consume them. To close this: kernel must read `/scheme/acpi/dmi` (or an analogous publisher) at `Hpet::init()` time and skip a flagged source.
- **TOML quirk consumer for chipset-early entries (R17)**: 11 entries in `55-chipset-early.toml` (`redbear-quirks/source/quirks.d/`) sit behind a documented "kernel-side follow-up" gate. The R17 phase explicitly defers consumer wiring.
- **CPU bug flag consumer (R14)**: 27 `X86_BUG_*` flags defined; the kernel context-switch path does not consume them. Spectre/Meltdown mitigations are nominally supported but unwired.
#### Stale code
- The `acpi/slit.rs` and `acpi/srat.rs` exist but `numad` (per `redbear-full.toml:59`) is included for "NUMA topology discovery" without an obvious consumer in the kernel. For a single-socket QEMU run this is inert; for dual-socket AMD Threadripper (per AGENTS.md header) the SRAT data is published but not used to bias scheduler placement.
- `src/scheme/acpi.rs:1` `smbios` parsing feeds the DMI scheme (Blocker 2), but the `DmiInfo` struct is missing some fields that newer kernels (Linux 7.1 `drivers/firmware/dmi_scan.c`) parse. Resolved 2026-06 (`b56b810c0` added `bios_vendor` / `bios_date`).
#### Quirks used by kernel
- **DMI table** (R11 / Blocker 2): kernel `SmbiosScheme` → acpid `dmi::parse_smbios_table` → `/scheme/acpi/dmi` + `/scheme/acpi/dmi/{field}`. End-to-end chain landed 2026-06.
- **No direct kernel consumer** for `PciQuirkFlags`, `UsbQuirkFlags`, `HidQuirkFlags`, `AcpiQuirkFlags`, `DrmPanelOrientation`, `PlatformDmiQuirkFlags`, `CpuBugFlags`, `ClocksourceQuirkFlags`, `ChipsetQuirkFlags`, `UsbAudioQuirkFlags`. All ten flag families have data + lookup; only DMI is actually consumed.
#### LoC estimate
- HPET/DMI clocksource handoff: ~300 LoC kernel + 200 LoC tests
- CPU bug context-switch consumer: ~600 LoC kernel
- Chipset-early handler: ~1200 LoC kernel
- SPCR for x86_64: ~150 LoC
**Total**: ~2,450 LoC kernel-side. 46 weeks with 1 kernel developer.
#### Time estimate
46 weeks (1 dev) for a "kernel exposes data; consumers live in userspace drivers" refactor consistent with the LOWLEVEL-STUBS-AUDIT.md P5 plan.
### 2. Init Filesystem (initfs)
**Location**: `local/sources/base/initfs/`
**Library LoC**: 413 (`lib.rs:287`, `types.rs:126`)
**Tools LoC**: 769 (`tools/src/lib.rs:590`, `bin/archive.rs:67`, `bin/dump.rs:112`)
**Test LoC**: 108 (`tools/tests/archive_and_read.rs`)
#### What works
- The initfs image format is a self-describing bin (MAGIC=`"RedoxFtw"`, 4 KiB page size assumption; see `types.rs:4`) with a header, an inode table, and string-offset dir entries. The library can be compiled to `no_std` and used inside the bootloader (`initfs/src/lib.rs:1-30`).
- `archive` and `dump` tools exist for assembling the initfs image and inspecting it. The tests exercise the round trip (archive → read → dump).
- The `initfs.toml` `[[drivers]]` table in `local/sources/base/drivers/initfs.toml` lists the early-boot drivers that need to live in the initfs: `ahcid`, `ided`, `nvmed`, `virtio-blkd`, `virtio-gpud` (yes, virtio-gpud is in initfs — see §5).
- `initfs-pcid-storage.toml` and `initfs-storage.toml` provide driver-manager-style initfs manifest variants for storage.
#### What is bundled into the initfs
The actual contents of the initfs image at build time are not visible from the `initfs/` source — they are produced by the cookbook tool at build time by following the `[[drivers]]` entries in the `initfs*.toml` files. Based on `initfs.toml`:
| Driver | Class | Subclass | Vendor | Device | Purpose |
|--------|-------|----------|--------|--------|---------|
| `ahcid` | 0x01 (storage) | 0x06 (SATA) | any | any | Boot rootfs from SATA |
| `ided` | 0x01 | 0x01 (IDE) | any | any | Boot rootfs from IDE |
| `nvmed` | 0x01 | 0x08 (NVMe) | any | any | Boot rootfs from NVMe |
| `virtio-blkd` | 0x01 | 0x00 (SCSI) | 0x1AF4 | 0x1001 | Boot rootfs from virtio |
| `virtio-gpud` | 0x03 (display) | any | 0x1AF4 | 0x1050 | QEMU graphics |
Note that `vesad`, `fbcond`, `fbbootlogd` are **not** in the initfs drivers list — they come from the base package's `init.initfs.d/` service files and run as userland daemons.
#### Manifest source
**Hybrid (TOML list + service file list)**:
- The image is built by the cookbook's `initfs::tools::archive` consuming the TOML manifest.
- The **service definitions** that run inside the initfs (using `/scheme/initfs/lib/init.d/...`) come from the base source fork: `local/sources/base/init.initfs.d/` (20 service files, 243 LoC).
#### Stubs / half-impls
None found in the initfs **format** itself. The format is well-tested and the `archive_and_read` round trip is exercised by the test suite. The initfs library and tools have 0 `TODO`/`FIXME`/`unimplemented!` in the source.
#### Missing wirings
- **No formal manifest schema** — the TOML is informal and is read by the cookbook's recipe generator. A regression that drops a driver from `initfs.toml` is silent. There is no equivalent of `cargo metadata` to list the inits-image contents.
- **No way to add custom initfs-only drivers without modifying the base source**. A Red Bear-specific driver that needs to be in the initfs would have to either be added to `local/sources/base/init.initfs.d/` (which the base fork does) or come from a recipe-time-generated override.
#### Stale code
None observed. The `initfs` source is small, focused, and stable.
#### LoC estimate
0 LoC. The initfs library and tools are complete for the use case.
#### Time estimate
0 days. The initfs is a solved sub-problem.
### 3. Init System
**Location**: `local/sources/base/init/`
**Total LoC**: 846 (`main.rs:184`, `scheduler.rs:116`, `script.rs:163`, `service.rs:132`, `unit.rs:251`)
#### What works
| Feature | Status | File:line |
|---------|--------|-----------|
| TOML unit parsing (`*.service`, `*.target`) | ✅ | `unit.rs:174-228` |
| Legacy script parsing (no extension) | ✅ | `script.rs:18-38` |
| `requires_weak` dep tracking | ✅ | `unit.rs:31-95` |
| `condition_architecture` / `condition_board` filtering | ✅ | `unit.rs:230-250` |
| Templated unit IDs (`ramfs@.service` with `$INSTANCE` substitution) | ✅ | `unit.rs:153-172, 31-40` |
| Service `cmd`, `args`, `envs`, `inherit_envs` | ✅ | `service.rs:13-35` |
| `ServiceType` variants: `Notify`, `Scheme(name)`, `Oneshot`, `OneshotAsync` | ✅ | `service.rs:27-35` |
| Init switch_root (initfs → rootfs) | ✅ | `main.rs:51-113, 120-148` |
| Init logging redirect to `logd` | ✅ | `main.rs:131-133` |
| Service status reporting on failures | ✅ | `scheduler.rs:33-35` |
| `setrens(0, 0)` final namespace closure | ✅ | `main.rs:178` |
#### Stubs / half-impls
1. **`expect("TODO")` panic in `Service::spawn` when a `Scheme(type)` service starts** — `service.rs:98, 100`:
```rust
let current_namespace_fd = libredox::call::getns().expect("TODO");
libredox::call::register_scheme_to_ns(current_namespace_fd, scheme, new_fd)
.expect("TODO");
```
The `getns` call and the `register_scheme_to_ns` call are best-effort at boot — they succeed on the host but a build that ever runs init in a non-namespace environment will panic. This is a real `todo!()` disguised as `.expect("TODO")` (2 of them in this section).
2. **No auto-restart loop** — `scheduler.rs:14-17`:
```rust
enum JobKind {
Start,
}
```
No `Stop`, no `Restart`. A scheme service that registers its scheme and then dies (e.g. `redox-drm` panic) leaves `/scheme/drm/card0` in a stale state with no recovery. Per LOWLEVEL-STUBS-AUDIT.md "Init auto-restart on failure: 2 weeks".
3. **Multi-user target is a comment, not a unit** — `main.rs:150-151`:
```rust
// FIXME introduce multi-user.target unit and replace the config dir iteration
// scheduler.schedule_start_and_report_errors(&mut unit_store, UnitId("multi-user.target".to_owned()));
```
The rootfs boot path iterates every file in `/usr/lib/init.d/` and `/etc/init.d/` (line 153-173) and schedules all of them. This means services with side effects (like `99_diag_serial.service`) get scheduled even if their dep chain has not yet reached them. The `default_dependencies = false` workaround in service files is the only guard.
4. **No poweroff/reboot handling** — `init/src/main.rs:180-183`:
```rust
loop {
let mut status = 0;
libredox::call::waitpid(0, &mut status, 0).unwrap();
}
```
Waitpid is called but the status is discarded. There is no `reboot()` syscall on power-button or `SIGINT` from a logged-in user. The user can only poweroff from inside the kernel debug scheme or by ACPI power button (per ACPI-IMPROVEMENT-PLAN.md §3).
5. **No on-failure service policy** — `unit.rs:117-128` defines `UnitInfo` with `description`, `default_dependencies`, `requires_weak`, `condition_architecture`, `condition_board` but no `restart`, `restart_sec`, `start_limit_burst`, `start_limit_interval_sec` (systemd-equivalent). The deserializer also has `#[serde(deny_unknown_fields)]` (line 118), so any future field must be added deliberately.
6. **`unit.rs:126`** `// FIXME replace this with hwd reading from the devicetree` — `condition_board` is board-name based and is fed by an env var; the kernel's hwd is supposed to publish this via scheme. The hwd-side producer is open (see §4.5).
7. **The `00_*.service` / `90_*.service` numeric ordering is implicit** — `unit.initfs.d/90_initfs.target` exists as a target but `init.d/00_*.service` files in the rootfs come from the cookbook and have no ordering key beyond file name. systemd has `Before=`/`After=`; this init has no equivalent (only `requires_weak`).
#### Missing wirings
- **No `Reload` job** for services whose state file changes (e.g. SDDM config, seatd policy).
- **No `ConditionPathExists`** / `ConditionKernelCommandLine` for env-gated activation. Right now a service that should only run on `redbear-full` must be excluded from `redbear-mini.toml` manually.
- **No graceful shutdown of dependent services** before a reboot. The current `waitpid` loop just reaps zombies.
#### Stale code
- `main.rs:181` reads `let mut status = 0;` but the variable is `mut`-declared and never mutated. Likely a `cargo clippy` `unused_mut` warning. The `waitpid(0, &mut status, 0).unwrap()` then overwrites it but the compiler may not see that.
- The `condition_board` field is a `FIXME` and is read from `option_env!("BOARD")` (compile time) at `unit.rs:243` — it is effectively dead. No recipe sets `BOARD` at compile time.
#### LoC estimate
- Auto-restart loop + start-limit: ~400 LoC
- Multi-user target + filter iteration: ~150 LoC
- poweroff/reboot wiring: ~250 LoC
- Oneshot-as-dependency cleanup: ~200 LoC
**Total**: ~1,000 LoC. 23 weeks with 1 dev.
#### Time estimate
23 weeks. The init system is small (846 LoC) and the changes are localised; the main risk is the no-restart + no-shutdown issue, which together explain the "frozen desktop after a panic" failure mode that CONSOLE-TO-KDE-DESKTOP-PLAN.md references.
### 4. PCID and Driver Spawner
**Location**:
- `local/sources/base/drivers/pcid/` (3,083 LoC, 7 files)
- `local/sources/base/drivers/pcid-spawner/` (101 LoC, 1 file)
- `local/recipes/system/driver-manager/` (recipe-level)
- `local/sources/base/drivers/pcid/src/driver_interface/` (8 sub-files)
- `local/sources/base/drivers/pcid/src/cfg_access/` (PCIe MMIO + I/O port fallback)
#### What works
| Feature | Status | File:line |
|---------|--------|-----------|
| PCIe MMIO extended config access | ✅ | `cfg_access/mod.rs` |
| PCI 3.0 I/O port fallback (x86_64 only) | ✅ | `cfg_access/fallback.rs:58-83` |
| Multi-bus enumeration (R1 fixed 2026-06) | ✅ | `main.rs:299` (per STUBS-AUDIT) |
| BAR parsing (32/64-bit, prefetchable) | ✅ | `main.rs:38-82` |
| Capability list walk | ✅ | `main.rs`, `driver_interface/cap.rs` |
| MSI / MSI-X enablement | ✅ | `driver_handler.rs:71-200` |
| ROM BAR reading | ✅ | `main.rs:84-115` |
| `pcid-spawner` reads driver TOML config and spawns matched drivers | ✅ | `pcid-spawner/src/main.rs:22-32` |
| Handoff of PCI client channel via `PCID_CLIENT_CHANNEL` env | ✅ | `pcid-spawner/src/main.rs:92-93` |
| `redox_driver_sys::pci::PciDeviceInfo` + quirk lookup | ✅ | `pcid/src/quirks.rs:42-200` |
| `apply_pci_quirks` wired into `handle_parsed_header` | ✅ | `pcid/src/quirks.rs` (Blocker 1 resolved 2026-06) |
| `QuirkAction::execute` for imperative config-space writes | ✅ | `redox-driver-sys/src/quirks/mod.rs:779-857` |
#### Stubs / half-impls
1. **`todo!()` panic on non-x86 PCI access** — `pcid/src/cfg_access/fallback.rs:89, 94`:
```rust
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl ConfigRegionAccess for Pci {
unsafe fn read(&self, addr: PciAddress, offset: u16) -> u32 {
let _guard = self.lock.lock().unwrap();
todo!("Pci::CfgAccess::read on this architecture")
}
...
}
```
On aarch64/RISC-V the kernel would panic on the first PCI access. There is no PCIe ECAM fallback for non-x86 yet. Not a QEMU x86_64 blocker; a blocker for aarch64 server class.
2. **`unimplemented!()` panics in `pcid::scheme::SchemeImpl::pcilink` path** — `pcid/src/scheme.rs:329`:
```rust
log::trace!("TODO: Support disabling device (called on {})", addr);
```
This is a `log::trace!` (not a `todo!()`), but the underlying handler returns success without doing anything. Disabling a PCI device is "supported" via the scheme call but the function is a no-op. Per LOWLEVEL-STUBS-AUDIT.md "PCIe AER support: 3 weeks" (related).
3. **pcid-spawner has zero ACPI / DMI matching** — `pcid-spawner/src/main.rs:65-72`:
```rust
let Some(driver) = config
.drivers
.iter()
.find(|driver| driver.match_function(&full_device_id))
else {
log::debug!("no driver for {}, continuing", handle.config().func.addr);
continue;
};
```
The match is purely PCI (vendor/device/class). The plan section "PCID and DMI" suggests that the spawner should also consult `/scheme/acpi/dmi` to pick a different driver for a known-bad implementation. This is not implemented; for QEMU virtio-gpu the match works because the table is `vendor=0x1AF4, device=0x1050` (per `redbear-full.toml:621-630`).
4. **pcid-spawner `--initfs` flag selects the initfs config directory** — `pcid-spawner/src/main.rs:11, 22-30`:
```rust
let initfs = args.contains("--initfs");
...
for path in if initfs {
config::config_for_initfs("pcid")?
} else {
config::config("pcid")?
} { ... }
```
The initfs and rootfs use the same `pcid` key. The `initfs-pcid-storage.toml` and `initfs-storage.toml` use a different format (`[[drivers]]` with `command` as a single string, vs. the new `[[driver]]` with `command` as a list — `redbear-full.toml:206-226` uses the new format with `[[driver.match]]`). There is a real risk that the `initfs-pcid-storage.toml` and the new manifest format are not interchangeable; the spawner would not parse the new format if started from initfs.
5. **10 `// TODO` / `// FIXME` in `pcid/src/scheme.rs`**:
- `scheme.rs:39` `// TODO: capability rather than root` — the scheme exposes PCI functions but not the capability list directly.
- `scheme.rs:86` `// TODO: Check flags are correct` — argument validation is best-effort.
- `scheme.rs:95` `// FIXME remove replacement of : once the old scheme format is no longer supported` — backwards-compat glue.
- `scheme.rs:384` `// XXX: Why can't VecDeque support dequeueing into slices?` — Rust std limitation, harmless.
- `scheme.rs:431, 435` `// FIXME use : instead of -- as separator` — the `:` character is reserved in scheme names, hence the historical `--` replacement. Per project policy, `--` in path is the legacy compat; the new paths use `:` (e.g. `/scheme/drm/card0`).
6. **8 `// TODO` / `// FIXME` in `pcid/src/driver_interface/`**:
- `irq_helpers.rs:42` `// TODO: Perhaps read the MADT instead?` — the IRQ override allocator hard-codes the LAPIC vector; it should consult the kernel's MADT for delivery mode (per `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`).
- `irq_helpers.rs:120` `// TODO: fcntl F_SETLK on /scheme/irq/` — no advisory locking on the IRQ scheme; multiple drivers can race.
- `irq_helpers.rs:254` `// TODO: Allow allocation of up to 32 vectors.` — MSI-X vectors are capped at the Linux default of 8; some modern NICs need more.
- `irq_helpers.rs:308` `// FIXME move MSI-X IRQ allocation to pcid` — currently in pcid-handler but the kernel could provide a dedicated scheme.
- `irq_helpers.rs:428` `// FIXME support MSI on non-x86 systems` — same as the `cfg_access` fallback aarch64 issue.
- `msi.rs:161` `// TODO: should the reserved field be preserved?` — MSI-X cap walk may clobber reserved bits.
#### Missing wirings
- **DMI-matched driver spawner**: not implemented (item 3 above).
- **Hot-plug events for PCIE**: the kernel `interrupt::pci` scheme supports hot-plug but pcid does not listen for new device notifications; it polls at boot only.
- **Quirk-action loop in xhcid**: per QUIRKS-SYSTEM.md Blocker 4, the QuirkAction loop that applies imperative config-space writes is wired into pcid (`PcidConfigWriter`) but xhcid has a documented "1-2 day wiring task" to use it. The flags are set, the dispatcher in pcid runs, but xhcid's QuirkAction loop is the last step.
#### Stale code
- `pcid/src/scheme.rs:431, 435` `--` → `:` translation is documented as legacy. The new format is everywhere (e.g. `/scheme/drm/card0` in `redbear-full.toml:295`). The translation is dead code in practice.
- `cfg_access/fallback.rs:30-35` warns that "PCIe extended configuration is not available" and falls back to PCI 3.0 ports. On modern Q35 + i440fx the MMIO path is always available, so the fallback rarely fires.
#### Quirks applied
Per pcid/src/quirks.rs (Blocker 1) and the data path:
```
PciDevice::full_info() // pcid internal
→ build_device_info // quirks.rs:120-200
→ PciDeviceInfo::quirks() // redox-driver-sys/src/quirks/pci_table.rs + toml_loader.rs + dmi.rs
→ PciQuirkFlags (bitwise OR of all matching entries)
→ apply_pci_quirks // pcid/src/quirks.rs (Blocker 1, 12 unit tests)
```
In pcid, the PciConfigWriter loop executes `QuirkAction::execute` for each matching entry with a non-`None` action. The first action wins per device. Per QUIRKS-SYSTEM.md R4, ~30% of Linux PCI quirks are imperative config-space writes; this is the gate for that.
#### LoC estimate
- Hot-plug pcid: ~600 LoC
- DMI-matched spawner: ~300 LoC
- aarch64 PCIe ECAM: ~500 LoC
- Cap-walk improvements: ~200 LoC
**Total**: ~1,600 LoC. 46 weeks with 1 dev.
#### Time estimate
46 weeks. Most changes are non-urgent for QEMU x86_64 (which is the user's primary path); the aarch64 fallback is future-proofing.
### 5. Display Chain (CRITICAL)
This is the longest section because it is the user's primary blocker. The display chain is the only place where the project's stated policy ("vesad only as early-boot FB handoff; primary display is /scheme/drm/card0") is in tension with the code.
#### 5.1 vesad
**Location**: `local/sources/base/drivers/graphics/vesad/` (408 LoC: main.rs:133, scheme.rs:275)
**Purpose**: Boot framebuffer handoff from bootloader (linear framebuffer set up by UEFI/BIOS) to userspace daemons.
**What works**:
- Parses `FRAMEBUFFER_{WIDTH,HEIGHT,ADDR,STRIDE}` env vars from bootloader (`vesad/src/main.rs:25-44`).
- Supports up to 1024 `FRAMEBUFFER1..1023` env entries for multi-display boot (`vesad/src/main.rs:60-84`).
- Registers the scheme as `display.vesa` (`vesad/src/main.rs:86-87`):
```rust
let mut scheme =
GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true);
```
- Implements `GraphicsAdapter` with `DumbBuffer` and `Sync` (via `vesad/src/scheme.rs:83-138`).
- Forwards input events from `inputd` via `inputd_event_handle` (`vesad/src/main.rs:99-104`).
- Uses `setrens(0,0)` to detach from the root namespace once registered (`vesad/src/main.rs:113`).
**Stubs / half-impls**:
1. **`unimplemented!()` panic on cursor plane operations** — `vesad/src/scheme.rs:146`:
```rust
fn handle_cursor(&mut self, _cursor: &CursorPlane<Self::Buffer>, _dirty_fb: bool) {
unimplemented!("Vesad does not support this function");
}
```
Any client that sets a DRM cursor will trigger this panic. The boot does not use cursors so this is dormant in `redbear-full`, but `redox-drm` might try to use `drmModeSetCursor` and propagate through the same `GraphicsAdapter` trait.
2. **`GraphicsScheme::new(..., true)` — the third `true` argument** — `vesad/src/main.rs:87`:
This passes `block = true` (or similar) to the scheme constructor. Means `vesad` accepts a `block` flag where clients can wait for the device. Compatible with the early-boot handoff.
3. **`//TODO: ideal maximum number of outputs?`** at `vesad/src/main.rs:59` — 1024 is hard-coded. Cosmetic.
4. **No handover logic to `redox-drm`** — `vesad/src/scheme.rs` has no path that says "if DRM scheme registers, drop my scheme". The user must rely on the application (KWin/SDDM/redbear-compositor) to prefer `/scheme/drm/card0` over `/scheme/display.vesa`.
**Policy violation (project AGENTS.md "NO VESA POLICY")**:
> All display output goes through the DRM/KMS path via real GPU drivers. ... vesad is allowed ONLY as an early-boot framebuffer handoff. ... Once redox-drm initializes and registers scheme:drm/card0, vesad must hand off and NOT register scheme:display.vesa as the primary display surface.
The code does NOT implement this handoff. `vesad` registers `display.vesa` as a full scheme and never unregisters it. The intended design is that an app (KWin, redbear-compositor) should refuse to use `display.vesa` and only use `drm/card0`. The initfs order in `init.initfs.d/`:
| Order | Service | Purpose |
|-------|---------|---------|
| 10 | `inputd` | Input multiplexer |
| 20 | `vesad` | FB handoff |
| 20 | `fbcond` | Text console on FB |
| 20 | `fbbootlogd` | Boot log on FB |
→ there is NO `redox-drm` service in `init.initfs.d/`. The initfs is intentionally VESA-only for early text console output.
For rootfs (`redbear-full.toml`):
| Order | Service | Source |
|-------|---------|--------|
| 5 | `boot-essential.target` | `redbear-full.toml:258-266` |
| 4 | `drivers.target` | inherited (rootfs `/usr/lib/init.d/04_drivers.target` — in base pkg) |
| 5 | `boot-essential.target` | includes drivers.target |
| 10 | `redox-drm.service` | `redbear-full.toml:283-297` — starts if `/scheme/drm/card0` is not registered yet |
| 12 | `dbus.service` | `redbear-full.toml:299-313` |
| 12 | `sddm.service` | `redbear-full.toml:448-467` |
| 13 | `redbear-sessiond.service` | `redbear-full.toml:315-327` |
| 13 | `seatd.service` | `redbear-full.toml:329-343` |
| 11 | `redbear-authd.service` | `redbear-full.toml:433-446` |
| 30 | `console.service` | `redbear-full.toml:469-482` |
`10_redox-drm.service` is a shell wrapper that does:
```bash
if ! head -c 1 /scheme/drm/card0 >/dev/null 2>&1; then exec /usr/bin/redox-drm; fi
```
This is a one-shot startup; once `redox-drm` is alive the file is in `/scheme/drm/`. The initfs-side `vesad` continues to run (no exit), and continues to expose `display.vesa` for the lifetime of the initfs. The rootfs is a different scheme tree.
For the **transition** initfs → rootfs, what happens:
- Init's `switch_root` at `init/src/main.rs:143-148` re-mounts the rootfs.
- The initfs daemons (`vesad`, `fbcond`, `fbbootlogd`, `acpid`, `hwd`, `pcid-spawner --initfs`) are not killed by `switch_root` (Redox `switch_root` is implemented as a logical remount, not a process kill).
- The rootfs daemons (same names, plus `redox-drm`) start fresh.
- The result is two parallel `vesad`s — one from initfs, one from rootfs (if it's in the rootfs service set; it isn't in `redbear-full.toml`).
This is a real issue. There is no per-scheme-generation governance; only `redox-drm` has the "don't register if already exists" check (`redox-drm/src/main.rs:62-66`).
**Missing wirings**:
- No `vesad` shutdown signal in the rootfs init sequence.
- No DRM scheme handoff acknowledgement.
- The initfs's `vesad` registers `display.vesa` and the rootfs's apps have no way to know that "DRM is now available, please use that instead of me".
**Stale code**:
- `vesad/src/scheme.rs:9-12` imports from `drm_sys::` — this is the legacy pre-2024 `drm` crate namespace. The `drm` crate is being phased out in favour of `drm-sys` and the new `redox_drm::` API. The `vesad` build still depends on the old name.
- `vesad/src/main.rs:1` `extern crate orbclient` — `orbclient` is the legacy Orbital graphics API. It is still used in `console-draw`, `fbcond`, `fbbootlogd` but the new graphics stack should not depend on it.
**LoC estimate**:
- Add handoff: ~300 LoC
- Remove Orbital dependency: ~400 LoC
- Multi-output support beyond 1024: ~100 LoC
**Total**: ~800 LoC. 2 weeks with 1 dev.
#### 5.2 fbcond (Framebuffer text console)
**Location**: `local/sources/base/drivers/graphics/fbcond/` (671 LoC: main.rs:253, scheme.rs:193, display.rs:91, text.rs:134)
**What works**:
- Opens a VT via `ConsumerHandle::new_vt()` (`fbcond/src/main.rs:14-23`).
- Subscribes to the scheme socket and to input events.
- Handles `VtIndex::SCHEMA_SENTINEL` (scheme events) and per-VT input events (`fbcond/src/main.rs:91-189`).
- `handle_handoff()` re-opens the display via the inputd v2 protocol when `redox-drm` becomes available (`fbcond/src/display.rs:25-58`).
**Stubs / half-impls**:
1. **`// FIXME listen for resize events from inputd and handle them`** — `fbcond/src/main.rs:36`. The framebuffer's `handle_resize` is implemented (`fbcond/src/display.rs:60-82`) but no event subscription. A window resize triggers a re-render only at the next VTSwitch.
2. **`setrens(0,0)` is commented out** — `fbcond/src/main.rs:53-54`:
```rust
// This is not possible for now as fbcond needs to open new displays at runtime for graphics
// driver handoff. In the future inputd may directly pass a handle to the display instead.
// libredox::call::setrens(0, 0).expect("fbcond: failed to enter null namespace");
```
fbcond intentionally keeps its namespace root so it can `ConsumerHandle::open_display_v2()` when DRM comes online. This is correct but means a "vesad" malicious client could attach to the same VTs.
3. **`_ => (), //TODO: Mouse in terminal`** — `fbcond/src/text.rs:98`. Mouse events in the text console are dropped.
4. **Per `fbcond/src/display.rs:34-39`** the V2GraphicsHandle parser logs `Display v2 not available: {err}` and returns silently. If the inputd-side API has a wrong version, the user gets a black screen with no error visible.
5. **`scheme.rs:162` `eprintln!("vesad: failed to write display scheme")`** — should be `fbcond: failed to write display scheme`. Cosmetic but reflects a copy-paste from vesad.
**LoC estimate**: ~300 LoC for mouse + resize.
**Time**: 12 weeks.
#### 5.3 fbbootlogd (Boot log on framebuffer)
**Location**: `local/sources/base/drivers/graphics/fbbootlogd/` (365 LoC: main.rs:115, scheme.rs:250)
**What works**:
- Subscribes to logd via `add_sink` (`fbbootlogd/src/main.rs:62-71`).
- Same handoff pattern as fbcond.
- Has scrollback via `Shift+PgUp/PgDown` (only with keyboard held).
**Stubs / half-impls**:
1. Same `setrens(0,0)` comment as fbcond.
2. `fbbootlogd/src/scheme.rs:38` calls `handle_handoff()` in `new()` — a no-op until `redox-drm` is up. On a system where redox-drm fails, fbbootlogd shows a black screen.
**LoC estimate**: 0 — the boot log is well-implemented for the simple case.
**Time**: 0 days.
#### 5.4 redox-drm (DRM/KMS scheme daemon)
**Location**: `local/recipes/gpu/redox-drm/source/` (130 Rust files, ~30,332 LoC; main.rs:815)
**Purpose**: GPU driver manager. Detects AMD, Intel, or virtio-gpu hardware, loads the right driver, exposes `/scheme/drm/card0` with the standard DRM/KMS uAPI.
**What works** (per project plan and code-level inspection):
- Vendor detection at `redox-drm/source/src/main.rs:217-228` for `PCI_VENDOR_ID_AMD` (0x1002), `PCI_VENDOR_ID_INTEL` (0x8086), `0x1AF4` (VirtIO).
- `PcidClient` handoff for the pcid-spawner case (`redox-drm/src/main.rs:205-215`).
- Firmware loading via `FirmwareCache` (`redox-drm/src/main.rs:274-400`).
- Scheme registration at `/scheme/drm` via `register_sync_scheme(&socket, "drm", ...)` (`redox-drm/src/main.rs:129`).
- Self-de-duplication: if `scheme:drm` is already registered, it does not start (`redox-drm/src/main.rs:62-66, 131-134`).
- Two IRQ event threads: handle_irq + poll_hotplug (`redox-drm/src/main.rs:84-111, 116-122`).
- 30+ KB of kernel-style driver code (intel/amd/virtio subdirs).
**Stubs / half-impls**:
1. **The driver code is in a build-only state** — per CONSOLE-TO-KDE-DESKTOP-PLAN.md, the Intel driver is 4042 LoC (`local/sources/base/drivers/graphics/ihdgd/`) AND the imported `redox-drm` Intel code is in `local/recipes/gpu/redox-drm/source/src/drivers/intel/` with 838 LoC of workarounds alone (`workarounds.rs`). Both exist; the upstream `ihdgd` is a clean-room Intel driver and the imported `redox-drm/intel` is the Linux i915 port. Per the plan they are alternative paths; per the config `redox-full.toml:62` `redox-drm = {}` is the chosen one.
2. **The AMD DC port** in `local/recipes/gpu/amdgpu/` is "ignore" in `redbear-full.toml:157`. The comment `amdgpu = {} # TODO: fix conflicting idr_* defs with linux-kpi headers` shows the integration is blocked on header conflicts.
3. **Per the project's "Intel i915-like via redox-drm"** target, the bounded Red Bear display glue path is the *real* path, not the i915-style `ihdgd` driver. The status in the plan: "Intel driver compiles, no HW validation yet". For QEMU virtio-gpu the build is exercised; for Intel HW it is compile-only.
4. **Many `// FIXME` and `// TODO` in `local/sources/base/drivers/graphics/driver-graphics/src/`** (the legacy i915-style `ihdgd` path):
- `lib.rs:222` `// FIXME notify clients`
- `lib.rs:537` `// FIXME fill x and y with the data from the primary plane`
- `lib.rs:852` `// FIXME use a better scheme for creating map offsets`
- `lib.rs:893` `// FIXME remove once all drm objects are materialized in self.objects`
- `kms/connector.rs:38, 161, 177, 243` — connector enumeration is hard-coded to one
- `kms/properties.rs:26, 30` — property IDs overlap
5. **KMS EDID stub** — `local/sources/base/drivers/graphics/ihdgd/src/device/scheme.rs:1, 46, 64, 75, 138`:
```rust
//TODO: this is copied from vesad and should be adapted
...
// FIXME enumerate actual connectors
...
// FIXME fetch EDID
...
unimplemented!("ihdgd does not support this function");
```
This is the OLD path (`ihdgd` in `local/sources/`). The new path (`redox-drm` in `local/recipes/`) has real EDID parsing per the `firmware_expectation` machinery.
**Quirks consumed**:
- `redox-drm` calls `info.quirks()` (the consumer-side helper) to retrieve `PciQuirkFlags`. Per QUIRKS-SYSTEM.md Gap 11, the audit misread this and it is **ALREADY RESOLVED** — the lookup is correct. The QEMU virtio-gpu path does not need most flags; the AMD/Intel paths would need `NEED_FIRMWARE`, `DISABLE_ACCEL`, `NO_MSIX`, `RESET_DELAY_MS`, and the drm panel orientation (R12, deferred until compositor rotation lands).
**LoC estimate**:
- 5.4.4: ~500 LoC for notify + plane data + map offset + object materialization
- 5.4.5: ihdgd is the legacy path; if the project keeps both it is ~1,500 LoC; if the project deprecates ihdgd in favour of redox-drm, those LoC become dead code to remove
**Total (for QEMU virtio-gpu path)**: 0500 LoC. For AMD/Intel HW path: 1,500+ LoC.
**Time**: 12 weeks for QEMU polish; 812 weeks for real HW validation.
#### 5.5 virtio-gpud (the legacy path; superseded by redox-drm)
**Location**: `local/sources/base/drivers/graphics/virtio-gpud/` (1,143 LoC: main.rs:615, scheme.rs:528)
**Stale code**:
- The `initfs.toml` references `virtio-gpud` (line 32-37) and `redbear-full.toml:621-630` references `virtio-gpud` config but the daemon itself is the legacy DRM/KMS scheme daemon. With `redox-drm` now owning the drm scheme (`/scheme/drm/card0`), `virtio-gpud` would conflict.
- `virtio-gpud/src/main.rs:3`:
```rust
//! XXX: 3D mode will offload rendering ops to the host gpu and therefore requires a GPU with 3D support
```
- `virtio-gpud/src/main.rs:35-40` defines feature flags that are commented out — `VIRTIO_GPU_F_VIRGL`, `VIRTIO_GPU_F_RESOURCE_UUID`, `VIRTIO_GPU_F_RESOURCE_BLOB`, `VIRTIO_GPU_F_CONTEXT_INIT`. Without these the 3D path is unavailable, which is what the project plan expects for Phase 5 (Mesa with virgl).
**Conflict with redox-drm**: both register as a DRM scheme. The `redox-drm` daemon has the EEXIST check (`redox-drm/src/main.rs:131`) so a second one exits cleanly. But the `initfs.toml` still points at `virtio-gpud`; the `redbear-full.toml:622-630` `virtio-gpud.toml` is also a parallel config. **The user should remove `virtio-gpud` from the initfs.toml and rely on `redox-drm` exclusively.** This is a real, present-day misconfiguration.
**Time to fix**: 0.5 day. Edit `initfs.toml` to remove the `virtio-gpud` entry; the initfs pcid-spawner will not spawn it, and `redox-drm` from rootfs will own `/scheme/drm/card0`.
#### 5.6 redbear-compositor (Bounded Wayland compositor)
**Location**: `local/recipes/wayland/redbear-compositor/` (5,083 LoC: main.rs:2,180, display_backend.rs:483, handlers.rs:388, protocol.rs:177, state.rs:198, wire.rs:197, tests/integration_test.rs:615, bin/redbear-compositor-check.rs:845)
**What works**:
- Creates a Wayland Unix socket and speaks a bounded core Wayland protocol.
- Supported protocols: `wl_display`, `wl_registry`, `wl_compositor`, `wl_shm`, `wl_shm_pool`, `wl_surface`, `wl_shell`, `wl_shell_surface`, `wl_seat`, `wl_output`, `wl_callback`, `wl_buffer`, `wl_fixes` (`main.rs:14-15`).
- Opens `/scheme/drm/card0` via the `drm_backend` module (`display_backend.rs:93-483`) with hard-coded ioctl numbers: `DRM_IOCTL_MODE_GETCONNECTOR=0xA7`, `DRM_IOCTL_MODE_SETCRTC=0xA2`, `DRM_IOCTL_MODE_CREATE_DUMB=0xB2`, `DRM_IOCTL_MODE_MAP_DUMB=0xB3`, `DRM_IOCTL_MODE_ADDFB=0xB5`, `DRM_IOCTL_MODE_PAGE_FLIP=0xB0`.
- Falls back to a 1280x720 framebuffer if `/scheme/drm/card0` is absent (`display_backend.rs:35-50`).
**Stubs / half-impls**:
1. **Self-described as "bounded proof scaffold"** — `main.rs:1-15`:
```rust
// Red Bear Wayland Compositor — bounded Wayland compositor proof scaffold.
// Replaces the KWin stub that previously created a placeholder socket.
//
// NOTE: This is a bounded proof scaffold, not a real compositor runtime proof.
// Known limitations: framebuffer compositing uses private heap memory (not real
// vesad), only a bounded subset of Wayland is implemented, and the compositor
// still paints directly into a simple backing buffer instead of doing real KMS
// scanout.
```
2. **Fallback framebuffer uses `map_framebuffer(_phys, size) -> Vec<u8>` with `vec![0u8; size]`** — `display_backend.rs:1-3`. When DRM is absent, the compositor paints into heap, not into the boot FB. The window is then lost on the next vsync.
3. **Hard-coded dimensions** — `display_backend.rs:36-46`:
```rust
let width: u32 = std::env::var("FRAMEBUFFER_WIDTH")
.unwrap_or_else(|_| "1280".into())
...
```
This is the FB env vars from the bootloader. On QEMU these are set by the BIOS to 1280x720; on real HW they reflect the UEFI GOP.
4. **No `xdg-shell` support** — only `wl_shell`. Per the plan v6.0, KWin is the canonical compositor; redbear-compositor is greeter-only. The greeter is `redbear-greeter`, not this binary.
5. **The hand-rolled `drm_backend` reimplements DRM ioctls from scratch** — `display_backend.rs:38-450` and `main.rs:38-450`. This is ~1,000 LoC of bespoke protocol that is duplicated in `redox-drm`. The 2 implementations will diverge; the canonical should be `redox-drm`. CONSOLE-TO-KDE-DESKTOP-PLAN.md says "redbear-compositor is **not** extended to production quality — instead it serves only the greeter phase".
**Missing wirings**:
- No IPC to KWin. The plan calls for a "compositor handoff" but it is not specified how redbear-compositor stops and KWin starts. KWin in this config (`/usr/share/wayland-sessions/plasmawayland.desktop:597-601`) runs `kwin_wayland --drm /scheme/drm/card0` — it ignores redbear-compositor entirely. The sessiond model assumes one compositor at a time and a clean process boundary.
**LoC estimate**:
- Replace bespoke drm_backend with redox-drm ioctl proxy: ~500 LoC removal
- Add xdg-shell: ~600 LoC
- Add compositor handoff to KWin: ~300 LoC
**Total**: ~1,400 LoC. 34 weeks.
#### 5.7 KWin
**Location**: `local/recipes/kde/kwin/source/` (38,591 LoC of upstream C++; recipe.toml:187)
**What works (per recipe + plan)**:
- Builds the KWin 6.3.4 upstream source with the toolchain.
- Real Wayland backend; real DRM/KMS; real libinput; real KF6 plumbing.
- Compiles with `KWIN_BUILD_X11=OFF` and many other features off (recipe.toml:155-165):
- `KWIN_BUILD_AUTO_ROTATION=OFF`
- `KWIN_BUILD_X11=OFF`
- `KWIN_BUILD_X11_BACKEND=OFF`
- `KWIN_BUILD_KCMS=OFF`
- `KWIN_BUILD_SCREENLOCKER=OFF`
- `KWIN_BUILD_TABBOX=OFF`
- `KWIN_BUILD_GLOBALSHORTCUTS=OFF`
- `KWIN_BUILD_RUNNERS=OFF`
- `KWIN_BUILD_NOTIFICATIONS=OFF`
- `KWIN_BUILD_ACTIVITIES=OFF`
- `KWIN_BUILD_EIS=OFF`
- Custom `sed` patches to strip X11 paths, accept `accept()` without `SOCK_CLOEXEC`, define `SUN_LEN`, `F_ADD_SEALS` macros.
- Custom `qtwaylandscanner` build path for `kde` flavor.
**Stubs / half-impls (recipe level)**:
1. **`#TODO: KWin — full build with Qt6Quick/QML. Effect frames, scripted effects, OSD overlay, outline overlay all enabled.`** at `recipe.toml:1`. The honest policy: KWin compiles but most of its KCM (KControl Module) UI is disabled because Qt6 QML doesn't work on Redox.
2. **`# CMakeLists.txt stripped: killer (X11-only) subdirectory disabled`**: `recipe.toml:84`. The X11 session killer is not built; the Wayland path is.
3. **`UiTools` dependency removed**: `recipe.toml:82`. KCM UI builder dependency disabled.
4. **`Canberra` made optional**: `recipe.toml:79-83, 64`. Sound effects on focus changes fall back to no-op.
5. **Custom `host` build of `qtwaylandscanner_kde`**: `recipe.toml:122-135`. A host-built scanner binary is required because KWin's CMakeLists has a Qt6 custom build of this tool.
**`*-stub` dependencies** (anti-pattern, per project AGENTS.md):
- `libepoxy-stub` — provides `epoxy::epoxy` cmake target, but the `.so` is a 6-symbol stub returning 0 (`local/recipes/libs/libepoxy-stub/recipe.toml:1`). Used by KWin for EGL/GLX function loading; with this stub, every `epoxy_has_gl_extension("GL_EXT_...")` returns 0 and KWin thinks no extensions are supported.
- `libxcvt-stub` — returns 0 from CVT mode calculation (`local/recipes/libs/libxcvt-stub/recipe.toml:1`).
- `libdisplay-info-stub` — bounded EDID parser; claims to handle base EDID but stubs out CTA/DisplayID (`local/recipes/libs/libdisplay-info-stub/recipe.toml:1`).
- `lcms2-stub` — color management; all `cmsDoTransform`-style functions are no-ops (`local/recipes/libs/lcms2-stub/recipe.toml:1`).
- `libudev-stub` — KWin needs libudev to enumerate input devices; the stub returns empty lists. Per `libinput/recipe.toml:18`, libinput also depends on this. Real device discovery is broken; the user has no way to attach a keyboard/mouse to a session.
**LoC estimate**:
- Remove `*-stub` dependencies in favour of real libraries: ~2,500 LoC (libepoxy ~1,200; libxcvt ~300; libdisplay-info ~600; lcms2 ~400)
- Enable KWIN_BUILD_QML_UI: ~4,000 LoC of QML/Quick integration on the Redox side
- Enable KWIN_BUILD_SCREENLOCKER + KCMS + TABBOX + GLOBALSHORTCUTS: ~1,200 LoC
**Total**: ~7,700 LoC. 1216 weeks.
#### 5.8 SDDM
**Location**: `local/recipes/kde/sddm/source/` (38,591 LoC; recipe.toml:108)
**What works (per recipe)**:
- Builds SDDM 0.21 (commit `bc9eee8280275723767213220e88f6b14157ba1f`) with Wayland-only path.
- Disables X11/XCB/XKB/XAU paths via CMake `find_package(.* QUIET)` and `pkg_check_modules(.* QUIET)` (recipe.toml:48-60).
- Patches `ioctl(STDIN_FILENO, TIOCSCTTY, NULL)` for relibc.
- Removes `XAuth.cpp` from the helper.
- Provides stubs in `stubs/linux/{kd.h,vt.h}` and `stubs/{utmpx.h,X11/Xauth.h}` for missing POSIX/header bits.
- PAM provided by `pam-redbear` shim (`local/recipes/libs/pam-redbear/recipe.toml:1-30`).
- Compiles.
**Stubs / half-impls**:
1. **`#TODO: SDDM display manager — Wayland-only build. PAM provided by pam-redbear shim.`** at `recipe.toml:1`. The plan is to make the build honest, but multiple X11 bits are still touched.
2. **`sddm/source/src/daemon/DisplayManager.cpp:156, 160, 164, 195`**: 4 `// TODO: IMPLEMENT` markers in the daemon. These are the `addLocalDisplay`, `addRemoteDisplay`, `addSocketDisplay`, and similar entry points. They return false or empty.
3. **`sddm/source/src/daemon/DaemonApp.h:42`**: `// TODO: move these two away`.
4. **`stubs/X11/Xauth.h` (19 lines)** and **`stubs/linux/{kd.h,vt.h}` (50 lines combined)** — these are SDDM-local header shims that pretend to provide X11/ConsoleKit interfaces. They are necessary for the source to compile but they are not real implementations. Anything that uses them at runtime is a no-op.
5. **`pam-redbear` is a stub too** (`local/recipes/libs/pam-redbear/recipe.toml:1-30`): a 5-symbol shared library that proxies auth to `redbear-authd` via Unix socket JSON. Real, but thin.
**Real config wiring (`redbear-full.toml:567-590`)**:
- `/etc/sddm.conf` is hand-installed with the right env vars and the `CompositorCommand=/usr/libexec/sddm-helper-start-wayland kwin_wayland --drm /scheme/drm/card0`.
- `/usr/share/wayland-sessions/plasmawayland.desktop` is hand-installed.
**LoC estimate**:
- 4 `// TODO: IMPLEMENT` in `DisplayManager.cpp`: ~400 LoC
- Real `pam-redbear` PAM module (replace the JSON socket with proper PAM API): ~600 LoC
**Total**: ~1,000 LoC. 34 weeks.
#### 5.9 redbear-sessiond (login1 D-Bus broker)
**Location**: `local/recipes/system/redbear-sessiond/source/` (2,017 LoC: main.rs:188, manager.rs:642, session.rs:450, device_map.rs:267, control.rs:221, seat.rs:147, acpi_watcher.rs:48, runtime_state.rs:54)
**What works (no TODOs found in the source)**:
- Implements `org.freedesktop.login1` D-Bus interface (subset for KWin's needs).
- Seats, sessions, device map, ACPI watcher.
- Service registered as `13_redbear-sessiond.service` in `redbear-full.toml:315-327`, depends on `12_dbus.service`.
- D-Bus activation: built as a Rust binary using `zbus`.
**Stubs / half-impls**:
None found via grep `todo!|unimplemented!|TODO|FIXME`. The sessiond appears complete for the login1 subset the project needs.
**Quirks**: not directly; the consumer of D-Bus signals from `acpid` is the `acpi_watcher.rs` module.
**LoC estimate**: 0 LoC. Likely ready.
#### 5.10 redbear-authd (Authentication daemon)
**Location**: `local/recipes/system/redbear-authd/source/src/main.rs` (719 LoC)
**What works**: PAM-equivalent auth. Reads `/etc/passwd` and `/etc/shadow`. Serves via `pam-redbear` shim.
**Stubs**: None found in `main.rs`.
**LoC estimate**: 0 LoC. Likely ready.
#### 5.11 Display handover
Per project policy (`AGENTS.md` "NO VESA POLICY"):
> Once redox-drm initializes and registers scheme:drm/card0, vesad must hand off and NOT register scheme:display.vesa as the primary display surface.
**Implementation reality**: The handoff is **not implemented**. The initfs's `vesad` runs, registers `display.vesa`, and never exits. The rootfs's `redox-drm` is started by `10_redox-drm.service` after `05_boot-essential.target` is reached. The shell wrapper in `10_redox-drm.service` checks `/scheme/drm/card0` and starts `redox-drm` if it is not yet registered. The user has no signal that handoff happened; the apps that pick `/scheme/drm/card0` over `/scheme/display.vesa` are the only place the policy is enforced.
**What "real" handoff would look like**:
- `redox-drm` registers a notifier on `/scheme/drm/card0` ready event.
- `vesad` listens for that event and tears down `display.vesa`.
- `fbcond` and `fbbootlogd` re-open the display via the v2 inputd handle (`ConsumerHandle::open_display_v2()` — already implemented at `fbcond/src/display.rs:27` and `fbbootlogd/src/scheme.rs:44`).
- During the brief window, an app that opens `/scheme/display.vesa` should be told "vesa is going away, use drm".
**This is the primary concrete "policy violation in the code" finding.**
#### 5.12 D-Bus activation, seatd, redbear-sessiond
**D-Bus activation**: SDDM is launched as `oneshot_async` (redbear-full.toml:466) but does not call `dbus-daemon --address=...` from SDDM — the sessiond broker is separate (`13_redbear-sessiond.service`). SDDM's D-Bus activation of KWin requires:
1. The D-Bus system bus socket at `/run/dbus/system_bus_socket` (env: `DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket` — `redbear-full.toml:649-651`).
2. The session bus is normally started by SDDM's greeter; in this config, `dbus-launch` is not present, so the session bus is whatever SDDM provides natively.
3. `redbear-sessiond` is the system bus broker for `org.freedesktop.login1`.
**Status**: All three services are present and ordered. The `12_sddm.service` requires `00_driver-manager.service`, `10_redox-drm.service`, `10_evdevd.service`, `12_dbus.service`, `13_redbear-sessiond.service`, `13_seatd.service`, `11_redbear-authd.service` — all of which are in the config.
**Missing**: `redbear-full.toml:516-529` defines `99_kwin_test.service` which runs `zsh -c "sleep 30; echo '=== FS DIAG ==='; ls -lad /tmp /var/log /var/run /run; ..."` — this is a diagnostic placeholder, not a real service. The text in the service file is a *shell script* in the data field, not a separate script. This is a real anti-pattern: large multi-line shell scripts inside TOML strings. Should be a real `.sh` file in `/usr/lib/redbear-diag/`.
**seatd**: `local/recipes/system/seatd/` (upstream 0.9.1) with the Red Bear build flags. Compiles, registers a Unix socket. Per `redbear-full.toml:540-545` the user is created (`sddm` uid 102) but `/var/run/seatd.sock` is not pre-created in the config. SDDM expects to talk to seatd at `SEATD_SOCK=/var/run/seatd.sock` (per `redbear-full.toml:527`).
### 6. Quirk System
**Location**: `local/recipes/drivers/redox-driver-sys/source/src/quirks/` (8 files)
**TOML data**: `local/recipes/system/redbear-quirks/source/quirks.d/` (22 files)
**Document**: `local/docs/QUIRKS-SYSTEM.md` (3,803 lines)
**Status as of 2026-06-09**: ALL phases R0-R22 RESOLVED OR DEFERRED. 131 host-buildable unit tests + 13 acpid + 12 pcid + 7 usbhidd + 4 evdevd + 3 iwlwifi = **170 host-or-target tests**.
#### What works (per QUIRKS-SYSTEM.md + code-level inspection)
| Subsystem | Bit count | Compiled-in entries | TOML entries | Consumer |
|-----------|-----------|---------------------|--------------|----------|
| `PciQuirkFlags` | 46 (bits 0-45) | ~50 in `pci_table.rs` | 30+ in `redbear-quirks/quirks.d/*.toml` | pcid (full), amdgpu (full), redbear-drm (full), xhcid (partial), usbhidd (full), evdevd (full), iwlwifi (full) |
| `UsbQuirkFlags` | 22 (bits 0-21) | multiple in `usb_table.rs` | `20-usb.toml` | usbhidd, xhcid |
| `HidQuirkFlags` | 24 (bits, with gaps to match Linux) | 9 in `hid_table.rs` | `40-hid.toml` | evdevd |
| `XhciControllerQuirkFlags` | 22 (bits, matching Linux) | 10+ in `xhci_controller_table.rs` | n/a (PCI-keyed) | xhcid (Blocker 4 partial) |
| `AcpiQuirkFlags` | 16 (bits 0-15) | empty initial | `47-acpi-button.toml` (18 rules) | acpid (in the table, deferred) |
| `DrmPanelOrientation` | 4 values | n/a | `50-drm-panel.toml` (36 entries) | redox-drm (deferred until Phase 4) |
| `PlatformDmiQuirkFlags` | 7 (bits 0-6) | n/a | 31 entries in `80-platform-x86.toml` | inputd, acpid, thermald (deferred) |
| `CpuBugFlags` | 27 (bits 0-26) | empty initial | 14 entries in `90-cpu-bugs.toml` | kernel (deferred) |
| `ClocksourceQuirkFlags` | 4 (bits 0-3) | 3 in `clocksource` | `35-clocksource.toml` | kernel (deferred) |
| `ChipsetQuirkFlags` | 10 (bits 0-9) | 11 in `55-chipset-early.toml` | (same TOML) | kernel (deferred) |
| `UsbAudioQuirkFlags` | 29 (bits 0-28) | empty initial | 30 entries in `60-usb-audio.toml` | redbear-usbaudiod (deferred) |
| DMI | struct + parser | full | `47-acpi-button.toml` etc. | acpid (DMI producer), all consumers (DMI match) |
#### Stubs / half-impls
None found in the quirks *data model* and *lookup* path. The code is exercised by 131 host-buildable unit tests. The data tables are complete.
#### Missing consumer wirings (per QUIRKS-SYSTEM.md)
These are the explicit "deferred until consumer lands" gaps:
1. **R12 (DrmPanelOrientation)**: Consumer in `redox-drm` is deferred until compositor rotation lands. The 36-entry table is correct data; the consumer reads it but does nothing.
2. **R13 (PlatformDmiQuirkFlags)**: Consumer wiring deferred. inputd, acpid, thermald do not yet read the platform subsystem dispatch.
3. **R14 (CpuBugFlags)**: Kernel-side consumer deferred. The 27 X86_BUG_* bits are defined; the kernel does not use them.
4. **R15 (ClocksourceQuirkFlags)**: Kernel `Hpet::init()` does not consult `PMTMR_BLACKLIST` etc.
5. **R17 (ChipsetQuirkFlags)**: Kernel-side consumer deferred. The 11-entry table is data-only.
6. **R20 (UsbAudioQuirkFlags)**: redbear-usbaudiod does not consume the 30-entry table.
7. **R21 (SUPPRESS_IVRS)**: iommu daemon does not read the DMI rule.
#### Driver integration matrix
| Driver | Quirk consumer status |
|--------|-----------------------|
| pcid | ✅ `PciConfigWriter` + `apply_pci_quirks` (Blocker 1, 12 unit tests) |
| xhcid | 🚧 QuirkAction loop pending (Blocker 4 partial, 1-2 day task per QUIRKS-SYSTEM.md) |
| usbhidd | ✅ `log_usb_quirks` + `log_hid_quirks` at enumeration (Blocker 3, 7 unit tests) |
| evdevd | ✅ `log_hid_quirks` (Gap 10, 4 unit tests) |
| redbear-iwlwifi | ✅ direct `lookup_pci_quirks` call (Gap 12, 3 unit tests) |
| amdgpu | ✅ `redox_quirk_bridge.c` extracted (Gap 15) |
| redox-drm | ✅ `info.quirks()` lookup (Gap 11, audit misread — already resolved) |
| e1000d | ❌ no quirk consumer (HIGH priority per AGENTS.md for low-level controllers plan) |
| ixgbed | ❌ no quirk consumer (HIGH priority) |
| rtl8168d | ❌ no quirk consumer (HIGH priority) |
| virtio-netd | ❌ no quirk consumer |
| virtio-blkd | ❌ no quirk consumer |
| acpid | 🚧 DMI producer complete, ACPI consumer deferred (R11) |
| kernel | ❌ no quirk consumer (R14, R15, R17) |
| iommu | ❌ no quirk consumer (R21) |
| thermald | ❌ no quirk consumer |
| redbear-usbaudiod | ❌ no quirk consumer (R20) |
| xhcid consumers (other than `force_poll` bit) | ❌ 17 xhcid bits have no consumer beyond `log_unenforced_xhci_quirks` warn line |
#### Quirk completeness
- **Compiled-in quirks**: 100% coverage of the Linux 7.1 PCI/USB/HID/xHCI/ACPI/DMI surface for the data the project has chosen to model.
- **TOML-loaded quirks**: 100% via the `redbear-quirks` package. The 22 TOML files are installed via the `redbear-quirks` recipe (script glob per QUIRKS-SYSTEM.md R7 audit fix).
- **DMI matching**: full — the chain `bootloader UEFI find_smbios() → kernel SmbiosScheme → acpid dmi::parse_smbios_table() → /scheme/acpi/dmi` was wired in 2026-06 (Blocker 2).
- **Driver integration**: ~50% of relevant drivers. The remaining 50% (network drivers, kernel, audio) are deferred per the canonical plan.
#### LoC estimate
For the deferred consumers:
- R12 redox-drm panel rotation: ~200 LoC
- R13 platform x86 (inputd/acpid/thermald): ~600 LoC
- R14 kernel CPU bug mitigations: ~800 LoC
- R15 kernel clocksource: ~200 LoC
- R17 kernel chipset-early: ~1,500 LoC
- R20 redbear-usbaudiod: ~400 LoC
- R21 iommu: ~150 LoC
- xhcid QuirkAction loop completion: ~150 LoC
- Network driver consumers (e1000d, ixgbed, rtl8168d, virtio-netd): ~800 LoC total
**Total**: ~4,800 LoC. 68 weeks with 1 dev.
#### Time estimate
68 weeks. The data side is solved; the consumers are the work.
---
## Cross-Cutting Issues
### Init Service Order (CRITICAL)
The canonical order from the task brief is:
```
1. logd (logging)
2. pcid (PCI enumeration)
3. pcid-spawner (launches GPU, USB, network drivers)
4. redox-drm (GPU driver registers /scheme/drm/card0)
5. vesad (early-boot framebuffer, runs only in initfs)
6. fbbootlogd (boot log)
7. fbcond (text console)
8. init (mounts sysroot, switches to rootfs)
9. redoxfs (rootfs)
10. logd (rootfs)
11. pcid (rootfs, takes over from initfs pcid)
12. d-bus system bus
13. seatd (seat management)
14. redbear-sessiond (login1 D-Bus broker)
15. redbear-authd (authentication)
16. SDDM (display + login)
```
**Actual state on disk**:
#### Initfs services (`local/sources/base/init.initfs.d/`, 20 files):
| File | Order | Service | Binary | In redbear-full? |
|------|-------|---------|--------|-------------------|
| 00_clock.service | 00 | Clock daemon | `clock` | via base pkg |
| 00_logd.service | 00 | Logger | `logd` | ✅ |
| 00_nulld.service | 00 | Null sink | `nulld` | ✅ |
| 00_randd.service | 00 | Random daemon | `randd` | ✅ |
| 00_zerod.service | 00 | Zero sink | `zerod` | ✅ |
| 00_runtime.target | 00 | Runtime target | n/a (target) | ✅ |
| ramfs@logging.service | 00 | Ramfs for logd | `ramfs logging` | ✅ |
| 10_inputd.service | 10 | Input multiplexer | `inputd` | ⚠️ conflicts with evdevd (plan v6.0) |
| 10_lived.service | 10 | Live disk | `lived` | ✅ (inherits from redbear-mini) |
| 20_fbbootlogd.service | 20 | Boot log | `fbbootlogd` | ✅ |
| 20_fbcond.service | 20 | Text console | `fbcond` | ✅ |
| 20_vesad.service | 20 | VESA FB handoff | `vesad` | ✅ |
| 20_graphics.target | 20 | Graphics target | n/a | ✅ |
| 30_acpid.service | 30 | ACPI daemon | `acpid` | ✅ |
| 40_bcm2835-sdhcid.service | 40 | RPi SD | `bcm2835-sdhcid` | ❌ (aarch64 only) |
| 40_drivers.target | 40 | Drivers target | n/a | ✅ |
| 40_hwd.service | 40 | Hardware manager | `hwd` | ✅ |
| 40_pcid-spawner-initfs.service | 40 | PCI spawner | `pcid-spawner --initfs` | ✅ |
| 40_ps2d.service | 40 | PS/2 | `ps2d` | ✅ |
| 50_rootfs.service | 50 | Rootfs mount | `redoxfs` | ✅ |
| 90_initfs.target | 90 | Initfs done | n/a | ✅ |
**Observations**:
- 1-7: logd, pcid (implicitly via pcid-spawner), pcid-spawner, redox-drm (via pcid-spawner), vesad, fbbootlogd, fbcond — all in the initfs.
- 8-9: init + redoxfs. Init does the switch_root; redoxfs is the rootfs mount.
- 10-15: not in the initfs; they start in the rootfs.
#### Rootfs services in redbear-full (`config/redbear-full.toml:194-529`):
| File path in TOML | Order | Service | Depends on | Notes |
|---------------------|-------|---------|------------|-------|
| `/etc/init.d/00_firmware-loader.service` | 00 | Firmware loader | 05_boot-essential | ✅ |
| `/etc/init.d/05_boot-essential.target` | 05 | Target | 04_drivers | ✅ |
| `/etc/init.d/13_iommu.service` | 13 | IOMMU | 05_boot-essential + 00_acpid | ✅ |
| `/etc/init.d/10_redox-drm.service` | 10 | GPU driver | 05_boot-essential + 00_driver-manager | ✅ (shell wrapper) |
| `/etc/init.d/12_dbus.service` | 12 | D-Bus | 12_boot-late + 00_ipcd | ✅ |
| `/etc/init.d/13_redbear-sessiond.service` | 13 | login1 | 12_dbus | ✅ |
| `/etc/init.d/13_seatd.service` | 13 | seatd | 12_dbus + 13_redbear-sessiond | ✅ |
| `/etc/init.d/13_redbear-keymapd.service` | 13 | keymap | 10_evdevd | ✅ |
| `/etc/init.d/13_redbear-ime.service` | 13 | IME | 10_evdevd | ✅ |
| `/etc/init.d/13_redbear-accessibility.service` | 13 | accessibility | 10_evdevd | ✅ |
| `/etc/init.d/14_redbear-upower.service` | 14 | UPower | 12_dbus | ✅ |
| `/etc/init.d/14_redbear-udisks.service` | 14 | UDisks2 | 12_dbus | ✅ |
| `/etc/init.d/14_redbear-polkit.service` | 14 | polkit | 12_dbus | ✅ |
| `/etc/init.d/11_redbear-authd.service` | 11 | authd | 12_dbus | ✅ |
| `/etc/init.d/12_sddm.service` | 12 | SDDM | 00_driver-manager + 10_redox-drm + 10_evdevd + 12_dbus + 13_redbear-sessiond + 13_seatd + 11_redbear-authd | ✅ |
| `/etc/init.d/30_console.service` | 30 | Console getty | 29_activate_console | ⚠️ 29_activate_console not defined in this config |
| `/etc/init.d/31_debug_console.service` | 31 | Debug console | 29_activate_console | ⚠️ same |
| `/etc/init.d/99_diag_serial.service` | 99 | Diag marker | 31_debug_console + 30_console + 12_dbus | ✅ |
| `/etc/init.d/99_kwin_test.service` | 99 | Diagnostic | 12_sddm | ⚠️ inline shell script in TOML — anti-pattern |
**Missing references**:
- `29_activate_console.service` is referenced by `30_console.service` and `31_debug_console.service` but is not defined. The console may not start.
- `12_boot-late.target` is referenced by `12_dbus.service` and not defined. The D-Bus service may not start until the cook recipe provides a service file with that name.
- `10_evdevd.service` is referenced by `12_sddm.service` and others; not defined here. May come from a recipe-level default.
- `04_drivers.target` is referenced; comes from `redbear-legacy-base.toml` (config inheritance, line 17 of redbear-full.toml says `include = ["redbear-mini.toml"]`).
- `00_driver-manager.service` is referenced; not visible in the redbear-full.toml — comes from a base recipe.
- `00_ipcd.service` is referenced; comes from base.
- `00_acpid.service` is referenced; comes from base.
**Order comparison (canonical plan vs actual)**:
| Step | Canonical | Actual initfs | Actual rootfs | Match? |
|------|-----------|---------------|---------------|--------|
| 1. logd | initfs | `00_logd.service` | inherits from base | ✅ |
| 2. pcid | rootfs | not in initfs (correct — pcid is a userspace daemon that needs the kernel to expose `scheme:pci`) | comes from base | ✅ |
| 3. pcid-spawner | both | `40_pcid-spawner-initfs.service` | `00_pcid-spawner.service` from base | ✅ |
| 4. redox-drm | rootfs | not in initfs (should it be? see plan v6.0) | `10_redox-drm.service` | ✅ (initfs is FB-only) |
| 5. vesad | initfs | `20_vesad.service` | n/a (intentionally — only initfs) | ✅ |
| 6. fbbootlogd | initfs | `20_fbbootlogd.service` | n/a | ✅ |
| 7. fbcond | initfs | `20_fbcond.service` | n/a | ✅ |
| 8. init | runtime | always PID 1 | n/a | ✅ |
| 9. redoxfs | rootfs | `50_rootfs.service` (in initfs) | n/a | ✅ |
| 10. logd (rootfs) | rootfs | inherits from base `00_logd.service` (PID 1 of rootfs reuses initfs's) | ✅ |
| 11. pcid (rootfs) | rootfs | not started explicitly in redbear-full.toml; pcid-spawner.service is at `00_` order so it runs early; the pcid **daemon** itself is not explicitly listed as a service file — relies on pcid-spawner spawning it on the first PCI function | ⚠️ |
| 12. dbus | rootfs | n/a | `12_dbus.service` | ✅ |
| 13. seatd | rootfs | n/a | `13_seatd.service` | ✅ |
| 14. redbear-sessiond | rootfs | n/a | `13_redbear-sessiond.service` | ✅ |
| 15. redbear-authd | rootfs | n/a | `11_redbear-authd.service` | ✅ |
| 16. SDDM | rootfs | n/a | `12_sddm.service` | ✅ |
**Issues with the order**:
- **Step 11 (pcid rootfs)**: the pcid daemon itself is not explicitly started. The pcid-spawner (`00_pcid-spawner.service` from base) is the consumer-side, but pcid is the producer of `/scheme/pci`. If pcid is not started, pcid-spawner has nothing to read. This is likely handled by pcid-spawner including pcid as a dependency, but I cannot verify without reading the base service file.
- **Step 12 (dbus) ordering**: `12_dbus.service` requires `12_boot-late.target` which is not in the config. If the target is provided by a recipe, OK; if not, dbus will fail to start.
- **Step 13 (seatd)**: requires `13_seatd.service` to start before SDDM, but SDDM requires both `13_redbear-sessiond.service` AND `13_seatd.service` — which means SDDM correctly waits for both. The order is correct.
- **Step 14 (redbear-sessiond)**: `13_redbear-sessiond.service` requires `12_dbus.service` only. Good.
- **Step 15 (redbear-authd)**: `11_redbear-authd.service` (note the 11 prefix, out of numeric order) requires only `12_dbus.service`. Good.
- **Step 16 (SDDM)**: requires everything. Good.
**Other issues found in the config**:
- The `12_sddm.service` is `oneshot_async` (line 466) — it does not notify readiness. SDDM runs in the background; if it fails, no one is watching.
- The 99_kwin_test.service is `oneshot_async` and runs a 600-character shell command embedded in the TOML `data` field. This is a real anti-pattern: shell scripts should be in `/usr/lib/redbear-diag/` as `.sh` files, not embedded.
#### Redbear-mini services (for context):
`redbear-mini.toml:1-200` is a separate config that does not pull in any of the desktop services. It is the text-only path.
#### Result:
The order is *correct* in the sense that dependencies are respected. The issues are:
1. A few target services (`12_boot-late.target`, `29_activate_console.service`) are referenced but not defined in the visible config — they may be provided by a recipe's `/usr/lib/init.d/` defaults.
2. SDDM is `oneshot_async` with no supervision.
3. The 99_kwin_test service is an in-TOML shell script.
4. The init has no auto-restart, so any failure requires a manual reboot.
### GPU Stack Chain (mesa → libdrm → libepoxy → redox-drm → qtbase → qtdeclarative → qtwayland → KF6 → KWin → SDDM → KDE Plasma)
For each link: does it compile? does it link? does it run?
| Link | Compile | Link | Run | Note |
|------|---------|------|-----|------|
| mesa | ✅ (per plan + project README) | ✅ | ❓ | Built with swrast, virgl, iris, crocus; EGL/GBM/GLES2 enabled. Not runtime-tested on redox HW. |
| libdrm | ✅ | ✅ | ❓ | Real library, no stub. Per project README: "DRM userspace library with Red Bear patches for render node and virtio-gpu support". |
| libepoxy | ❌ — stub installed | n/a | ❌ | `libepoxy-stub` installed to satisfy CMake find_package. Anti-pattern. |
| redox-drm | ✅ | ✅ | ❓ | Daemon compiles. Bounded QEMU virtio-gpu runtime path works. Real HW validation pending. |
| qtbase | ✅ | ✅ | ❓ | Per project README: built with -DFEATURE_opengl=ON, -DFEATURE_egl=ON (project policy). |
| qtdeclarative | ✅ | ✅ | ❓ | QML/Quick is a Phase 0 blocker. |
| qtsvg | ✅ | ✅ | ❓ | — |
| qtwayland | ✅ | ✅ | ❓ | — |
| qt6-wayland-smoke | ✅ | ✅ | ❓ | Smoke test only. |
| qt6-sensors | ✅ | ✅ | ❓ | — |
| KF6 (32/32) | ✅ per AGENTS.md | ✅ | ❓ | kirigami is blocked (QML gate). |
| kdecoration | ✅ | ✅ | ❓ | — |
| kwin | ✅ with KWIN_BUILD_*=OFF | ✅ | ❓ | Per recipe.toml:1 `#TODO: KWin — full build with Qt6Quick/QML`. |
| sddm | ✅ with sed-stripped X11 | ✅ | ❓ | Per recipe.toml:1 `#TODO: SDDM display manager — Wayland-only build`. |
| KDE Plasma (plasma-framework, plasma-workspace, plasma-desktop) | ❌ BLOCKED | n/a | n/a | Comments out in `redbear-full.toml:147-150` (QML gate). |
**Summary**: 12 of 14 links compile and link. 1 is a stub (libepoxy). 1 is blocked (Plasma). Runtime validation: open.
### Display Handover
**Project policy** (from `AGENTS.md` "NO VESA POLICY"):
> All display output goes through the DRM/KMS path via real GPU drivers. ... Once redox-drm initializes and registers scheme:drm/card0, vesad must hand off and NOT register scheme:display.vesa as the primary display surface.
**Implementation**:
| Layer | Mechanism | Implementation status |
|-------|-----------|----------------------|
| Bootloader linear FB | UEFI/BIOS GOP | ✅ |
| vesad (initfs) | registers `display.vesa` | ✅ but violates policy — never unregisters |
| redox-drm (rootfs) | registers `drm` | ✅ with EEXIST check |
| fbcond | `ConsumerHandle::open_display_v2()` re-open | ✅ (handoff support is there, but only triggered on input event) |
| fbbootlogd | same | ✅ |
| redbear-compositor | prefers DRM over FB | ✅ but does not actively drop FB |
| KWin | uses `--drm /scheme/drm/card0` | ✅ |
| SDDM | uses KWin via `CompositorCommand` | ✅ |
| user shell | `/scheme/drm/card0` | per-app choice |
**The handoff is *de facto* but not *de jure*.** No code in `vesad` ever tears down `display.vesa`. The policy is enforced by app choice (KWin, SDDM, redbear-compositor) to use DRM. If a user app opens `/scheme/display.vesa`, they get the boot framebuffer — not what the project wants.
**Verification question from the audit brief**:
> Does the early-boot vesad properly hand off to redox-drm?
> Per project policy: "vesad must hand off and NOT register scheme:display.vesa as the primary display surface"
> Verify this is implemented in the actual code (not just docs).
**Answer**: **No, it is not implemented.** The code at `vesad/src/main.rs:86-87` registers `display.vesa` permanently. There is no teardown path. The handoff is *app-level*, not *daemon-level*.
To fix:
1. Add a scheme-watcher in `vesad` that listens for `scheme:drm/card0` to be created.
2. On creation, call `libredox::call::unregister_scheme(...)` for `display.vesa`.
3. Add a fallback: if `scheme:drm` is not created within N seconds, keep `display.vesa` for debugging.
4. Document the behaviour change in `redbear-full.toml` config.
This is a 2-week, ~300 LoC change.
---
## Implementation Roadmap
### Phase 1: Unblock Display Handover (2 weeks, ~800 LoC)
1. **vesad handoff** (`local/sources/base/drivers/graphics/vesad/src/main.rs:86-87` + new `handoff.rs`):
- Watch `/scheme/drm` for the `card0` file.
- On detection, unregister `display.vesa` via `libredox::call::unregister_scheme(...)`.
- Add a CLI flag `--no-handoff` for debugging.
2. **Initfs vesad exit signal** (in `init.d/50_rootfs.service` or a new `51_vesad-stop.service`):
- Send SIGTERM to vesad's PID after rootfs is up.
3. **Remove `virtio-gpud` from initfs.toml**:
- `local/sources/base/drivers/initfs.toml:32-37` should drop the `virtio-gpu` entry; rely on `redox-drm` exclusively.
4. **Add a watchdog** in the rootfs `10_redox-drm.service` to restart redox-drm if `/scheme/drm/card0` disappears.
### Phase 2: Wire Init Auto-Restart and Shutdown (3 weeks, ~1,000 LoC)
1. **Auto-restart loop in `init/src/scheduler.rs`**:
- Add `enum JobKind { Start, Stop, Restart }`.
- Add `OnFailure=restart`, `RestartSec=5s`, `StartLimitBurst=3`, `StartLimitIntervalSec=60s` to `UnitInfo`.
2. **Poweroff/reboot**:
- Add `reboot(2)` and `poweroff(2)` syscalls to kernel; `init` calls them on a magic file (`/run/systemd/reboot` or similar).
3. **Multi-user target**:
- Replace the `for entry in entries` loop in `init/src/main.rs:153-173` with a single `multi-user.target` schedule that pulls in the dep graph.
4. **Status reporting**:
- Pipe `waitpid` status to a ring buffer; expose as `/scheme/init/status`.
### Phase 3: Replace `*-stub` Recipes (3-4 weeks, ~2,500 LoC)
For each of `libepoxy-stub`, `libxcvt-stub`, `libdisplay-info-stub`, `lcms2-stub`, `libudev-stub`:
1. **libepoxy**: replace with the real libepoxy 1.5.10 recipe (local or upstream). Real GL/EGL function pointer loading.
2. **libxcvt**: real libxcvt (it is small, ~300 LoC of pure C).
3. **libdisplay-info**: real libdisplay-info 0.2.0 (the stub is bounded to base EDID; the real lib supports CTA/DisplayID too).
4. **lcms2**: real lcms2 2.15. The stub has 8 functions; the real lib has ~100.
5. **libudev**: real libudev (or `udev-shim` proper, exposing `scheme:udev`).
Per project AGENTS.md: "Any stub found in the tree is a bug to be fixed, not a precedent to follow". The `redbear-quirks` recipe already has the data; the consumers need the real libraries.
### Phase 4: SDDM Real Build (3-4 weeks, ~1,000 LoC)
1. **Implement 4 `// TODO: IMPLEMENT`** in `local/recipes/kde/sddm/source/src/daemon/DisplayManager.cpp:156,160,164,195`. These are `addLocalDisplay`, `addRemoteDisplay`, `addSocketDisplay`, etc. Real implementations need to talk to `redbear-sessiond` for seat assignment.
2. **Replace `pam-redbear` shim** with a real PAM module:
- Implement the full PAM API (pam_start, pam_authenticate, pam_acct_mgmt, pam_open_session, pam_close_session, pam_setcred, pam_end).
- Use Unix socket JSON to `redbear-authd` for the auth backend.
3. **Remove `stubs/linux/{kd.h,vt.h}` and `stubs/X11/Xauth.h`** in favour of real relibc headers.
4. **Hand-rolled shell script in `99_kwin_test.service`** → move to `/usr/lib/redbear-diag/kwin-test.sh`.
### Phase 5: KWin Real QML Build (12-16 weeks, ~7,700 LoC)
1. **Implement Qt6Quick/QML on Redox** (this is Phase 0 of the canonical plan; the actual work is upstream-bound):
- Implement `QQuickWindow` (window, scene graph, render thread).
- Implement `QQmlEngine` (parser, type system, JIT).
- Implement `QQuickItem` (scene item tree, transforms, events).
2. **Re-enable KWIN_BUILD_QML_UI=ON** in `kwin/recipe.toml:155-165`.
3. **Re-enable KWIN_BUILD_SCREENLOCKER, KWIN_BUILD_TABBOX, KWIN_BUILD_GLOBALSHORTCUTS, KWIN_BUILD_KCMS** — each is a separate piece of QML/Quick UI.
4. **Add DrmPanelOrientation consumer** in redox-drm (R12 deferred).
5. **Quirk consumers** (R12, R14, R15, R17, R20) — see §6.
### Phase 6: Plasma + Apps (8-12 weeks, beyond this assessment)
Per the canonical plan, after KWin real-QML lands, plasma-framework, plasma-workspace, plasma-desktop can be re-enabled. Dolphin, Kate, Gwenview, Konsole as separate recipes.
---
## Testing Strategy
### Unit tests (host-buildable)
- **redox-driver-sys**: 131 unit tests covering all 10 quirk flag families + DMI + QuirkAction.
- **pcid**: 12 unit tests (mock + dispatch + conversions + cap-list walker).
- **usbhidd**: 7 unit tests.
- **evdevd**: 4 unit tests.
- **redbear-iwlwifi**: 3 unit tests.
- **redox-drm**: bring-up + ioctl proxy tests.
- **init**: needs unit tests; currently 0. The TOML deserializer is a natural target.
- **initfs**: 1 round-trip test (`archive_and_read`).
### Integration tests (QEMU)
- `local/scripts/test-phase1-runtime.sh --qemu redbear-full` — POSIX fd-event tests.
- `local/scripts/test-greeter-qemu.sh --check` — redbear-greeter bounded QEMU proof.
- `local/scripts/test-phase6-kde-qemu.sh --check` — KWin Phase 6.
- `local/scripts/test-lowlevel-controllers-qemu.sh` — xHCI, IOMMU, PS/2, timer proofs.
- `local/scripts/test-usb-maturity-qemu.sh` — xHCI mode, full USB stack, USB storage.
### Bare-metal smoke tests
- AMD Ryzen Threadripper 128-thread (per AGENTS.md header).
- Intel ARC (Xe driver) — not yet covered by tests.
- `local/scripts/test-baremetal.sh`.
### Gap
- No automated test for the `vesad → redox-drm` handoff. The user has to manually reboot after the handoff is implemented and verify that the display transitions cleanly.
- No test for SDDM activation in headless QEMU. SDDM requires a display; CI cannot exercise it without a graphical session.
- No test for KWin on QEMU. The recipe compiles but the binary has never been run in a CI harness.
---
## Risk Assessment
### What happens if we ship as-is?
- `redbear-mini` boots to a text console on QEMU ✅ (per the project README).
- `redbear-full` boots to a text console on QEMU (vesad + fbcond work) ✅.
- `redbear-full` boots to a black screen if `redox-drm` is missing (the `10_redox-drm.service` shell wrapper exits 0 if DRM is already registered but the user has no other surface to fall back to).
- KWin may compile but fail to start due to the missing libudev-stub for input device discovery. The user gets a blank screen.
- SDDM starts but the login is broken because the `// TODO: IMPLEMENT` in DisplayManager.cpp returns false for all display types.
### Minimum to make Phase 1 work (boot to text login)
Already done. `redbear-mini` is functional. Cost: 0 LoC.
### Minimum to make Phase 2 work (boot to Wayland compositor on QEMU)
- Phase 1 + remove virtio-gpud from initfs.toml + remove `*-stub` deps that KWin needs at runtime.
- Cost: 0.5 day for the initfs cleanup + 3-4 weeks for the stubs. With stubs left in, the user can boot a `redbear-compositor` (not KWin) Wayland session.
- Time: 3-4 weeks.
### Minimum to make Phase 3 work (SDDM login)
- Phase 2 + implement the 4 DisplayManager TODOs + real pam-redbear.
- Cost: 3-4 weeks.
- Time: 6-8 weeks from today.
### Minimum to make Phase 4 work (KDE desktop)
- Phase 3 + QML/Quick on Redox + re-enable KWIN_BUILD_QML_UI.
- Cost: 12-16 weeks.
- Time: 18-24 weeks from today.
### Highest-impact stub to fix first
The **5 `*-stub` recipes** are the single highest-impact change because they block the entire KWin + SDDM chain. If they are removed and replaced with real libraries, the user gets a working KWin that can render a real desktop (sans QML effects). Cost: 3-4 weeks.
The **vesad → redox-drm handoff** is the second-highest because it makes the system policy-compliant. Cost: 2 weeks.
The **4 `// TODO: IMPLEMENT` in DisplayManager.cpp** are the third because they block SDDM from displaying anything. Cost: 2-3 weeks.
### Risk register
| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| `vesad` is also used by the bootloader UEFI GOP fallback (a real feature) | Removing the scheme would break the boot | High (if handoff is too aggressive) | Add the `--no-handoff` flag and a `REDOX_VESAD_HANDOFF=0` env var |
| Replacing `libepoxy-stub` requires Mesa EGL headers that may not be installed | KWin link fails | Medium | Verify the Mesa EGL/GLES2 install in the sysroot first |
| SDDM activation in QEMU needs a real seatd socket; `SEATD_SOCK=/var/run/seatd.sock` is not created in the config | SDDM cannot find seatd | Medium | Add a `make_socket /var/run/seatd.sock` step in the seatd service file |
| The plan v6.0 single-evdev-producer is a big refactor of the input path | Will break the boot | Medium | Land it in redbear-mini first, then in redbear-full |
| KWin QML on Redox requires ~4,000 LoC of Qt6Quick/QQmlEngine | Phase 5 fails | High | Re-evaluate KWin as the canonical compositor; consider weston or a custom compositor |
| The user has an NVIDIA GPU | Not in the AMD+Intel parity path | Low (out of scope) | Document in the hardware validation matrix |
---
## Appendix A: Grep Results (raw)
### A.1 `todo!()` / `unimplemented!()` in the chain
| File:line | Snippet |
|-----------|---------|
| `local/sources/base/drivers/pcid/src/cfg_access/fallback.rs:89` | `todo!("Pci::CfgAccess::read on this architecture")` |
| `local/sources/base/drivers/pcid/src/cfg_access/fallback.rs:94` | `todo!("Pci::CfgAccess::write on this architecture")` |
| `local/sources/base/drivers/graphics/vesad/src/scheme.rs:146` | `unimplemented!("Vesad does not support this function");` |
| `local/sources/base/drivers/graphics/ihdgd/src/device/scheme.rs:138` | `unimplemented!("ihdgd does not support this function");` |
| `local/sources/base/drivers/input/ps2d/src/controller.rs:133` | `unimplemented!()` |
| `local/sources/base/drivers/input/ps2d/src/vm.rs:68` | `unimplemented!()` |
**Total**: 6 `unimplemented!()` / `todo!()` panics in non-test code on the boot→display path.
### A.2 `expect("TODO")` in the chain
| File:line | Snippet |
|-----------|---------|
| `local/sources/base/init/src/service.rs:98` | `let current_namespace_fd = libredox::call::getns().expect("TODO");` |
| `local/sources/base/init/src/service.rs:100` | `.expect("TODO");` |
**Total**: 2 `expect("TODO")` panics in init service spawn.
### A.3 `// TODO` / `// FIXME` counts (chain files)
| File or directory | TODO count |
|--------------------|------------|
| `local/sources/kernel/src/**/*.rs` | 330 (per LOWLEVEL-STUBS-AUDIT.md) |
| `local/sources/base/init/src/` | 4 (2 in main.rs, 1 in service.rs, 1 in unit.rs) |
| `local/sources/base/initfs/src/` | 0 |
| `local/sources/base/drivers/pcid/src/` | 23 (per init grep) |
| `local/sources/base/drivers/pcid-spawner/src/` | 0 |
| `local/sources/base/drivers/graphics/{vesad,fbcond,fbbootlogd,virtio-gpud,driver-graphics,ihdgd,console-draw}` | 100+ (per init grep) |
| `local/sources/base/drivers/acpid/src/` | 10 (per init grep) |
| `local/sources/base/drivers/hwd/src/` | 5 (per init grep) |
| `local/sources/base/drivers/input/{ps2d,usbhidd}` | 23 (per init grep) |
| `local/recipes/gpu/redox-drm/source/src/` | 0 (per init grep) |
| `local/recipes/wayland/redbear-compositor/source/src/` | 0 (per init grep) — but explicit "bounded proof scaffold" comment |
| `local/recipes/system/redbear-sessiond/source/src/` | 0 (per init grep) |
| `local/recipes/system/redbear-authd/source/src/` | 0 (per init grep) |
| `local/recipes/system/redbear-greeter/source/src/` | 0 (per init grep) |
| `local/recipes/system/dbus/source/` | 239 (upstream dbus, expected) |
| `local/recipes/system/seatd/source/` | 3 (TODO in seatd/server.c, seatd/client.c, common/connection.c) |
| `local/recipes/kde/sddm/source/src/daemon/` | 5 (4 TODO:IMPLEMENT in DisplayManager.cpp + 1 in DaemonApp.h) |
| `local/recipes/kde/kwin/source/src/` | (upstream KWin 6.3.4; many TODOs) |
**Total in the chain (excluding upstream KWin/SDDM/dbus)**: ~500+.
### A.4 Anti-pattern grep results
```
$ grep -rE "stub" local/recipes/libs/ --include="*.toml"
local/recipes/libs/libinput/recipe.toml:18: "libudev-stub",
local/recipes/libs/lcms2-stub/recipe.toml:1: #TODO: lcms2 stub — provides lcms2::lcms2 cmake target for KWin linking
local/recipes/libs/libepoxy-stub/recipe.toml:1: #TODO: libepoxy stub — provides epoxy::epoxy cmake target for KWin linking
local/recipes/libs/libxcvt-stub/recipe.toml:1: #TODO: libxcvt stub — provides libxcvt pkgconfig for KWin linking
local/recipes/libs/libdisplay-info-stub/recipe.toml:1: #TODO: bounded libdisplay-info shim for the KWin reduced path
```
5 stub recipes installed in the build chain.
```
$ grep -n "display\.vesa" local/sources/base/drivers/graphics/vesad/src/
local/sources/base/drivers/graphics/vesad/src/main.rs:1: extern crate orbclient;
local/sources/base/drivers/graphics/vesad/src/main.rs:87: GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned(), true);
```
vesad still registers as `display.vesa` (policy violation).
### A.5 Service file enumeration
```
$ ls local/sources/base/init.initfs.d/ | wc -l
20
$ ls local/sources/base/init.d/ | wc -l
10
$ grep -c "\[\[files\]\]" config/redbear-full.toml
19
```
20 initfs services, 10 rootfs services from base, 19 config `[[files]]` overrides in redbear-full.
### A.6 Quirks data TOML enumeration
```
$ ls local/recipes/system/redbear-quirks/source/quirks.d/ | wc -l
22
```
22 TOML files in `redbear-quirks`. After the R7 audit fix (glob install), all 22 ship to `/etc/quirks.d/`.
---
## Appendix B: File-by-file Line Counts (chain)
### B.1 Kernel
```
$ find local/sources/kernel/src -name "*.rs" | xargs wc -l | tail -1
~21,555 total
```
(Per LOWLEVEL-STUBS-AUDIT.md.) Per-file breakdown not re-tabulated here; see the audit.
### B.2 Init + Initfs
```
$ wc -l local/sources/base/init/src/*.rs
184 local/sources/base/init/src/main.rs
116 local/sources/base/init/src/scheduler.rs
163 local/sources/base/init/src/script.rs
132 local/sources/base/init/src/service.rs
251 local/sources/base/init/src/unit.rs
846 total
```
```
$ wc -l local/sources/base/initfs/src/*.rs
287 local/sources/base/initfs/src/lib.rs
126 local/sources/base/initfs/src/types.rs
413 total
```
```
$ wc -l local/sources/base/initfs/tools/src/lib.rs local/sources/base/initfs/tools/src/bin/*.rs
590 local/sources/base/initfs/tools/src/lib.rs
67 local/sources/base/initfs/tools/src/bin/archive.rs
112 local/sources/base/initfs/tools/src/bin/dump.rs
769 total
```
```
$ wc -l local/sources/base/init.initfs.d/* local/sources/base/init.d/*
243 total (20 + 10 files)
```
### B.3 PCID
```
$ wc -l local/sources/base/drivers/pcid/src/*.rs
284 local/sources/base/drivers/pcid/src/driver_handler.rs
6 local/sources/base/drivers/pcid/src/lib.rs
392 local/sources/base/drivers/pcid/src/main.rs
597 local/sources/base/drivers/pcid/src/quirks.rs
444 local/sources/base/drivers/pcid/src/scheme.rs
1723 (these 5)
$ wc -l local/sources/base/drivers/pcid/src/cfg_access/*.rs
~360 cfg_access/mod.rs
96 cfg_access/fallback.rs
$ wc -l local/sources/base/drivers/pcid/src/driver_interface/*.rs
~1300 (8 files: bar.rs, cap.rs, config.rs, id.rs, irq_helpers.rs, mod.rs, msi.rs)
$ wc -l local/sources/base/drivers/pcid-spawner/src/*.rs
101 pcid-spawner/src/main.rs
$ echo "pcid total: ~3083"
```
### B.4 Display chain
```
$ wc -l local/sources/base/drivers/graphics/vesad/src/*.rs
133 vesad/src/main.rs
275 vesad/src/scheme.rs
408 total
$ wc -l local/sources/base/drivers/graphics/fbcond/src/*.rs
91 fbcond/src/display.rs
253 fbcond/src/main.rs
193 fbcond/src/scheme.rs
134 fbcond/src/text.rs
671 total
$ wc -l local/sources/base/drivers/graphics/fbbootlogd/src/*.rs
115 fbbootlogd/src/main.rs
250 fbbootlogd/src/scheme.rs
365 total
$ wc -l local/sources/base/drivers/graphics/virtio-gpud/src/*.rs
615 virtio-gpud/src/main.rs
528 virtio-gpud/src/scheme.rs
1143 total
$ wc -l local/sources/base/drivers/graphics/driver-graphics/src/**/*.rs local/sources/base/drivers/graphics/driver-graphics/src/*.rs
~1140 (lib.rs + kms/{connector,mod,objects,properties}.rs)
$ wc -l local/sources/base/drivers/graphics/ihdgd/src/main.rs local/sources/base/drivers/graphics/ihdgd/src/device/*.rs
~4042 (1 main + 13 device files)
```
### B.5 redox-drm
```
$ find local/recipes/gpu/redox-drm/source/src -name "*.rs" | xargs wc -l | tail -1
30332 total (130 files)
```
```
$ wc -l local/recipes/gpu/redox-drm/source/src/main.rs
815 redox-drm/src/main.rs
```
### B.6 redbear-compositor
```
$ wc -l local/recipes/wayland/redbear-compositor/source/src/*.rs local/recipes/wayland/redbear-compositor/source/src/bin/*.rs
2180 main.rs
483 display_backend.rs
388 handlers.rs
177 protocol.rs
198 state.rs
197 wire.rs
845 bin/redbear-compositor-check.rs
4468 (excluding tests)
```
```
$ wc -l local/recipes/wayland/redbear-compositor/source/tests/integration_test.rs
615 tests/integration_test.rs
```
### B.7 KWin + SDDM
```
$ find local/recipes/kde/kwin/source -name "*.cpp" -o -name "*.h" 2>/dev/null | xargs wc -l | tail -1
~38591 (upstream KWin 6.3.4)
$ find local/recipes/kde/sddm/source -name "*.cpp" -o -name "*.h" 2>/dev/null | xargs wc -l | tail -1
~38591 (upstream SDDM; same file count)
```
The KWin and SDDM LoC are essentially the upstream tarball size, not Red Bear work. The Red Bear work is in `recipe.toml` (~187 for KWin, ~108 for SDDM) and the patches.
### B.8 Session / Auth / Greeter
```
$ wc -l local/recipes/system/redbear-sessiond/source/src/*.rs
48 acpi_watcher.rs
221 control.rs
267 device_map.rs
642 manager.rs
188 main.rs
54 runtime_state.rs
450 session.rs
147 seat.rs
2017 total
$ wc -l local/recipes/system/redbear-authd/source/src/main.rs
719
$ wc -l local/recipes/system/redbear-greeter/source/src/main.rs local/recipes/system/redbear-greeter/source/ui/*.qml
656 main.rs
206 ui/Main.qml
862 total
```
### B.9 Quirks
```
$ wc -l local/recipes/drivers/redox-driver-sys/source/src/quirks/*.rs
~1300 (mod.rs ~1100 + 7 sub-files)
```
```
$ ls local/recipes/system/redbear-quirks/source/quirks.d/ | wc -l
22 (TOML files)
```
### B.10 Total LoC in the chain
| Stage | LoC |
|-------|-----|
| Kernel | ~21,555 |
| Init + Initfs + tools | ~2,028 |
| PCID + pcid-spawner | ~3,083 |
| Display (vesad, fbcond, fbbootlogd, virtio-gpud, driver-graphics, ihdgd) | ~8,932 |
| redox-drm | ~30,332 |
| redbear-compositor (with tests) | ~5,083 |
| KWin (upstream) | ~38,591 |
| SDDM (upstream) | ~38,591 |
| redbear-sessiond | 2,017 |
| redbear-authd | 719 |
| redbear-greeter (with QML) | 862 |
| Quirk system (redox-driver-sys) | ~1,300 |
| Quirk data TOMLs | 22 files |
| **Total (without KWin/SDDM upstream)** | **~76,000 LoC** |
| **Total (with KWin/SDDM upstream)** | **~153,000 LoC** |
Of the ~76k LoC of Red Bear work, the largest single piece is `redox-drm` (~30k LoC) and the kernel (~21.5k LoC). The display chain is well-sized at ~9k LoC; the user-facing compositor chain (redbear-compositor + KWin stubs) is small.
---
## Cross-references to existing project docs
- **`local/docs/AGENTS.md` / `AGENTS.md`** — project policies cited throughout this doc.
- **`local/docs/STUBS-AUDIT-AND-REWRITE-PLAN.md`** (994 LoC, 2026-06-09) — low-level input/keyboard/HID/serio/ACPI/USB/PCI/audio/storage/network/graphics stubs.
- **`local/docs/LOWLEVEL-STUBS-AUDIT.md`** (1,091 LoC, 2026-06-09) — ACPI/PCI/IRQ/IOMMU/Boot/Init infrastructure stubs.
- **`local/docs/USB-STUBS-AUDIT.md`** (501 LoC) — USB stubs.
- **`local/docs/HID-STUBS-AUDIT.md`** (419 LoC) — HID stubs.
- **`local/docs/QUIRKS-SYSTEM.md`** (3,803 LoC) — comprehensive quirks data + lookup + 131 unit tests.
- **`local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`** (1,380 LoC, v6.0, 2026-06-08) — canonical desktop path.
- **`local/docs/DBUS-INTEGRATION-PLAN.md`** (D-Bus for KDE Plasma 6 + Wayland).
- **`local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md`** (greeter/auth/session-launch split).
- **`local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`** (PCI/IRQ/MSI/MSI-X/IOMMU plan).
- **`local/docs/ACPI-IMPROVEMENT-PLAN.md`** (ACPI for AMD).
- **`local/docs/WIFI-IMPLEMENTATION-PLAN.md`**, **`local/docs/BLUETOOTH-IMPLEMENTATION-PLAN.md`**, **`local/docs/USB-IMPLEMENTATION-PLAN.md`** — out of scope for this assessment but referenced.
This document is the **kernel → initfs → init → display → Wayland → KDE** slice of the same plan.
---
**End of Assessment.**