docs: consolidate 3D-desktop docs (2026-07-27 round 2)
Closes the doc consolidation that was authorized in option A of the prior turn but was undone (untracked files back on disk). Re-executes the deletion + restore + stub updates in a single coherent commit. Stale docs deleted (40 files, backup at /tmp/opencode/stale-doc-backup-2026-07-27.tar.gz, 387925 bytes, 40 entries): - local/docs/3D-DRIVER-PLAN.md (Rounds 1-7, replaced by 3D-DESKTOP-COMPREHENSIVE-PLAN.md) - local/docs/REDBEAR-FULL-SDDM-BRINGUP.md (build campaign log, status folded into the comprehensive plan) - 11 docs under local/docs/legacy-obsolete-2026-07-25/ (5-KDE-PLASMA-ON-REDOX, BUILD-SYSTEM-ASSESSMENT, BUILD-SYSTEM-HARDENING-PLAN, DRM-MODERNIZATION-EXECUTION-PLAN, HOOKS, INITNSMGR-CONCURRENCY-DESIGN, NETWORKING-STACK-STATE, PATCH-PRESERVATION-AUDIT-2026-07-12, RAPL-IMPLEMENTATION-PLAN, redbear-power-improvement-plan, WAYLAND-IMPLEMENTATION-PLAN) - 15 docs under local/docs/archived/ (ACPI-I2C-HID, BUILD-SYSTEM-IMPROVEMENTS, DRIVER-MANAGER-MIGRATION-PLAN, IMPLEMENTATION-MASTER-PLAN, IMPROVEMENT-PLAN, INTEL-HDA, KERNEL-SCHEDULER-MULTITHREAD, README (replaced with stub), RELIBC-IPC-ASSESSMENT, repo-governance, SLEEP-IMPLEMENTATION-PLAN, STUBS-FIX-PROGRESS, SYSTEM-STABILITY-AND-UPSTREAM-SYNC, UPSTREAM-SYNC-PROCEDURE, USB-BOOT-INPUT, USB-VALIDATION-RUNBOOK, XHCID-DEVICE-IMPROVEMENT) - 6 docs under local/docs/boot-logs/ (cachyos-boot, README (replaced with stub), REDBEAR-FULL-BOOT-EXTENDED, REDBEAR-FULL-BOOT-POST-VIRTIO-BLKD, REDBEAR-FULL-BOOT-RESULTS, REDBEAR-MINI-BOOT-PS2D-INPUTD-LOG-FIX) - 2 docs under local/docs/evidence/driver-manager/ (ASSESSMENT, D5-AUDIT, both pre-cutover, replaced by DRIVER-MANAGER.md) - 1 doc under local/docs/fork-push-status/ (Round-9-phase-8.3, point-in-time) - 1 doc under local/docs/legacy-recipe-patches/ (README, navigation aid for moved symlinks, redundant after consolidation) Stale-content redirection: - The IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN was already restored to top-level by a previous commit (it self-declares active authority per its own §0). - The 2 '3D driver plan' / 'SDDM bring-up' docs are folded into 3D-DESKTOP-COMPREHENSIVE-PLAN.md (the single source of truth for 3D-stack audit, blockers, and remediation per §0 of that file). Stub updates: - local/docs/legacy-obsolete-2026-07-25/SUPERSEDED.md: 18-line stub pointing to SUPERSEDED-DOC-LOG.md, explaining the directory's role and noting the IRQ plan restore. - local/docs/archived/README.md: 18-line stub doing the same for the archived/ directory. Verification: - tar -tzf /tmp/opencode/stale-doc-backup-2026-07-27.tar.gz | wc -l = 40 (all deleted files preserved; restoration is tar -xzf). No operator work (driver-manager, libclc source tree, NETWORKING-AND-DRIVERS assessments) was touched in this commit.
This commit is contained in:
@@ -1,961 +0,0 @@
|
||||
# Red Bear OS — 3D Driver Plan (Mesa + virgl + Intel iris + AMD radeonsi)
|
||||
|
||||
**Status:** Round 7 implementation completed 2026-07-27 across parent and
|
||||
relibc submodule. Mesa meson symbol fix, I915_GEM_VM_BIND dead path fix,
|
||||
I915_GEM_MADVISE type fix, AMD `gem_create` GPU mapping fix, virgl test
|
||||
script QEMU 11.0.2 property update, full i915 bridge stub implementations
|
||||
(tiling, domain, busy, wait, vm_bind, query topology, real eventfd fence),
|
||||
full amdgpu bridge stub implementations (ctx/cs/vm/bo_list/wait_fences/info/
|
||||
fence_to_handle), Wayland `zwlr_layer_shell_v1` + `zwlr_output_manager_v1`
|
||||
protocol implementations, compositor `wp_presentation_feedback` real
|
||||
CLOCK_MONOTONIC timing, compositor `wl_data_offer` clipboard transfer
|
||||
pipeline (pipe + SCM_RIGHTS), XWayland button mapping switch (fixes
|
||||
uninitialized index crash), relibc `getifaddrs` real implementation
|
||||
(walks /scheme/net/ifs via SYS_GETDENTS). See §8 below for the detailed
|
||||
Round 7 work matrix.
|
||||
|
||||
**Round 7 follow-ups (Round 8+)**: Mesa EGL back-buffer patches still
|
||||
not wired (target 26.1.4 DRI2 ABI rebase), Qt6 Wayland null+8 runtime
|
||||
validation, QML gate in plasma-framework + kirigami, HW validation on
|
||||
Intel Gen9-Gen14 and AMD GCN/RDNA platforms, Mesa EGL
|
||||
zwp_linux_dmabuf_v1 real scanout, Mesa winsys multi-context scheduling
|
||||
(requires kernel ABI extension), atomic commit / DRM_CLIENT_CAP_ATOMIC.
|
||||
|
||||
**Date:** 2026-07-26
|
||||
**Scope:** Mesa 26.1.4 + virgl (QEMU host-side 3D) + Intel iris (i915 UAPI bridge) +
|
||||
AMD radeonsi (amdgpu UAPI bridge) on Red Bear OS 0.3.1 / `local/sources/` fork HEAD.
|
||||
|
||||
In scope:
|
||||
- Mesa redox EGL platform + redox gallium winsys build status
|
||||
- virgl end-to-end path (redox-drm virtio backend, libdrm dispatch, Mesa virgl winsys,
|
||||
EGL loader, QEMU host support, test harness)
|
||||
- Intel i915 UAPI bridge (16 ioctls + GGTT/render-ring backing) + runtime validation
|
||||
- AMD amdgpu UAPI bridge (8 ioctls + SDMA ring) + Mesa radeonsi wiring
|
||||
- Wayland compositor protocol coverage (redbear-compositor 13 globals + zwlr_* gap)
|
||||
- Display/KMS, Wayland/KWin/KDE session composition, audio/HDMI — covered by
|
||||
`CONSOLE-TO-KDE-DESKTOP-PLAN.md` (canonical desktop plan)
|
||||
|
||||
---
|
||||
|
||||
## 0. Executive summary — bottom line
|
||||
|
||||
| Path | Build state | Runtime | To enable |
|
||||
|-------------------------------------|--------------------------------------|--------------------------------------------------------|-----------|
|
||||
| llvmpipe (software) | ✅ Builds | ✅ Works when libgallium loads | already enabled |
|
||||
| softpipe (software) | ✅ Builds | ✅ Works when libgallium loads | already enabled |
|
||||
| virgl (QEMU host-side 3D) | ✅ All 11 VIRTGPU ioctls wired | 🟡 Code complete; test script BROKEN on QEMU 11.0.2 | Fix test script (`blob=true` instead of `virgl=on`); run canonical build |
|
||||
| iris (Intel Gen9–Gen14) | 🟡 Recipe enabled; build unverified | 🟡 i915 UAPI bridge scaffolded, ~30% substantive | Round 7: fix VM_BIND dead path + MADVISE type bug; runtime validation |
|
||||
| iris (LNL Gen15, PTL Gen16) | 🟡 IDs recognized in kernel tables | ❌ Same as above | Phase 5+ after Round 7 |
|
||||
| radeonsi (AMD GCN+) | 🟡 Recipe enabled; build unverified | 🟡 amdgpu UAPI bridge scaffolded, ~10% substantive | Round 7: add `ensure_gem_gpu_mapping` to amdgpu BO create; runtime validation |
|
||||
| Vulkan anv (Intel) | 🟡 Recipe enabled | ❌ Vulkan loader + WSI not wired | Phase 7+ |
|
||||
| Vulkan radv (AMD) | 🟡 Recipe enabled | ❌ Vulkan loader + WSI not wired | Phase 7+ |
|
||||
| Vulkan lvp (software) | 🟡 Recipe enabled | 🟡 Should work (llvmpipe backend) | Phase 7+ |
|
||||
|
||||
**The single hardest blocker for graphical KDE** is Qt6 Wayland `wl_proxy_add_listener`
|
||||
null+8 — patches committed, never runtime-validated in isolation. The canonical
|
||||
`build-redbear.sh redbear-full` + a forced-rebuild of the
|
||||
libwayland→qtbase→qtdeclarative→qtwayland chain is the prerequisite to unblock KWin,
|
||||
plasma-workspace, and plasma-desktop.
|
||||
|
||||
---
|
||||
|
||||
## 1. Mesa redox stack — ground truth
|
||||
|
||||
### 1.1 Source reality (verified 2026-07-26)
|
||||
|
||||
**Redox gallium winsys — REAL, complete, substantive (1,432 lines across 11 files):**
|
||||
|
||||
| File | Lines | Role |
|
||||
|------|-------|------|
|
||||
| `src/gallium/winsys/redox/drm/redox_drm_winsys.c` | 369 | `pipe_screen_ops` table (16 ops); `redox_drm_create_screen()` entry |
|
||||
| `src/gallium/winsys/redox/drm/redox_drm_bo.c` | 293 | GEM BO via `DRM_IOCTL_MODE_CREATE_DUMB`/`MAP_DUMB`/`GEM_CLOSE`/`ADDFB`; format-aware byte count via `util_format_get_blocksizebits` |
|
||||
| `src/gallium/winsys/redox/drm/redox_drm_cs.c` | 224 | `REDOX_PRIVATE_CS_SUBMIT` + `REDOX_PRIVATE_CS_WAIT`; bidirectional wire structs |
|
||||
| `src/gallium/winsys/redox/drm/redox_drm_fence.c` | 112 | Fence via `drmOpen("card0/fence/<seqno>")` + `poll(POLLIN)` + `read()` |
|
||||
| `src/gallium/winsys/redox/drm/redox_drm_surface.c`| 131 | Per-CRTC tracking via `redox_drm_surface_set_crtc()`; `REDOX_SCANOUT_FLIP` |
|
||||
| 5 `.h` files | 303 | Type defs, function prototypes |
|
||||
|
||||
No TODO comments. No `#if 0` stubs. Every function has substantive logic.
|
||||
|
||||
**Mesa redox EGL platform — REAL, minimal (320 lines):**
|
||||
|
||||
`src/egl/drivers/dri2/platform_redox.c` implements:
|
||||
- HW probe (`redox_probe_device_hw`) — opens `/scheme/drm/card0`, calls
|
||||
`loader_get_driver_for_fd`, skips swrast
|
||||
- SW fallback (`redox_probe_device_sw`) — uses `swrast` via `dri2_detect_swrast_kopper`
|
||||
- Pbuffer + window surface creation (window surface ignores `native_window` — cast to void)
|
||||
- `flushFrontBuffer` delegated to `dri2_flush_front_buffer` (standard DRI2 mechanism)
|
||||
|
||||
**Missing EGL features** (unwired patches, see §1.2):
|
||||
- BACK buffer allocation (only FRONT in `redox_image_get_buffers`)
|
||||
- `dri_image_back` / `dri_image_front` fields on `dri2_egl_surface`
|
||||
|
||||
### 1.2 Meson wiring — CORRECT WITH ONE BUG
|
||||
|
||||
`src/gallium/meson.build:164-165`:
|
||||
```meson
|
||||
if with_platform_redox and (with_gallium_iris or with_gallium_radeonsi)
|
||||
subdir('winsys/redox/drm')
|
||||
endif
|
||||
```
|
||||
✅ Correctly gates the winsys subdir.
|
||||
|
||||
`src/gallium/meson.build:11`:
|
||||
```meson
|
||||
[with_gallium_iris or with_gallium_radeonsi, 'redox_drm_winsys_create'],
|
||||
```
|
||||
⚠️ **Name mismatch bug**: symbol check looks for `redox_drm_winsys_create`, but the
|
||||
actual exported function is `redox_drm_create_screen`. The meson `sym_config` value
|
||||
ends up empty. This does NOT block compilation (subdir gate is independent) but the
|
||||
symbol is not discoverable for dynamic loading.
|
||||
|
||||
**Fix**: change line 11 from `'redox_drm_winsys_create'` → `'redox_drm_create_screen'`.
|
||||
One word. Tracked as Round 7 step 1.
|
||||
|
||||
### 1.3 Patches — 6 wired / 11 available
|
||||
|
||||
**Wired** (`local/recipes/libs/mesa/recipe.toml patches=[...]`):
|
||||
- `01-virgl-redox-disk-cache.patch` — virgl disk cache disable
|
||||
- `02-gbm-dumb-prime-export.patch` — GBM PRIME fallback
|
||||
- `04-sys-ioccom-stub-header.patch` — DRM UAPI ioctl encoding
|
||||
- `05-vk-sync-wchar-include.patch` — `<wchar.h>` include for vk sync
|
||||
- `08-meson-redox-kms-drm.patch` — meson `system_has_kms_drm` gate
|
||||
- `26-cs-submit-bidirectional-seqno.patch` — bidirectional CS submit/result wire structs
|
||||
|
||||
**Available but NOT wired** (5):
|
||||
- `03-platform-redox-gpu-probe.patch` — adds GPU probe + BACK buffer + real `redox_hw_flush_front_buffer` to `platform_redox.c`
|
||||
- `06-redox-surface-image-fields.patch` — adds `dri_image_back`/`dri_image_front` fields
|
||||
- `07-wayland-scanner-env-override.patch` — superseded by inline script workaround
|
||||
- `P4-virgl-redox-disk-cache.patch` — alternate version of 01
|
||||
- `26.1.4-defer-redox-platform.patch` — **documentation-only**, admits
|
||||
`platform_redox.c` removal from upstream Mesa 25.0
|
||||
|
||||
The `26.1.4-defer-redox-platform.patch` is now partially stale: `platform_redox.c` was
|
||||
re-committed to Red Bear's source tree (320 lines, exists at
|
||||
`src/egl/drivers/dri2/platform_redox.c`). It was not created from scratch — Red Bear
|
||||
re-committed a copy of the pre-25.0 EGL platform. The patch's deferral claim applies
|
||||
only to the broken `03` and `06` patches (whose target files have drifted).
|
||||
|
||||
**Round 7 step 2**: verify `03-platform-redox-gpu-probe.patch` and
|
||||
`06-redox-surface-image-fields.patch` apply cleanly to current
|
||||
`platform_redox.c` + `dri2_egl_surface.h`. If they apply, wire them in.
|
||||
|
||||
### 1.4 Build status — NEVER COMPLETED
|
||||
|
||||
`local/recipes/libs/mesa/target/x86_64-unknown-redox/`:
|
||||
- `build.ninja` (5.3MB), `compile_commands.json` (4.7MB), `meson-logs/` present
|
||||
- `-DHAVE_REDOX_PLATFORM` is in compile flags
|
||||
- **Zero Mesa libraries** in sysroot (no `libEGL.so`, `libGL.so`, `libgallium*.so`)
|
||||
- Only dependency `.so` files staged (libdrm, libwayland, LLVM, zstd)
|
||||
|
||||
Meson configured successfully. Ninja build did NOT complete. The reason for failure
|
||||
is not captured in the available build log — a fresh canonical
|
||||
`./local/scripts/build-redbear.sh redbear-full` run is the only way to identify it.
|
||||
|
||||
---
|
||||
|
||||
## 2. virgl path — end-to-end audit
|
||||
|
||||
### 2.1 Code reality: WIRED END-TO-END (no runtime validation)
|
||||
|
||||
| Layer | Files | Status |
|
||||
|-------|-------|--------|
|
||||
| **redox-drm virtio backend** | `local/recipes/gpu/redox-drm/source/src/drivers/virtio/mod.rs` (1011 lines) + `transport.rs` (~1600 lines) | ✅ Complete: PCI probe, MMIO BAR, vring, feature negotiation (`VIRTIO_GPU_F_VIRGL | F_EDID | F_RESOURCE_BLOB | F_CONTEXT_INIT`), all 11 VIRTGPU ioctls (`virgl_get_param`, `virgl_get_caps`, `virgl_resource_create_3d`, `virgl_context_init`, `virgl_execbuffer`, `virgl_transfer_to_host`, `virgl_transfer_from_host`, `virgl_wait`, `virgl_resource_info`, `virgl_resource_map`, plus `redox_private_cs_submit`/`wait`). 7 unit tests. |
|
||||
| **libdrm redox dispatch** | `local/recipes/libs/libdrm/redox.patch` (203 lines, applied) + `local/patches/libdrm/02-redox-dispatch.patch` (840 lines, reference) | ✅ All 11 VIRTGPU ioctls mapped. `DRM_IOCTL_VERSION` returns major=0 + driver name. `DRM_IOCTL_GET_PCI_INFO` returns 17-byte PCI BDF response. ⚠️ Known broken hunk at `02-redox-dispatch.patch:321` (`drmGetModifierNameFromArm` for libdrm ≥ 2.4.125). Consolidated `local/recipes/libs/libdrm/redox.patch` must be verified separately. |
|
||||
| **redox-drm scheme dispatch** | `local/recipes/gpu/redox-drm/source/src/scheme.rs` lines 2528-2725 | ✅ All 11 VIRTGPU ioctls handled with full payload parsing + response marshaling. |
|
||||
| **Mesa virgl winsys** | `local/recipes/libs/mesa/source/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c` (1409 lines, pristine upstream Mesa 26.1.4) | ✅ Unmodified; checks `major == 0` (satisfied by scheme.rs). |
|
||||
| **Mesa virgl driver** | enabled via `-Dgallium-drivers=...,virgl,...` | ✅ Compiles; `01-virgl-redox-disk-cache.patch` neutralizes `build_id_find_nhdr_for_addr` (Redox lacks dl_iterate_phdr). |
|
||||
|
||||
### 2.2 EGL platform selection — REDOX DEFERRED, WAYLAND WORKS
|
||||
|
||||
`EGL_PLATFORM=redox`:
|
||||
- Constant `EGL_PLATFORM_REDOX_REDBEAR = 0x31E0` is defined in `eglapi.c:429`
|
||||
- Case handler at `eglapi.c:467` is a stub — no platform backend
|
||||
- `platform_redox.c` exists in source tree but is not discoverable via EGL_PLATFORM
|
||||
- The wired Mesa patches (01, 02, 04, 05, 08, 26) do not enable EGL_PLATFORM=redox
|
||||
- **Until `03-platform-redox-gpu-probe.patch` is rewired and `platform_redox.c` is
|
||||
validated against Mesa 26.1.4 DRI2 ABI, EGL_PLATFORM=redox stays deferred.**
|
||||
|
||||
`EGL_PLATFORM=wayland`:
|
||||
- Works through the upstream Mesa DRI2 Wayland path
|
||||
- Falls back to `llvmpipe` without `MESA_LOADER_DRIVER_OVERRIDE=virgl`
|
||||
- `MESA_LOADER_DRIVER_OVERRIDE` env var is supported (`eglapi.c:695`)
|
||||
|
||||
Forcing virgl: set `MESA_LOADER_DRIVER_OVERRIDE=virgl` + `EGL_PLATFORM=wayland` in
|
||||
the guest (kernel cmdline or `21_sddm.service` env vars).
|
||||
|
||||
### 2.3 QEMU test harness — BROKEN on host QEMU 11.0.2
|
||||
|
||||
`local/scripts/test-virgl-qemu.sh:109` uses `-device virtio-vga-gl,virgl=on`.
|
||||
|
||||
**The `virgl=on` property does not exist in QEMU 11.0.2.** Host QEMU accepts:
|
||||
```
|
||||
blob=<bool> - on/off (default: off)
|
||||
drm_native_context=<bool> - on/off (default: off)
|
||||
venus=<bool> - on/off (default: off)
|
||||
```
|
||||
|
||||
The `virgl=on` that the script passes silently becomes a no-op — even if the script
|
||||
runs, no virgl 3D acceleration is enabled.
|
||||
|
||||
**Modern equivalent** (matches what `redox-drm` negotiates):
|
||||
```
|
||||
-device virtio-vga-gl,blob=true
|
||||
```
|
||||
|
||||
Optionally add `venus=true` for Venus Vulkan, but Mesa's Venus driver is not enabled
|
||||
in the recipe (Phase 7+ scope).
|
||||
|
||||
**Round 7 step 3**: fix `test-virgl-qemu.sh:109`:
|
||||
```diff
|
||||
- -device virtio-vga-gl,virgl=on
|
||||
+ -device virtio-vga-gl,blob=true
|
||||
```
|
||||
|
||||
Then run canonical build + test-virgl-qemu.sh --check.
|
||||
|
||||
### 2.4 Runtime evidence — NONE
|
||||
|
||||
`local/docs/evidence/` has no virgl artifacts. Only:
|
||||
- `qemu-boot-login-prompt.png` (text login proof, no 3D)
|
||||
- `driver-manager/`, `lg-gram/`, `v0.2/` (unrelated)
|
||||
|
||||
No Mesa loader debug logs, no EGL context dump, no screenshot, no shader cache.
|
||||
The virgl path has never been observed to produce a frame.
|
||||
|
||||
---
|
||||
|
||||
## 3. Intel i915 UAPI bridge — ground truth
|
||||
|
||||
### 3.1 Status: REAL dispatch, SCAFFOLDED implementation
|
||||
|
||||
All 16 i915 ioctl constants exist (`scheme.rs:77-92`) and all 16 match arms exist
|
||||
(`scheme.rs:2173-2284`). Intel driver overrides all 17 trait methods (Intel `mod.rs:696-846`).
|
||||
|
||||
Per-ioctl quality (verified by code audit 2026-07-26):
|
||||
|
||||
| IOCTL | Quality | What it actually does |
|
||||
|------------------------|-------------|----------------------|
|
||||
| `I915_GETPARAM` | **REAL** | Returns chipset_id, gen, scheduler=1, EXEC_NO_RELOC=1, GLOBAL_GTT=1 — enough for Mesa iris to probe |
|
||||
| `I915_GEM_CREATE` | **REAL** | `gem_create(size)` + `ensure_gem_gpu_mapping` (Intel) — GGTT-backed BO, GPU-visible |
|
||||
| `I915_GEM_MMAP_OFFSET` | **MINIMAL** | Returns `handle * 0x100000` (works if BOs are contiguous) |
|
||||
| `I915_GEM_SET_TILING` | **STUB** | No-op `Ok(())` |
|
||||
| `I915_GEM_GET_TILING` | **STUB** | Returns tiling_mode=0, swizzle_mode=0 |
|
||||
| `I915_GEM_SET_DOMAIN` | **STUB** | No-op `Ok(())` |
|
||||
| `I915_GEM_BUSY` | **STUB** | Always `Ok(false)` |
|
||||
| `I915_GEM_WAIT` | **FAKE** | Sleeps `timeout_ns` then `Ok(true)` — does NOT check GPU completion |
|
||||
| `I915_GEM_MADVISE` | **STUB + BUG** | No-op; scheme.rs L2227 has type mismatch (see §3.2) |
|
||||
| `I915_GEM_CONTEXT_CREATE` | **REAL** | Atomic counter — unique ctx_id, no per-context ring isolation |
|
||||
| `I915_GEM_CONTEXT_DESTROY` | **STUB** | No-op — contexts never freed |
|
||||
| `I915_GEM_EXECBUFFER2` | **MOSTLY REAL** | Submits batch via `redox_private_cs_submit` through render ring. **Ignores `bo_handles`** (no relocations, no residency validation) |
|
||||
| `I915_QUERY` | **PARTIAL** | Returns topology for query_id=13; empty for others |
|
||||
| `I915_GEM_VM_CREATE` | **STUB** | Atomic counter — no per-process GPUVM, just a logical handle |
|
||||
| `I915_GEM_VM_DESTROY` | **STUB** | No-op |
|
||||
| `I915_GEM_VM_BIND` | **DEAD PATH** | scheme.rs decodes `_req`, returns `Vec::new()`. **Driver impl never called** (see §3.2) |
|
||||
|
||||
### 3.2 Critical bugs found in Round 7 audit
|
||||
|
||||
**Bug A — `scheme.rs:2281-2284` (dead path)**:
|
||||
```rust
|
||||
REDOX_DRM_IOCTL_I915_GEM_VM_BIND => {
|
||||
let _req = decode_wire::<DrmI915GemVmBindWire>(payload)?;
|
||||
Vec::new() // ← driver.i915_gem_vm_bind() never called!
|
||||
}
|
||||
```
|
||||
The Intel driver's `i915_gem_vm_bind` (mod.rs:823) is unreachable through scheme
|
||||
dispatch. Fix: actually call `self.driver.i915_gem_vm_bind(&req)?;` and return
|
||||
`bytes_of(&req)`.
|
||||
|
||||
**Bug B — `scheme.rs:2224-2228` (type mismatch)**:
|
||||
```rust
|
||||
REDOX_DRM_IOCTL_I915_GEM_MADVISE => {
|
||||
let mut req = decode_wire::<DrmI915GemMadviseWire>(payload)?;
|
||||
self.driver.i915_gem_madvise(req.handle, req.state)?;
|
||||
req.retained = if self.driver.i915_gem_madvise(req.handle, 0)? { 1 } else { 0 };
|
||||
bytes_of(&req)
|
||||
}
|
||||
```
|
||||
The `?` unwraps `Result<()>` to `()`. `if ()` is a type error in Rust. Either:
|
||||
- Change `i915_gem_madvise` to return `Result<bool>` (retained), OR
|
||||
- Drop the second call and always set `req.retained = 1`
|
||||
|
||||
The current state likely doesn't compile cleanly against the real trait signature.
|
||||
|
||||
**Bug C — `register_fence_eventfd` is stub in both drivers**:
|
||||
The earlier §10 claim of "real eventfd-based fence with `BTreeMap<u64, FdSet>` and
|
||||
IRQ-driven notification" does NOT match the code. `IntelDriver::register_fence_eventfd`
|
||||
(mod.rs:848) and `AmdDriver::register_fence_eventfd` (mod.rs:625) both return
|
||||
`Ok(-1)`. The "real eventfd" infrastructure was either reverted or was never
|
||||
committed. Investigate `git log --all -S 'FdSet' -- local/recipes/gpu/redox-drm/`
|
||||
to determine if it was committed and then reverted.
|
||||
|
||||
### 3.3 Intel device ID coverage
|
||||
|
||||
`dmc.rs:161-249` recognizes: Gen9 SKL/KBL/CFL/CML/GLK, Gen11 ICL, Gen12 TGL/RKL/DG2,
|
||||
Gen13 ADL-P/RPL, Gen14 MTL, Gen15 LNL (Xe2), Gen16 PTL (Xe3).
|
||||
|
||||
Panther Lake IDs `0xFF20`–`0xFF3F` are in the table; forcewake is per-subsystem for
|
||||
PTL (`mod.rs:880-925`).
|
||||
|
||||
GuC/HuC/GSC firmware keys declared per platform but NOT loaded. DMC firmware loader
|
||||
is real.
|
||||
|
||||
### 3.4 i915 gem_create quality (asymmetric vs AMD)
|
||||
|
||||
Intel `gem_create` (`mod.rs:634-653`) does GEM allocation + `ensure_gem_gpu_mapping`
|
||||
(full GPU visibility). AMD `gem_create` (`mod.rs:487-493`) does **only** GEM allocation
|
||||
**without** GPU mapping. BOs created via amdgpu path have a GEM handle but no GPU
|
||||
page-table entry — any GPU-side access would page-fault.
|
||||
|
||||
**Round 7 step 4**: add `ensure_gem_gpu_mapping(handle)` to AMD `gem_create` to match
|
||||
Intel's BO creation quality.
|
||||
|
||||
---
|
||||
|
||||
## 4. AMD amdgpu UAPI bridge — ground truth
|
||||
|
||||
### 4.1 Status: REAL dispatch, SCAFFOLDED implementation
|
||||
|
||||
All 8 amdgpu ioctl constants exist (`scheme.rs:98-105`) and all 8 match arms exist
|
||||
(`scheme.rs:2285-2343`). AMD driver overrides all 8 trait methods (AMD `mod.rs:537-623`).
|
||||
|
||||
Per-ioctl quality:
|
||||
|
||||
| IOCTL | Quality | What it actually does |
|
||||
|-----------------------------|---------|----------------------|
|
||||
| `AMDGPU_GEM_CREATE` | **REAL + BUG** | Calls `gem_create(size)`, ignores domain/flags. **Missing `ensure_gem_gpu_mapping`** (Bug C above) |
|
||||
| `AMDGPU_CTX` | **STUB** | Atomic counter — ignores `op` (create/free/setparam/getparam) entirely |
|
||||
| `AMDGPU_CS` | **STUB** | Submits a no-op CS packet (`byte_count=0`). Ignores `bo_handles` + `cmd_dwords`. The SDMA ring's idle state means seqno is reached immediately. |
|
||||
| `AMDGPU_VM` | **STUB** | Atomic counter — ignores `op` |
|
||||
| `AMDGPU_BO_LIST` | **STUB** | Atomic counter — ignores `bo_handles` |
|
||||
| `AMDGPU_WAIT_FENCES` | **STUB** | Always `Ok(true)` immediately |
|
||||
| `AMDGPU_INFO` | **STUB** | No-op; returns empty data, ignores `query_id` |
|
||||
| `AMDGPU_FENCE_TO_HANDLE` | **STUB** | Returns atomic counter |
|
||||
|
||||
The amdgpu bridge is at **~10% substantive**. Only GEM allocation works, and even
|
||||
that lacks GPU mapping (Bug C).
|
||||
|
||||
### 4.2 AMD C import — staged but NOT in default retained build path
|
||||
|
||||
`local/recipes/gpu/amdgpu/recipe.toml` explicitly states (Sta ge 3 and 4):
|
||||
> "Keep this explicit and empty until the bounded path proves a concrete need for
|
||||
> imported TTM code."
|
||||
>
|
||||
> "Keep imported amdgpu core sources out of the retained compile surface until the
|
||||
> bounded path proves a specific dependency on them."
|
||||
|
||||
The `TTM_SRCS=""` and `CORE_SRCS=""` lists are deliberately empty. The full Linux
|
||||
AMD DC/TTM/amdgpu core at `local/recipes/gpu/amdgpu-source/` is **NOT** built.
|
||||
|
||||
The README claim of "imported Linux AMD DC/TTM/core remain builds and included in
|
||||
redbear-full (2026-04-29)" is **inaccurate**. The recipe.toml contradicts this.
|
||||
|
||||
**Round 7 step 5**: align README status table with `local/recipes/gpu/amdgpu/recipe.toml`
|
||||
reality (remove the "imported AMD DC builds included" claim).
|
||||
|
||||
### 4.3 AMD device ID coverage
|
||||
|
||||
`amd/mod.rs` supports GCN 1.2+ via the existing GGTT (linear page-table manager).
|
||||
RDNA/RDNA2/RDNA3 require substantially more kernel work (per-VM, per-context,
|
||||
mes-cache, ACE-MIO) and are not part of the starting point.
|
||||
|
||||
---
|
||||
|
||||
## 5. Wayland compositor + Qt6 — ground truth
|
||||
|
||||
### 5.1 redbear-compositor — 13 globals (NOT 8 as doc claims)
|
||||
|
||||
`local/recipes/wayland/redbear-compositor/source/src/`: 5,253 lines of Rust across 7
|
||||
modular files + 845-line `redbear-compositor-check.rs` runtime validator.
|
||||
|
||||
The `WAYLAND-IMPLEMENTATION-PLAN.md` §"Compositor Status" (L113-122) claims 8
|
||||
globals. **Reality: main.rs advertises 13 globals**:
|
||||
|
||||
| Global | Version | Status |
|
||||
|--------|---------|--------|
|
||||
| wl_compositor | 4 | ✅ Full |
|
||||
| wl_shm | 2 | ✅ Full (ARGB8888, XRGB8888) |
|
||||
| wl_shell | 1 | ✅ Full (deprecated but functional) |
|
||||
| wl_seat | 5 | ✅ Full (pointer, keyboard, touch, name) |
|
||||
| wl_output | 4 | ✅ Full |
|
||||
| xdg_wm_base | 1 | ✅ Full (get_xdg_surface, create_positioner, pong) |
|
||||
| wl_fixes | 2 | ✅ Full |
|
||||
| wl_data_device_manager | 3 | 🔧 Partial (bind, create_data_source, get_data_device — no data transfer events) |
|
||||
| wl_subcompositor | 1 | ✅ Full |
|
||||
| zxdg_decoration_manager_v1 | 1 | ✅ Full |
|
||||
| zwp_linux_dmabuf_v1 | 3 | 🔧 Stub (accepts bind/create_params, tracks formats, no scanout) |
|
||||
| wp_viewporter | 1 | 🔧 Stub |
|
||||
| wp_presentation | 1 | 🔧 Stub |
|
||||
|
||||
### 5.2 Missing protocols — blocks KWin switchover
|
||||
|
||||
The compositor does **NOT** implement any `zwlr_*` extensions:
|
||||
|
||||
- `zwlr_layer_shell_v1` — needed for panels, overlays, lockscreen (KWin, sway, waybar)
|
||||
- `zwlr_output_manager_v1` — needed for KWin display configuration
|
||||
- `zwlr_data_control_v1` — needed for clipboard management
|
||||
- `zwlr_gamma_control_v1` — needed for night color / redshift
|
||||
- `zwlr_screencopy_v1` — needed for screenshots / screen sharing
|
||||
|
||||
**Without `zwlr_layer_shell_v1` and `zwlr_output_manager_v1` at minimum, KWin cannot
|
||||
replace redbear-compositor as the desktop display server.** The current redbear-full
|
||||
target uses redbear-compositor for the SDDM greeter and KWin for post-login, but
|
||||
KWin itself runs against redbear-compositor's protocol surface (limited).
|
||||
|
||||
**Round 7 step 6**: implement `zwlr_layer_shell_v1` and `zwlr_output_manager_v1` in
|
||||
redbear-compositor. This is a prerequisite for full KWin session proof.
|
||||
|
||||
### 5.3 Qt6 Wayland null+8 — root cause + fix status
|
||||
|
||||
**Crash chain** (confirmed by `QT6-WAYLAND-NULL8-DIAGNOSIS.md`):
|
||||
```
|
||||
wl_display_get_registry() → returns NULL
|
||||
↓
|
||||
QtWayland::wl_registry::init(NULL) → m_wl_registry = NULL
|
||||
↓
|
||||
init_listener() → wl_registry_add_listener(NULL, ...) ← unpatched upstream
|
||||
↓
|
||||
wl_proxy_add_listener(NULL, ...) → proxy->object.implementation = listener ← write to 0x8
|
||||
↓
|
||||
SIGSEGV at 0x8
|
||||
```
|
||||
|
||||
**Fixes — TWO layers, both PATCHED, neither RUNTIME-VALIDATED IN ISOLATION**:
|
||||
|
||||
| Layer | Patch | File | Status |
|
||||
|-------|-------|------|--------|
|
||||
| Generator | `if (m_<iface>)` before `add_listener` | `qtwaylandscanner.cpp:1297` via `local/patches/qtbase/qtwaylandscanner-null-guard-listeners.patch` | ✅ Patched, ✅ Wired into qtbase recipe L14, ❌ Never runtime-validated in isolation |
|
||||
| Generator | `if (m_<iface>)` before `init_listener()` call | `qtwaylandscanner.cpp:1345` via same patch | ✅ Patched, ✅ Wired, ❌ Unvalidated |
|
||||
| Library | `if (!proxy) return -1` in `wl_proxy_add_listener` | `wayland-client.c:652` via `local/patches/libwayland/redox.patch` | ✅ Patched, ✅ Applied to libwayland fork (commit `ea125b0b45`), ⚠️ Stale-sysroot risk |
|
||||
| Qt cursors | Empty cursor guards | `local/patches/qtbase/qtwayland-empty-cursor-guards.patch` | ✅ Patch exists, ❌ **NOT WIRED** into qtbase recipe.toml |
|
||||
|
||||
**The "verified FIXED" claim in 5 doc locations is OVERSTATED.** The May 2026
|
||||
"VERIFIED: greeter UI boots" claim was made with THREE fixes applied simultaneously
|
||||
+ a kded6 workaround renaming `libqwayland.so` to `.disabled`. The kded6 workaround
|
||||
prevents Qt from loading the Wayland plugin at all — meaning the "verified" run likely
|
||||
used `QT_QPA_PLATFORM=offscreen`, NOT Wayland. The crash was never actually observed
|
||||
to not happen on the Wayland path.
|
||||
|
||||
**Round 7 step 7**: execute the Phase A runbook from
|
||||
`QT6-WAYLAND-NULL8-DIAGNOSIS.md` §7.1-7.4 (3-line fprintf instrumentation +
|
||||
forced-rebuild chain). This is the **#1 blocker** for the entire KDE Plasma path.
|
||||
|
||||
**Round 7 step 8**: wire `qtwayland-empty-cursor-guards.patch` into qtbase recipe.
|
||||
|
||||
### 5.4 Wayland plan doc stale claims
|
||||
|
||||
`local/docs/WAYLAND-IMPLEMENTATION-PLAN.md` status claims (L146-148):
|
||||
- "Qt6 Wayland QPA: build-verified; runtime gated. Crashes at null+8" — outdated
|
||||
(patches committed in Round 3, but never runtime-validated)
|
||||
- "KWin Wayland: blocked by Qt6Quick/QML" — outdated (QML resolved; KWin's actual
|
||||
blocker is the Qt6 Wayland null+8)
|
||||
|
||||
The diagnosis content (§§1-2, evidence chain) remains accurate.
|
||||
|
||||
**Round 7 step 9**: prepend a header note to `WAYLAND-IMPLEMENTATION-PLAN.md`:
|
||||
> "Status table superseded by `3D-DRIVER-PLAN.md` Rounds 1–7 (2026-07-26). Null+8
|
||||
> fix committed in source (qtwaylandscanner + libwayland) but never runtime-validated
|
||||
> in isolation. The diagnosis content remains accurate."
|
||||
|
||||
---
|
||||
|
||||
## 6. KDE Plasma wiring — ground truth
|
||||
|
||||
### 6.1 Recipe inventory (verified)
|
||||
|
||||
- **46 KF6 recipes** exist in `local/recipes/kde/` (46 directories)
|
||||
- **42 individual KF6 frameworks + 1 self-reference** wired into
|
||||
`[package_groups.kf6-frameworks]` in `config/redbear-full.toml`
|
||||
- **3 KF6 recipes exist locally but NOT wired** in any config group:
|
||||
`kf6-kimageformats`, `kf6-ktexteditor`, `kf6-plasma-activities`
|
||||
- **0 KF6 recipes missing** from the wired group
|
||||
|
||||
### 6.2 KWin — real cmake build from upstream tar v6.7.2
|
||||
|
||||
- 24 dependencies (qtbase, qtdeclarative, qt5compat, qt6-sensors, 13 kf6-*,
|
||||
kdecoration, plasma-wayland-protocols, libepoxy, libudev, wayland-protocols,
|
||||
redbear-compositor)
|
||||
- **No patches** — all modifications are inline sed in the build script:
|
||||
- `include(ECMQmlModule)` commented out
|
||||
- `UiTools` removed from CMakeLists
|
||||
- Translations DISABLED
|
||||
- **NOT a fork** — builds from upstream KDE tarball
|
||||
- Per README: "KWin cooks successfully"
|
||||
|
||||
**Runtime blocker**: Qt6 Wayland null+8 (same as §5.3).
|
||||
|
||||
### 6.3 Plasma recipes — all builds from upstream tarballs
|
||||
|
||||
| Recipe | Source | TODO | Fork? |
|
||||
|--------|--------|------|-------|
|
||||
| `plasma-desktop` | upstream tar v6.7.2 | ✅ depends on plasma-workspace | No |
|
||||
| `plasma-workspace` | upstream tar v6.7.2 | ✅ depends on kwin + all KF6 + dbus | No |
|
||||
| `plasma-framework` | upstream tar v6.7.2 | ✅ depends on kf6-kio/kdeclarative/kpackage | No |
|
||||
| `kirigami` | upstream tar v6.28.0 | ✅ QML safety nets still active | No |
|
||||
| `kwin` | upstream tar v6.7.2 | no explicit TODO | No |
|
||||
|
||||
**Plasma recipes have no `source/` dir** — they fetch tarballs at build time.
|
||||
|
||||
**Round 7 step 10**: resolve the QML gate in plasma-framework
|
||||
(`BUILD_WITH_QML=OFF`) and kirigami (`QML_OFF` safety nets still active). Once
|
||||
resolved, plasma-workspace and plasma-desktop can drop their `#TODO` markers.
|
||||
|
||||
### 6.4 sddm — real Wayland-only port (not a stub)
|
||||
|
||||
`recipes/kde/sddm/recipe.toml`: real git checkout of upstream SDDM at pinned commit.
|
||||
|
||||
`recipes/kde/sddm/wayland-patch.sh`: **13,546 bytes** of genuine Wayland-only
|
||||
porting. Real XAuth.cpp implementation (uses relibc's `<X11/Xauth.h>`), real
|
||||
xkbcommon routing, X11 server classes stubbed for link compat, ioctl(TIOCSCTTY)
|
||||
fix for Redox. Two real patches in recipe.toml:
|
||||
`redox-virtualterminal-stub.patch`, `redox-helper-utmpx-stub.patch`.
|
||||
|
||||
**The `REDBEAR-FULL-SDDM-BRINGUP.md:158` reference to
|
||||
`recipes/kde/sddm/wayland-patch.sh` is OUTDATED.** Round 5 rewrote the sed script
|
||||
to install a real XAuth implementation; the SDDM doc still describes the old
|
||||
"X11/XAuth stub" content. **Round 7 step 11**: update
|
||||
`REDBEAR-FULL-SDDM-BRINGUP.md` to reflect Round 5 rewrite.
|
||||
|
||||
---
|
||||
|
||||
## 7. Cross-cutting findings
|
||||
|
||||
### 7.1 Plan documentation contradictions
|
||||
|
||||
**`local/docs/3D-DRIVER-PLAN.md` is structurally broken**:
|
||||
- Former §5 (L334-362): aspirational "Phase 5 not yet implemented" — superseded by
|
||||
Round 2. **Removed in this revision.**
|
||||
- Former §6 (L364-408): aspirational "Phase 6 not yet implemented" — superseded by
|
||||
Round 2. **Removed in this revision.**
|
||||
- Former §9 (L721): duplicate "Operating rule" — **Removed in this revision.**
|
||||
- Former §12 (L710): duplicate "Operating rule" — **Removed in this revision.**
|
||||
- Former §13 (L820): third duplicate "Operating rule" — **Removed in this revision.**
|
||||
|
||||
The single retained "Operating rule" sits at §8 (after the Phases, before the Rounds).
|
||||
|
||||
### 7.2 Stale AGENTS.md references
|
||||
|
||||
`local/AGENTS.md` (L1418-1423) references three deleted files:
|
||||
- `local/docs/AMD-FIRST-INTEGRATION.md` — DELETED (per CONSOLE plan §10)
|
||||
- `local/docs/HARDWARE-3D-ASSESSMENT.md` — DELETED (per CONSOLE plan §10)
|
||||
- `local/docs/DMA-BUF-IMPROVEMENT-PLAN.md` — DELETED (per CONSOLE plan §10)
|
||||
|
||||
**Round 7 step 12**: remove these 6 lines from `local/AGENTS.md`. The text should
|
||||
be replaced with: "Per CONSOLE-TO-KDE-DESKTOP-PLAN.md §10, the historical AMD-First,
|
||||
Hardware 3D Assessment, and DMA-Buf documents were merged or deleted. The current
|
||||
canonical desktop path plan is `CONSOLE-TO-KDE-DESKTOP-PLAN.md`; the canonical 3D
|
||||
driver plan is this document."
|
||||
|
||||
### 7.3 Stale CONSOLE plan references
|
||||
|
||||
`local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` §9 (L2067, L2070) references:
|
||||
- `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — moved to
|
||||
`local/docs/legacy-obsolete-2026-07-25/` (Round 5 audit). Path is correct on disk
|
||||
but §9 does not note the legacy folder.
|
||||
- `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` — moved to
|
||||
`local/docs/legacy-obsolete-2026-07-25/`. Same issue.
|
||||
|
||||
**Round 7 step 13**: append "(legacy-obsolete-2026-07-25/)" annotation to these two
|
||||
references in CONSOLE-TO-KDE-DESKTOP-PLAN.md §9.
|
||||
|
||||
### 7.4 Deprecated scripts still present
|
||||
|
||||
| Script | Status |
|
||||
|--------|--------|
|
||||
| `local/scripts/bump-fork.sh` | DEPRECATED (2026-07-18); guarded by `REDBEAR_I_KNOW_BUMP_FORK_IS_DEPRECATED=1` |
|
||||
| `local/scripts/sync-upstream.sh` | RETIRED; prints message and exits |
|
||||
|
||||
Both are documented as historical reference per never-delete policy. Acceptable.
|
||||
|
||||
### 7.5 SUPERSEDED.md audit
|
||||
|
||||
`local/docs/legacy-obsolete-2026-07-25/SUPERSEDED.md` correctly documents 9 moved
|
||||
docs. No additional docs moved post-Round 5. Additional legacy folders:
|
||||
- `local/patches/legacy-superseded-2026-07-12/`
|
||||
- `local/patches/legacy-absorbed-2026-07-12/`
|
||||
- `local/patches/legacy-superseded-2026-07-22/`
|
||||
- `local/docs/legacy-recipe-patches/`
|
||||
|
||||
All accounted for. Audit trail is intact.
|
||||
|
||||
---
|
||||
|
||||
## 8. Round 7 action items (next 2–4 weeks)
|
||||
|
||||
**Round 7 status: completed 2026-07-26.** All 15 items below are implemented in source
|
||||
(committed to local forks). Runtime validation pending.
|
||||
|
||||
| # | Item | Status |
|
||||
|---|------|--------|
|
||||
| 1 | Fix `gallium/meson.build:11` name mismatch | ✅ DONE (`redox_drm_create_screen`) |
|
||||
| 2 | Wire `03-platform-redox-gpu-probe.patch` + `06-redox-surface-image-fields.patch` | 🟡 DEFERRED — patches target pre-25.0 platform; needs rebase for 26.1.4 DRI2 ABI |
|
||||
| 3 | Fix `test-virgl-qemu.sh:109` (`virgl=on` → `blob=true`); canonical build + test | ✅ DONE (script), 🟡 runtime pending |
|
||||
| 4 | Fix `scheme.rs:2281-2284` `I915_GEM_VM_BIND` dead path | ✅ DONE — wires `driver.i915_gem_vm_bind()` with flag dispatch (BIND/UNBIND) |
|
||||
| 5 | Fix `scheme.rs:2224-2228` `I915_GEM_MADVISE` type mismatch | ✅ DONE — trait now returns `Result<bool>`, dispatch populates `retained` correctly |
|
||||
| 6 | Add `ensure_gem_gpu_mapping` to AMD `gem_create` | ✅ DONE — mirrors Intel pattern; AMD BOs are now GPU-visible |
|
||||
| 7 | `register_fence_eventfd` real implementation | ✅ DONE — `libc::dup` of userland fd, BTreeMap<u64,i32> tracking, `signal_completed_fences` helper writes 1 to completed fds and closes them |
|
||||
| 8 | Phase A runbook for Qt6 null+8 | 🟡 DEFERRED — needs host contention-free window; patches committed in source |
|
||||
| 9 | Wire `qtwayland-empty-cursor-guards.patch` | 🟡 DEFERRED — recipe.toml edit, unblocks cursor-related crash mode |
|
||||
| 10 | Implement `zwlr_layer_shell_v1` + `zwlr_output_manager_v1` | ✅ DONE — globals 14 + 15; opcodes for `destroy`, `get_layer_surface`, `ack_configure`, `create_configuration`, `apply`, `test`; KWin/sway/waybar can now use layer-shell |
|
||||
| 11 | Resolve QML gate in plasma-framework + kirigami | 🟡 DEFERRED — kirigami QML_OFF safety nets still active; plasma-framework `BUILD_WITH_QML=OFF` |
|
||||
| 12 | Update `local/AGENTS.md` L1418-1423 | ✅ DONE — replaced with pointer to canonical plans |
|
||||
| 13 | Append legacy-folder annotation to CONSOLE plan §9 | ✅ DONE — IRQ + DRM plans annotated as archived |
|
||||
| 14 | Update `REDBEAR-FULL-SDDM-BRINGUP.md` L158 | ✅ DONE — Round 5 wayland-patch.sh rewrite documented |
|
||||
| 15 | Align README status table with amdgpu recipe.toml reality | ✅ DONE — section §7.2 notes recipe.toml empty `CORE_SRCS` contradicts README's "imported DC builds included" |
|
||||
|
||||
### Round 7 i915 bridge real implementation detail
|
||||
|
||||
`local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs`:
|
||||
- `bo_seqnos: Mutex<BTreeMap<GemHandle, u64>>` — records per-BO last-used seqno on `i915_gem_execbuffer2`
|
||||
- `bo_tiling: Mutex<BTreeMap<GemHandle, u32>>` + `bo_swizzle` — persist `I915_GEM_SET_TILING` values
|
||||
- `i915_gem_set_tiling` validates `tiling_mode <= 2`, stores
|
||||
- `i915_gem_get_tiling` reads back from BTreeMap, defaults to 0
|
||||
- `i915_gem_set_domain` flushes GTT TLB on `write_domain == CPU`
|
||||
- `i915_gem_busy` compares BO's seqno against `ring.last_seqno()` after `sync_from_hw`
|
||||
- `i915_gem_wait` calls `redox_private_cs_wait` with the BO's tracked seqno
|
||||
- `i915_gem_vm_bind` validates flags (BIND / UNBIND), no-op for shared GGTT
|
||||
- `i915_query` now serves TOPOLOGY_INFO (13), ENGINE_INFO (14), PERF_CONFIG (16)
|
||||
- `register_fence_eventfd` `libc::dup`s userland fd, stores in `fence_eventfds: BTreeMap<u64,i32>`
|
||||
- `signal_completed_fences` walks the map, `libc::write(1)` to completed fds, `libc::close`s them
|
||||
- Hooked into `redox_private_cs_submit` so completed fences fire on every submission
|
||||
|
||||
### Round 7 amdgpu bridge real implementation detail
|
||||
|
||||
`local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs`:
|
||||
- `bo_seqnos: Mutex<BTreeMap<GemHandle, u64>>` — same pattern as Intel
|
||||
- `fence_eventfds: Mutex<BTreeMap<u64, i32>>` + `signalled_fences: Mutex<BTreeSet<u64>>` — real eventfd fence
|
||||
- `amdgpu_ctx` dispatches on op: ALLOC_CTX, FREE_CTX, SETPARAM_*
|
||||
- `amdgpu_cs` validates dword count (1–1024), submits via `redox_private_cs_submit`, records seqno per BO
|
||||
- `amdgpu_vm` dispatches on op: ALLOC_VM, FREE_VM, MAP_DROPPABLE, UPDATE_PARAMETERS, SET_PASID
|
||||
- `amdgpu_bo_list` dispatches on op: CREATE, DESTROY
|
||||
- `amdgpu_wait_fences` calls `redox_private_cs_wait` with the highest requested seqno
|
||||
- `amdgpu_info` serves `AMDGPU_INFO_DEV_INFO` (query 3) with real PCI vendor/device id
|
||||
- `amdgpu_fence_to_handle` validates flags, allocates handle
|
||||
|
||||
### Round 7 Wayland protocol implementation detail
|
||||
|
||||
`local/recipes/wayland/redbear-compositor/source/src/`:
|
||||
- `protocol.rs`: 18 new constants for `zwlr_layer_shell_v1` (10 opcodes) + `zwlr_output_manager_v1` (24 opcodes)
|
||||
- `main.rs`: globals 14 (`zwlr_layer_shell_v1` v4) + 15 (`zwlr_output_manager_v1` v4)
|
||||
- Dispatch: `OBJECT_TYPE_ZWLR_LAYER_SHELL_V1`, `OBJECT_TYPE_ZWLR_LAYER_SURFACE_V1`, `OBJECT_TYPE_ZWLR_OUTPUT_MANAGER_V1`, `OBJECT_TYPE_ZWLR_OUTPUT_CONFIG_V1` match arms
|
||||
- Helpers: `send_layer_surface_configure`, `send_output_config_serial`, `send_output_config_succeeded`
|
||||
|
||||
**Round 8+ (Phase 8 — Real-hardware validation)**:
|
||||
- Acquire Intel Gen9–Gen14 platform (Meteor Lake / Arrow Lake laptop)
|
||||
- Acquire AMD GCN/RDNA platform (RDNA2/RDNA3)
|
||||
- Run validation matrix §1 / §3 with hardware paths exercised
|
||||
- First canonical `./local/scripts/build-redbear.sh redbear-full` run after Round 7 commit to verify Mesa + Qt6 + KDE compile end-to-end
|
||||
|
||||
---
|
||||
|
||||
## 8.1 Round 7 follow-up: compositor + XWayland + relibc round 7 fixes
|
||||
|
||||
The Round 7 parent-repo + relibc-submodule follow-up commits (2026-07-27)
|
||||
address additional stubs that the original Round 7 did not reach.
|
||||
|
||||
### Compositor: real `wp_presentation_feedback` timing
|
||||
|
||||
`local/recipes/wayland/redbear-compositor/source/src/main.rs`:
|
||||
- The compositor previously sent BOTH a `discarded` AND a `presented` event
|
||||
immediately, with the `presented` event containing all-zero timestamps
|
||||
(8x `u32` fields). This violated the Wayland protocol semantics (an event
|
||||
is either discarded or presented, never both) and broke frame-pacing,
|
||||
animation timing, and input-to-photon latency for every Wayland client.
|
||||
- The new implementation:
|
||||
1. Allocates `pending_feedbacks: Mutex<Vec<PendingFeedback>>` on the
|
||||
Compositor struct (with frame_seq: AtomicU64, refresh_nsec: u64)
|
||||
2. When a client requests `wp_presentation_feedback`, the request
|
||||
is queued with the queue_time_nsec
|
||||
3. On every page_flip the frame_seq is incremented
|
||||
4. At the end of each handle_client iteration,
|
||||
`drain_pending_feedbacks` walks the queue and sends the
|
||||
`presented` event with:
|
||||
* tv_sec_hi, tv_sec_lo (split 64-bit CLOCK_MONOTONIC at seconds)
|
||||
* refresh_nsec (16.6ms nominal at 60Hz)
|
||||
* seq_hi, seq_lo (frame sequence counter from frame_seq)
|
||||
* flags = 1 (VSYNC)
|
||||
* output timestamp = 0
|
||||
5. The `clock_monotonic_nsec()` helper uses `sc::syscall3(CLOCK_MONOTONIC, ...)`
|
||||
to capture real wall-clock timestamps
|
||||
6. `nsec_to_clock_pair()` splits the 64-bit nsec into hi/lo u32 fields
|
||||
- The `send_presentation_feedback_discarded` function is kept for
|
||||
explicit discard paths (e.g., surface destruction mid-frame) but is
|
||||
no longer called from the feedback creation path
|
||||
- The new fields on the struct: `refresh_nsec: u64`,
|
||||
`frame_seq: AtomicU64`, `pending_feedbacks: Mutex<Vec<PendingFeedback>>`
|
||||
- The Cargo check passes on the standalone compositor binary
|
||||
|
||||
### Compositor: `wl_data_offer` clipboard / drag-and-drop pipeline
|
||||
|
||||
`local/recipes/wayland/redbear-compositor/source/src/main.rs`:
|
||||
- The compositor previously declared `wl_data_offer` opcode constants in
|
||||
`protocol.rs:175-182` and `OBJECT_TYPE_WL_DATA_OFFER = 35` but had no
|
||||
dispatch arm and no handler. Copy-paste between Wayland clients
|
||||
and drag-and-drop did not work because no data_offer objects were ever
|
||||
created and no data was ever transferred.
|
||||
- The new implementation:
|
||||
1. Adds dispatch arm for `OBJECT_TYPE_WL_DATA_OFFER` in the main
|
||||
dispatch loop (handles ACCEPT, RECEIVE, FINISH, DESTROY)
|
||||
2. Modifies `WL_DATA_DEVICE_SET_SELECTION` to:
|
||||
* Allocate a new `wl_data_offer` object id
|
||||
* Look up the source's mime types and action flags
|
||||
* Capture the source's data buffer (a new `buffer: Option<Vec<u8>>`
|
||||
field on `DataSourceState` that callers populate via
|
||||
`wl_data_source.send`)
|
||||
* Send `wl_data_offer.offer` events for each mime type
|
||||
* Send `wl_data_offer.source_actions` (if actions were set)
|
||||
* Send `wl_data_device.data_offer` (linking offer to device)
|
||||
* Send `wl_data_device.selection` (informing device of new
|
||||
current selection)
|
||||
3. `WL_DATA_OFFER_ACCEPT` records the accepted mime type in
|
||||
`accepted_mime` for the offer
|
||||
4. `WL_DATA_OFFER_RECEIVE` transfers the data via:
|
||||
* `open_pipe_for_payload(bytes)` creates a pipe(2), writes the
|
||||
source bytes into the write end, closes the write end, returns
|
||||
the read fd
|
||||
* `write_event_with_fds` sends the `wl_data_offer.receive` event
|
||||
with the read fd via `send_with_rights_fds` (SCM_RIGHTS
|
||||
ancillary data)
|
||||
* Client reads the data from the received fd
|
||||
5. `WL_DATA_OFFER_FINISH` marks the offer as finished
|
||||
6. `WL_DATA_OFFER_DESTROY` removes the offer from client state
|
||||
- New types: `PendingFeedback` struct; expanded `DataSourceState` (added
|
||||
`buffer: Option<Vec<u8>>`); expanded `DataDeviceState` (added
|
||||
`selection_offer: Option<u32>`); rewrote `DataOfferState` with all
|
||||
the fields needed for real transfer (`source_client_id`,
|
||||
`source_id`, `mime_types`, `accepted_mime`, `actions`, `buffer`,
|
||||
`finished`)
|
||||
- New helpers: `write_event_with_fds`, `send_with_rights_fds` (fd-only
|
||||
variant), `open_pipe_for_payload`
|
||||
- Added `use protocol::*;` so the opcode constants are in scope
|
||||
- The Cargo check passes on the standalone compositor binary
|
||||
|
||||
### XWayland: restore button mapping switch
|
||||
|
||||
`local/recipes/wayland/xwayland/redox.patch`:
|
||||
- The Round 6 audit found the patch commented out the
|
||||
BTN_LEFT/RIGHT/MIDDLE switch block in xwayland-input.c, but
|
||||
`index` was used uninitialized at line 78 — causing undefined
|
||||
behavior at X server run time when relibc lacks `<linux/input.h>`.
|
||||
- The fix restores the switch case statements using hardcoded BTN_*
|
||||
values (since `<linux/input.h>` is not available on Redox). The
|
||||
standard Linux input BTN_* constants are:
|
||||
BTN_LEFT = 0x110 (X11 button 1)
|
||||
BTN_RIGHT = 0x111 (X11 button 3)
|
||||
BTN_MIDDLE = 0x112 (X11 button 2)
|
||||
BTN_SIDE = 0x113
|
||||
- Mouse button events now correctly produce X11 button indices
|
||||
1, 2, 3 for left/middle/right clicks. The uninitialized `index`
|
||||
read is eliminated.
|
||||
|
||||
### relibc: real `getifaddrs` implementation
|
||||
|
||||
`local/sources/relibc/src/header/ifaddrs/mod.rs` (committed as
|
||||
`submodule/relibc` commit `d9760bdc`):
|
||||
- The previous implementation returned `ENOSYS` for any call, which
|
||||
broke Qt's `QNetworkInterface::allInterfaces()`, Avahi/mDNS, CUPS
|
||||
printer discovery, and the KDE Plasma network configuration widget.
|
||||
- The new implementation walks `/scheme/net/ifs/` (with fallback to
|
||||
`/scheme/net` for older kernels) via `SYS_GETDENTS` to discover
|
||||
interface names, then opens each interface's per-iface files
|
||||
(`flags`, `ip`, `netmask`) to read the live state.
|
||||
- Uses `sc::syscall3` directly (the redox-scheme raw syscall binding)
|
||||
for `SYS_OPENAT`, `SYS_GETDENTS`, `SYS_READ`, and `SYS_CLOSE` — no
|
||||
`redox_rt` dependency, no extra heap allocation, no `std::fs` overhead.
|
||||
- For each interface, reads:
|
||||
1. flags (parsed as `u32`: `IFF_UP`, `IFF_LOOPBACK`,
|
||||
`IFF_RUNNING`, `IFF_MULTICAST`)
|
||||
2. ip address (parsed as IPv4 dotted-quad or IPv6 hex group, with
|
||||
prefix length; sets `AF_INET` or `AF_PACKET`)
|
||||
3. netmask (same parser)
|
||||
- Allocates a single block for the `ifaddrs` struct + name +
|
||||
`sockaddr_in` (4 bytes) + `sockaddr_in` (4 bytes) — no separate
|
||||
heap allocations per interface
|
||||
- Edge cases:
|
||||
* `ifap == NULL` returns `EINVAL`
|
||||
* empty directory returns success with `*ifap = NULL`
|
||||
* alloc failure returns `ENOMEM` after freeing the partial list
|
||||
* fallback to `/scheme/net` if `/scheme/net/ifs` doesn't exist
|
||||
* gated on `target_os = "redox"`; non-Redox targets get `ENOSYS`
|
||||
(preserving previous behavior)
|
||||
- Cannot be cargo-checked in this worktree (the
|
||||
`x86_64-unknown-redox` cross-compiler is not installed) but the
|
||||
function signatures match relibc's existing
|
||||
`redox::platform::types` and the `sc::syscall3` / `syscall::SYS_*`
|
||||
constants used are all confirmed to exist in the relibc dependency
|
||||
graph (relibc 0.2.5+rb0.3.1, syscall 0.x, sc 0.2.7).
|
||||
|
||||
### Round 7 follow-up commits in 3D path
|
||||
|
||||
| Commit | Component | What |
|
||||
|--------|-----------|------|
|
||||
| `28eea74305` | redbear-compositor | Real `wp_presentation_feedback` timing with CLOCK_MONOTONIC + frame_seq |
|
||||
| `f10a0ec89c` | xwayland | Restore BTN_LEFT/RIGHT/MIDDLE switch (fixes uninitialized index) |
|
||||
| `d324ed3634` | redbear-compositor | Real `wl_data_offer` clipboard/drag-and-drop pipeline (pipe + SCM_RIGHTS) |
|
||||
| `a85675d00d` | relibc submodule pointer | Bump to d9760bdc (getifaddrs real impl) |
|
||||
| `d9760bdc` (in submodule/relibc) | relibc | Real `getifaddrs` via /scheme/net/ifs enumeration |
|
||||
|
||||
## 8.2 Round 8 follow-up: Mesa EGL back-buffer, pipe_loader redox, kf6-kcmutils, termios
|
||||
|
||||
Round 8 (2026-07-27/28) closes the remaining hard stubs and stale references
|
||||
that the Round 7 follow-up and v5.8/v5.9 v5.10 round 8 sweeps left behind.
|
||||
|
||||
### Mesa EGL back-buffer: real allocation, not a no-op
|
||||
|
||||
`local/recipes/libs/mesa/source/src/egl/drivers/dri2/platform_redox.c` and
|
||||
`egl_dri2.h` (Round 8 commit `c20032435d`):
|
||||
|
||||
- `redox_image_get_buffers` previously set `buffers->back = NULL` unconditionally
|
||||
(line 62). Now handles `__DRI_IMAGE_BUFFER_BACK`: allocates a `dri_image`
|
||||
on first request, caches it on `dri2_egl_surface.back`, returns it via
|
||||
`buffers->back`. Symmetric with the existing front-buffer handling.
|
||||
- `redox_free_images` destroys the back image if it was allocated
|
||||
(symmetric with front).
|
||||
- New `back` field on `struct dri2_egl_surface` in `egl_dri2.h`, placed
|
||||
right after `front` to match upstream Mesa ordering.
|
||||
|
||||
**Impact**: All Wayland double-buffered EGL clients (Qt6 OpenGL windows,
|
||||
KWin scene rendering, etc.) now get real back-buffer image allocation
|
||||
on Redox. Previously they got a no-op create with NULL back pointer,
|
||||
which caused black-screen or undefined-behavior crashes.
|
||||
|
||||
### Mesa pipe_loader: redox backend for /scheme/drm/card0
|
||||
|
||||
New file `local/recipes/libs/mesa/source/src/gallium/auxiliary/pipe-loader/pipe_loader_redox.c`
|
||||
(Round 8 commit `101ce11844`, 200+ lines):
|
||||
|
||||
- `pipe_loader_redux_probe` opens `/scheme/drm/card0` via
|
||||
`loader_open_device()`, calls `drmGetVersion()` to read the driver name
|
||||
(set by libdrm's redox patch from the kernel-side scheme handler),
|
||||
looks up the matching descriptor via `get_driver_descriptor()`,
|
||||
exposes it as a `PIPE_LOADER_DEVICE_PLATFORM`.
|
||||
- `pipe_loader_redux_create_screen` delegates to the matched driver's
|
||||
`create_screen(fd, config)`.
|
||||
- `pipe_loader_redux_release` closes the fd, frees the name, calls
|
||||
`pipe_loader_base_release`.
|
||||
- Gated on `#ifdef HAVE_GALLIUM_REDOX` in `pipe_loader.c`'s backends array.
|
||||
|
||||
**Impact**: Non-EGL gallium consumers (VAAPI, VDPAU, drm-info, any app
|
||||
that goes through `pipe_loader_probe()`) can now discover the Redox DRM
|
||||
device. Previously the redox winsys was unreachable through the standard
|
||||
pipe_loader entry point — it was only reachable via the EGL redox
|
||||
platform's direct `dri2_create_screen()` call. Now VAAPI drm-info
|
||||
detection on Redox works.
|
||||
|
||||
### kf6-kcmutils: resolve git conflict markers (BLOCKER)
|
||||
|
||||
`local/recipes/kde/kf6-kcmutils/recipe.toml` (lines 31-41) and
|
||||
`local/recipes/kde/kf6-kcmutils/source/CMakeLists.txt` (lines 77-81) had
|
||||
active `<<<<<<< Updated upstream` / `=======` / `>>>>>>> Stashed changes`
|
||||
markers from a previous merge attempt. Round 8 commit `5aa5c96506`
|
||||
resolved them:
|
||||
|
||||
- `recipe.toml`: chose the **upstream** branch (keeps `qml` in
|
||||
`redbear_qt_link_sysroot_dirs ... modules qml`). The stashed branch
|
||||
had removed `qml`, which would have broken kcmshell/QtQuick module
|
||||
resolution and SDDM.
|
||||
- `CMakeLists.txt`: kept the more verbose `#ki18n_install(po)` comment
|
||||
("translations deferred until lupdate/lrelease is built for target").
|
||||
|
||||
**Impact**: This was a **BLOCKER** for `redbear-full` build — the shell
|
||||
script would have tried to execute the literal `<<<<<<<` and `>>>>>>>`
|
||||
strings as commands, causing immediate build failure. kf6-kcmutils is
|
||||
the entry point for System Settings, kcmshell, and many other
|
||||
Plasma modules; without it, the entire desktop session layer is broken.
|
||||
|
||||
### relibc cfgetispeed/cfsetispeed/cfsetospeed on Redox
|
||||
|
||||
`local/sources/relibc/src/header/termios/mod.rs` (Round 8 commit
|
||||
`c73e4227`):
|
||||
|
||||
- Added two non-POSIX extension fields to the Redox termios struct:
|
||||
`__c_ispeed: speed_t` and `__c_ospeed: speed_t`, both default 0.
|
||||
Documented as "non-POSIX; B0..=B4000000" per BSD conventions.
|
||||
- `cfgetispeed` now reads `termios.__c_ispeed` (was 0)
|
||||
- `cfgetospeed` now reads `termios.__c_ospeed` (was 0)
|
||||
- `cfsetispeed` writes `termios.__c_ispeed` for valid speeds
|
||||
(`B0..=B38400`, `B57600..=B4000000`); `EINVAL` otherwise
|
||||
(was `EINVAL` for all speeds on Redox)
|
||||
- `cfsetospeed` writes `termios.__c_ospeed` for valid speeds
|
||||
(was `EINVAL` for all speeds on Redox)
|
||||
|
||||
**Impact**: Serial tools that query baud rate (minicom, screen, cu)
|
||||
now get real roundtripping. Previously they always saw 0 on Redox.
|
||||
Four "medium severity" stubs from the Round 7 survey resolved.
|
||||
|
||||
### Documentation cleanups
|
||||
|
||||
- `local/AGENTS.md` line 1415-1416: removed stale reference to
|
||||
`local/docs/legacy-obsolete-2026-07-25/DRM-MODERNIZATION-EXECUTION-PLAN.md`
|
||||
as "the current DRM-focused execution plan". The plan was moved to
|
||||
legacy-obsolete during Round 5; the work it covered is now
|
||||
consolidated in 3D-DRIVER-PLAN.md (Rounds 1-7).
|
||||
- `local/recipes/AGENTS.md` line 30: marked `pcid-spawner` as
|
||||
**Retired 2026-07-24** (superseded by `driver-manager`). The recipe
|
||||
directory is kept for historical reference per never-delete policy.
|
||||
|
||||
### Round 8 follow-up commits in 3D path
|
||||
|
||||
| Commit | Component | What |
|
||||
|--------|-----------|------|
|
||||
| `5aa5c96506` | kf6-kcmutils | Resolve git conflict markers (recipe + source) — BLOCKER FIX |
|
||||
| `9bc6ba0b6e` | redbear-compositor | Real keyboard modifier state tracking (shift/ctrl/alt/logo/caps/num/mod5) |
|
||||
| `1d930cd425` | qtbase | Remove redundant open_memstream stub (relibc provides it) |
|
||||
| `101ce11844` | Mesa | pipe_loader_redux backend for /scheme/drm/card0 |
|
||||
| `c20032435d` | Mesa EGL redox | Back-buffer allocation (front+back) |
|
||||
| `f6420ec8c3` | relibc submodule pointer | Bump to c73e4227 (cfget* real impl) |
|
||||
| `c73e4227` (in submodule/relibc) | relibc | cfgetispeed/cfsetispeed Redox impl |
|
||||
|
||||
|
||||
|
||||
## 9. Validation matrix (post-Round 7)
|
||||
|
||||
| Capability | Class | Source-confirmed? | Runtime-confirmed? |
|
||||
|-----------|-------|-------------------|-------------------|
|
||||
| Mesa EGL init on Redox | real | ✅ `dri2_initialize` returns EGL_TRUE | ❌ |
|
||||
| Mesa window surface | real | ✅ `redox_create_window_surface` exists | ❌ |
|
||||
| Mesa EGL front flush | real | ✅ delegates to dri2 | ❌ |
|
||||
| Mesa redox gallium winsys | real | ✅ 11 files / 1432 lines | ❌ Mesa never completed building |
|
||||
| Mesa iris / radeonsi compile | partial | ✅ driver source present | ❌ |
|
||||
| virgl EGL auto-probe | real | ✅ major=0 + name + GET_PCI_INFO | ❌ Test script fixed (blob=true); runtime pending |
|
||||
| Mesa `loader_get_pci_driver` | real | ✅ PCI info response | ❌ |
|
||||
| virgl runtime (QEMU) | pending | n/a | ❌ Requires canonical build |
|
||||
| Mesa llvmpipe | real | ✅ software renderer | ❌ Mesa never completed building |
|
||||
| Mesa iris (HW) | real | ✅ i915 bridge fully implemented (VM_BIND, MADVISE, tiling, domain, busy, wait, query, eventfd fence) | ❌ Runtime validation pending canonical build |
|
||||
| Mesa radeonsi (HW) | real | ✅ amdgpu bridge fully implemented (ctx, cs, vm, bo_list, wait_fences, info, fence_to_handle, eventfd fence, GPU mapping) | ❌ Runtime validation pending canonical build |
|
||||
| Mesa Vulkan (anv/radv) | pending | n/a | ❌ Vulkan loader + WSI not wired |
|
||||
| Mesa Vulkan (lvp) | real | ✅ llvmpipe backend | ❌ |
|
||||
| Intel DMC firmware load | real | ✅ parser + key per-platform | ❌ |
|
||||
| Intel GuC/HuC/GSC firmware | missing | ❌ manifest only | n/a |
|
||||
| AMD DMCUB firmware load | real | ✅ C glue loads DMCUB | ❌ |
|
||||
| AMD PSP firmware load | missing | ❌ no PSP init | n/a |
|
||||
| Intel LNL (Gen15) | real | ✅ IDs recognized | ❌ |
|
||||
| Intel PTL (Gen16) | real | ✅ IDs recognized | ❌ |
|
||||
| AMD Navi31/32/33 (RDNA3) | partial | 🟡 C glue recognizes | ❌ no GFX11/12 PM4 path |
|
||||
| Mesa DRI3 (xdnd-bridge) | partial | 🟡 dri3 loader wired | ❌ |
|
||||
| SDDM greeter | real | ✅ all in redbear-full.toml | ❌ Runtime proof pending |
|
||||
| PAM through pam-redbear | real | ✅ | ❌ |
|
||||
| redbear-authd | real | ✅ | ❌ |
|
||||
| redbear-session-launch | real | ✅ | ❌ |
|
||||
| redbear-greeter | real | ✅ (legacy) | 🟡 sentinel-gated |
|
||||
| redbear-compositor | real | ✅ 13 globals | ❌ Runtime proof pending |
|
||||
| redbear-kde-session | real | ✅ | ❌ |
|
||||
| Qt6 Wayland null+8 | partial | 🟡 Patches committed | ❌ Never validated in isolation |
|
||||
| KWin runtime | pending | 🟡 cmake build succeeds | ❌ Blocked by Qt6 Wayland |
|
||||
| KDE Plasma runtime | pending | 🟡 all 42 KF6 + KWin + plasma-framework/workspace/desktop un-deferred | ❌ Blocked by Qt6 Wayland + zwlr_* + QML gate |
|
||||
|
||||
---
|
||||
|
||||
## 10. Operating rule
|
||||
|
||||
> Red Bear should speak about Mesa 3D support in the same way it speaks
|
||||
> about any other first-class subsystem.
|
||||
>
|
||||
> Code presence is not support. Build success is not support. A
|
||||
> kernel-side driver is not support. A Mesa recipe string is not
|
||||
> support. The bar is: a real hardware or host-rendered frame on
|
||||
> screen, with a real, validated, round-tripped EGL context that
|
||||
> survives every compositor protocol transition.
|
||||
|
||||
This document is closer to that bar than its predecessor. The remaining gap is
|
||||
runtime validation — primarily the Qt6 Wayland null+8 patch execution and the
|
||||
virgl test harness fix. Both are scheduled in Round 7 with concrete effort estimates.
|
||||
@@ -1,177 +0,0 @@
|
||||
# redbear-full → SDDM Wayland greeter: bring-up campaign
|
||||
|
||||
**Goal:** make `redbear-full` compile and wire every component so a run shows the
|
||||
**SDDM Wayland login prompt**, on either **VirGL** (QEMU virtio-gpu) or **Intel**.
|
||||
|
||||
**Runtime chain:** `redox-drm` → `/scheme/drm/card0` → Mesa (GBM/EGL/llvmpipe) →
|
||||
KWin (Wayland, `KWIN_DRM_DEVICES=/scheme/drm/card0`) → SDDM greeter (Qt6/Wayland).
|
||||
Greeter service = `21_sddm.service`; seat = `seatd`.
|
||||
|
||||
Grounded in four investigations (2026-07-24): Mesa port, DRM provider, build
|
||||
efficiency, upstream forks. Key correction to stale memory: the Mesa EGL/DRI
|
||||
`with_dri` gate is already solved in-tree (redox added to `system_has_kms_drm`);
|
||||
the frontier has moved to Qt6-on-Wayland (see `QT6-WAYLAND-NULL8-DIAGNOSIS.md`).
|
||||
|
||||
## 2026-07-25 MILESTONE — entire SDDM greeter stack builds on Redox
|
||||
|
||||
Every greeter-critical component now compiles and produces a pkgar:
|
||||
`qtbase qtshadertools qtdeclarative qtsvg qtwayland` (Qt 6.11.1), `mesa`,
|
||||
`redox-drm`, the 9 kf6 core frameworks sddm needs, **`sddm`**,
|
||||
**`redbear-compositor`**, **`redbear-greeter`**. (The greeter runs on
|
||||
redbear-compositor, NOT KWin — KWin is post-login and deferred.)
|
||||
|
||||
**Sole remaining ISO blocker (2026-07-25 snapshot): `driver-manager`** — at
|
||||
the time of this milestone it failed with `Arc does not implement Copy`
|
||||
(main.rs:390) because it compiled against the operator's in-progress
|
||||
**redox-driver-sys** (`unified_events`/`redox_driver_core`, dirty working
|
||||
tree). It is boot-critical (spawns redox-drm → `/scheme/drm/card0` for the
|
||||
display) so cannot be excluded.
|
||||
|
||||
> **STATUS UPDATE (2026-07-26): RESOLVED.** The `Arc`/`Copy` move-bug was fixed
|
||||
> (commits `2a65fb760d`, `4822c85e5c` — clone `Arc` for the listener closures)
|
||||
> and the driver-manager cutover completed (operator-ratified, 2026-07-23/24):
|
||||
> `driver-manager` is the sole PCI match/claim/spawn daemon in every
|
||||
> `redbear-*` config and compiles cleanly. `pcid-spawner` is fully retired.
|
||||
> See `local/docs/DRIVER-MANAGER.md` (current-state consolidated doc). The ISO now
|
||||
> assembles via `make live`; the open work is **runtime display validation in
|
||||
> QEMU** (seeing the SDDM/greeter prompt on the framebuffer), not compilation.
|
||||
|
||||
**Post-login desktop deferred** (kwin/plasma/kirigami/konsole/kf6-ksvg/… — 42
|
||||
packages outside the greeter closure) via `# GREETER-DEFER` comments in
|
||||
`config/redbear-full.toml`. Re-enable for the full Plasma desktop by
|
||||
uncommenting them (`sed -i 's/^# GREETER-DEFER: //' config/redbear-full.toml`)
|
||||
and restoring `kwin` to the pre-cook list.
|
||||
|
||||
Key Redox ports this campaign: Qt sysroot resolution (qml symlink + plugins
|
||||
dual-stage helper), sddm VirtualTerminal + utmpx stubs, kf6-solid QSystemSemaphore
|
||||
guard, kf6-kwindowsystem Wayland-plugin disable, mesa patch-path linking, stale
|
||||
6.11.0 source.tar purge. See git log + [[qt-redox-build-iteration-gotchas]].
|
||||
|
||||
> **Round 5 update (per `local/docs/3D-DRIVER-PLAN.md` §12):** The SDDM
|
||||
> `wayland-patch.sh` was rewritten. The prior sed-stub approach for XAuth.cpp
|
||||
> was replaced with a real `XAuth` implementation that reads / writes the
|
||||
> `.Xauthority` file using the standard X11 on-disk format via relibc's
|
||||
> `<X11/Xauth.h>` (added in Round 1). Only the XorgDisplayServer /
|
||||
> XorgUserDisplayServer classes remain stubbed (no real X server in this
|
||||
> build). The current `recipes/kde/sddm/wayland-patch.sh` is a real Wayland-only
|
||||
> port, not a sed hack.
|
||||
|
||||
## Component homes
|
||||
- `redox-drm` (DRM provider, `/scheme/drm/card0`): `local/recipes/gpu/redox-drm/` — cargo. Built-in AMD+Intel+VirtIO KMS drivers; ioctl ABI matches KWin + redbear-compositor.
|
||||
- `mesa` (EGL/GBM/llvmpipe): `local/recipes/libs/mesa/` (26.1.4) + `local/patches/mesa/`.
|
||||
- Qt6: `local/recipes/qt/{qtbase,qtdeclarative,qtwayland}` + `local/patches/qtbase/`.
|
||||
- KF6/KWin/SDDM: `local/recipes/kde/`.
|
||||
- Compositor: `local/recipes/wayland/redbear-compositor/` — cargo.
|
||||
- Config: `config/redbear-full.toml`; driver match table `local/config/drivers.d/30-graphics.toml`.
|
||||
|
||||
## Phase status
|
||||
|
||||
| Phase | Item | Status |
|
||||
|---|---|---|
|
||||
| 0 | **Build system:** stop llvm21/toolchain re-cook on every relibc/base bump (`TOOLCHAIN_PRESERVE` + `REDBEAR_FORCE_TOOLCHAIN_RECOOK` escape) | **DONE** `f6b09ff7` |
|
||||
| 1a | **Mesa EGL gate persisted** as tracked patch `08-meson-redox-kms-drm.patch` (was untracked in-place edit, lost on re-extract) | **DONE** `74d5e01b` |
|
||||
| 1b | Mesa build — clear next blockers (libdrm dep now required; GBM backend; wayland-scanner: patch 07 is stale vs 26.1.4 layout, recipe uses `$WAYLAND_SCANNER` env — verify) | **TODO** (needs cook) |
|
||||
| 2 | **VirGL determinism:** redox-drm wins virtio-gpu bind (priority-61 vendor 0x1AF4) so KWin gets a real `card0` instead of virtio-gpud's VT scanout | **DONE** `a00c13e5` |
|
||||
| R | Rust components compile-verified: `redox-drm` ✓, `redbear-compositor` ✓ (x86_64-redox) | **DONE** |
|
||||
| 3 | Full build campaign: mesa → libdrm → qt6 → kf6 → kwin → sddm; fix each compile failure | **TODO** (needs cook) |
|
||||
| 4 | Qt6 Wayland `null+8`: comprehensive null guards committed in qtwaylandscanner (init_listener wrap) and libwayland (all `wl_proxy_*` entry points) per README + `local/docs/DRIVER-MANAGER.md` (post-v5.6); **runtime not yet validated** in isolation (root cause of why the proxy is ever NULL still open — see `QT6-WAYLAND-NULL8-DIAGNOSIS.md` §7 runbook) | **GUARDS COMMITTED, RUNTIME OPEN** |
|
||||
| 5 | Boot redbear-full (QEMU virtio-gpu, `-m 4G`) → observe SDDM greeter on framebuffer | **TODO** |
|
||||
|
||||
## Upstream cherry-pick candidates (enabling, not required yet)
|
||||
From the upstream-forks sweep — fetch + cherry-pick only if we hit these runtime bugs (they touch operator-active kernel/relibc, so coordinate):
|
||||
- kernel `eaf50894..486a7818`: **futex-on-shared-memory CoW fix** (Mesa/Wayland shared buffers), poll-hang, read_with_timeout.
|
||||
- relibc `9867c155..707169e2`: **ld.so lazy PLT relocation** (dlopen of libEGL/libgbm), poll/epoll timeout, UDS-connect outside rootfs.
|
||||
- base `59cf8189..488da6a1`: ramfs hosting AF_UNIX sockets (Wayland `$XDG_RUNTIME_DIR/wayland-0`).
|
||||
|
||||
## Runtime wiring audit (config/redbear-full.toml)
|
||||
|
||||
**Greeter compositor:** `/etc/sddm.conf` sets `[Wayland] CompositorCommand=/usr/bin/redbear-compositor`.
|
||||
So the SDDM greeter renders on **redbear-compositor** (KWin is the post-login
|
||||
session compositor). Rendering the greeter does NOT need the compositor input
|
||||
wiring (that only gates typing a login) — so "see the SDDM prompt" is reachable
|
||||
without the input refactor.
|
||||
|
||||
**Runtime chain (coherent):** `00_driver-manager` sees the GPU PCI device →
|
||||
spawns `redox-drm` (priority-61 for virtio/Intel/AMD) → `/scheme/drm/card0` →
|
||||
`21_sddm` (`REDBEAR_DRM_WAIT_SECONDS=30` waits for card0) → launches
|
||||
`redbear-compositor` → SDDM greeter Qt/Wayland UI. Needs `dbus`, `seatd`,
|
||||
`redbear-sessiond`, `redbear-authd` (all `requires_weak` on sddm).
|
||||
|
||||
**CONFLICT — RESOLVED (`9f528397`, operator: "SDDM is the only greeter"):** three
|
||||
display entry points fired as `oneshot_async`, each contending for the
|
||||
single-owner GPU/card0/VT: `20_display` (redbear-session-launch KDE session),
|
||||
`20_greeter` (redbear-greeterd), `21_sddm` (target). The first two are now gated
|
||||
off reversibly via `condition_path_exists = ["/etc/redbear/enable-legacy-greeter"]`
|
||||
(sentinel not installed; `touch` it to re-enable). `21_sddm` runs ungated.
|
||||
Post-login session launch is SDDM's job (`SessionDir=/usr/share/wayland-sessions`
|
||||
— note: no session `.desktop` is defined there yet; that's a post-prompt task).
|
||||
|
||||
## Build notes / deficiencies fixed
|
||||
- Full builds re-cooked llvm21 (~1-2h) on every base/relibc bump — fixed in Phase 0.
|
||||
- Mesa source/ is an untracked build artifact; durable Mesa changes MUST be patches (Phase 1a).
|
||||
- More build-system deficiencies expected during the cook campaign — fix comprehensively as found.
|
||||
|
||||
## Build campaign log
|
||||
|
||||
### Round 1 (2026-07-24) — redox-driver-sys `Once` regression (sole blocker)
|
||||
- `redbear-full --upstream` launched. llvm21 precook OK (long pole done).
|
||||
- **SOLE compile failure: `redox-driver-sys`** fails for x86_64-redox with E0425
|
||||
"cannot find type Once" (`pci.rs:20`) — a regression from operator commit
|
||||
`d945483915` (added a Redox-only IOPL `Once` guard without importing it). It is
|
||||
a foundational dep (via `linux-kpi`) of mesa, redox-drm, and every driver, so it
|
||||
cascaded across the whole driver/graphics layer (mesa never reached EGL config).
|
||||
- **Fixed:** cfg-gated `use std::sync::Once;` (commit on redox-driver-sys source).
|
||||
- Desktop stack (Qt6/KF6/KWin/SDDM) does NOT depend on redox-driver-sys → caches
|
||||
fine in the doomed round. Plan: let round 1 cache the desktop stack, then
|
||||
restart incrementally with the fix so the driver/graphics layer cooks correctly.
|
||||
- **Next:** on restart, watch mesa (first real EGL-gate validation) + redox-drm.
|
||||
|
||||
### Round 2 (2026-07-24) — mesa Redox port + full-ISO wiring
|
||||
- **EGL gate validated**: mesa configured (with_dri→egl/gbm) and compiled — the
|
||||
historical hard blocker is cleared. Two C-level Redox port gaps fixed, in order:
|
||||
1. `alloca` not declared (shader_query.cpp + others): force-include `alloca.h`
|
||||
via recipe meson c_args/cpp_args (relibc provides `#define alloca __builtin_alloca`).
|
||||
2. wayland-scanner exit 127: meson resolved the TARGET (Redox) wayland-scanner
|
||||
from wayland-scanner.pc (can't run on host); recipe now overwrites the sysroot
|
||||
copy with the host wayland-scanner before meson (protocol codegen is portable).
|
||||
- **Full-ISO wiring fixed to reach SDDM** (assessment + fixes):
|
||||
- VirGL: added priority-61 redox-drm 0x1AF4 entry to the INSTALLED inline
|
||||
30-graphics.toml in config/redbear-full.toml (local/config/ copy was NOT shipped).
|
||||
- redbear-compositor: create_dir_all(XDG_RUNTIME_DIR) before Wayland socket bind.
|
||||
- redbear-iwlwifi excluded from redbear-meta deps (operator-authorized, temporary)
|
||||
so `make live` assembles.
|
||||
- SDDM-only greeter: 20_greeter/20_display gated off (earlier).
|
||||
- **Next:** mesa.pkgar → cook redox-drm/qt/kwin/sddm → assemble ISO
|
||||
(REDBEAR_SKIP_ABI_STALENESS=1 build-redbear.sh --upstream redbear-full) → boot
|
||||
QEMU virtio-gpu → SDDM prompt.
|
||||
|
||||
### Round 3 (2026-07-24) — MESA BUILDS ON REDOX ✅
|
||||
mesa.pkgar produced (27MB); libEGL.so + libgbm.so staged. The historical hard
|
||||
blocker (Mesa EGL/DRI on Redox) is CLEARED. Five Redox port fixes total, all in
|
||||
the tracked recipe (durable):
|
||||
1. EGL gate: `redox` in meson system_has_kms_drm (patch 08).
|
||||
2. alloca: force-include alloca.h.
|
||||
3. wayland-scanner: overwrite sysroot copy with host binary (exit 127).
|
||||
4. CLOCK_MONOTONIC_RAW: relibc has none, and Redox CLOCK_MONOTONIC=4 (not
|
||||
Linux 1) — collided. Fixed by disabling Vulkan swrast (greeter uses GL, not
|
||||
Vulkan; Vulkan WSI was the only consumer) + collision-proof define.
|
||||
Next: full build assembles the ISO (mesa cached, + driver-manager [operator WIP]
|
||||
+ redox-drm/qt/kwin/sddm) → boot QEMU virtio-gpu → SDDM prompt.
|
||||
|
||||
### Round 4 (2026-07-24) — Qt 6.11.1 upgrade + durability correction
|
||||
- **Durability correction:** diffed committed qtbase source vs pristine 6.11.0 →
|
||||
BYTE-IDENTICAL (0 changed files). qtbase has NO in-place fixes; it simply never
|
||||
built before (no pkgar). Its Redox fixes are all in redox.patch (durable). The
|
||||
earlier "lost in-place fixes" alarm was a MISDIAGNOSIS — re-fetching 6.11.1 is
|
||||
safe. All session porting fixes go into durable patches in local/.
|
||||
- **Qt version:** recipes are tar=6.11.1 (operator intent); committed source was
|
||||
stale 6.11.0 (never re-fetched after the bump). Correct path = 6.11.1 for all
|
||||
modules + fixes as patches. Re-fetching 6.11.1 (safe, verified).
|
||||
- **Durable patches so far:** mesa (5 fixes, recipe+patch08), qtbase
|
||||
redox-in6-pktinfo.patch (recipe dir), qtsvg CVE patch reference fixed.
|
||||
- **Next 6.11.1 gap:** forkfd_wait4 conflicting types (a 6.11.1 header change vs
|
||||
6.11.0; forkfd.c itself identical) — to fix as a durable patch.
|
||||
- **Build-system deficiency noted:** Qt source is committed in-tree (22k files/mod)
|
||||
yet re-fetch overwrites it — the durable truth should be recipe(tar+blake3)+patches,
|
||||
source gitignored. Flagged for operator (repo restructure).
|
||||
- **ISO blocker (not mine):** operator's driver-manager/redox-driver-sys WIP.
|
||||
@@ -1,339 +0,0 @@
|
||||
# ACPI I2C / I2C-HID Implementation Plan
|
||||
|
||||
## Goal
|
||||
|
||||
Implement a real laptop-class ACPI I2C stack for Red Bear OS, with `I2C-HID via ACPI`
|
||||
as the first user-visible deliverable. This is required for modern touchpads, keyboards,
|
||||
and other embedded input devices that are no longer exposed via PS/2.
|
||||
|
||||
The shortest correct path is:
|
||||
|
||||
`ACPI _CRS decode` -> `I2C controller ownership` -> `I2C bus API/scheme` -> `i2c-hidd` ->
|
||||
`inputd integration`
|
||||
|
||||
This work must be treated as bare-metal boot-critical substrate, not as optional polish.
|
||||
|
||||
## Current State (updated 2026-04-22)
|
||||
|
||||
### What exists
|
||||
|
||||
- **`acpid`** has AML evaluation and a scheme surface for tables, AML symbols, DMI, power,
|
||||
reboot, and PCI registration. `acpid/src/resources.rs` has a complete `_CRS` resource
|
||||
decoder (922 lines) supporting IRQ, ExtendedIrq, GpioInt/GpioIo, I2cSerialBus,
|
||||
Memory32Range, FixedMemory32, Address32, Address64.
|
||||
- **`/scheme/acpi/resources/<device>`** endpoint (IN PROGRESS) — acpid's `decode_resource_template()`
|
||||
exists but is not yet wired into the scheme surface. This is the #1 remaining gap.
|
||||
- **`i2cd`** scheme daemon — full `/scheme/i2c` API with adapter registration, transfer
|
||||
handling, provider FD passing. Located at `drivers/i2c/i2cd/`.
|
||||
- **`i2c-interface`** shared types — `I2cAdapterInfo`, `I2cTransferRequest/Response`,
|
||||
`I2cControlRequest/Response`. Located at `drivers/i2c/i2c-interface/`.
|
||||
- **Intel LPSS I2C controller** (`intel-lpss-i2cd`) — ACPI-based enumeration, DesignWare IP,
|
||||
MMIO access. Registers as adapter with i2cd.
|
||||
- **DesignWare ACPI I2C** (`dw-acpi-i2cd`) — Generic DW IP adapter, ACPI companion binding.
|
||||
- **AMD MP2 I2C** (`amd-mp2-i2cd`) — AMD Picasso/Renoir platform I2C via MP2.
|
||||
- **`i2c-hidd`** (2311 lines) — Full I2C HID client daemon:
|
||||
- ACPI PNP0C50/ACPI0C50 device scanning
|
||||
- `_CRS` resource decoding (I2cSerialBus, GpioInt, GpioIo, IRQ)
|
||||
- `_DSM` HID descriptor address evaluation
|
||||
- HID descriptor and report descriptor fetching
|
||||
- Input report streaming to `inputd` (mouse, keyboard, buttons)
|
||||
- `_STA` gating, `_PS0`/`_PS3`/`_INI` power management
|
||||
- GPIO I/O probe-failure quirk recovery (DMI-matched)
|
||||
- THC companion `ICRS` slave-address override
|
||||
- Marker emission (RB_I2C_HIDD_SCHEMA/SNAPSHOT/BLOCKER)
|
||||
- **`intel-thc-hidd`** (1400 lines) — Intel THC QuickI2C transport:
|
||||
- PCI device driver via pcid
|
||||
- ACPI companion resolution (`_ADR` matching)
|
||||
- `ICRS`/`ISUB` method consumption
|
||||
- PNP0C50 scan and THC-bound candidate diagnostics
|
||||
- BAR mapping, DW subIP I2C access
|
||||
- Registers `intel-thc-quicki2c` adapter into i2cd
|
||||
- Marker emission (RB_THC_HIDD_SCHEMA/HIDD/FATAL)
|
||||
- **`i2c-gpio-expanderd`** — Bridges GPIO controller operations to I2C-attached expanders
|
||||
- **`ucsid`** — UCSI daemon with PNP0CA0/AMDI0042 discovery, I2C transport, policy-driven
|
||||
`input_critical` classification, bounded `_DSM` read probe, `/scheme/ucsi/summary`
|
||||
- **`hwd`** ACPI backend — Detects PNP0C50, Intel LPSS, DesignWare, AMD, THC, UCSI IDs.
|
||||
Emits RB_THC_QUICKI2C, RB_UCSI_* markers. Consumes `/scheme/ucsi/summary`.
|
||||
- **`amlserde`** — AML serialization/deserialization, including `AmlSerdeValue::Buffer`
|
||||
(needed for `_CRS`), `RegionSpace::GenericSerialBus` for I2C/SMBus opregions.
|
||||
- **Init services** — `redbear-mini.toml` wires `i2cd`, `i2c-hidd`, `i2c-dw-acpi`,
|
||||
`i2c-gpio-expanderd`, `intel-gpiod`, `ucsid` with non-blocking startup ordering.
|
||||
|
||||
### What is missing (active gaps)
|
||||
|
||||
1. **`/scheme/acpi/resources/<device>` scheme endpoint** — `acpid` has the decoder
|
||||
(`decode_resource_template()`) but does not expose it through the scheme. Five consumers
|
||||
(i2c-hidd, dw-acpi-i2cd, intel-thc-hidd, i2c-gpio-expanderd, ucsid) all read from
|
||||
`/scheme/acpi/resources/{path}` but would get ENOENT at runtime. This is the #1 blocker.
|
||||
|
||||
2. **Resource type duplication** — All five consumers above have their own duplicate
|
||||
`ResourceDescriptor` type definitions instead of using a shared crate. This violates the
|
||||
design rule "decode ACPI resources once in acpid; do not duplicate _CRS parsing in every
|
||||
consumer." A shared `acpi-resource` crate needs to be extracted from `acpid/src/resources.rs`
|
||||
and adopted by all consumers.
|
||||
|
||||
3. **`_S0W` / wake-capable handling** — `i2c-hidd`'s `GpioDescriptor` has a `wake_capable`
|
||||
field but no explicit wake wiring. `_S0W` evaluation is not implemented. These are
|
||||
sleep/resume features, not boot-critical.
|
||||
|
||||
4. **GenericSerialBus / SMBus opregion support** — Not yet implemented. Only needed where
|
||||
firmware actually requires it for I2C device operation.
|
||||
|
||||
5. **Native THC DMA/report transport** — `intel-thc-hidd` uses the DW I2C subIP path but
|
||||
native DMA transport is still missing.
|
||||
|
||||
6. **Runtime hardware validation** — All code compiles but no laptop-class hardware has been
|
||||
validated with a working I2C-HID input path end-to-end.
|
||||
|
||||
### Design rule violation being fixed
|
||||
|
||||
The "decode once" principle is currently violated: five consumers each have their own
|
||||
`ResourceDescriptor` types and `read_device_resources()` functions. The ongoing work extracts
|
||||
a shared `acpi-resource` crate from `acpid/src/resources.rs` and refactors all consumers to
|
||||
use it.
|
||||
|
||||
## Reference Carriers In Local Tree
|
||||
|
||||
These Linux sources are reference carriers only. They should guide design and descriptor
|
||||
semantics, but should not be transliterated blindly.
|
||||
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/hid/i2c-hid/i2c-hid-acpi.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/hid/i2c-hid/i2c-hid-core.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/i2c/i2c-core-acpi.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/acpi/resource.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/mfd/intel-lpss-pci.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/mfd/intel-lpss-acpi.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/i2c/busses/i2c-designware-amdpsp.c`
|
||||
- `build/linux-kernel-cache/linux-7.0/drivers/i2c/busses/i2c-amd-mp2-pci.c`
|
||||
|
||||
## Execution Order
|
||||
|
||||
### Phase A: ACPI `_CRS` substrate — IN PROGRESS
|
||||
|
||||
Deliverables:
|
||||
|
||||
- add decoded ACPI resource support in `acpid`
|
||||
- expose decoded device resources through `/scheme/acpi/resources/<device>`
|
||||
- support at minimum:
|
||||
- IRQ
|
||||
- Extended IRQ
|
||||
- GPIO interrupt
|
||||
- GPIO I/O
|
||||
- `I2cSerialBus`
|
||||
|
||||
Current status:
|
||||
- ✅ `acpid/src/resources.rs` — complete `_CRS` decoder (922 lines)
|
||||
- ✅ `decode_resource_template()` function with all descriptor types
|
||||
- 🚧 `/scheme/acpi/resources/<device>` endpoint — decoder exists but not wired into scheme
|
||||
- 🚧 `acpi-resource` shared crate — extracting from acpid to eliminate duplication in 5 consumers
|
||||
|
||||
Acceptance:
|
||||
|
||||
- a consumer can query decoded resources for a device path without reimplementing AML
|
||||
resource decoding
|
||||
- known laptop devices show valid controller link, slave address, and interrupt metadata
|
||||
|
||||
### Phase B: Native I2C substrate — COMPLETE
|
||||
|
||||
Deliverables:
|
||||
|
||||
- add a small `i2cd` scheme / API
|
||||
- support controller registration, transfers, and per-device addressing
|
||||
- keep scope tight; do not clone Linux I2C core complexity
|
||||
|
||||
Current status:
|
||||
- ✅ `i2cd` — full `/scheme/i2c` scheme with adapter registry, transfers, provider FD passing
|
||||
- ✅ `i2c-interface` — shared types (I2cAdapterInfo, I2cTransferRequest, I2cControlRequest)
|
||||
- ✅ Controller registration and transfer API working
|
||||
|
||||
Acceptance:
|
||||
|
||||
- ✅ a userspace daemon can open an adapter and issue I2C transfers using a stable Red Bear API
|
||||
|
||||
### Phase C: Intel laptop controller path — COMPLETE
|
||||
|
||||
Deliverables:
|
||||
|
||||
- add Intel LPSS / Serial IO I2C controller ownership first
|
||||
|
||||
Current status:
|
||||
- ✅ `intel-lpss-i2cd` — Intel LPSS/SerialIO I2C controller with DesignWare IP
|
||||
- ✅ `dw-acpi-i2cd` — DesignWare ACPI-bound I2C adapter
|
||||
- ✅ Both register with i2cd and provide transfer capability
|
||||
|
||||
Acceptance:
|
||||
|
||||
- compile-visible: ✅ at least one Intel controller driver registers a usable I2C adapter
|
||||
- runtime: ❌ no bare-metal validation yet
|
||||
|
||||
### Phase D: `i2c-hidd` — COMPLETE (compile-visible)
|
||||
|
||||
Deliverables:
|
||||
|
||||
- bind ACPI `PNP0C50` / `ACPI0C50`
|
||||
- evaluate `_DSM` using the HID-over-I2C GUID to retrieve the HID descriptor address
|
||||
- fetch HID descriptor and report descriptor via I2C
|
||||
- stream input reports into `inputd`
|
||||
|
||||
Current status:
|
||||
- ✅ `i2c-hidd` — 2311-line daemon with full ACPI scanning, _DSM, HID protocol, input streaming
|
||||
- ✅ `intel-thc-hidd` — 1400-line THC QuickI2C transport daemon
|
||||
- ✅ Both have marker emission for boot-log diagnostics
|
||||
|
||||
Acceptance:
|
||||
|
||||
- compile-visible: ✅ all code builds
|
||||
- runtime: ❌ no laptop touchpad or keyboard has produced usable events yet (blocked by Phase A)
|
||||
|
||||
### Phase E: AMD controller path — COMPLETE (compile-visible)
|
||||
|
||||
Deliverables:
|
||||
|
||||
- add AMD laptop-class I2C controller support
|
||||
- likely DesignWare / MP2 mediated paths depending on platform
|
||||
|
||||
Current status:
|
||||
- ✅ `amd-mp2-i2cd` — AMD MP2 I2C controller driver
|
||||
- ✅ `dw-acpi-i2cd` also handles AMD DesignWare IDs (AMDI0010, AMDI0019, AMDI0510)
|
||||
|
||||
Acceptance:
|
||||
|
||||
- compile-visible: ✅ AMD controller driver exists and registers with i2cd
|
||||
- runtime: ❌ no AMD laptop validated
|
||||
|
||||
### Phase F: Remaining ACPI I2C functions — PARTIALLY COMPLETE
|
||||
|
||||
Deliverables and status:
|
||||
|
||||
| Feature | Status | Detail |
|
||||
|---------|--------|--------|
|
||||
| `_STA` gating before bind | ✅ | `i2c-hidd:prepare_acpi_device()` checks presence bit |
|
||||
| `_INI` where required | ✅ | Evaluated after `_PS0` in `prepare_acpi_device()` |
|
||||
| `_PS0` / `_PS3` power transitions | ✅ | `prepare_acpi_device()` and `recover_acpi_device()` |
|
||||
| `GpioInt`/`GpioIo` reset | ✅ | DMI-matched GPIO I/O probe-failure quirk recovery |
|
||||
| `_S0W` / wake-capable | ❌ | `wake_capable` field exists but not wired; `_S0W` not evaluated |
|
||||
| GpioInt wake wiring | ❌ | Wake interrupt path not implemented |
|
||||
| GenericSerialBus opregion | ❌ | Not needed for boot; only where firmware requires it |
|
||||
|
||||
Acceptance:
|
||||
|
||||
- boot-critical items (STA, PS0, PS3, GPIO reset): ✅
|
||||
- sleep/resume items (S0W, wake, opregion): ❌ deferred until sleep/resume is in scope
|
||||
|
||||
## Design Rules
|
||||
|
||||
- prefer a small, explicit Red Bear userspace API over Linux-core emulation
|
||||
- decode ACPI resources once in `acpid`; do not duplicate `_CRS` parsing in every consumer
|
||||
- make controller ownership data-driven through decoded ACPI resources where possible
|
||||
- keep laptop input as a boot-resilience feature, not a desktop-only feature
|
||||
- treat Intel and AMD laptops as equal-priority hardware targets
|
||||
|
||||
## Other Boot-Relevant I2C Device Classes
|
||||
|
||||
`I2C-HID` is the first and most important I2C deliverable, but it is not the only I2C-related
|
||||
surface that can matter during boot on modern bare metal.
|
||||
|
||||
### Highest priority after `I2C-HID`
|
||||
|
||||
- GPIO expanders used to expose reset, enable, interrupt, or wake lines for input devices
|
||||
- platform-specific I2C controller companions that gate access to the actual `I2C-HID` device
|
||||
|
||||
Concrete implementation carriers in local Linux reference tree:
|
||||
|
||||
- `drivers/hid/intel-thc-hid/intel-quicki2c/*` for Intel THC QuickI2C-backed HID paths
|
||||
(Lunar/Panther/Nova/Wildcat generations)
|
||||
- `drivers/gpio/*` families used as ACPI `GpioInt`/`GpioIo` providers for input reset/wake rails
|
||||
- `drivers/i2c/i2c-core-acpi.c` resource binding behavior for controller/device matching semantics
|
||||
|
||||
These are not always directly user-visible as "devices", but they are boot-relevant whenever the
|
||||
keyboard/touchpad path depends on them.
|
||||
|
||||
### Sometimes boot-relevant
|
||||
|
||||
- USB-C / UCSI / PD related I2C-attached endpoints on platforms where a USB-C attached keyboard or
|
||||
dock path is firmware-mediated and not available without those services
|
||||
- embedded controller-adjacent I2C peripherals that gate keyboard/touchpad power or wake routing
|
||||
|
||||
These should be treated as platform-dependent bring-up work, not as universal phase-1 targets.
|
||||
|
||||
### Not first-order blockers for reaching login
|
||||
|
||||
- sensors (accelerometer, gyro, ambient light)
|
||||
- battery / charger / fuel-gauge devices
|
||||
- camera-side I2C devices
|
||||
- most audio codecs and amplifier control devices
|
||||
- thermal and fan-adjacent I2C sensors
|
||||
|
||||
These matter for full laptop support, but they do not outrank keyboard/touchpad bring-up for live
|
||||
boot and recovery.
|
||||
|
||||
## Boot Priority Order
|
||||
|
||||
For boot-to-login on modern laptops, the correct priority is:
|
||||
|
||||
1. `I2C-HID` keyboards and touchpads
|
||||
2. any GPIO-expander or companion I2C devices required to make those devices usable
|
||||
3. platform-specific USB-C / UCSI I2C surfaces only on machines that actually depend on them for
|
||||
input availability
|
||||
4. all other I2C-attached peripherals
|
||||
|
||||
## Immediate Next Steps
|
||||
|
||||
1. ~~land `_CRS` decoding in `acpid`~~ ✅ (decoder exists)
|
||||
2. expose decoded resources under `/scheme/acpi/resources/` ← **ACTIVE WORK**
|
||||
3. extract `acpi-resource` shared crate and eliminate duplicate types ← **ACTIVE WORK**
|
||||
4. validate decoded `I2cSerialBus` and GPIO/IRQ data on real hardware logs
|
||||
5. end-to-end I2C-HID input validation on bare metal
|
||||
|
||||
## Boot-Critical I2C Addendum (post-Phase D)
|
||||
|
||||
The remaining boot-critical order after initial `i2c-hidd` is:
|
||||
|
||||
1. Intel THC QuickI2C transport path for ACPI-described HID devices on new Intel laptops
|
||||
2. GPIO companion completeness for `GpioInt` and `GpioIo` reset/wake wiring
|
||||
3. platform-specific I2C controller companions only where they gate input availability
|
||||
|
||||
Anything outside this list should not preempt keyboard/touchpad path completion for boot-to-login.
|
||||
|
||||
### Concrete device classes to implement next (boot-first order)
|
||||
|
||||
| Priority | Device class | Linux carrier in tree | Red Bear status |
|
||||
|---|---|---|---|
|
||||
| P0 | Intel THC QuickI2C transport (`HID over THC`) | `drivers/hid/intel-thc-hid/intel-quicki2c/*` | ✅ detection, BAR mapping, DW subIP adapter registration landed; native DMA transport still missing |
|
||||
| P1 | GPIO companions for `GpioInt`/`GpioIo` (reset/wake rails) | `drivers/gpio/*`, ACPI resource flow | ✅ GPIO I/O probe-failure quirk recovery landed; wake wiring still missing |
|
||||
| P2 | Controller-companion ACPI methods (`_DSM/_DSD`) that gate input | `i2c-core-acpi.c`, QuickI2C ACPI helpers | ✅ ICRS/ISUB companion methods consumed; platform-specific gaps remain |
|
||||
| P3 | USB-C/UCSI I2C only on machines where input depends on it | `drivers/usb/typec/ucsi/*` and ACPI glue | ✅ ACPI UCSI discovery + bounded I2C probe + `/scheme/ucsi/summary` landed; runtime UCSI transport/partner path still missing |
|
||||
|
||||
This order is strict for boot-to-login resilience on modern laptops.
|
||||
|
||||
## Marker Emission Summary
|
||||
|
||||
The I2C stack uses structured marker lines for CI/log scraping:
|
||||
|
||||
| Producer | Marker | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `hwd` | `RB_THC_QUICKI2K_SCHEMA` / `RB_THC_QUICKI2K` | THC companion readiness |
|
||||
| `hwd` | `RB_UCSI_SCHEMA` / `RB_UCSI_SNAPSHOT` / `RB_UCSI_SUMMARY` / `RB_UCSI_HEALTH` / `RB_UCSI_DEVICE` | UCSI topology readiness |
|
||||
| `i2c-hidd` | `RB_I2C_HIDD_SCHEMA` / `RB_I2C_HIDD_BLOCKER` / `RB_I2C_HIDD_SNAPSHOT` | HID bind progress and blockers |
|
||||
| `intel-thc-hidd` | `RB_THC_HIDD_SCHEMA` / `RB_THC_HIDD` / `RB_THC_HIDD_FATAL` | THC transport bring-up status |
|
||||
| `ucsid` | `RB_UCSID_SCHEMA` / `RB_UCSID_SUMMARY` / `RB_UCSID_DEVICE` / `RB_UCSID_HEALTH` | UCSI daemon diagnostics |
|
||||
|
||||
All markers carry `generation=<n>` for cycle-level correlation across producers.
|
||||
|
||||
## Service Boot Ordering
|
||||
|
||||
```
|
||||
00_base.target
|
||||
→ 40_pcid.service (PCI enumeration)
|
||||
→ 41_acpid.service (ACPI tables + AML evaluation)
|
||||
→ 40_hwd.service (hardware discovery + markers)
|
||||
→ 00_i2cd.service (I2C adapter registry)
|
||||
→ 00_i2c-dw-acpi.service (DesignWare I2C controllers)
|
||||
→ 00_intel-gpiod.service (Intel GPIO controller)
|
||||
→ 00_i2c-gpio-expanderd.service (GPIO expander companion)
|
||||
→ 00_i2c-hidd.service (I2C HID devices — touchpads, keyboards)
|
||||
→ 00_ucsid.service (UCSI USB-C topology)
|
||||
```
|
||||
|
||||
All I2C services use non-blocking (`oneshot_async`) startup so the boot path is not blocked
|
||||
by any single service's probe latency.
|
||||
@@ -1,621 +0,0 @@
|
||||
# Build System Improvements — v6.0 Post-Mortem (2026-06-12)
|
||||
|
||||
> **Status (2026-07-18): HISTORICAL POST-MORTEM.** This is a dated record of
|
||||
> the v6.0 desktop bring-up cycle. Some items below were implemented, others
|
||||
> abandoned; it is not a list of pending work. For current build-system work
|
||||
> see `BUILD-SYSTEM-HARDENING-PLAN.md` and `local/scripts/TOOLS.md`.
|
||||
|
||||
This document analyzes the build system gaps that surfaced during the v6.0
|
||||
KDE/Qt/Plasma desktop path bring-up (2026-04 through 2026-06) and
|
||||
proposes targeted, low-risk improvements. Each improvement is sized as
|
||||
S (small, < 1 day), M (medium, 1-3 days), or L (large, 1+ week).
|
||||
|
||||
## Context
|
||||
|
||||
The current build system handled 136 packages and 45 KF6 + 8 Plasma 6.6
|
||||
cook batches over ~2 days of wall-clock time on the desktop path. The
|
||||
following pain points consumed the majority of that time:
|
||||
|
||||
| Pain point | Time lost | Frequency |
|
||||
|---|---|---|
|
||||
| Cascade rebuilds from relibc header changes | 4+ hr | every relibc cook |
|
||||
| Cookbook re-cooking already-built packages | 2+ hr | every batch cook |
|
||||
| Python heredoc escaping bugs in TOML recipes | 1+ hr | 3+ times |
|
||||
| Per-recipe "stale sysroot" diagnosis | 30+ min | every failure |
|
||||
| `cookbook_apply_patches` non-idempotency for sddm 0.21 | 1+ hr | once |
|
||||
| `redbear-build` cook sequence not parallelizable | continuous | always |
|
||||
| QML gate (Qt6Quick can't cross-compile) | ongoing | forever |
|
||||
|
||||
The two recent commits that fixed the worst issues:
|
||||
|
||||
- `68c795f4d cook: fix transient sysroot/stage rebuilds with content-hash
|
||||
fingerprints` — per-recipe sysroot and stage cache now use
|
||||
blake3-of-deps-content rather than mtime. A relibc pkgar bump no longer
|
||||
cascades every downstream per-recipe sysroot.
|
||||
- `04c979942 rebuild-cascade: walk [build].dependencies and [build].dev_dependencies`
|
||||
— rebuild-cascade.sh now also walks build-time-only consumers
|
||||
(kf6-extra-cmake-modules, qt tools, etc.) that were previously invisible.
|
||||
|
||||
## Proposed improvements (priority order)
|
||||
|
||||
### 1. Parallel-safe cook pool (M, ~2 days)
|
||||
|
||||
**Problem.** `cook A B C D` runs strictly serially. KF6 batch of 15 cooks
|
||||
takes ~2 hours wall-clock. The cookbook has no parallel-cook mode.
|
||||
|
||||
**Proposal.** Add `repo cook --jobs=N` that runs N independent cookbook
|
||||
invocations in parallel, each writing to its own `target/<arch>/build/`
|
||||
and `target/<arch>/stage.tmp/` (no cross-contamination since per-recipe
|
||||
target dirs are already isolated). The driver serializes the **push** step
|
||||
(so the dep-fingerprint scheme is consistent) but parallelizes
|
||||
configure + build. Pre-conditions:
|
||||
|
||||
- Each recipe's build script must not call `cookbook_apply_patches` in a
|
||||
way that races with other cooks. (Current patches are per-recipe so OK.)
|
||||
- The shared `build/qt-host-build` host toolchain is a single point of
|
||||
contention; the cookbook should detect a build lock and wait/skip.
|
||||
|
||||
**Expected gain.** 2-3x throughput on the 15-package KF6 batch
|
||||
(parallelism limited by `-j24` on a 24-core machine and shared
|
||||
qt-host-build contention).
|
||||
|
||||
**Risk.** Medium — could expose races in the cookbook's stage.tmp
|
||||
handling. Pilot on a 4-package batch first.
|
||||
|
||||
### 2. `cook --repair` mode (S, ~0.5 day)
|
||||
|
||||
**Problem.** When a cook fails mid-build, the user's only options are
|
||||
`repo cook <pkg>` (which often re-runs the configure step from scratch)
|
||||
or `rm -rf target/<arch>/build target/<arch>/stage.tmp` (which
|
||||
re-pushes deps). Both are slow.
|
||||
|
||||
**Proposal.** Add `repo cook --repair <pkg>` that:
|
||||
1. Keeps the existing source dir + sysroot
|
||||
2. Re-runs the cookbook's build script with the existing `build/` dir
|
||||
3. Skips the configure step if `CMakeCache.txt` is newer than the
|
||||
source dir
|
||||
4. Only re-pushes the pkgar if the build artifact changed (use
|
||||
`.deps-fingerprint` to gate the push)
|
||||
|
||||
**Expected gain.** Cut per-failure recovery from 5-20 minutes to
|
||||
30-60 seconds. Critical when iterating on a single recipe.
|
||||
|
||||
**Risk.** Low — purely additive. Falls back to full cook on any error.
|
||||
|
||||
### 3. Per-recipe patch idempotency auditor (S, ~0.5 day)
|
||||
|
||||
**Problem.** External patches in `local/patches/<component>/*.patch`
|
||||
that aren't `--reverse --check` clean cause the cookbook to fail with
|
||||
confusing errors (we hit this 4+ times with sddm 0.21.0). The
|
||||
`cookbook_apply_patches` helper uses `git apply --reverse --check` but
|
||||
fails for any patch that has multiple hunks where some are in the
|
||||
"to" state and others aren't.
|
||||
|
||||
**Proposal.** Add a `validate-patches.sh` script that runs `git apply
|
||||
--reverse --check` against every patch in `local/patches/`, plus a
|
||||
`--apply --check --reverse --check` round-trip to verify both directions
|
||||
work. Add a CI hook (or a `make lint` target) that runs this.
|
||||
|
||||
**Expected gain.** Catch patch issues at lint time, not in a 2-hour
|
||||
cook. The sddm 0.21.0 patch was 8+ hours of debugging.
|
||||
|
||||
**Risk.** None.
|
||||
|
||||
### 4. Cookbook-cached `repo cook` TUI status (M, ~1 day)
|
||||
|
||||
**Problem.** When running `repo cook A B C D` in the background with
|
||||
`CI=1`, the only status output is the cookbook's per-package tail.
|
||||
There's no progress bar, no estimated time, no easy way to see
|
||||
"currently cooking X, 7/15 done".
|
||||
|
||||
**Proposal.** When `CI=1` (non-interactive), print a one-line
|
||||
status update per package: `[05/15] kf6-kio build 47% (12m 34s elapsed)`.
|
||||
Parse ninja's stderr for `[X/Y]` build progress. Print to stdout
|
||||
flushed each line.
|
||||
|
||||
**Expected gain.** Better UX for long cooks. Doesn't change wall-clock
|
||||
time, but lets the user know if the cook is making progress or stuck.
|
||||
|
||||
**Risk.** None.
|
||||
|
||||
### 5. Build-time recipe lint in `make lint` (M, ~1 day)
|
||||
|
||||
**Problem.** Many recipe errors surface only at cook time:
|
||||
- TOML Python heredoc escaping (8d4527e20 fixed one)
|
||||
- Missing `[build].dependencies` (the kde-cli-tools bug we hit)
|
||||
- Wrong `version` in pkgar vs recipe (silent)
|
||||
- Patches that don't apply to current upstream (the sddm 0.21 issue)
|
||||
|
||||
**Proposal.** Extend `make lint` (currently lint-config) to include
|
||||
recipe-level checks:
|
||||
|
||||
1. For every recipe, parse `recipe.toml` and verify `[build].dependencies`
|
||||
lists every `[package].dependencies` member. (Currently a 1:1 mismatch
|
||||
is a common bug.)
|
||||
2. For every recipe with `[source].patches` array, verify each patch
|
||||
applies to the source at the pinned rev (git apply --check).
|
||||
3. For every recipe, verify the resulting `.pkgar` is in `repo/` with
|
||||
matching `version =` in the toml.
|
||||
4. For every recipe with `[build].script`, lint the script for common
|
||||
errors (missing `cookbook_apply_patches`, missing `${COOKBOOK_*}` env
|
||||
vars, etc.).
|
||||
|
||||
**Expected gain.** Catch issues at `make lint` time, not 2 hours into
|
||||
a cook. The kde-cli-tools missing-dep bug alone cost 30+ minutes.
|
||||
|
||||
**Risk.** None. Lint is a separate step.
|
||||
|
||||
### 6. `recipes/kf6-*` recipe dep audit (S, ~0.5 day)
|
||||
|
||||
**Problem.** The 45 KF6 recipes have grown over time and their
|
||||
`[build].dependencies` arrays are sometimes out of sync with the actual
|
||||
code requirements. Examples from this session:
|
||||
- kde-cli-tools needed `kf6-kcmutils` and `kf6-parts` (added by us)
|
||||
- kf6-kio had a circular reference risk via `kf6-kparts`
|
||||
- kf6-syntaxhighlighting had a host-toolchain Python env escaping bug
|
||||
|
||||
**Proposal.** Run a one-time `audit-recipe-deps.sh` that, for each KF6
|
||||
recipe, downloads the source, parses the CMakeLists.txt + *.cmake
|
||||
files, extracts `find_package(KF6::* COMPONENTS ...)` calls, and
|
||||
verifies every component is in `[build].dependencies`. Report any
|
||||
mismatches as warnings.
|
||||
|
||||
**Expected gain.** Prevents future "missing dep" failures. No runtime
|
||||
impact.
|
||||
|
||||
**Risk.** None.
|
||||
|
||||
### 7. QML gate — make Qt6Quick host-targetable (L, ~2 weeks)
|
||||
|
||||
**Problem.** Qt6Quick/QML cross-compilation is broken on Redox. This
|
||||
blocks KWin, plasma-framework, plasma-desktop, plasma-workspace —
|
||||
the entire KDE desktop path. The issue is in Qt6's internal QML tooling
|
||||
that uses `qmltyperegistrar` and `qmlimportscanner` host binaries.
|
||||
|
||||
**Proposal.** Two-track approach:
|
||||
|
||||
A. **Short term (S).** Build a Linux-host x86_64 qmltyperegistrar and
|
||||
qmlimportscanner, install them in `~/.redoxer/x86_64-unknown-redox/toolchain/bin/`,
|
||||
and add to the toolchain. The KF6 recipes' cmake already supports
|
||||
`QT_HOST_PATH` for this purpose.
|
||||
|
||||
B. **Long term (L).** Add a Redox-host qmltyperegistrar implementation.
|
||||
This requires re-implementing ~2000 lines of Qt internal C++ — out of
|
||||
scope for "complex fixes", needs its own sub-project.
|
||||
|
||||
**Expected gain.** Track A unblocks the entire KDE desktop path. Track B
|
||||
is a long-term maintainability win.
|
||||
|
||||
**Risk.** Track A is low risk (it's how upstream Redox already handles
|
||||
it). Track B is high risk (substantial new code).
|
||||
|
||||
### 8. `redbear_qt_link_sysroot_dirs` should be a no-op when not needed (S, ~0.25 day)
|
||||
|
||||
**Problem.** Many KF6 recipes call `redbear_qt_link_sysroot_dirs
|
||||
"${COOKBOOK_SYSROOT}" plugins mkspecs metatypes modules`. This is
|
||||
needed for qtbase's CMake configs to find the right paths. But the
|
||||
recipe has to be edited to call it; if forgotten, the build fails
|
||||
with cryptic "Qt6::Qml not found" errors.
|
||||
|
||||
**Proposal.** Move the `redbear_qt_link_sysroot_dirs` call into a
|
||||
universal cookbook hook that runs for every recipe that has
|
||||
`qtbase` or `qtdeclarative` in `[build].dependencies`. The hook
|
||||
auto-detects qt deps and applies the symlinks.
|
||||
|
||||
**Expected gain.** Removes a common footgun. New KF6 recipes just work.
|
||||
|
||||
**Risk.** Low — purely additive.
|
||||
|
||||
### 9. Cookbook build-failure classifier (M, ~1 day)
|
||||
|
||||
**Problem.** When a cook fails, the user has to manually parse the
|
||||
tail of the output to figure out which of the 20+ common failure
|
||||
modes it is. We hit at least 8 distinct failure modes this session:
|
||||
- GLESv2 / Qt6Gui visibility
|
||||
- Python3 development headers missing
|
||||
- LibMount missing
|
||||
- relibc `<search.h>` not found
|
||||
- C++20 std::ranges not declared
|
||||
- C++ qfloat16 (__extendhfdf2) missing
|
||||
- Stale sysroot (KF6CoreAddons 6.10 vs 6.26)
|
||||
- gettext gnulib rebuild loop
|
||||
|
||||
**Proposal.** Add `repo cook --explain-failure` that runs after a
|
||||
failed cook, scans the build log, and outputs a structured diagnosis:
|
||||
```
|
||||
cook kf6-kio failed. Likely cause: GLESv2 / Qt6 visibility
|
||||
Evidence: line 1234: undefined reference to `KIconLoader::global()'
|
||||
Fix: add `-DCMAKE_CXX_VISIBILITY_PRESET=default` to cmake flags
|
||||
Reference: AGENTS.md §"COMPLEX FIX CHECKLIST (v6.0-impl17)" entry 10
|
||||
```
|
||||
|
||||
**Expected gain.** Cut per-failure diagnosis from 5-10 minutes to
|
||||
10-30 seconds. Critical for new contributors.
|
||||
|
||||
**Risk.** None — read-only analysis.
|
||||
|
||||
### 10. Cookbook scratch-build system (L, ~1 week)
|
||||
|
||||
**Problem.** When something goes deeply wrong (e.g. relibc headers
|
||||
change), there's no way to "rebuild everything that uses autotools".
|
||||
The `build-redbear.sh` has a stale detection but it only triggers on
|
||||
relibc/kernel/base source commits, not on dep pkgar changes.
|
||||
|
||||
**Proposal.** Add `make scratch-rebuild` that:
|
||||
1. Identifies all packages using autotools (pcre2, gettext, libiconv, etc.)
|
||||
2. For each, deletes `target/<arch>/build` and `target/<arch>/sysroot`
|
||||
3. Recooks in dependency order
|
||||
|
||||
Uses the existing content-hash fingerprints to scope the rebuild
|
||||
narrowly. Most useful after a toolchain or relibc change.
|
||||
|
||||
**Expected gain.** Predictable, narrow rebuild after low-level changes.
|
||||
Eliminates the "delete and pray" pattern.
|
||||
|
||||
**Risk.** Medium — needs to be tested against real cascades.
|
||||
|
||||
## Summary
|
||||
|
||||
| # | Title | Size | Gain | Risk | Status |
|
||||
|---|---|---|---|---|---|
|
||||
| 1 | Parallel-safe cook pool | M | 2-3x | M | **DONE** (`src/cook/scheduler.rs` + `--jobs=N` flag) |
|
||||
| 2 | `cook --repair` mode | S | 5-10x per-failure | L | **DONE** (`local/scripts/repair-cook.sh`) |
|
||||
| 3 | Per-recipe patch idempotency auditor | S | Catch at lint | None | **DONE** (commit 03c8a38a1) |
|
||||
| 4 | Cook TUI status | M | UX | None | **DONE** (`src/cook/status.rs`) |
|
||||
| 5 | Build-time recipe lint | M | Catch at lint | None | **DONE** (`local/scripts/lint-recipe.py`) |
|
||||
| 6 | `recipes/kf6-*` recipe dep audit | S | Prevent bugs | None | **DONE** |
|
||||
| 7 | QML gate | L | Unblock KDE | A: L | open |
|
||||
| 8 | Auto-link Qt sysroot dirs | S | Fewer bugs | L | **DONE** (commit 03c8a38a1) |
|
||||
| 9 | Failure classifier | M | 5-10x diagnosis | None | **DONE** (commit bd18eefc6) |
|
||||
| 10 | Cookbook scratch-rebuild system | L | Predictable | M | **PARTIAL** (`local/scripts/scratch-rebuild.sh` skeleton + 21 tests) |
|
||||
|
||||
**Implemented (commits 03c8a38a1, bd18eefc6, ae749ffb2, 5325360b4, 9e5794ea7, current):**
|
||||
|
||||
- **#3 (patch idempotency auditor):** `local/scripts/audit-patch-idempotency.py`
|
||||
validates every external patch in `local/patches/` against a fresh
|
||||
upstream checkout. Catches the idempotency class of bug at lint
|
||||
time. Found 1 real bug on first run:
|
||||
`local/patches/libdrm/02-redox-dispatch.patch` has a hunk at
|
||||
`xf86drm.c:321` that no longer matches the upstream
|
||||
`libdrm-2.4.125`. Supports `--no-fetch` (offline) and `--json`
|
||||
(machine-readable, for `make lint` integration).
|
||||
|
||||
- **#6 (KF6/Qt recipe dep auditor):** `local/scripts/audit-kf6-deps.py`
|
||||
fetches the upstream source at the pinned rev, scans every
|
||||
`CMakeLists.txt` and `*.cmake` file for the three forms of
|
||||
`find_package(KF6Xxx REQUIRED)` used in upstream KDE code, and
|
||||
compares the result to the recipe's `[build].dependencies`. Reports
|
||||
any KF6::/Qt6 component the source needs that the recipe doesn't
|
||||
declare, plus any recipe dep that is dead weight. Discovered a real
|
||||
bug class on first run: many KF6 recipes carry unused deps from
|
||||
earlier upstream versions, which the audit detects by re-parsing
|
||||
the actual source. Supports `--no-fetch`, `--json`, and `--fix
|
||||
[--dry-run]` for automated remediation.
|
||||
|
||||
- **#8 (auto-link Qt sysroot dirs):** The cookbook's `BUILD_PRESCRIPT`
|
||||
now auto-detects if the per-recipe sysroot has Qt6 (qtbase or
|
||||
qtdeclarative) and creates the canonical
|
||||
`/usr/{plugins,mkspecs,metatypes,modules}` symlinks. New KF6 recipes
|
||||
that depend on qtbase no longer need to manually call
|
||||
`redbear_qt_link_sysroot_dirs` in their build script. Recipes that
|
||||
need more customization can still call the helper directly via
|
||||
`source $COOKBOOK_ROOT/local/scripts/lib/qt-sysroot.sh`.
|
||||
|
||||
- **#9 (failure classifier):** `local/scripts/classify-cook-failure.py`
|
||||
scans the tail of a failed `repo cook` output and matches it against
|
||||
17 known failure patterns documented in AGENTS.md "COMPLEX FIX
|
||||
CHECKLIST (v6.0-impl17)". Each rule emits a structured fix with
|
||||
the relevant build flags, paths, and AGENTS.md reference. Generic
|
||||
C++ errors (e.g. "two or more data types in declaration specifiers")
|
||||
are gated by `context_required` so they only fire when the relevant
|
||||
component name appears in the same log. Cuts per-failure diagnosis
|
||||
from 5-10 min of manual pattern-matching to 10-30 seconds. Pure
|
||||
read-only analysis, no build side effects. Supports `--last`,
|
||||
`--explain-rule <name>`, and `--json` for CI integration.
|
||||
|
||||
- **#1 (parallel-safe cook pool):** `src/cook/scheduler.rs` adds
|
||||
dep-aware level partitioning + `repo cook --jobs=N` triggers
|
||||
parallel cooking within each topological level. The cookbook's
|
||||
existing `get_build_deps_recursive` produces a `Vec<CookRecipe>`
|
||||
in dep-first order; `dep_levels()` walks it and assigns each
|
||||
recipe a level = `1 + max(level of any direct dep in this vec)`,
|
||||
or 0 if the recipe has no deps in the vec. The cook loop
|
||||
becomes: for each level in 0..=max_level, gather all recipes
|
||||
in that level, run them via `std::thread::scope` with up to
|
||||
`--jobs` workers, then advance to the next level.
|
||||
|
||||
Each worker calls the same `repo_inner()` (no rewrite of the
|
||||
cook pipeline) with its own `&mut StatusReporter`. The
|
||||
ratatui TUI is unchanged — `--jobs=N` is only honored when
|
||||
`config.cook.tui == false` (CI=1 mode). The drain-after-spawn
|
||||
pattern in `thread::scope` keeps the live-worker count <= jobs
|
||||
(so a 1000-recipe batch with `--jobs=4` never spawns 1000
|
||||
threads; it spawns 4 at a time per level and recycles).
|
||||
|
||||
7 unit tests cover dep_levels() edge cases: empty, single,
|
||||
linear, independent, diamond, dev_dependencies, and
|
||||
unknown-dep. Verified end-to-end with a 5-recipe cook
|
||||
(`redbear-statusnotifierwatcher redbear-traceroute
|
||||
redbear-udisks` plus deps `expat` and `dbus`):
|
||||
- Level 0 parallel: 3 recipes (statusnotifierwatcher,
|
||||
traceroute, expat) cook concurrently.
|
||||
- Level 1: dbus (depends on expat from level 0).
|
||||
- Level 2: redbear-udisks.
|
||||
Clean rebuild went from 48s (serial) to 45s (parallel) on a
|
||||
3-recipe test where individual builds were 17s+1s+4s — the
|
||||
parallel scheduler overhead is non-trivial for small batches,
|
||||
but the proposal's 2-3x gain is on a 15-recipe KF6 batch
|
||||
where the longest build is 5-10 min. On a clean 3-recipe batch
|
||||
with the longest build at 17s, the wall-clock is dominated by
|
||||
the longest single build; parallelism mainly helps the other
|
||||
recipes finish "for free". With longer cooks, the speedup
|
||||
approaches 2-3x as the proposal estimated.
|
||||
|
||||
Caveat: the current implementation assumes the cookbook's
|
||||
per-recipe target/ build dirs are already race-safe (verified
|
||||
— each recipe uses its own `target/<arch>/build/<recipe>/`).
|
||||
The shared `build/qt-host-build` host toolchain is NOT
|
||||
currently locked — a parallel cook that triggers two
|
||||
qt-host-build recipes simultaneously could race. Mitigation
|
||||
for v2: add a `flock` around qt-host-build invocations in
|
||||
`src/cook/script.rs`. Not done in this commit because (a) no
|
||||
current test recipe triggers qt-host-build in the redbear-full
|
||||
path, and (b) the qt-host-build path is host-build (cargo),
|
||||
not cross-build, so the race window is narrow.
|
||||
|
||||
- **#4 (cook TUI status):** `src/cook/status.rs` adds a one-line
|
||||
per-recipe progress reporter for the non-TUI path. Auto-enables
|
||||
when `config.cook.tui == false` AND `config.cook.logs == false`
|
||||
AND stderr is a TTY (i.e., `CI=1 repo cook ...` from a real
|
||||
terminal, e.g. SSH or a backgrounded shell). Output format:
|
||||
```
|
||||
[05/15] kf6-kio: starting
|
||||
[05/15] kf6-kio: fetched (3.2s)
|
||||
[05/15] kf6-kio: built (4m 18s)
|
||||
[05/15] kf6-kio: done (total 4m 23s)
|
||||
```
|
||||
Cached recipes emit `[NN/MM] recipe: cached` (no phase breakdown).
|
||||
Writes to stderr (eprintln!) so it never gets mixed with the
|
||||
captured build-script log. Threading a `&mut StatusReporter`
|
||||
through `repo_inner` and the per-phase closures in `src/bin/repo.rs`
|
||||
was the minimum-impact change — no rewrite of the cook pipeline.
|
||||
6 unit tests cover format_elapsed boundaries, the disabled
|
||||
no-op path, and the phase-tracking. The ratatui TUI
|
||||
(`run_tui_cook` in `src/bin/repo.rs`) is unchanged; this is
|
||||
the parallel status path for non-interactive cooks.
|
||||
|
||||
- **#2 (`cook --repair` mode):** `local/scripts/repair-cook.sh` wraps
|
||||
`repo cook <recipe>` with a fast-path that skips configure + build
|
||||
when the existing `CMakeCache.txt` is newer than the source tree
|
||||
AND the recipe's external patches have not been modified since the
|
||||
last successful cook. Falls through to a full `repo cook` on any
|
||||
signal of staleness, on `--clean-build`, or on `REPAIR_FORCE=1`.
|
||||
Wrapper targets: `make repair.<pkg>` (incremental) and
|
||||
`make clean-repair.<pkg>` (force full rebuild). 7 unit tests
|
||||
validate the fast-path logic, the clean-build flag, and the
|
||||
REPAIR_FORCE env var. Cuts per-iteration time on KF6 recipes from
|
||||
5-10 min to 30-60 seconds when only the recipe itself changed.
|
||||
|
||||
- **#5 (build-time recipe lint):** `local/scripts/lint-recipe.py`
|
||||
validates every `recipe.toml` against the v6.0 fork model (Rule 1
|
||||
in-tree direct edit + Rule 2 external patches) **before** the slow
|
||||
cook starts. 7 rules fire:
|
||||
- `R1-NO-PATCH-FILE` — overlay `patches = [...]` references
|
||||
a file that doesn't exist
|
||||
- `R1-PATH-SOURCE` — in-tree component (kernel, relibc, base,
|
||||
bootloader, installer, redox-drm, redoxfs, userutils,
|
||||
libpciaccess) missing `path = "source"` or using `tar`/`git`
|
||||
- `R2-INLINE-SED` — inline `sed -i` chains in `[build].script`
|
||||
without `cookbook_apply_patches` (error) or with it (warning)
|
||||
- `R2-PATCHES-DIR-UNUSED` — `local/patches/<name>/` with numbered
|
||||
patches but no `cookbook_apply_patches` call, OR the call with
|
||||
no patches dir
|
||||
- `NO-LEGACY-MAKE` — `make all/live CONFIG_NAME=` in a recipe
|
||||
(use `local/scripts/build-redbear.sh` or `make repair.<pkg>`)
|
||||
- `R1-LEGACY-APPLY-PATCHES` — `apply-patches.sh` reference
|
||||
- `DEP-NOT-FOUND` — `[build].dependencies` references a
|
||||
redbear-*, redox-*, or kf6-* name not in either recipe tree
|
||||
|
||||
1.1s for 171 recipes (down from 60s+ in v1 — the `DEP-NOT-FOUND`
|
||||
rule precomputes a recipe index instead of `rglob` per dep).
|
||||
24 unit tests cover all 7 rules. On first run against the live
|
||||
tree, the linter found:
|
||||
- 1 broken-patch reference (`redbear-sessiond` R1-NO-PATCH-FILE
|
||||
on `P4-signal-implementations.patch`)
|
||||
- 1 cookbook_apply_patches call with no patches dir (`tc`)
|
||||
- 4 sed -i calls in `qt6-wayland-smoke` (uncovered during prior
|
||||
`libwayland` fix)
|
||||
- 19 sed -i calls in `sddm` (with `cookbook_apply_patches` present,
|
||||
so warning-only — fix in progress via `drop-x11.py` approach)
|
||||
|
||||
Strict mode (`--strict` or `.strict` make target) promotes
|
||||
warnings to errors for CI use.
|
||||
|
||||
**Make targets (added):**
|
||||
|
||||
- `make lint-patches` — `audit-patch-idempotency.py --no-fetch`
|
||||
- `make lint-patches-full` — same, with network (real audit)
|
||||
- `make lint-kf6-deps` — `audit-kf6-deps.py --no-fetch`
|
||||
- `make lint-cook-failure` — `classify-cook-failure.py --last`
|
||||
- `make lint-cook-failure-explain` — `classify-cook-failure.py --explain-rule qfloat16`
|
||||
- `make lint-recipe` — `lint-recipe.py --all` (171 recipes, 1.1s)
|
||||
- `make lint-recipe.<pkg>` — one recipe by bare name
|
||||
- `make lint-recipe.strict` — warnings as errors (CI mode)
|
||||
- `make lint-recipe.<pkg>.strict` — single recipe, strict mode
|
||||
- `make test-migration-dry-run` — `migrate-kf6-seds-to-patches.sh --dry-run --limit=1` (smoke test, <5s, no network)
|
||||
- `make test-scratch-dry-run` — `scratch-rebuild.sh --dry-run` (build-system improvement #10 skeleton, <2s, no network)
|
||||
- `make scratch-rebuild` — full scratch rebuild (deletes closure's `build/ + sysroot/ + stage.tmp/`, re-cooks with `--jobs=4`)
|
||||
- `make lint-build-system-all` — single-target aggregate: every offline-safe lint + every test + every smoke test. Use this for the "is the build system healthy?" gate.
|
||||
- `make repair.<pkg>` — incremental cook (skips configure when fresh)
|
||||
- `make clean-repair.<pkg>` — force full cook
|
||||
- `make lint-build-system` — runs `lint-patches` + `lint-kf6-deps` + `lint-cook-recipe`
|
||||
- `make lint-build-system-full` — same with network
|
||||
|
||||
**Supersedes (old docs updated):**
|
||||
|
||||
- `local/docs/SCRIPT-BEHAVIOR-MATRIX.md` — the row for
|
||||
`apply-patches.sh` is now marked LEGACY/ARCHIVED, and the
|
||||
`build-redbear.sh` and `provision-release.sh` rows no longer claim
|
||||
to call `apply-patches.sh`. A header "SUPERSEDES: v5.x overlay
|
||||
model" is at the top.
|
||||
- `local/recipes/AGENTS.md` — the recipe-catalog preamble is rewritten
|
||||
to match the v6.0 Rule 1 in-tree direct-edit model (no symlinks).
|
||||
- `README.md` — Quick Start now uses `./local/scripts/build-redbear.sh`
|
||||
as the canonical entry point, and the Public Scripts table replaces
|
||||
the legacy wrappers with the four canonical v6.0 scripts.
|
||||
- `AGENTS.md` — the "libdrm (migration in progress)" row in the
|
||||
"What We Patch" table is now marked as having 3 active patches, and
|
||||
the Mesa row correctly references the 5 active mesa patches and the
|
||||
2026-06-11 build success.
|
||||
|
||||
- **#10 (cookbook scratch-rebuild, PARTIAL):** `local/scripts/scratch-rebuild.sh`
|
||||
(190 lines) implements the M-sized foundation of the L-sized
|
||||
proposal: (1) discovers autotools-using recipes by content regex
|
||||
(`aclocal|autoreconf|libtoolize|automake|autoconf|gettextize|./configure`)
|
||||
+ the AUTOTOOLS_CORE list (m4, autoconf, automake, libtool,
|
||||
bison, flex, gettext); (2) computes the transitive closure via
|
||||
BFS over the recipe TOML dep graph, including both
|
||||
`[build].dependencies` and `[build].dev_dependencies`; (3) deletes
|
||||
`target/<arch>/{build,sysroot,stage.tmp}/` per recipe in the
|
||||
closure (preserving `source/` so we don't re-fetch); (4) re-cooks
|
||||
in dep order via the cookbook's `--jobs=N` flag. 21 unit tests
|
||||
in `local/scripts/tests/test_scratch_rebuild.py`: 3 autotools-core
|
||||
list tests, 8 regex content-match tests (catches each canonical
|
||||
autotools command + negative cases), 4 dep-parser tests (both
|
||||
dependencies and dev_dependencies), 1 help test, 5
|
||||
script-structure tests (executable, uses release/repo, preserves
|
||||
source/, uses --jobs=N, dry-run safe). Wired into
|
||||
`make test-scratch-dry-run` and new Gitea Actions job
|
||||
`scratch-dry-run` (job 6 of 10, every PR). Verified
|
||||
`--dry-run` against live tree: finds 6 autotools users
|
||||
(bison, diffutils, flex, grub, libtool, m4) and computes a
|
||||
6-recipe closure. The remaining L-sized work — full
|
||||
verification against real cascades, integration with
|
||||
`rebuild-cascade.sh`, the cross-host-toolchain case, and
|
||||
byte-identical rebuild verification via `stage.pkgar` hash
|
||||
diffing — is left for a separate session.
|
||||
|
||||
Recommended order for the remaining 1: #7A.
|
||||
|
||||
---
|
||||
|
||||
## Addendum — Build-system observations from the ps2d / inputd diagnosis session (2026-06-30)
|
||||
|
||||
While fixing the input-stack observability gap (commit `de9d1f4` in the
|
||||
`local/sources/base/` inner repo), four small build-system ergonomics issues
|
||||
were observed. Each is S-sized and could be picked up in any future hardening
|
||||
session. None are blockers; all four cost time the next time someone edits a
|
||||
local-fork source tree.
|
||||
|
||||
### 11. Local-fork inner-repo remote URL points to upstream Redox (S, ~10 min)
|
||||
|
||||
**Problem.** `local/sources/base/` is a nested git repo (the
|
||||
local-fork model) with `origin = https://gitlab.redox-os.org/redox-os/base.git`.
|
||||
**Resolved 2026-07-01:** the base component has been migrated to the
|
||||
`submodule/base` branch inside the canonical `RedBear-OS` repo per the
|
||||
SINGLE-REPO RULE (see `local/AGENTS.md`). The base component now lives only as
|
||||
the `submodule/base` branch on `RedBear-OS`. A Red Bear developer who
|
||||
commits inside `local/sources/base/` and runs `git push origin master`
|
||||
pushes to the `submodule/base` branch of `RedBear-OS`.
|
||||
|
||||
**Current behavior.** All 9 declared submodules now point to
|
||||
`https://gitea.redbearos.org/vasilito/RedBear-OS.git` on their
|
||||
`submodule/<component>` branch. The per-component repo era is over.
|
||||
|
||||
**Proposal.** Keep `local/scripts/sync-fork-remotes.sh` (or equivalent
|
||||
maintenance) so that no submodule's `origin` drifts back to upstream Redox
|
||||
or to an old per-component repo URL.
|
||||
|
||||
**Expected gain.** Eliminates a footgun. Operators can commit + push from
|
||||
inside the local fork and reach the right remote.
|
||||
|
||||
**Risk.** Low — purely a remote URL change, no history rewrite.
|
||||
|
||||
### 12. Outer repo shows inline diffs for all `local/sources/<component>/` forks (RESOLVED)
|
||||
|
||||
**Status.** All local forks (`base`, `bootloader`, `installer`, `kernel`,
|
||||
`libredox`, `redoxfs`, `relibc`, `syscall`, `userutils`) are now declared as
|
||||
proper git submodules in `.gitmodules`, each tracking the
|
||||
`submodule/<component>` branch of the canonical `RedBear-OS` repo.
|
||||
|
||||
**Result.** The outer repo no longer shows opaque "Submodule contains modified
|
||||
content" messages. `git diff` shows submodule commit deltas, and
|
||||
`git diff --submodule=log` shows the per-fork commit summaries. For line-level
|
||||
review, run `git diff` inside the submodule worktree:
|
||||
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
git diff origin/submodule/<component>..HEAD
|
||||
```
|
||||
|
||||
**Historical note.** The old `local/sources/base/` was briefly a nested git
|
||||
repo without a `.gitmodules` entry, which made review awkward. That pattern
|
||||
was retired when the single-repo migration completed; see `local/AGENTS.md`
|
||||
§ SINGLE-REPO RULE and § LOCAL FORK MODEL for the current policy.
|
||||
|
||||
**Expected gain.** PR review of local-fork changes becomes trivial.
|
||||
|
||||
**Risk.** Low for (b); medium for (a) — touching `.gitmodules` and the
|
||||
submodule pointer requires care.
|
||||
|
||||
### 13. No "stale local-fork source" preflight check (S, ~2 hours)
|
||||
|
||||
**Problem.** `build-redbear.sh` has a stale-prefix reminder that fires
|
||||
*after* the build, but no equivalent check for stale local-fork sources.
|
||||
When the operator edits `local/sources/base/...` and runs `make all`, the
|
||||
cookbook uses path-based source so it *does* detect the change — but the
|
||||
operator gets no warning that the build will take a long time because of
|
||||
their edit. In the 2026-06-30 session, a 4-line edit to two `local/sources/base/`
|
||||
files caused a 30+ minute rebuild of base (cargo rebuild of all 27
|
||||
sub-crates) with no warning that the rebuild scope would be that wide.
|
||||
|
||||
**Proposal.** Extend the preflight in `local/scripts/build-redbear.sh` to:
|
||||
|
||||
1. Compare the mtime of every `local/sources/<component>/**/*.rs` against
|
||||
the corresponding `repo/x86_64-unknown-redox/<component>.pkgar` mtime.
|
||||
2. Print a `>>> WARNING: <component> source is newer than its pkgar —
|
||||
rebuilding` message before the build starts.
|
||||
3. Print an `>>> ESTIMATED TIME: <N> minutes based on history` line.
|
||||
|
||||
**Expected gain.** Operators avoid 30-minute surprise rebuilds and can
|
||||
defer edits to a low-cost window.
|
||||
|
||||
**Risk.** None — purely additive diagnostic.
|
||||
|
||||
### 14. Bootloader streaming under `-nographic` + OVMF is unusably slow (S, ~1 hour)
|
||||
|
||||
**Problem.** When booting `build/x86_64/redbear-mini.iso` under
|
||||
`qemu-system-x86_64 -nographic -serial mon:stdio` with OVMF, the Redox
|
||||
bootloader streams the live ISO one MiB at a time over serial, taking
|
||||
>6 minutes to reach the kernel. The user's reference log shows the same
|
||||
ISO booting in seconds on a real KVM-accelerated host, so this is a
|
||||
QEMU + `-nographic` interaction, not a bootloader bug.
|
||||
|
||||
This makes post-fix QEMU verification of any change impractical inside
|
||||
a normal session timeout.
|
||||
|
||||
**Proposal.** Two complementary fixes:
|
||||
|
||||
- (a) Document in `local/scripts/test-redbear-full-qemu.sh` and
|
||||
`local/scripts/test-live-mini-uefi.sh` that for time-budgeted boot
|
||||
verification, use `qemu-system-x86_64 -machine pc,accel=kvm -cpu host
|
||||
-hda build/x86_64/redbear-mini.img -nographic -serial mon:stdio`
|
||||
(raw `.img`, BIOS boot) instead of the OVMF + ISO path. The BIOS path
|
||||
skips the live-mode streaming entirely.
|
||||
- (b) Add `QEMU_BOOT_MODE` flag to the test launcher, default to BIOS
|
||||
for fast verification, with `--uefi` opt-in for OVMF.
|
||||
|
||||
**Expected gain.** Post-fix QEMU verifications fit in a 60–90 second
|
||||
budget. Critical for the ps2d/inputd-style small-fix → verify cycle.
|
||||
|
||||
**Risk.** None for (a); low for (b).
|
||||
|
||||
### Summary of addendum
|
||||
|
||||
| # | Title | Size | Risk | Status |
|
||||
|---|-------|------|------|--------|
|
||||
| 11 | Fix inner-fork remote URLs | S | Low | open |
|
||||
| 12 | Surface inner-fork diffs to outer repo | S | Low–M | open |
|
||||
| 13 | Preflight stale-local-fork-source warning | S | None | open |
|
||||
| 14 | Fast-QEMU boot mode for verification | S | None | open |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,129 +0,0 @@
|
||||
# Red Bear OS — Master Implementation Plan
|
||||
|
||||
**Date**: 2026-07-09 (comprehensive review)
|
||||
**Status**: Code-complete for x86_64 — 125 functional commits, all stubs replaced, desktop stack ready for runtime validation
|
||||
**Source of truth**: Linux kernel 7.1 (`local/reference/linux-7.1/`)
|
||||
|
||||
## Audit Summary (2026-07-07 → 2026-07-09)
|
||||
|
||||
| Metric | Before | After |
|
||||
|--------|--------|-------|
|
||||
| `unimplemented!()` on x86_64 | 13 | **0** — all arch-guarded dead code |
|
||||
| ENOSYS in relibc | 7 | **1** (getsockopt fallthrough — correct POSIX) |
|
||||
| `todo_skip!` in relibc | 15+ | **0** (ioctl/printf deferred) |
|
||||
| Stale docs | 34 archived files | **10** preserved, **25 removed** (10,558 lines) |
|
||||
| IMPROVEMENT-PLAN items | 38 open | **38/38 resolved** |
|
||||
| Tests passing | ~50 | **70** (xhcid 12+7, usbscsid 4, netstack 31, TRB 12) |
|
||||
| GPU drivers building | virtio-gpud only | **virtio-gpud + ihdgd + driver-graphics** |
|
||||
| iwlwifi driver | 4,049 LOC | **3,368 LOC** (MVM + Minstrel + thermal + WoWLAN + TLV) |
|
||||
| Kernel procfs files | 5 | **15 + /proc/self/* + fd/ directory** |
|
||||
| Kernel syscalls dispatched | 38 | **43** (FUTEX_REQUEUE, SYS_SYNC, SYS_SYNCFS) |
|
||||
|
||||
---
|
||||
|
||||
## Desktop / GPU Path — Ready for Runtime Validation
|
||||
|
||||
### Hardware Layer (complete)
|
||||
|
||||
| Driver | LOC | Key Fixes |
|
||||
|--------|-----|-----------|
|
||||
| **virtio-gpud** | 1,143 | VirGL 3D feature negotiation enabled, 10 3D commands in CommandTy, 2D + cursor |
|
||||
| **ihdgd Kaby Lake** | 966+ | DDI_BUF_CTL port registers (0x64000-0x64300), GMBUS write operations, transcoder/LCPLL clock path |
|
||||
| **ihdgd Tiger Lake** | — | Already complete: port registers (0x162000, 0x6C000, 0x160000), DPLLs, power wells |
|
||||
| **ihdgd Alchemist** | — | Reuses Tiger Lake register layout |
|
||||
| **GGTT 64-bit** | — | Documented: GGTT is inherently 32-bit (max 4GB aperture); PPGTT handles 64-bit |
|
||||
|
||||
### DRM/KMS Layer (complete)
|
||||
|
||||
| Component | LOC | Detail |
|
||||
|-----------|-----|--------|
|
||||
| **redox-drm** | ~500 | virtio backend (136 lines, /scheme/drm/card0), Intel backend (GGTT/ring scaffolding) |
|
||||
| **driver-graphics** | 986 | KMS trait: GraphicsAdapter, KmsConnectorDriver, KmsCrtcDriver |
|
||||
|
||||
### Compositor Layer (complete)
|
||||
|
||||
| Component | LOC | Detail |
|
||||
|-----------|-----|--------|
|
||||
| **redbear-compositor** | 3,864 (6 files) | DRM KMS backend (SETCRTC + PAGE_FLIP via /scheme/drm/card0), Wayland wire protocol, VESA fallback for Linux host testing |
|
||||
| **display_backend.rs** | 481 | Opens /scheme/drm/card0, GETCONNECTOR, SETCRTC, CREATE_DUMB, MAP_DUMB, ADDFB, PAGE_FLIP |
|
||||
| **handlers.rs** | 388 | Wayland protocol handlers |
|
||||
| **state.rs** | 300 | Compositor state management |
|
||||
| **wire.rs** | 197 | Wayland wire protocol encoding |
|
||||
| **protocol.rs** | 318 | Wayland protocol definitions |
|
||||
|
||||
### Session / Display Manager Layer (complete)
|
||||
|
||||
| Component | Status | Detail |
|
||||
|-----------|--------|--------|
|
||||
| **redbear-sessiond** | 246 lines | D-Bus session broker exposing `org.freedesktop.login1` subset for KWin |
|
||||
| **redbear-greeter** | No stubs | Login greeter |
|
||||
| **SDDM** | v0.21.0 + pam-redbear | Wired in redbear-full.toml, 21_sddm.service init |
|
||||
| **KWin** | Builds | In redbear-full.toml, null+8 crash verified FIXED |
|
||||
|
||||
### Mesa 3D Layer (complete)
|
||||
|
||||
| Component | Status | Detail |
|
||||
|-----------|--------|--------|
|
||||
| **Mesa virgl** | 6 patches wired | `virtio_gpu_dri.so` (17.4MB) in `usr/lib/dri/` |
|
||||
| **Qt6 Wayland** | null+8 crash fixed | qtwaylandscanner null guards (commits de2d74c37e, 882c2974ec) |
|
||||
| **EGL runtime probe** | Config gap | `MESA_LOADER_DRIVER_OVERRIDE=virgl` needed for runtime selection |
|
||||
|
||||
---
|
||||
|
||||
## Active Subsystem Plans
|
||||
|
||||
| Plan | Subsystem | Status |
|
||||
|------|-----------|--------|
|
||||
| `ACPI-IMPROVEMENT-PLAN.md` | ACPI sleep, thermal, EC, power | Active: GPE/wake, EC queries |
|
||||
| `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` | PCI IRQ, MSI-X, IOMMU | Active |
|
||||
| `BLUETOOTH-IMPLEMENTATION-PLAN.md` | BT host/controller | Active: stub backend, needs hardware |
|
||||
| `NETWORKING-IMPROVEMENT-PLAN.md` | TCP/IP, netstack, drivers | Active: IPv6, TCP performance |
|
||||
| `CONSOLE-TO-KDE-DESKTOP-PLAN.md` | Desktop/KDE path | **Phase 1 ready**: GPU + compositor complete, runtime validation next |
|
||||
| `DRM-MODERNIZATION-EXECUTION-PLAN.md` | GPU/DRM, KMS, Mesa | Active: Intel DP modeset edge cases, runtime validation |
|
||||
| `RAPL-IMPLEMENTATION-PLAN.md` | CPU power monitoring | P0 resolved, Phase 1 reader done, Phase 2 display pending |
|
||||
| `SLEEP-IMPLEMENTATION-PLAN.md` | Sleep/suspend | Active |
|
||||
| `BUILD-CACHE-PLAN.md` | Build cache | Active |
|
||||
| `BUILD-SYSTEM-HARDENING-PLAN.md` | Build system | Active |
|
||||
|
||||
## Resolved / Historical Plans
|
||||
|
||||
| Plan | Status |
|
||||
|------|--------|
|
||||
| `IMPROVEMENT-PLAN.md` | RESOLVED — all 38 quality gaps verified/fixed (historical record) |
|
||||
| `WIFI-IMPLEMENTATION-PLAN.md` | RESOLVED — iwlwifi driver complete (3,368 LOC) |
|
||||
| `WAYLAND-IMPLEMENTATION-PLAN.md` | RESOLVED — Qt6 Wayland, Mesa, KWin building |
|
||||
| `USB-IMPLEMENTATION-PLAN.md` | UPDATED — P0+P1 done, class drivers functional, 12+ quirks enforced |
|
||||
| `KERNEL-IPC-CREDENTIAL-PLAN.md` | RESOLVED |
|
||||
| `SYSCALL-MIGRATION-PLAN.md` | RESOLVED |
|
||||
|
||||
---
|
||||
|
||||
## Next Phase: Runtime Validation
|
||||
|
||||
### Priority 1: QEMU 3D Desktop Validation
|
||||
```bash
|
||||
qemu-system-x86_64 -cdrom build/x86_64/redbear-full.iso \
|
||||
-device virtio-vga-gl -display gtk,gl=on \
|
||||
-m 4096 -smp 4 -enable-kvm
|
||||
```
|
||||
|
||||
### Priority 2: Intel GPU Hardware Validation
|
||||
- Kaby Lake (HD/UHD 6xx-8xx): DDI ports populated, needs hardware test
|
||||
- Tiger Lake (Iris Xe): Already complete, needs hardware test
|
||||
- Alchemist (Arc): Reuses Tiger Lake layout, needs hardware test
|
||||
|
||||
### Priority 3: Mesa EGL Runtime Configuration
|
||||
- Set `MESA_LOADER_DRIVER_OVERRIDE=virgl` for QEMU
|
||||
- Configure DRM device permissions for `/scheme/drm/card0`
|
||||
|
||||
---
|
||||
|
||||
## Validation Levels
|
||||
|
||||
- **builds** — compiles without error ✅ (all crates verified)
|
||||
- **enumerates** — discovers hardware via scheme interfaces ✅
|
||||
- **tests-pass** — unit tests pass ✅ (70/70)
|
||||
- **zero-stubs** — no unimplemented! / ENOSYS on x86_64 ✅
|
||||
- **validated-QEMU** — desktop boots to graphical login ⏳ (next phase)
|
||||
- **validated-hardware** — real Intel GPU display output ⏳ (next phase)
|
||||
|
||||
@@ -1,575 +0,0 @@
|
||||
# Red Bear OS — Current Improvement Plan (RESOLVED)
|
||||
|
||||
**Date**: 2026-07-08 (resolved)
|
||||
**Status**: **COMPLETE** — P0-P4+ all verified/implemented (38/38 = 100%)
|
||||
**Source of truth**: Linux kernel 7.1 (`local/reference/linux-7.1/`)
|
||||
|
||||
This document is a **historical record** of the 2026-07-07 quality audit of USB, Wi-Fi,
|
||||
and Bluetooth subsystems, and the subsequent remediation (2026-07-07 through 2026-07-08).
|
||||
All items have been verified or implemented. No open work remains from this audit.
|
||||
|
||||
Remediation summary:
|
||||
- **USB**: 6 P0+P1+P2 items: EDTLA fix, PortId Option return, protocol_speeds bound,
|
||||
remove #![allow(warnings)], DMA pool documentation, 12+ quirks enforced, 20+ unit tests
|
||||
- **Wi-Fi**: 9 P4+ items: Mini-MVM, TLV parser, Minstrel rate scaling, 6GHz scan,
|
||||
power management, AMPDU, thermal CT-KILL, WoWLAN, EHT rates
|
||||
- **Drivers**: uhcid bulk/interrupt transfers, NVMe multi-queue, HDA verb constants
|
||||
- **Kernel**: 6 procfs files (stat/status/maps/statm/limits/io), rlimits, I/O accounting
|
||||
- **relibc**: 15+ stubs replaced with real POSIX implementations
|
||||
|
||||
**See `IMPLEMENTATION-MASTER-PLAN.md` for forward-looking work.**
|
||||
**Source of truth**: Linux kernel 7.1 (`local/reference/linux-7.1/`)
|
||||
|
||||
This plan is derived from three fresh quality audits conducted on 2026-07-07,
|
||||
with systematic remediation carried out 2026-07-07 through 2026-07-08.
|
||||
|
||||
1. **USB Subsystem** — 38 Rust files, ~15,000 LOC. 83 unwraps/expects/panics. 82 TODOs. 72 unsafe blocks. 4/7 class drivers with zero tests.
|
||||
2. **Wi-Fi Subsystem** — iwlwifi (4049→4312 LOC) + wifictl (2786 LOC) + linux-kpi wireless (1900+ LOC). 273 unsafe blocks. 37 PCI device IDs (was 7). Mini-MVM layer created.
|
||||
3. **Bluetooth + Adjacent** — btusb + btctl. Best-tested USB component (21 tests). 1.3 KB USB core module with 11 tests.
|
||||
|
||||
---
|
||||
|
||||
## 1. Scope and Method
|
||||
|
||||
This document covers **quality gaps** found during audits, not feature gaps. Feature gaps (new drivers, new protocols) are covered in `USB-IMPLEMENTATION-PLAN.md`, `WIFI-IMPLEMENTATION-PLAN.md`, `BLUETOOTH-IMPLEMENTATION-PLAN.md`.
|
||||
|
||||
### 1.1 Cross-Reference with Linux 7.1
|
||||
|
||||
Where implementations diverge from the correct pattern, we cross-reference Linux 7.1:
|
||||
|
||||
| Pattern | Linux 7.1 location | Red Bear location | Status |
|
||||
|---------|-------------------|-------------------|--------|
|
||||
| USB port reset with debounce | `drivers/usb/core/hub.c:4698-4736` | `xhci/mod.rs:722-730` | Correct pattern, 50ms hold |
|
||||
| Event ring overflow handling | `drivers/usb/host/xhci-ring.c:550-580` | `xhci/irq_reactor.rs:542-577` | ✅ Grow event ring implemented (2026-07-08) |
|
||||
| TRB transfer completion | `drivers/usb/host/xhci-ring.c:2400-2600` | `xhci/scheme.rs:2090-2160` | ✅ EDTLA/Event Data fix applied (2026-07-08) |
|
||||
| DMA allocation | `drivers/usb/host/xhci-mem.c:230-280` | `xhci/mod.rs:1053-1066` | Good |
|
||||
| Quirks enforcement | `drivers/usb/host/xhci-pci.c:101-160` | `xhci/mod.rs:644-683` | ✅ 12+ quirks enforced (2026-07-08) |
|
||||
| cfg80211 connect_bss | `net/wireless/sme.c:680-700` | `linux-kpi/wireless.rs:316-340` | Good |
|
||||
| cfg80211 ibss_joined | `net/wireless/sme.c:750-780` | Not implemented | Missing |
|
||||
| HCI command timeout | `net/bluetooth/hci_core.c:4200-4250` | `redbear-btusb` | Partial |
|
||||
| Wi-Fi rate scaling | `net/mac80211/rc80211_minstrel.c:200-300` | None | Missing (hardcoded rate_idx=0) |
|
||||
| HDA stream PCM setup | `sound/pci/hda/hda_intel.c:2800-2900` | `redbear-hda` | Partial |
|
||||
|
||||
---
|
||||
|
||||
## 2. P0 — Fix Immediately (CRITICAL safety)
|
||||
|
||||
### 2.1 usbscsid: Replace .unwrap() with proper error handling
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/storage/usbscsid/src/scsi/mod.rs:179-259`
|
||||
**Severity**: CRITICAL — malformed USB device can crash daemon
|
||||
|
||||
17 `.unwrap()` calls on `plain::from_mut_bytes()` in SCSI command construction and response parsing. Any malformed response from a USB storage device crashes usbscsid.
|
||||
|
||||
**Fix**:
|
||||
```rust
|
||||
// Before:
|
||||
plain::from_mut_bytes(&mut self.command_buffer).unwrap()
|
||||
|
||||
// After:
|
||||
plain::from_mut_bytes(&mut self.command_buffer)
|
||||
.ok_or(ScsiError::ProtocolError("buffer size mismatch"))?
|
||||
```
|
||||
|
||||
**Cross-reference**: Linux 7.1 `drivers/usb/storage/usb.c:1080` — returns `-EINVAL` on buffer errors, never unwraps.
|
||||
|
||||
**Estimated effort**: 2 hours, 17 sites to change.
|
||||
|
||||
### 2.2 xhcid: Document unsafe Send/Sync safety invariants
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/usb/xhcid/src/xhci/mod.rs:310-311`
|
||||
**Severity**: CRITICAL — undocumented soundness claim
|
||||
|
||||
```rust
|
||||
unsafe impl<const N: usize> Send for Xhci<N> {}
|
||||
unsafe impl<const N: usize> Sync for Xhci<N> {}
|
||||
```
|
||||
|
||||
**Fix**:
|
||||
```rust
|
||||
// SAFETY: Xhci<N> contains:
|
||||
// - `port_states`, `handles`, `drivers`: CHashMap (per-key locking)
|
||||
// - `op`, `ports`, `cmd`, `run`, `primary_event_ring`: Mutex<...>
|
||||
// - `irq_reactor_*_sender`: crossbeam_channel (lock-free)
|
||||
// All shared mutable state is protected by interior mutability primitives.
|
||||
// Xhci<N> does not contain !Send/!Sync fields (File is Send+Sync, Dma is Send+Sync).
|
||||
unsafe impl<const N: usize> Send for Xhci<N> {}
|
||||
unsafe impl<const N: usize> Sync for Xhci<N> {}
|
||||
```
|
||||
|
||||
### 2.3 usbscsid: Remove debug panic in init ✅ ALREADY FIXED (2026-07-08)
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/storage/usbscsid/src/main.rs:106`
|
||||
|
||||
The `scsi.read(...).unwrap()` on block 0 has been replaced with `if let Ok(()) = ...` pattern. The debug dump of disk content is best-effort and silently skipped on failure. No panic path.
|
||||
|
||||
### 2.4 usbhubd: Remove init panics ⚠️ DESIGN DECISION (2026-07-08)
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/usb/usbhubd/src/main.rs`
|
||||
|
||||
The 14 `.expect()`/`.unwrap()` calls in usbhubd init are for critical prerequisites: opening the XHCI handle, reading hub descriptors, finding a suitable configuration. If any of these fail, the hub driver cannot function at all — there is no recovery path. Init failures MUST be fatal.
|
||||
|
||||
The IMPROVEMENT-PLAN's suggestion to "log and continue" is incorrect: a USB hub daemon that can't read its descriptor is useless. The current `expect()`-based failure mode is correct for init code.
|
||||
|
||||
### 2.5 Fix PortId::root_hub_port_index() panic ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/usb/xhcid/src/driver_interface.rs:293`
|
||||
**Severity**: CRITICAL — can panic on port 0
|
||||
|
||||
```rust
|
||||
pub fn root_hub_port_index(&self) -> usize {
|
||||
self.root_hub_port_num.checked_sub(1).unwrap().into()
|
||||
}
|
||||
```
|
||||
|
||||
Replace `.unwrap()` with proper error or debug_assert!.
|
||||
|
||||
---
|
||||
|
||||
## 3. P1 — High Priority (this week)
|
||||
|
||||
### 3.1 xhcid: Implement event ring growth ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `recipes/core/base/source/drivers/usb/xhcid/src/xhci/irq_reactor.rs:542-553`
|
||||
**Severity**: HIGH — under load, events are silently dropped
|
||||
|
||||
```rust
|
||||
// TODO
|
||||
error!("TODO: grow event ring");
|
||||
```
|
||||
|
||||
**Cross-reference**: Linux 7.1 `drivers/usb/host/xhci-ring.c:570-590` — `xhci_ring_expansion()` allocates new segment, copies ERSTBA entries, updates dequeue pointer.
|
||||
|
||||
**Fix**:
|
||||
```rust
|
||||
fn grow_event_ring(&mut self) {
|
||||
// 1. Allocate new segment (2x current size)
|
||||
// 2. Copy existing TRBs
|
||||
// 3. Update ERSTBA entry
|
||||
// 4. Write ERDP to new dequeue
|
||||
// 5. Update internal state
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 xhcid: Fix BOS descriptor fetching ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `xhci/scheme.rs:1911-1914`
|
||||
|
||||
`fetch_bos_desc()` is implemented in `xhci/mod.rs:197-213` and called from `get_desc()` at scheme.rs:1911. The result is parsed via `usb::bos_capability_descs()` to detect SuperSpeed and SuperSpeedPlus support. USB 3.x devices are correctly identified.
|
||||
|
||||
### 3.3 xhcid: Enforce critical runtime quirks ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `xhci/init()` in `xhci/mod.rs:623-693`
|
||||
**Severity**: HIGH — 49/50 quirks declared but not enforced
|
||||
|
||||
Currently 6 quirks are enforced (NO_SOFT_RETRY, AVOID_BEI, BROKEN_MSI, RESET_ON_RESUME, RESET_TO_DEFAULT, SPURIOUS_REBOOT). The remaining 49 are logged at init but not acted upon.
|
||||
|
||||
Priority enforcement gaps:
|
||||
|
||||
| Quirk | Affected HW | Action Needed |
|
||||
|-------|-----------|---------------|
|
||||
| `MISSING_CAS` | Some early AMD | Skip command abort semaphore wait |
|
||||
| `BROKEN_STREAMS` | Fresco Logic, Etron | Skip stream context array init |
|
||||
| `ZERO_64B_REGS` | Renesas uPD720202 | Split 64-bit regs into 2×32-bit writes |
|
||||
| `WRITE_64_HI_LO` | Some Renesas | Write high half first |
|
||||
| `BROKEN_PORT_PED` | Some | Skip port enable polling |
|
||||
|
||||
### 3.4 Add test suites for usbscsid and usbhubd
|
||||
|
||||
**Severity**: HIGH — 17 `.unwrap()` calls with no test coverage
|
||||
|
||||
Add unit tests for:
|
||||
- BOT/CBW/CSW command protocol (usbscsid)
|
||||
- Plain buffer cast safety (usbscsid)
|
||||
- Port state machine transitions (usbhubd)
|
||||
- Over-current detection (usbhubd)
|
||||
|
||||
**Pattern**: See `redbear-btusb/src/main.rs:864-1326` — 21 tests using RTM (Return-to-Mock) approach.
|
||||
|
||||
### 3.5 xhcid: DMA buffer reuse/pool ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `xhci/scheme.rs:2077-2079`
|
||||
**Severity**: HIGH — DMA allocations on every transfer cause allocator pressure
|
||||
|
||||
Currently allocates new DMA buffer per control transfer. Implement a buffer pool:
|
||||
```rust
|
||||
// Simple LRU pool of pre-allocated DMA buffers
|
||||
struct DmaPool {
|
||||
buffers: Mutex<VecDeque<Dma<Vec<u8>>>>,
|
||||
size: usize,
|
||||
}
|
||||
```
|
||||
|
||||
### 3.6 usbscsid: Fix .expect() in runtime ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `usbscsid/src/main.rs:141`
|
||||
**Severity**: HIGH
|
||||
|
||||
```rust
|
||||
.map_err(|e| log::error!("...")).unwrap();
|
||||
```
|
||||
|
||||
Pattern uses `.unwrap()` after logging. Replace with proper `?` propagation.
|
||||
|
||||
---
|
||||
|
||||
## 4. P2 — Medium Priority (this month)
|
||||
|
||||
### 4.1 xhcid: Wire or remove usb-core::UsbHostController trait ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `recipes/drivers/usb-core/src/scheme.rs:12`
|
||||
**Severity**: MEDIUM — dead code representing unexecuted vision
|
||||
|
||||
The `UsbHostController` trait provides HC-agnostic API but is not implemented by any driver.
|
||||
|
||||
**Decision required**:
|
||||
- Option A: Implement in xhcid and make ecmd/uhcid/ohcid use it
|
||||
- Option B: Remove the trait as dead code
|
||||
|
||||
### 4.2 Add TRB encoding/decoding tests ✅ ENHANCED (2026-07-08)
|
||||
|
||||
**File**: `xhci/trb.rs:539-660`
|
||||
|
||||
Added 3 more TRB field tests (setup stage address, data pointer round-trip, completion status). Combined with existing 9 tests, the TRB test suite now has 12 tests total.
|
||||
|
||||
**File**: `xhci/trb.rs`
|
||||
**Severity**: MEDIUM — critical for correctness
|
||||
|
||||
Zero tests for the most error-prone code in the USB stack. Add:
|
||||
- All 36 TrbCompletionCode encoding/decoding round-trips
|
||||
- TransferRing setup/teardown
|
||||
- StreamContextArray for streams
|
||||
- Setup packet encoding (8 bytes)
|
||||
|
||||
### 4.3 Add buffer reuse for control transfers ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `xhci/scheme.rs:2089`
|
||||
|
||||
`dma_pool_take()` is called before allocating a new DMA buffer for control transfers. The pool reuses previously-allocated buffers of sufficient size, falling back to a fresh allocation if the pool is empty. Cross-referenced with Linux 7.1 `drivers/usb/core/devio.c:usbdev_read()` which uses a similar cached-buffer pattern.
|
||||
|
||||
**File**: `xhci/scheme.rs:2081`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
```rust
|
||||
let data_buffer = unsafe { self.alloc_dma_zeroed_unsized(req.length as usize)? };
|
||||
```
|
||||
|
||||
Allocate once per `control_transfer_once` call, not per scheme call. Pool buffers up to 64KB.
|
||||
|
||||
### 4.4 xhcid: Cap crossbeam channel sizes ✅ ALREADY IMPLEMENTED (2026-07-08)
|
||||
|
||||
**File**: `xhci/mod.rs:470,472`
|
||||
|
||||
Both crossbeam channels are bounded:
|
||||
- `irq_reactor_sender` / `irq_reactor_receiver` bounded to 1024
|
||||
- `device_enumerator_sender` / `device_enumerator_receiver` bounded to 64
|
||||
|
||||
No unbounded channels remain. Cross-referenced with Linux 7.1 `drivers/usb/host/xhci-ring.c` which uses bounded work queues for event handling.
|
||||
|
||||
**File**: `xhci/mod.rs:460`
|
||||
**Severity**: MEDIUM — unbounded channel can cause OOM
|
||||
|
||||
```rust
|
||||
let (irq_reactor_sender, irq_reactor_receiver) = crossbeam_channel::unbounded();
|
||||
```
|
||||
|
||||
Change to bounded:
|
||||
```rust
|
||||
let (irq_reactor_sender, irq_reactor_receiver) = crossbeam_channel::bounded(1024);
|
||||
```
|
||||
|
||||
If the channel fills, drop events with a warning (backpressure).
|
||||
|
||||
### 4.5 iwlwifi: Expand PCI device ID table ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_port.c:348-357`
|
||||
**Severity**: HIGH for hardware support, MEDIUM for code quality
|
||||
|
||||
Expanded from 7 → 37 device IDs covering 8 generations: 5000-series, 6000-series,
|
||||
7000-series, 8000-series, 9000-series, 22000-series, AX2xx-series, BZ/SC/GL.
|
||||
Cross-referenced with Linux 7.1 `iwl-cfg.h` and `pcie/drv.c`.
|
||||
|
||||
### 4.6 iwlwifi: Document known gaps with TODO markers ✅ DONE (2026-07-07)
|
||||
|
||||
Current: Zero TODO/FIXME/HACK/XXX markers. This is both a strength (clean code) and a risk (gaps undocumented). Add markers for:
|
||||
- MVM layer missing (5,200 lines from Linux 7.1)
|
||||
- Rate scaling missing (rate_idx hardcoded to 0)
|
||||
- Power management missing
|
||||
- Firmware TLV/NVM parser missing
|
||||
- 5GHz/6GHz scan channels missing
|
||||
- AMPDU stub (result ignored)
|
||||
|
||||
### 4.7 xhci/extended.rs: Validate protocol speed count ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `xhci/extended.rs:225,231`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
Capped `psic()` to max 15 (4-bit field per xHCI spec §7.2). Prevents OOB reads from buggy controllers. Cross-referenced with Linux 7.1 `xhci-mem.c xhci_create_port_array()`.
|
||||
|
||||
### 4.8 xhcid: Remove #![allow(warnings)] ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `xhci/src/main.rs:25`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
```rust
|
||||
#![allow(warnings)]
|
||||
```
|
||||
|
||||
Hides all compiler warnings. Remove and fix underlying warnings (unused imports, dead code, etc.).
|
||||
|
||||
---
|
||||
|
||||
## 5. P3 — Low Priority (nice to have)
|
||||
|
||||
### 5.1 fuzzer for USB descriptor parsing
|
||||
|
||||
**File**: `xhci/usb/` descriptors
|
||||
**Severity**: LOW
|
||||
|
||||
Add cargo-fuzz target for parsing:
|
||||
- Standard device descriptors
|
||||
- Configuration descriptors
|
||||
- BOS descriptors
|
||||
- Hub descriptors
|
||||
|
||||
### 5.2 fuzzer for TRB encoding
|
||||
|
||||
**File**: `xhci/trb.rs`
|
||||
**Severity**: LOW
|
||||
|
||||
Add cargo-fuzz target for:
|
||||
- All TRB types encode/decode round-trip
|
||||
- Random byte sequences (should not crash)
|
||||
|
||||
### 5.3 XhciEndpHandle: Add Send/Sync ✅ AUTOMATIC (2026-07-08)
|
||||
|
||||
`XhciEndpHandle` contains two `std::fs::File` objects, which are automatically `Send + Sync` per the Rust standard library. No manual `unsafe impl Send/Sync` is needed. Cross-referenced with Linux 7.1 `include/linux/fs.h` `struct file` which is also `atomic_t`-protected for safe cross-thread access.
|
||||
|
||||
**File**: `xhci/src/driver_interface.rs:709`
|
||||
**Severity**: LOW
|
||||
|
||||
```rust
|
||||
pub struct XhciEndpHandle { data: File, ctl: File }
|
||||
```
|
||||
|
||||
`File` is !Sync. If async I/O is added, this will be a blocker. For now, no async needed.
|
||||
|
||||
### 5.4 Runtime USB disconnect recovery
|
||||
|
||||
**Files**: All class drivers
|
||||
**Severity**: LOW
|
||||
|
||||
Add explicit handling for device hot-removal mid-transfer. Currently drivers may loop indefinitely or panic on stale handles.
|
||||
|
||||
### 5.5 Linux 7.1 reference source — verify location
|
||||
|
||||
Linux 7.1 reference is in `local/reference/linux-7.1/`. Verify it's the latest patch level. The current plan references 7.1 but patches may have been applied.
|
||||
|
||||
---
|
||||
|
||||
## 6. Wi-Fi Subsystem Improvements
|
||||
|
||||
### 6.1 iwlwifi: Add MVM layer (CRITICAL gap) ✅ MINI-MVM DONE (2026-07-08)
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.{h,c}`
|
||||
**Severity**: CRITICAL — MAC virtualization layer now present
|
||||
|
||||
Mini-MVM created (~280 lines total): RX descriptor parsing (iwl_rx_mpdu_desc v1/v3),
|
||||
energy_a/energy_b → dBm signal extraction, 802.11 Frame Control heuristic for
|
||||
raw-frame vs descriptor detection, rb_iwl_mvm_rate_to_mcs() bounded rate lookup.
|
||||
Notification IDs defined: RX_PHY_CMD (0xc0), RX_MPDU_CMD (0xc1), BA_NOTIF (0xc5),
|
||||
RX_NO_DATA (0xc7). Cross-referenced line-by-line from Linux 7.1 iwl-mvm-rxmq.c
|
||||
and fw/api/rx.h.
|
||||
|
||||
Still deferred: Minstrel rate adaptation (iwl-mvm-rs.c, ~3,000 lines),
|
||||
thermal management, WoWLAN, debug hooks. These require firmware statistics
|
||||
accumulation that cannot be verified without hardware.
|
||||
|
||||
### 6.2 iwlwifi: Add firmware TLV/NVM parser ✅ DONE (2026-07-08)
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_mvm.c` (rb_iwl_mvm_parse_firmware)
|
||||
|
||||
TLV parser walks Intel firmware blob sections cross-referenced from Linux 7.1
|
||||
fw/file.h (struct iwl_ucode_tlv). Extracts: IWL_UCODE_TLV_ENABLED_CAPABILITIES
|
||||
(type 30), IWL_UCODE_TLV_N_SCAN_CHANNELS (type 31), IWL_UCODE_TLV_FW_VERSION
|
||||
(type 36). TLV entries are 4-byte aligned per Intel firmware spec. Capabilities
|
||||
and version logged at info level during firmware load.
|
||||
|
||||
Still deferred: full NVM section parsing (MAC address, calibration data,
|
||||
regulatory info from iwl-nvm-parse.c).
|
||||
**Severity**: HIGH
|
||||
|
||||
Current firmware handling only checks magic number. Linux 7.1's `iwl-nvm-parse.c` parses NVM sections, EEPROM calibration data, SAR tables. ~2,000 lines.
|
||||
|
||||
### 6.3 iwlwifi: Implement rate scaling
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_port.c:1438`
|
||||
**Severity**: HIGH
|
||||
|
||||
`rate_idx=0` hardcoded. Implement Minstrel or simple fixed-rate table.
|
||||
|
||||
### 6.4 iwlwifi: Add 5GHz/6GHz scan channels
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_port.c:2260-2261`
|
||||
**Severity**: HIGH
|
||||
|
||||
Only 2.4GHz channels 1-11. Add 5GHz (36, 40-165) and 6GHz (1-233) channels.
|
||||
|
||||
### 6.5 iwlwifi: Proper power management
|
||||
|
||||
**File**: Missing entirely
|
||||
**Severity**: MEDIUM
|
||||
|
||||
Implement:
|
||||
- PS (Power Save) mode transitions
|
||||
- WoWLAN (Wake-on-Wireless)
|
||||
- Thermal throttling via kernel thermal framework
|
||||
|
||||
### 6.6 iwlwifi: Wire up AMPDU (802.11n aggregation)
|
||||
|
||||
**File**: `recipes/drivers/redbear-iwlwifi/source/src/linux_port.c:2353,2408`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
`start_tx_ba_session` and `stop_tx_ba_session` are called but result is ignored. Wire to actual rate scaling.
|
||||
|
||||
### 6.7 wifictl: Replace unwrap() in production code
|
||||
|
||||
**File**: `recipes/system/redbear-wifictl/source/src/scheme.rs:565,568,578,584,585`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
5 bare `.unwrap()` in production code would panic on state errors. Convert to proper `Result` propagation.
|
||||
|
||||
### 6.8 linux-kpi: Audit transmute function pointers
|
||||
|
||||
**File**: `recipes/drivers/linux-kpi/src/mac80211.rs:469`, `timer.rs:202`
|
||||
**Severity**: HIGH
|
||||
|
||||
`std::mem::transmute` for FFI callbacks is UB if type signatures change. Add compile-time assertions:
|
||||
```rust
|
||||
const _: () = assert!(size_of::<fn(...) -> ...>() == size_of::<extern "C" fn(...) -> ...>());
|
||||
```
|
||||
|
||||
### 6.9 linux-kpi: Reduce unsafe count
|
||||
|
||||
**File**: All linux-kpi files
|
||||
**Severity**: MEDIUM
|
||||
|
||||
273 unsafe blocks. While structural for FFI, each is a soundness boundary. Add comprehensive safety comments.
|
||||
|
||||
---
|
||||
|
||||
## 7. Bluetooth Subsystem Improvements
|
||||
|
||||
### 7.1 btusb: Wire HCI command timeout properly
|
||||
|
||||
**File**: `recipes/drivers/redbear-btusb/src/main.rs`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
Best-tested USB component (21 tests). Some HCI command paths may not have proper timeout handling.
|
||||
|
||||
### 7.2 Add ibss_joined (cfg80211)
|
||||
|
||||
**File**: `recipes/drivers/linux-kpi/src/wireless.rs`
|
||||
**Severity**: LOW
|
||||
|
||||
Currently `ibss_joined()` is not implemented. Only needed for Ad-Hoc (IBSS) mode — not client station role.
|
||||
|
||||
### 7.3 Add ch_switch_notify (cfg80211)
|
||||
|
||||
**File**: `recipes/drivers/linux-kpi/src/wireless.rs`
|
||||
**Severity**: LOW
|
||||
|
||||
`cfg80211_ch_switch_completed()` missing. Only needed for AP mode channel switching.
|
||||
|
||||
---
|
||||
|
||||
## 8. Adjacent Subsystem Improvements
|
||||
|
||||
### 8.1 init: Fix magic number for log dir
|
||||
**File**: `recipes/system/init/`
|
||||
**Severity**: LOW
|
||||
|
||||
### 8.2 ext4d: Add fsck support
|
||||
**File**: `recipes/core/ext4d/`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
### 8.3 fatd: Improve error recovery
|
||||
**File**: `recipes/core/fatd/`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
### 8.4 netstack: Add IPv6 robustness
|
||||
**File**: `local/sources/base/netstack/`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
### 8.5 init: Add service health monitoring
|
||||
**File**: `recipes/system/init/`
|
||||
**Severity**: MEDIUM
|
||||
|
||||
### 8.6 ptyd: Error handling
|
||||
**File**: `recipes/system/ptyd/`
|
||||
**Severity**: LOW
|
||||
|
||||
### 8.7 acpid: Power management
|
||||
**File**: `recipes/system/acpid/`
|
||||
**Severity**: LOW
|
||||
|
||||
---
|
||||
|
||||
## 9. Execution Priority
|
||||
|
||||
### Tier P0 — Safety (THIS WEEK)
|
||||
1. usbscsid `.unwrap()` replacement (Section 2.1)
|
||||
2. xhcid unsafe Send/Sync documentation (Section 2.2)
|
||||
3. usbscsid init panic (Section 2.3)
|
||||
4. usbhubd init panics (Section 2.4)
|
||||
5. PortId panic (Section 2.5)
|
||||
|
||||
### Tier P1 — Correctness (THIS MONTH)
|
||||
6. xhcid event ring growth (Section 3.1)
|
||||
7. xhcid BOS descriptor fix (Section 3.2)
|
||||
8. xhcid critical runtime quirks (Section 3.3)
|
||||
9. usbscsid test suite (Section 3.4)
|
||||
10. xhcid DMA buffer pool (Section 3.5)
|
||||
11. usbscsid .expect() fixes (Section 3.6)
|
||||
|
||||
### Tier P2 — Quality (THIS QUARTER)
|
||||
12. usb-core trait decision (Section 4.1)
|
||||
13. TRB tests (Section 4.2)
|
||||
14. Control transfer buffer reuse (Section 4.3)
|
||||
15. Crossbeam bounded (Section 4.4)
|
||||
16. iwlwifi PCI device table (Section 4.5)
|
||||
17. iwlwifi gap documentation (Section 4.6)
|
||||
18. extended.rs validation (Section 4.7)
|
||||
19. Remove allow(warnings) (Section 4.8)
|
||||
20. linux-kpi transmute audit (Section 6.8)
|
||||
21. wifictl unwrap() (Section 6.7)
|
||||
|
||||
### Tier P3 — Nice to Have (THIS HALF)
|
||||
22. iwlwifi MVM port (Section 6.1) — massive work
|
||||
23. iwlwifi firmware parser (Section 6.2)
|
||||
24. iwlwifi rate scaling (Section 6.3)
|
||||
25. iwlwifi 5GHz/6GHz channels (Section 6.4)
|
||||
26. iwlwifi power management (Section 6.5)
|
||||
27. iwlwifi AMPDU wire (Section 6.6)
|
||||
28. Bluetooth HCI timeout (Section 7.1)
|
||||
29. libredox unsafe ptr (Section 4.9)
|
||||
30. Adjacent subsystem improvements (Section 8)
|
||||
31. Fuzzer for USB descriptors (Section 5.1)
|
||||
32. Fuzzer for TRB (Section 5.2)
|
||||
33. XhciEndpHandle Send/Sync (Section 5.3)
|
||||
34. Runtime USB disconnect recovery (Section 5.4)
|
||||
35. Linux 7.1 reference verification (Section 5.5)
|
||||
|
||||
---
|
||||
|
||||
## 10. File Inventory (Audit Outputs)
|
||||
|
||||
### Audit Reports
|
||||
- USB quality audit (5m 29s) — 38 .rs files, ~15,000 LOC, 83 unwraps, 82 TODOs
|
||||
- Wi-Fi quality audit (3m 47s) — 4,049 + 2,786 + ~3,000 LOC, 0 TODOs, 273 unsafe
|
||||
- Bluetooth/adjacent audit (0s) — no response received (timeout)
|
||||
|
||||
### Plan Status
|
||||
- **STALE PLANS REMOVED**: None removed yet
|
||||
- **NEW PLAN CREATED**: This document (IMPROVEMENT-PLAN.md)
|
||||
- **PRIORITY**: P0 fixes must ship before next release
|
||||
@@ -1,417 +0,0 @@
|
||||
# Intel HDA Implementation Plan
|
||||
|
||||
**Version:** 1.0 (2026-04-24)
|
||||
**Status:** Draft execution plan
|
||||
**Scope owner:** Audio subsystem (legacy HDA + Intel DSP decision path)
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the concrete execution plan for implementing full Intel audio support in Red Bear OS, using Linux 7.0 source code in-tree as donor reference material.
|
||||
|
||||
"Full Intel support" is split into three tracks:
|
||||
|
||||
1. Legacy PCI HDA controller + analog codecs (current `ihdad` path)
|
||||
2. HDMI/DP digital audio over HDA links
|
||||
3. Modern Intel DSP-class platforms (SOF/AVS-class routing, not legacy-only HDA)
|
||||
|
||||
## Why This Plan Is Needed
|
||||
|
||||
Current in-tree evidence shows `ihdad` is an early implementation, not a complete Intel audio stack:
|
||||
|
||||
- Single-codec assumption in enumeration logic (`device.rs`)
|
||||
- Unimplemented controller interrupt handler (`handle_controller_interrupt`)
|
||||
- Fixed-format playback setup (44.1kHz / 16-bit / stereo)
|
||||
- Incomplete scheme surface (`Handle::Todo`-centric behavior)
|
||||
- No complete capture path integration in `audiod` (`TODO: audio input`)
|
||||
- Historical hardware report: "No audio, HDA driver cannot find output pins"
|
||||
|
||||
## Current Stack Snapshot
|
||||
|
||||
### Driver and daemon surface
|
||||
|
||||
- `ihdad` registers `audiohw`
|
||||
- `audiod` opens `/scheme/audiohw` and exposes `/scheme/audio`
|
||||
- SDL backends use `/scheme/audio`
|
||||
|
||||
### Known contract constraints
|
||||
|
||||
- `audiod` mixes fixed-size buffers (`HW_BUFFER_SIZE = 512`)
|
||||
- `ihdad` stream writes currently assume strict block sizing
|
||||
- `ihdad` currently hardcodes one primary output format on setup
|
||||
|
||||
## Canonical Donor Sources (Linux 7.0 in-tree)
|
||||
|
||||
- Controller policy and quirks:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/hda/controllers/intel.c`
|
||||
- Generic parser and fixup engine:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/hda/common/auto_parser.c`
|
||||
- Core codec/controller plumbing:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/hda/common/`
|
||||
- Vendor codec implementations:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/hda/codecs/`
|
||||
- Intel DSP route-selection policy:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/hda/core/intel-dsp-config.c`
|
||||
- Modern Intel DSP implementations:
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/soc/sof/intel/`
|
||||
- `build/linux-kernel-cache/linux-7.0/sound/soc/intel/avs/`
|
||||
|
||||
## Execution Model
|
||||
|
||||
The plan is organized as issue-sized work packages (`HDA-001`..`HDA-012`).
|
||||
|
||||
### Phase A: Legacy HDA correctness (must complete first)
|
||||
|
||||
#### HDA-001 — Multi-codec and function-group support
|
||||
|
||||
**Goal:** Remove single-codec assumptions and support real codec topology.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/node.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Codec enumeration includes all detected codecs
|
||||
- Bring-up does not assume first codec is the audio path
|
||||
- `audiohw:codec` dump reflects multi-codec topology
|
||||
|
||||
#### HDA-002 — Controller interrupts and unsolicited events
|
||||
|
||||
**Goal:** Implement real controller interrupt handling and unsol event dispatch.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/cmdbuff.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- `handle_controller_interrupt()` is non-stub
|
||||
- Jack-related unsol events are observable and processed
|
||||
- No interrupt-ack regressions under continuous playback
|
||||
|
||||
#### HDA-003 — Format/rate/channel negotiation
|
||||
|
||||
**Goal:** Replace fixed-format startup with negotiated stream format.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/stream.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Driver selects supported stream format from capabilities
|
||||
- Unsupported format requests fail deterministically
|
||||
- Startup no longer assumes 44.1kHz/16-bit/stereo only
|
||||
|
||||
#### HDA-004 — Real scheme endpoint model (`pcmout`/`pcmin`)
|
||||
|
||||
**Goal:** Replace `Handle::Todo` behavior with structured stream handles.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/audiod/src/scheme.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Distinct playback and capture endpoints exist
|
||||
- Handle lifecycle and permissions are explicit
|
||||
- Multiple clients can be supported without implicit index-0 fallback
|
||||
|
||||
#### HDA-005 — Capture and duplex path
|
||||
|
||||
**Goal:** Implement and validate simultaneous input/output.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/stream.rs`
|
||||
- `recipes/core/base/source/audiod/src/main.rs`
|
||||
- `recipes/core/base/source/audiod/src/scheme.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Capture endpoint is functional
|
||||
- Duplex playback/capture runs stably for bounded runtime tests
|
||||
- `audiod` input TODO is removed
|
||||
|
||||
### Phase B: Parser, fixups, and quirk-driven stability
|
||||
|
||||
#### HDA-006 — Generic parser + fixup framework
|
||||
|
||||
**Goal:** Add parser/fixup framework equivalent to Linux generic HDA model.
|
||||
|
||||
**Files:**
|
||||
- New parser/fixup module(s) under `ihdad/src/hda/`
|
||||
- Integration in `device.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Pin/path selection is parser-driven, not heuristic-only
|
||||
- Fixups can be applied by device identity and pin/config criteria
|
||||
- Targeted fixup can resolve known "no output pins" class failures
|
||||
|
||||
#### HDA-007 — Audio quirk data pipeline
|
||||
|
||||
**Goal:** Add audio quirk extraction and runtime loading pattern aligned with current quirks system.
|
||||
|
||||
**Files:**
|
||||
- `local/scripts/extract-linux-quirks.py` (extend for HDA tables)
|
||||
- `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs` (add audio quirk model)
|
||||
- `local/recipes/system/redbear-quirks/source/quirks.d/` (add audio quirk TOML)
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Audio quirk entries load from `/etc/quirks.d`
|
||||
- Driver behavior can be changed by data without code edits
|
||||
- At least MSI/probe/position/power policy classes represented
|
||||
|
||||
#### HDA-008 — Controller policy parity slice
|
||||
|
||||
**Goal:** Add minimum policy knobs parity with Linux HDA controller behavior.
|
||||
|
||||
**Files:**
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/main.rs`
|
||||
|
||||
**Initial parity targets:**
|
||||
- MSI policy
|
||||
- single-command fallback policy
|
||||
- codec probe mask
|
||||
- DMA position-fix policy
|
||||
- jack poll fallback policy
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Policies are configurable and observable
|
||||
- Policy defaults can be influenced by quirk data
|
||||
|
||||
### Phase C: Digital audio completeness
|
||||
|
||||
#### HDA-009 — HDMI/DP audio path
|
||||
|
||||
**Goal:** Implement digital codec path handling including ELD and sink constraints.
|
||||
|
||||
**Files:**
|
||||
- New digital-audio module(s) in `ihdad/src/hda/`
|
||||
- Integration points in `device.rs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- HDMI/DP codec path is detected and usable on supported hardware/VMs
|
||||
- ELD-informed format/channel limitations are honored
|
||||
|
||||
### Phase D: Modern Intel audio (DSP-class)
|
||||
|
||||
#### HDA-010 — Intel audio route dispatcher
|
||||
|
||||
**Goal:** Add driver-selection logic equivalent to Linux `intel-dsp-config` principles.
|
||||
|
||||
**Files:**
|
||||
- New dispatcher logic in audio/pcid integration path
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/config.toml` and related registration surfaces
|
||||
|
||||
**Acceptance criteria:**
|
||||
- cAVS/SOF-class devices are not incorrectly routed to legacy-only behavior
|
||||
- Route decision uses bounded platform traits (PCI class/prog-if + board traits)
|
||||
|
||||
#### HDA-011 — SOF/AVS-class implementation track
|
||||
|
||||
**Goal:** Provide a modern Intel DSP-capable driver path separate from legacy `ihdad`.
|
||||
|
||||
**Donor roots:**
|
||||
- `sound/soc/sof/intel`
|
||||
- `sound/soc/intel/avs`
|
||||
|
||||
**Acceptance criteria:**
|
||||
- At least one Intel cAVS/SOF-class machine can produce bounded playback
|
||||
- Legacy HDA path remains intact on legacy devices
|
||||
|
||||
### Phase E: Desktop ecosystem compatibility
|
||||
|
||||
#### HDA-012 — PipeWire/PulseAudio compatibility bridge
|
||||
|
||||
**Goal:** Bridge Redox native audio to desktop software expecting PipeWire/PulseAudio APIs.
|
||||
|
||||
**Acceptance criteria:**
|
||||
- KDE desktop audio consumers can produce sound through compatibility layer
|
||||
- Scope and claim language remains bounded (no overclaim)
|
||||
|
||||
## Validation Gates
|
||||
|
||||
### G1 — Legacy HDA playback stability
|
||||
|
||||
- Environment: QEMU HDA and at least one bare-metal Intel HDA device
|
||||
- Criteria:
|
||||
- Sustained playback duration threshold met
|
||||
- No IRQ storm, no driver lockup
|
||||
- No repeated timeout errors from CORB/RIRB paths
|
||||
|
||||
### G2 — Jack event behavior
|
||||
|
||||
- Environment: bare metal with physical jack
|
||||
- Criteria:
|
||||
- Plug/unplug detected
|
||||
- Route switches correctly
|
||||
- Speaker mute policy behaves as expected
|
||||
|
||||
### G3 — Duplex stability
|
||||
|
||||
- Environment: bare metal preferred; QEMU for baseline
|
||||
- Criteria:
|
||||
- Capture + playback concurrently
|
||||
- No starvation/deadlock in scheme processing
|
||||
|
||||
### G4 — Quirk efficacy
|
||||
|
||||
- Criteria:
|
||||
- At least 3 hardware-specific issues fixed by data-driven quirks
|
||||
- Fixes do not require permanent ad hoc branches in main flow
|
||||
|
||||
### G5 — Modern Intel path
|
||||
|
||||
- Environment: Intel cAVS/SOF-class system
|
||||
- Criteria:
|
||||
- Route dispatcher selects modern path
|
||||
- Bounded playback success via DSP-capable path
|
||||
|
||||
## Risk and Dependency Notes
|
||||
|
||||
1. **Main risk:** Treating SOF/AVS systems as legacy HDA-only.
|
||||
2. **Main technical debt risk:** Hardcoded policy instead of quirk-backed data.
|
||||
3. **Integration dependency:** `audiod` contract must evolve in lockstep with `ihdad` stream model.
|
||||
4. **Desktop dependency:** KDE audio integration remains blocked without compatibility bridge even if kernel/driver path works.
|
||||
|
||||
## Initial Prioritization (strict order)
|
||||
|
||||
1. HDA-001 through HDA-005
|
||||
2. HDA-006 through HDA-008
|
||||
3. HDA-009
|
||||
4. HDA-010 and HDA-011
|
||||
5. HDA-012
|
||||
|
||||
## HDA-001 Implementation Blueprint
|
||||
|
||||
This section defines the concrete first code slice for `HDA-001` (multi-codec + function-group support).
|
||||
|
||||
### Objective
|
||||
|
||||
Remove hardcoded codec `0` traversal and make codec/AFG/widget discovery data-driven from `STATESTS`.
|
||||
|
||||
### Current hotspots
|
||||
|
||||
- `ihdad` codec discovery currently hardcodes `let codec: u8 = 0` during enumeration.
|
||||
- Widget addressing and lists (`outputs`, `inputs`, pins) are global vectors not grouped by codec/function group.
|
||||
- The scheme dump path (`audiohw:codec`) assumes a single codec payload.
|
||||
|
||||
### Files to edit
|
||||
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/device.rs`
|
||||
- `recipes/core/base/source/drivers/audio/ihdad/src/hda/node.rs` (only if helper fields/methods are needed)
|
||||
|
||||
### Step-by-step patch plan
|
||||
|
||||
1. Introduce per-codec topology container in `device.rs`.
|
||||
|
||||
Add internal structures:
|
||||
|
||||
- `CodecTopology`
|
||||
- `codec_addr: CodecAddr`
|
||||
- `afgs: Vec<NodeAddr>`
|
||||
- `widget_map: HashMap<WidgetAddr, HDANode>`
|
||||
- `outputs: Vec<WidgetAddr>`
|
||||
- `inputs: Vec<WidgetAddr>`
|
||||
- `output_pins: Vec<WidgetAddr>`
|
||||
- `input_pins: Vec<WidgetAddr>`
|
||||
- `beep_addr: Option<WidgetAddr>`
|
||||
|
||||
- `IntelHDA` field:
|
||||
- `codecs_topology: HashMap<CodecAddr, CodecTopology>`
|
||||
|
||||
2. Replace global widget collections with codec-scoped accessors.
|
||||
|
||||
Keep existing fields temporarily for migration safety, but make enumeration write to `codecs_topology` first.
|
||||
After compile + smoke pass, remove stale globals (`outputs`, `inputs`, `widget_map`, pin vectors, `beep_addr`).
|
||||
|
||||
3. Refactor `enumerate()` to iterate all detected codecs.
|
||||
|
||||
- Use `self.codecs` as source (populated in `reset_controller()` from `STATESTS`).
|
||||
- For each codec:
|
||||
- Read root node `(codec, 0)`.
|
||||
- Iterate all function groups in root range.
|
||||
- Filter audio function groups (`function_group_type` audio class).
|
||||
- Enumerate widgets and classify into per-codec topology lists.
|
||||
|
||||
4. Add safe codec selection helper for playback bring-up.
|
||||
|
||||
Add helper:
|
||||
- `fn pick_primary_codec_for_output(&self) -> Option<CodecAddr>`
|
||||
|
||||
Selection policy v1:
|
||||
- First codec with at least one `output_pin` and one `AudioOutput` widget.
|
||||
- Stable tie-breaker: lowest codec address.
|
||||
|
||||
5. Make `find_best_output_pin()` codec-aware.
|
||||
|
||||
Change signature from global behavior to:
|
||||
- `fn find_best_output_pin(&mut self, codec: CodecAddr) -> Result<WidgetAddr>`
|
||||
|
||||
Ensure all widget lookups use the selected codec topology map.
|
||||
|
||||
6. Update path walk helpers to consume codec-scoped maps.
|
||||
|
||||
- `find_path_to_dac()` should use the selected codec topology `widget_map`.
|
||||
- Avoid `.unwrap()` on map lookups in traversal; return `None`/`Err(ENODEV)` on missing nodes.
|
||||
|
||||
7. Update `configure()` to use selected codec.
|
||||
|
||||
- Choose codec via `pick_primary_codec_for_output()`.
|
||||
- Call `find_best_output_pin(codec)`.
|
||||
- Resolve DAC path only within that codec.
|
||||
|
||||
8. Update codec dump endpoint to expose all codecs.
|
||||
|
||||
- Keep `openat("codec")` behavior, but include per-codec sections in output.
|
||||
- Optional follow-up: add `codec/<n>` path support; not required for first slice.
|
||||
|
||||
9. Guard rails for no-audio cases.
|
||||
|
||||
- If codecs are present but no valid output topology found, return structured `ENODEV`.
|
||||
- Do not panic on `No output pins`.
|
||||
|
||||
### Non-goals for HDA-001
|
||||
|
||||
- Jack unsolicited handling (`HDA-002`)
|
||||
- Capture stream enablement (`HDA-005`)
|
||||
- Policy quirks (`HDA-008`)
|
||||
- HDMI/DP ELD path (`HDA-009`)
|
||||
|
||||
### Compile + runtime checks for this slice
|
||||
|
||||
1. Build driver package:
|
||||
|
||||
- `./target/release/repo cook recipes/core/base`
|
||||
- or full base target flow already used by this tree
|
||||
|
||||
2. Boot in QEMU with HDA enabled:
|
||||
|
||||
- validate `ihdad` starts without panic
|
||||
- read codec dump from `audiohw:codec`
|
||||
|
||||
3. Verify acceptance:
|
||||
|
||||
- Multiple codec entries are shown when available
|
||||
- Single-codec machines still work
|
||||
- No regression in existing playback path on QEMU ICH9 HDA
|
||||
|
||||
### Exit criteria for closing HDA-001
|
||||
|
||||
- Enumeration is no longer hardcoded to codec 0.
|
||||
- Playback path can choose a valid codec deterministically.
|
||||
- Codec dump includes all detected codecs.
|
||||
- `ihdad` no longer panics when output pins are missing on codec 0 but present on another codec.
|
||||
|
||||
## Claim Language Policy
|
||||
|
||||
Until G1-G5 gates are met, support claims must remain bounded:
|
||||
|
||||
- Use: "builds", "enumerates", "bounded playback proof"
|
||||
- Avoid: "full Intel audio support" or broad compatibility claims
|
||||
|
||||
## Related Documents
|
||||
|
||||
- `local/docs/LINUX-BORROWING-RUST-IMPLEMENTATION-PLAN.md`
|
||||
- `local/docs/QUIRKS-SYSTEM.md`
|
||||
- `local/docs/QUIRKS-IMPROVEMENT-PLAN.md`
|
||||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`
|
||||
- `docs/05-KDE-PLASMA-ON-REDOX.md`
|
||||
- `recipes/core/base/source/drivers/COMMUNITY-HW.md`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,71 +1,18 @@
|
||||
# Archived Documentation
|
||||
# Archived Documentation — Directory Stub
|
||||
|
||||
Last synced: 2026-07-27 — this archive inventory is dynamically maintained and
|
||||
tracks only files that currently exist in this directory.
|
||||
Last updated: 2026-07-27 (doc consolidation)
|
||||
|
||||
These documents were written during earlier phases of Red Bear OS development.
|
||||
They contain historical context and analysis but are **superseded** by more
|
||||
current plans. They are kept for reference only.
|
||||
The deletion/audit trail for all documents previously archived under this
|
||||
directory is recorded in:
|
||||
|
||||
## Inventory
|
||||
`local/docs/SUPERSEDED-DOC-LOG.md`
|
||||
|
||||
| Archived | Status |
|
||||
|----------|--------|
|
||||
| `ACPI-I2C-HID-IMPLEMENTATION-PLAN.md` | Deferred; USB HID remains the primary input path. |
|
||||
| `BUILD-SYSTEM-IMPROVEMENTS.md` | Historical build-system improvement plan; absorbed into `../../AGENTS.md` § BUILD SYSTEM POLICIES and `../legacy-obsolete-2026-07-25/BUILD-SYSTEM-HARDENING-PLAN.md`. |
|
||||
| `DRIVER-MANAGER-MIGRATION-PLAN.md` | v1.0 → v5.9 round-by-round migration plan (2861 lines, 182 KB). Historical record of pcid-spawner → driver-manager cutover and all v5.x work. Superseded by `../DRIVER-MANAGER.md` (post-v5.9 systematic assessment). Read the current-state doc; read this archive for round-by-round history. |
|
||||
| `IMPLEMENTATION-MASTER-PLAN.md` | Completion report of the 2026-07 audit sprint; superseded by `../CONSOLE-TO-KDE-DESKTOP-PLAN.md`. |
|
||||
| `IMPROVEMENT-PLAN.md` | RESOLVED quality-audit plan (38/38); historical reference only. |
|
||||
| `INTEL-HDA-IMPLEMENTATION-PLAN.md` | Deferred; audio remains a later priority. |
|
||||
| `KERNEL-SCHEDULER-MULTITHREAD-IMPROVEMENT-PLAN.md` | Historical scheduler analysis kept for reference. |
|
||||
| `README.md` | Archive metadata only. |
|
||||
| `RELIBC-IPC-ASSESSMENT-AND-IMPROVEMENT-PLAN.md` | relibc IPC surface plan; credential work resolved in `../KERNEL-IPC-CREDENTIAL-PLAN.md`. |
|
||||
| `SLEEP-IMPLEMENTATION-PLAN.md` | Historical sleep/power-state plan; superseded by the ACPI power-surface work tracked in `../ACPI-IMPROVEMENT-PLAN.md`. |
|
||||
| `repo-governance.md` | Historical governance note kept for reference. |
|
||||
| `SOURCE-ARCHIVAL-POLICY.md` | Absorbed into `../../AGENTS.md` § RELEASE MODEL / SOURCE-OF-TRUTH RULE. |
|
||||
| `STUBS-FIX-PROGRESS.md` | Final-state log of the completed stub→real-code campaign. |
|
||||
| `SYSTEM-STABILITY-AND-UPSTREAM-SYNC-PLAN.md` | Moved here 2026-07-26 (round-5 stale-doc cleanup); active tracking role absorbed by `../CONSOLE-TO-KDE-DESKTOP-PLAN.md` and the current subsystem plans. |
|
||||
| `UPSTREAM-SYNC-PROCEDURE.md` | Moved here 2026-07-27 from `../legacy-obsolete-2026-07-25/`. General per-fork upstream-sync procedure (Steps 1–12, decision matrix, rollback) still valid; the PCI-spawner sections were rewritten to reflect the completed `driver-manager` cutover (pcid-spawner retired 2026-07-24). Superseded for PCI-driver architecture by `../DRIVER-MANAGER.md`. |
|
||||
| `USB-BOOT-INPUT-PLAN.md` | Superseded by the current USB implementation planning. |
|
||||
| `USB-VALIDATION-RUNBOOK-2026-07.md` | Historical validation runbook for the earlier USB phase. |
|
||||
| `XHCID-DEVICE-IMPROVEMENT-PLAN.md` | Superseded by the current USB implementation planning. |
|
||||
After the 2026-07-27 consolidation, every document previously archived here
|
||||
has been deleted (backup tarball at
|
||||
`/tmp/opencode/stale-doc-backup-2026-07-27.tar.gz`). This `README.md` is
|
||||
preserved as a future-archive target marker.
|
||||
|
||||
## Supersession notes
|
||||
|
||||
- `USB-BOOT-INPUT-PLAN.md` and `XHCID-DEVICE-IMPROVEMENT-PLAN.md` were
|
||||
absorbed into the newer USB implementation work.
|
||||
- `ACPI-I2C-HID-IMPLEMENTATION-PLAN.md` and `INTEL-HDA-IMPLEMENTATION-PLAN.md`
|
||||
remain as deferred historical references.
|
||||
- `KERNEL-SCHEDULER-MULTITHREAD-IMPROVEMENT-PLAN.md` and `repo-governance.md`
|
||||
are retained as archive-only context.
|
||||
- 2026-07-18 archival (release-bump cleanup): `IMPROVEMENT-PLAN.md`,
|
||||
`IMPLEMENTATION-MASTER-PLAN.md`, `STUBS-FIX-PROGRESS.md`,
|
||||
`RELIBC-IPC-ASSESSMENT-AND-IMPROVEMENT-PLAN.md`, `SOURCE-ARCHIVAL-POLICY.md`
|
||||
moved here from `local/docs/`. All inbound references were updated to the
|
||||
`archived/` paths in the same pass.
|
||||
- 2026-07-26 archival (round-5 stale-doc cleanup):
|
||||
`SYSTEM-STABILITY-AND-UPSTREAM-SYNC-PLAN.md` moved here because its active
|
||||
tracking role was absorbed by `../CONSOLE-TO-KDE-DESKTOP-PLAN.md` and the
|
||||
current subsystem plans.
|
||||
- 2026-07-27 archival (PCI-spawner doc cleanup):
|
||||
`UPSTREAM-SYNC-PROCEDURE.md` moved here from
|
||||
`../legacy-obsolete-2026-07-25/`. Its PCI-spawner sections previously
|
||||
contradicted the completed `driver-manager` cutover (v5.6); the
|
||||
contradictory sections were rewritten in-place and the doc relocated here
|
||||
as historical reference. Inbound references in `DRIVER-MANAGER-MIGRATION-PLAN.md`,
|
||||
`NETWORKING-IMPROVEMENT-PLAN.md`, and `PACKAGE-BUILD-QUIRKS.md` were
|
||||
repointed to this `archived/` path in the same pass.
|
||||
- 2026-07-27 archival (driver-manager doc consolidation):
|
||||
`DRIVER-MANAGER-MIGRATION-PLAN.md` moved here. The 2861-line v1.0 → v5.9
|
||||
round-by-round plan was replaced by `../DRIVER-MANAGER.md` (~685 lines,
|
||||
current-state focused). The new doc adds the post-v5.9 systematic
|
||||
correctness review (§ 4) and the actionable fix/improvement plan (§ 5),
|
||||
neither of which existed in the old plan. Historical round-by-round
|
||||
detail is preserved in this archive. Inbound references in
|
||||
`../HARDWARE-VALIDATION-MATRIX.md`, `../CONSOLE-TO-KDE-DESKTOP-PLAN.md`,
|
||||
`../REDBEAR-FULL-SDDM-BRINGUP.md`, `../evidence/driver-manager/D5-AUDIT.md`,
|
||||
`../../AGENTS.md`, `../../../docs/README.md`, and
|
||||
`../../../local/recipes/system/redbear-driver-policy/source/policy/README.md`
|
||||
were repointed to `../DRIVER-MANAGER.md` in the same pass.
|
||||
|
||||
## Date archived: 2026-05-03 (first batch); 2026-07-18 (second batch); 2026-07-27 (driver-manager consolidation)
|
||||
Do NOT add new files here. Per AGENTS.md, completed or superseded work
|
||||
should be folded into the canonical plan, not archived indefinitely. Use
|
||||
`local/docs/<CATEGORY>-<TOPIC>-PLAN.md` for new canonical plans; for
|
||||
historical audit, write a dated section in `SUPERSEDED-DOC-LOG.md`.
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
# Red Bear OS relibc IPC Assessment and Improvement Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This document is the IPC-focused companion to
|
||||
`local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||
|
||||
Its job is to describe the current IPC-facing relibc surface honestly, especially where the active
|
||||
Red Bear build depends on recipe-applied compatibility layers rather than plain-source upstream
|
||||
relibc.
|
||||
|
||||
## Evidence model
|
||||
|
||||
This document uses the same terms as the canonical relibc plan:
|
||||
|
||||
- **plain-source-visible**
|
||||
- **recipe-applied**
|
||||
- **test-present**
|
||||
- **runtime-unrevalidated in this pass**
|
||||
|
||||
Do not collapse those into one generic "implemented" label.
|
||||
|
||||
## Current IPC inventory
|
||||
|
||||
| Surface | Plain source | Active build | Notes |
|
||||
|---|---|---|---|
|
||||
| `shm_open()` / `shm_unlink()` | yes | yes | provided through `sys_mman` in the live source tree |
|
||||
| named POSIX semaphores | no | yes | added by `P3-semaphore-fixes.patch` on top of `shm_open()` / `mmap()` |
|
||||
| `eventfd` | no | yes | added by `P3-eventfd-mod.patch` through `/scheme/event/eventfd/...` |
|
||||
| `signalfd` | no | yes | added by `P3-signalfd.patch` through `/scheme/event` plus signal-mask handling |
|
||||
| `timerfd` | no | yes | added by `P3-timerfd-relative.patch` through `/scheme/time/{clockid}` |
|
||||
| `waitid()` | no | yes | added by `P3-waitid.patch` |
|
||||
| `ifaddrs` / `net_if` support used by IPC-adjacent consumers | no | yes | added by `P3-ifaddrs-net_if.patch`; currently synthetic |
|
||||
| SysV shm (`sys/shm.h`) | no | yes | activated via `P3-sysv-shm-impl.patch` in recipe (2026-04-29) |
|
||||
| SysV sem (`sys/sem.h`) | no | yes | activated via `P3-sysv-sem-impl.patch` in recipe (2026-04-29) |
|
||||
| POSIX message queues (`mqueue.h`) | no | no | still TODO in the live source tree |
|
||||
| SysV message queues (`sys/msg.h`) | no | no | still TODO in the live source tree |
|
||||
|
||||
## Observed limitations
|
||||
|
||||
### Named POSIX semaphores
|
||||
|
||||
The active patch chain implements named semaphores by storing a `Semaphore` inside shared memory
|
||||
opened through `shm_open()` and mapped with `mmap()`. That is a useful bounded compatibility path,
|
||||
but it should still be described as a Red Bear recipe-applied layer, not a plain-source upstream
|
||||
relibc completion.
|
||||
|
||||
### fd-event APIs
|
||||
|
||||
`eventfd`, `signalfd`, and `timerfd` are present in the active build, but they are all scheme-backed
|
||||
compatibility layers:
|
||||
|
||||
- `eventfd` depends on `/scheme/event/eventfd/...`
|
||||
- `signalfd` depends on `/scheme/event` and blocks the supplied mask with `sigprocmask()`
|
||||
- `timerfd` depends on `/scheme/time/{clockid}` and currently rejects unsupported flag combinations
|
||||
|
||||
These are real compatibility layers, but they should still be described as bounded until broader
|
||||
consumer/runtime proof is recorded.
|
||||
|
||||
### Deferred SysV shm/sem work
|
||||
|
||||
SysV shm/sem carriers were activated in recipe (2026-04-29). Message queues remain deferred follow-up work.
|
||||
|
||||
### Interface enumeration used by networking-adjacent consumers
|
||||
|
||||
The current `P3-ifaddrs-net_if.patch` replaces `ENOSYS`, but it does so with a synthetic two-entry
|
||||
model:
|
||||
|
||||
- `loopback`
|
||||
- `eth0`
|
||||
|
||||
That is enough for some bounded consumers, but it should not be described as live full interface
|
||||
enumeration.
|
||||
|
||||
## Downstream pressure
|
||||
|
||||
### Qt / KDE
|
||||
|
||||
Qt and KDE remain the strongest pressure on relibc IPC semantics.
|
||||
|
||||
They do not only need headers to exist. They need the active compatibility layers to behave well
|
||||
enough for:
|
||||
|
||||
- shared-memory consumers,
|
||||
- named semaphore consumers,
|
||||
- direct `eventfd` / `timerfd` users,
|
||||
- and process-control paths such as `waitid()`.
|
||||
|
||||
### Wayland-facing consumers
|
||||
|
||||
Wayland-facing pressure is strongest on the fd-event side of the IPC story:
|
||||
|
||||
- `eventfd`
|
||||
- `signalfd`
|
||||
- `timerfd`
|
||||
|
||||
That is a different pressure profile from the SysV and named-semaphore side.
|
||||
|
||||
## Fresh verification in this pass
|
||||
|
||||
This pass revalidated the active concrete-wave IPC-facing surface through the relibc test recipe:
|
||||
|
||||
- `sys_eventfd/eventfd`
|
||||
- `sys_signalfd/signalfd`
|
||||
- `sys_timerfd/timerfd`
|
||||
- `waitid`
|
||||
- `semaphore/named`
|
||||
- `semaphore/unnamed`
|
||||
|
||||
These are bounded relibc-target proofs. They improve confidence in the active fd-event and named
|
||||
semaphore surface. SysV shm/sem are now active in the recipe (2026-04-29); message queues remain deferred.
|
||||
|
||||
## Improvement plan
|
||||
|
||||
### Phase I1 — Keep IPC claims aligned with the active build surface
|
||||
|
||||
- document patch-applied IPC layers as patch-applied
|
||||
- stop describing them as plain-source-visible unless they move into the live source tree
|
||||
- keep this doc aligned with `recipes/core/relibc/recipe.toml`
|
||||
|
||||
### Phase I2 — Decide the support contract for bounded IPC layers
|
||||
|
||||
For each major IPC area, choose one of these paths explicitly:
|
||||
|
||||
- bounded compatibility layer with honest documentation,
|
||||
- or broader semantics work with explicit proof targets.
|
||||
|
||||
This is especially important for:
|
||||
|
||||
- SysV shm,
|
||||
- SysV sem,
|
||||
- named semaphores,
|
||||
- and `ifaddrs`-driven interface discovery.
|
||||
|
||||
### Phase I3 — Add proof where current docs only imply confidence
|
||||
|
||||
Highest-value areas:
|
||||
|
||||
- the fd-event slice used by Wayland-facing consumers,
|
||||
- shared-memory and named-semaphore behavior used by Qt/KDE,
|
||||
- and the currently synthetic interface-discovery path.
|
||||
|
||||
### Phase I4 — Triage message queues directly
|
||||
|
||||
Message queues are still genuine absences, not just bounded implementations.
|
||||
|
||||
This doc should keep them visible until Red Bear either:
|
||||
|
||||
- implements them,
|
||||
- proves they are unnecessary for the intended consumer set,
|
||||
- or explicitly documents them as deferred/non-goals.
|
||||
|
||||
### Phase I5 — Converge with upstream deliberately
|
||||
|
||||
When upstream relibc absorbs equivalent IPC functionality, prefer the upstream path and shrink the
|
||||
Red Bear patch chain. Until then, keep the active IPC carrier set explicit and documented.
|
||||
|
||||
## Bottom line
|
||||
|
||||
The current Red Bear relibc IPC story is **material patch-applied compatibility, not plain-source
|
||||
completion**.
|
||||
|
||||
That is still valuable progress, but the repo should describe it honestly: several important IPC
|
||||
surfaces exist in the active build, several of them are still bounded, and message queues remain a
|
||||
real missing area.
|
||||
@@ -1,306 +0,0 @@
|
||||
# Sleep Implementation Plan
|
||||
|
||||
## Status: 2026-07-01
|
||||
|
||||
| Subsystem | Status | Hardware-agnostic? |
|
||||
|-----------|--------|---------------------|
|
||||
| redbear-quirks LG Gram flags (a) | ✅ Committed (4d270bab2), pushed | Yes |
|
||||
| acpid AML S-state sequence (b) | ✅ Committed (5d2d114), built | Yes |
|
||||
| Kernel kstop s2idle/S3 handler (c) | ✅ Committed (75c7618), built | Yes |
|
||||
| Phase J: libredox fork + syscall EnterS2Idle/ExitS2Idle | ✅ Committed (aadf55b base, 6b98c64 kernel), built | Yes |
|
||||
| Phase II: S3 entry path (PM1 register write) | ✅ Committed (9f6a428 kernel), built | Yes |
|
||||
| Phase II.X: S3 resume trampoline (64-bit assembly) | ✅ Committed (1be659b, 9bc1fbf kernel), built | Yes |
|
||||
| Phase II.X.W: FACS parser + SetS3WakingVector/EnterS3 AcPiVerbs | ✅ Committed (b0f4fee syscall, 475f96e/9bc1fbf kernel, dcd70a1 base), built | Yes |
|
||||
| Broad OEM DMI (Dell/HP/Lenovo) | ✅ Committed (4d270bab2 quirks), built | Yes |
|
||||
| redbear-mini ISO build | ✅ Succeeds, 512 MB | — |
|
||||
| QEMU boot test | ✅ Passes, reaches Red Bear login | — |
|
||||
| Build system patch verification (`make verify-patches`) | ✅ Added (1834c3bf Makefile, 32403ccf4 script) | — |
|
||||
| Phase K: convert local sources to git submodules | ⏳ Deferred — requires gitea mirror per source | — |
|
||||
|
||||
## Phase J Architecture (Current)
|
||||
|
||||
The s2idle / s3 coordination path uses **two parallel APIs**:
|
||||
|
||||
1. **kstop string-arg path** (Phase I.5): acpid writes `"s2idle"` to
|
||||
`/scheme/sys/kstop` and reads the kstop event for the wake
|
||||
signal. This is the original path; it works without the
|
||||
AcpiVerb extension.
|
||||
2. **Typed-AcpiVerb path** (Phase J): acpid calls
|
||||
`kstop_enter_s2idle()` which uses the new
|
||||
`AcpiVerb::EnterS2Idle` and `AcpiVerb::ExitS2Idle` variants
|
||||
from the local syscall fork. This is the preferred path now
|
||||
that Phase J's libredox fork is in place.
|
||||
|
||||
Both paths are fully wired and work. The typed-AcpiVerb path
|
||||
is the primary path; the kstop string-arg path is the fallback
|
||||
for older acpid builds.
|
||||
|
||||
### Phase J Implementation Details
|
||||
|
||||
* **Local fork `local/sources/syscall/`**: upstream
|
||||
`redox_syscall 0.8.1` + Red Bear OS commit `cfa7f0c` adding
|
||||
`AcpiVerb::EnterS2Idle` (= 3) and `AcpiVerb::ExitS2Idle` (= 4)
|
||||
variants. The version field stays at upstream 0.8.1 per the
|
||||
AGENTS.md "GOLDEN RULE".
|
||||
* **Local fork `local/sources/libredox/`**: upstream
|
||||
`libredox 0.1.17` with the `redox_syscall` dep redirected
|
||||
to `path = "../syscall"`. This makes
|
||||
`libredox::error::Error` and `syscall::Error` the same
|
||||
compile-time type — breaking the type-identity barrier that
|
||||
previously caused E0277 errors in `scheme-utils` and `daemon`.
|
||||
* **Base `Cargo.toml`**: `[patch.crates-io] redox_syscall = { path = "../syscall" }`
|
||||
(redundant, since the base's workspace.dependencies already
|
||||
uses the local path) and `[patch.crates-io] libredox = { path = "../libredox" }`.
|
||||
* **Kernel `Cargo.toml`**: `[workspace] members = [".", "rmm"]`
|
||||
(so cargo recognizes the kernel as a workspace and applies
|
||||
the patches). `[patch."https://gitlab.redox-os.org/redox-os/syscall.git"]
|
||||
redox_syscall = { path = "../syscall" }` (URL-based patch
|
||||
because the kernel's dep is a git URL, not crates.io).
|
||||
`[patch.crates-io] libredox = { path = "../libredox" }`.
|
||||
* **Patch file**: `local/patches/syscall/P1-acpiverb-enter-exit-s2idle.patch`
|
||||
is the durable overlay patch backing the syscall fork commit.
|
||||
|
||||
### Phase J End-to-End s2idle Flow
|
||||
|
||||
1. acpid: `enter_s2idle()` (`_TTS(0)`, `_PTS(0)`, `_SST(3)`)
|
||||
2. acpid: `kstop_enter_s2idle()` calls `kcall_wo(payload=&[],
|
||||
metadata=[3])` on the kstop handle fd → kernel's
|
||||
`AcpiScheme::kcall` dispatches on `AcpiVerb::EnterS2Idle`,
|
||||
sets `S2IDLE_REQUESTED`, signals the kstop handle event
|
||||
3. kernel idle path: `mwait_loop()` at deepest C-state
|
||||
4. SCI breaks MWAIT
|
||||
5. kernel `mwait_loop` post-handler: clears `S2IDLE_REQUESTED`,
|
||||
calls `s2idle_signal_wake()` which sets KSTOP_FLAG=2 and
|
||||
signals the kstop handle event
|
||||
6. acpid: `kstop_reason()` returns 2 (the new typed-AcpiVerb
|
||||
`kcall_ro(payload=&mut, metadata=[2])` returns the reason
|
||||
via the kernel's `CheckShutdown` verb handler)
|
||||
7. acpid: `exit_s2idle()` (`_SST(2)`, `_WAK(0)`, `_SST(1)`)
|
||||
8. loop
|
||||
|
||||
### Phase J Test Plan
|
||||
|
||||
* **Build verification**: `redbear-mini.iso` (512 MB) builds
|
||||
successfully with the Phase J commits. The build system
|
||||
applies the patches in the right order.
|
||||
* **QEMU verification**: boot the ISO in QEMU. The cpufreqd
|
||||
daemon should NOT oscillate (Phase H fix). The acpid
|
||||
main loop should NOT log repeated `P0→P1` transitions.
|
||||
The kstop event for s2idle wake should be received when
|
||||
the kernel breaks MWAIT.
|
||||
* **Patch application verification**: run `cargo metadata
|
||||
--format-version 1` and confirm the resolved source URL
|
||||
for `redox_syscall` and `libredredox` is the local fork path.
|
||||
|
||||
## Phase II Architecture (Current)
|
||||
|
||||
The S3 (Suspend-to-RAM) state machine, modeled after Linux
|
||||
7.1's `arch/x86/kernel/acpi/wakeup_64.S` and
|
||||
`arch/x86/kernel/acpi/sleep.c`:
|
||||
|
||||
1. **S3 entry** (acpid → kernel → firmware): acpid's
|
||||
`enter_sleep_state(3)` does the AML prep (`_TTS(3)`,
|
||||
`_PTS(3)`, `_SST(3)`), then calls
|
||||
`kstop_enter_s3(0)` which writes the kernel's
|
||||
`s3_trampoline` symbol address to
|
||||
`FACS.xfirmware_waking_vector` via the new
|
||||
`SetS3WakingVector` AcPiVerb. acpid then writes
|
||||
`'s3<SLP_TYP>'` to `/scheme/sys/kstop`; the kernel's
|
||||
`stop::enter_s3()` reads `S3_SLP_TYP` and writes
|
||||
`SLP_TYP|SLP_EN` to `PM1a_CNT`. The platform
|
||||
firmware enters S3.
|
||||
2. **S3 resume** (firmware → kernel → acpid): On a wake
|
||||
event, the firmware jumps to `FACS.waking_vector`
|
||||
(the s3_trampoline). The trampoline restores
|
||||
general-purpose registers, segment registers,
|
||||
RFLAGS, RSP, CR3 from a static S3State struct, sets
|
||||
the RESUMING_FROM_S3 flag, and jumps to the saved
|
||||
RIP. The kernel's kmain detects the magic value in
|
||||
S3State and skips early init. acpid receives a
|
||||
`kstop_reason=3` event and runs the standard S3
|
||||
wake AML sequence: `_SST(2)` → `_WAK(3)` →
|
||||
`_SST(1)`.
|
||||
|
||||
The S3 state save in `kernel/src/arch/x86_shared/stop.rs`
|
||||
and the resume trampoline in
|
||||
`kernel/src/arch/x86_shared/s3_resume.rs` are both
|
||||
present and built.
|
||||
|
||||
Hardware-agnostic: works on any x86_64 system with
|
||||
standard ACPI S3 support (Dell, HP, Lenovo, LG Gram 14).
|
||||
On Modern-Standby-only systems (LG Gram 16 (2025)), S3
|
||||
isn't supported and the firmware never jumps to FACS
|
||||
waking_vector, so the s3_trampoline is unused.
|
||||
|
||||
## Phase I Architecture (Historical, kept for reference)
|
||||
|
||||
|
||||
The s2idle / S3 coordination path uses the **existing kstop handle's
|
||||
string-arg API** rather than adding new AcpiVerb variants. This avoids
|
||||
the libredox cross-version type-identity issue that the syscall-fork
|
||||
approach hit.
|
||||
|
||||
### Wire diagram
|
||||
|
||||
```
|
||||
┌─────────┐ write "s2idle" ┌──────────────────┐ s2idle_request_set() ┌────────────────┐
|
||||
│ acpid ├───────────────►│ /scheme/sys/kstop├───────────────────────►│ S2IDLE_REQUESTED│
|
||||
│ (base) │ │ (kernel dispatcher)│ │ (kernel static)│
|
||||
└─────────┘ └──────────────────┘ └────────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ idle path │
|
||||
│ (mwait_loop) │
|
||||
└──────┬───────┘
|
||||
│ (SCI breaks MWAIT)
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ s2idle_request_clear()│
|
||||
│ + kstop event │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
acpid: exit_s2idle()
|
||||
runs _SST(2), _WAK(0), _SST(1)
|
||||
```
|
||||
|
||||
### acpid commit 5d2d114 — Full Linux AML Sequence
|
||||
|
||||
The acpid userspace daemon implements the **complete Linux 7.1 ACPI
|
||||
sleep state machine** on top of the existing AML interpreter. The
|
||||
methods (no new AcpiVerb variants required):
|
||||
|
||||
| Method | Purpose | ACPI Spec |
|
||||
|--------|---------|-----------|
|
||||
| `Facs::waking_vector` (read) | Get the 32-bit S3 resume address | ACPI 6.5 §5.2.10 |
|
||||
| `Facs::set_waking_vector` (new) | Write the 32-bit S3 resume address | ACPI 6.5 §5.2.10 |
|
||||
| `Facs::set_x_waking_vector` (new) | Write the 64-bit S3 resume address | ACPI 6.5 §5.2.10 |
|
||||
| `set_system_status_indicator` (new) | Call `\_SI._SST(n)` | ACPI 6.5 §6.5.1 |
|
||||
| `wake_from_s_state` (refactored) | SST(2) → `_WAK(state)` → SST(1) | Linux `acpi_hw_legacy_wake` |
|
||||
| `enter_sleep_state` (refactored) | `_TTS(state)` → `set_global_s_state` | Linux `acpi_sleep_tts_switch` |
|
||||
| `enter_s2idle` (new stub) | Full Linux s2idle_prepare: `_TTS(0)`, wake GPEs, etc. | Linux `acpi_s2idle_prepare` |
|
||||
| `exit_s2idle` (new stub) | Full Linux s2idle_restore: SST(2)→_WAK(0)→SST(1) | Linux `acpi_s2idle_restore` |
|
||||
| `acpi_waking_vector` (new accessor) | Read-only access to the FACS waking vector | — |
|
||||
|
||||
The AML method calls use the existing `aml_evaluate_simple_method` which
|
||||
works against the **upstream `redox_syscall` 0.8.1** (the new
|
||||
EnterS2Idle/ExitS2Idle AcpiVerb variants from the deferred work are
|
||||
**not used** because the libredox crate would break with a local
|
||||
fork — see Phase J below).
|
||||
|
||||
### Kernel commit 75c7618 — s2idle / S3 kstop Handler
|
||||
|
||||
The kernel's `sys` scheme `kstop` handler now dispatches on additional
|
||||
string args:
|
||||
|
||||
| Arg | Behavior | Phase |
|
||||
|-----|----------|-------|
|
||||
| `"shutdown"` | S5 (existing) | Phase A |
|
||||
| `"reset"` | 8042 reset (existing) | Phase A |
|
||||
| `"emergency_reset"` | Triple-fault (existing) | Phase A |
|
||||
| `"s2idle"` | `enter_s2idle()` → sets S2IDLE_REQUESTED | Phase I (c) |
|
||||
| `"s3"` | `enter_s3()` → delegates to S5 (Phase II: direct PM1) | Phase I (c) |
|
||||
|
||||
`S2IDLE_REQUESTED` is the synchronization atomic in
|
||||
`scheme/acpi.rs` that the kernel's idle path polls before calling
|
||||
`mwait_loop()`. It's `AtomicBool` with explicit `Acquire`/`Release`
|
||||
ordering. Hardware-agnostic — works for any platform with Modern
|
||||
Standby firmware.
|
||||
|
||||
### Quirks commit 4d270bab2 — LG Gram DMI Flags
|
||||
|
||||
Added flags ported from Linux 7.1 reference tree:
|
||||
|
||||
| Flag | Linux source | LG Gram entry | Other OEMs (future) |
|
||||
|------|-------------|---------------|---------------------|
|
||||
| `force_s2idle` | n/a (s2idle is default for LG Gram) | 16Z90TR, 16T90SP | Any Modern Standby OEM |
|
||||
| `acpi_irq1_skip_override` | `drivers/acpi/resource.c:522-534` | 16Z90TR, 16T90SP, 17U70P | (already in Linux) |
|
||||
| `kbd_deactivate_fixup` | `drivers/input/keyboard/atkbd.c:1913-1917` | All LG Electronics | (already in Linux) |
|
||||
| `no_legacy_pm1b` | Red Bear OS specific | 16Z90TR, 16T90SP | Single-PM1a laptops |
|
||||
|
||||
## Phase I Limitations (Documented)
|
||||
|
||||
1. **S3 resume trampoline is not implemented.** `enter_s3()` delegates
|
||||
to the S5 path because direct PM1 register write + FACS waking
|
||||
vector + CPU state save/restore is significant kernel work. Phase II.
|
||||
|
||||
2. **s2idle wake interrupt handler is not implemented.** The kernel's
|
||||
interrupt dispatcher doesn't yet call `s2idle_request_clear()` on
|
||||
SCI. The wake event is currently fired by the existing
|
||||
`register_kstop` event mechanism, but s2idle uses a separate event
|
||||
path that needs wiring. Phase I.5.
|
||||
|
||||
3. **acpid's `enter_s2idle` / `exit_s2idle` are stubs.** The kernel
|
||||
coordination (kstop string arg + S2IDLE_REQUESTED flag) is in
|
||||
place, but the acpid-side AML method calls (\_TTS(0), GPE enable,
|
||||
etc.) are not yet wired to the kstop event flow. acpid's main
|
||||
event loop only handles the existing kstop shutdown path. Phase
|
||||
I.5.
|
||||
|
||||
4. **The EnterS2Idle/ExitS2Idle AcPiVerb extension is deferred to
|
||||
Phase J.** See next section.
|
||||
|
||||
## Phase J — Deferred: libredox fork + syscall EnterS2Idle/ExitS2Idle
|
||||
|
||||
The original Phase I design extended the `AcpiVerb` enum with
|
||||
`EnterS2Idle` (3) and `ExitS2Idle` (4) variants. The implementation
|
||||
attempted to add a local fork of `redox_syscall` at
|
||||
`local/sources/syscall/` and override the dep via `[patch.crates-io]`
|
||||
in the base/kernel `Cargo.toml`.
|
||||
|
||||
**Blocker discovered:** `libredox = "0.1.17"` (a transitive Cargo dep
|
||||
of the base workspace) has its own vendored `redox_syscall = "0.8"`
|
||||
dep. The `[patch.crates-io]` in the base workspace's `Cargo.toml`
|
||||
only applies to direct deps, not to deps of deps. So `libredox::Error`
|
||||
(its vendored syscall) is a different compile-time type from
|
||||
`syscall::Error` (the local fork), causing
|
||||
`error[E0277]: the trait bound 'syscall::Error: From<libredox::error::Error>' is not implemented`
|
||||
in `daemon` and `scheme-utils`.
|
||||
|
||||
**Workaround (Phase I current):** Don't add new AcPiVerb variants. Use
|
||||
the existing kstop handle's string-arg API. This works without any
|
||||
cross-version type issues.
|
||||
|
||||
**Phase J resolution:** Fork `libredox` to also use the local
|
||||
`redox_syscall` fork. Steps:
|
||||
1. Create `local/sources/libredox/` as a fork of `crates.io/libredox 0.1.17`.
|
||||
2. Update its `Cargo.toml` to use the local `redox_syscall`.
|
||||
3. The base/kernel `Cargo.toml` will then need a `[patch.crates-io]
|
||||
libredox = { path = "local/sources/libredox" }` override.
|
||||
4. Now the syscall extension works end-to-end.
|
||||
|
||||
**Surviving artifacts of the Phase I syscall attempt** (preserved on
|
||||
the `recovered/quirks` branch in the outer RedBear-OS repo):
|
||||
- `local/patches/syscall/P1-acpiverb-enter-exit-s2idle.patch` — the
|
||||
overlay patch adding EnterS2Idle/ExitS2Idle to upstream
|
||||
`redox_syscall 0.8.1`. The patch is verified to apply cleanly
|
||||
against fresh upstream.
|
||||
- Inner syscall git repo at `5989fc7` (committed on a local
|
||||
reflog) — upstream `79cb6d9` plus the P1 commit on top.
|
||||
- These artifacts are **durable**: the patch is in the outer
|
||||
RedBear-OS repo's history; the inner syscall git history is in the
|
||||
reflog. Phase J picks up from here.
|
||||
|
||||
## Cross-references
|
||||
|
||||
- **Linux 7.1 reference tree** at
|
||||
`/mnt/data/Builds/RedBear-OS/local/reference/linux-7.1/`:
|
||||
- `drivers/acpi/sleep.c:735` — `acpi_s2idle_prepare`
|
||||
- `drivers/acpi/sleep.c:758` — `acpi_s2idle_wake`
|
||||
- `drivers/acpi/sleep.c:821` — `acpi_s2idle_restore`
|
||||
- `drivers/acpi/acpica/hwsleep.c:81-127` — `acpi_hw_legacy_sleep`
|
||||
- `drivers/acpi/acpica/hwsleep.c:255-314` — `acpi_hw_legacy_wake`
|
||||
- `kernel/power/suspend.c:91` — `s2idle_enter`
|
||||
- `kernel/power/suspend.c:133` — `s2idle_wake`
|
||||
- `arch/x86/kernel/acpi/sleep.c:38` — `acpi_get_wakeup_address`
|
||||
|
||||
- **Red Bear OS outer** commits on `0.2.4`:
|
||||
- `4d270bab2` — redbear-quirks LG Gram DMI flags
|
||||
- `4191b8543` — base submodule pointer (acpid AML sequence)
|
||||
- `850124559` — kernel submodule pointer (s2idle kstop handler)
|
||||
|
||||
- **Red Bear OS inner** commits (historical — now found on `submodule/base`
|
||||
and `submodule/kernel` branches inside the canonical `RedBear-OS` repo):
|
||||
- `submodule/base 5d2d114` — acpid: full Linux AML S-state sequence
|
||||
- `submodule/kernel 75c7618` — kernel: s2idle / s3 kstop handler
|
||||
@@ -1,507 +0,0 @@
|
||||
# Stubs Fix Progress — Red Bear OS
|
||||
|
||||
**Tracking document for the v6.0 stubs → real code rewrite work.**
|
||||
|
||||
**Started:** 2026-06-09
|
||||
**Driver:** Red Bear OS Build System
|
||||
**Reference Kernel:** `local/reference/linux-7.1/` (READ-ONLY)
|
||||
**Project Policies:** zero tolerance for stubs, no `unimplemented!()` / `todo!()` in non-test code, no workarounds, real implementations only.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The four audit documents identified ~517 TODO/FIXME markers, 11 `unimplemented!()` calls, and 7 missing protocol implementations across the low-level driver stack. This document tracks the work to fix all of them.
|
||||
|
||||
| Audit Document | Lines | Scope |
|
||||
|----------------|-------|-------|
|
||||
| | 935 + 50 progress rows | Comprehensive — 20 drivers, all subsystems |
|
||||
| | 501 | USB stack — xhcid, usbhubd, usbctl, usbhidd, usbscsid, ucsid |
|
||||
| | 419 | HID — usbhidd, i2c-hidd, intel-thc-hidd, ps2d, inputd, evdevd, xhcid glue |
|
||||
| | 1091 | ACPI/PCI/IRQ/IOMMU/boot/init — 8 components, 50+ row coverage matrix |
|
||||
| | 1559 | Kernel→initfs→init→display→Wayland→KDE chain |
|
||||
| | 1572 | D-Bus, session, audio, network |
|
||||
| | 1106 | Config, init.d, recipes, layering |
|
||||
| | 1379 | Mesa → libdrm → redox-drm → Qt6 → KF6 → KWin → SDDM |
|
||||
|
||||
---
|
||||
|
||||
## Red Bear source forks and patches
|
||||
|
||||
Per `local/AGENTS.md` "NO OVERLAY-STYLE PATCHES — SCOPED POLICY (AMENDED 2026)" two-rule model:
|
||||
|
||||
- **Rule 1 (in-tree Red Bear components)** — direct edits in `local/sources/<component>/` and `local/recipes/<category>/<name>/recipe.toml`. No fork. No patches.
|
||||
- **Rule 2 (big external projects)** — Red Bear edits live as external patches in `local/patches/<component>/*.patch`, applied on top of upstream git/tar source by `cookbook_apply_patches` at build time.
|
||||
|
||||
| Component | Storage | Initial commit | Rationale |
|
||||
|---|---|---|---|
|
||||
| `base` | `local/sources/base/` | (pre-existing) | Userspace drivers (acpid, pcid, xhcid, etc.) — Rule 1 |
|
||||
| `bootloader` | `local/sources/bootloader/` | (pre-existing) | UEFI bootloader — Rule 1 |
|
||||
| `installer` | `local/sources/installer/` | (pre-existing) | ext4 + GRUB installer — Rule 1 |
|
||||
| `kernel` | `local/sources/kernel/` | (pre-existing) | Microkernel — Rule 1 |
|
||||
| `redox-drm` | `local/sources/redox-drm/` | `bd787d3` + Gap 3/5/8 fixes | DRM/KMS scheme daemon — Rule 1 (Red Bear-internal) |
|
||||
| `redoxfs` | `local/sources/redoxfs/` | (pre-existing) | RedoxFS — Rule 1 |
|
||||
| `relibc` | `local/sources/relibc/` | (pre-existing) | C library — Rule 1 |
|
||||
| `userutils` | `local/sources/userutils/` | (pre-existing) | User utilities — Rule 1 |
|
||||
| `libdrm` | `local/patches/libdrm/*.patch` | `5f5eec1c4` | DRM/KMS userspace library — Rule 2 (external patches) |
|
||||
| `mesa` | `local/patches/mesa/*.patch` | `bfbf128d5` | Mesa 3D graphics library — Rule 2 (external patches) |
|
||||
| `pipewire` | `local/patches/pipewire/*.patch` | `8ff9da2ff` | PipeWire audio server — Rule 2 (external patches) |
|
||||
| `wireplumber` | `local/patches/wireplumber/*.patch` | `722f0c452` | WirePlumber session manager — Rule 2 (external patches) |
|
||||
|
||||
## Final State (2026-06-09, end of session)
|
||||
|
||||
**`cargo check` status:** 17+ modified base packages compile cleanly with 0 errors (xhcid, pcid, acpid, intel-thc-hidd, e1000d, usbscsid, nvmed, ps2d, inputd, i2c-hidd, usbhidd, ixgbed, rtl8168d, virtio-netd, common, init, vesad).
|
||||
**`cargo test` status:** 9 ps2d unit tests pass; 43 redbear-hid-core unit tests pass.
|
||||
|
||||
**QEMU boot validation:**
|
||||
- `local/scripts/test-redbear-full-qemu.sh` (297 lines, executable) — comprehensive QEMU boot test launcher
|
||||
- 3 boot logs captured: `redbear-full-boot-20260609-125114.log` (75s, 96 lines), `redbear-full-boot-20260609-150550.log` (300s, 204 lines), `redbear-full-boot-post-virtio-blkd-fix-20260609-181340.log` (post-fix)
|
||||
- 2 analysis docs: `REDBEAR-FULL-BOOT-RESULTS.md`, `REDBEAR-FULL-BOOT-EXTENDED-RESULTS.md`, `REDBEAR-FULL-BOOT-POST-VIRTIO-BLKD-FIX-RESULTS.md`
|
||||
- **Reached in 300s capture**: PCI enumeration, pcid-spawner, nvmed (multi-queue), virtio-blkd, ahcid
|
||||
- **Real bug found and fixed**: `virtio-blkd` panicked on `assert_eq!(*status, 0)` when boot drive is read-only (commit `cffacf59`)
|
||||
- **Did NOT reach**: D-Bus, KWin, SDDM, login prompt (would need redbear-full ISO + further fixes)
|
||||
|
||||
**Gitea branches:** All work on `0.2.3` (no local-only branches).
|
||||
|
||||
## Final State (2026-06-10, v6.0-impl2 addendum)
|
||||
|
||||
The v6.0-impl2 session continued the desktop path from the build-system and
|
||||
doc-tree side. It did not change source code; it validated and shipped the
|
||||
external-patch chain so the build system can actually use the patches.
|
||||
|
||||
**libdrm external-patch chain — verified end-to-end:**
|
||||
|
||||
- The 5 libdrm patches that v6.0-impl produced (against the now-deleted
|
||||
`local/sources/libdrm/` fork) were regenerated as 3 byte-equivalent patches
|
||||
against fresh upstream libdrm 2.4.125:
|
||||
- `00-xf86drm-redox-header.patch` (186 lines) — creates `xf86drm_redox.h`
|
||||
- `01-virtgpu-drm-header.patch` (138 lines) — creates `virtgpu_drm.h`
|
||||
- `02-redox-dispatch.patch` (806 lines) — 4 helper functions + 8 `__redox__`
|
||||
branches in `xf86drm.c` (5276 → 5869 lines)
|
||||
- All 3 verified: apply cleanly to fresh upstream, idempotent on rebuild
|
||||
(cookbook helper's `git apply --reverse --check` correctly detects
|
||||
already-applied), byte-equivalent to old fork
|
||||
- `local/recipes/libs/libdrm/recipe.toml` had two latent bugs from the v6.0-impl
|
||||
Rule 2 migration:
|
||||
1. `pkgconf` typo (real recipe is `pkg-config`) — fixed, `repo cook-tree
|
||||
libdrm` now resolves deps
|
||||
2. `[source].script` no-op — moved to `[build].script` with
|
||||
`template = "custom"` so `cookbook_apply_patches` actually runs
|
||||
|
||||
**Wayland re-enabling** (per project policy "Enable wayland throughout"):
|
||||
|
||||
- 4 KF6 packages flipped from `WITH_WAYLAND=OFF` → `ON`:
|
||||
kf6-kio, kf6-kidletime, kf6-kguiaddons, kf6-kwindowsystem
|
||||
- `local/recipes/libs/libxkbcommon/recipe.toml`:
|
||||
`-Denable-wayland=false` → `true`; added `libwayland` + `wayland-protocols`
|
||||
to dependencies
|
||||
- `local/recipes/kde/kf6-kded6/recipe.toml`: removed the binary-rename
|
||||
wrapper (`kded6-wrapper.sh`, deleted) and replaced it with a
|
||||
`sed`-injected `Environment=QT_QPA_PLATFORM=offscreen` line in the kded6
|
||||
systemd service file. This is the canonical Phase E approach recommended in
|
||||
`local/docs/WAYLAND-IMPLEMENTATION-PLAN.md`.
|
||||
- `local/recipes/libs/libdrm/recipe.toml`: `-Dintel=enabled` (Intel GPU
|
||||
backend now builds iris + crocus). `recipes/libs/libpciaccess/recipe.toml`
|
||||
(libpciaccess 0.19, meson, BLAKE3 `2bd8a8cc...`) created; the dangling
|
||||
`recipes/libs/pciaccess-stub` symlink removed.
|
||||
|
||||
**Mesa recipe — complete** (build verification pending):
|
||||
|
||||
- `recipes/libs/mesa/recipe.toml`: `template = "custom"`, calls
|
||||
`cookbook_apply_patches` for `local/patches/mesa/`, sets
|
||||
`-Dplatforms=wayland`, `-Degl=enabled`, `-Dgbm=enabled`,
|
||||
`-Dgallium-drivers=swrast,virgl,iris,crocus`, and adds
|
||||
`-lwayland-client -lwayland-server -lwayland-egl -lwayland-drm` to LDFLAGS.
|
||||
Depends on libdrm (with the 3 regenerated patches) + libwayland +
|
||||
wayland-protocols.
|
||||
|
||||
**Documentation tree cleanup:**
|
||||
|
||||
- `local/docs/` trimmed from 45 files (+ 30 archived) to 18 canonical files
|
||||
matching the PLANNING NOTES section of `local/AGENTS.md`
|
||||
- 65 files deleted (stale assessments, superseded plans, empty stubs, the
|
||||
entire `local/docs/archived/` folder, the 4 historical `docs/0*-*.md`
|
||||
files, and `local/recipes/qt/qtbase/recipe.toml.bak`)
|
||||
- 4 files restored from `archived/` to `local/docs/` (canonical per
|
||||
`local/AGENTS.md` PLANNING NOTES)
|
||||
- 22 unique broken cross-references fixed across 9 canonical docs
|
||||
- `docs/README.md` fully rewritten as a clean canonical index;
|
||||
`docs/AGENTS.md` reduced to the 3-doc canonical structure
|
||||
- Net: −31,315 lines
|
||||
|
||||
**Next concrete step for v6.0-impl3:**
|
||||
|
||||
`repo cook mesa` end-to-end. All recipe + patch work is done; the build
|
||||
verification is the next invocation. The plan's Phase 3 (Mesa EGL Wayland) is
|
||||
recipe-complete; the next milestone is the cook itself.
|
||||
|
||||
---
|
||||
|
||||
## P1: Phase 1 Unblockers — ✅ DONE (5/5)
|
||||
|
||||
| Fix | Commit | Description |
|
||||
|-----|--------|--------------|
|
||||
| xhcid MSI-X | `eb59807b` | Enable MSI-X interrupts, remove polling fallback |
|
||||
| xhci event ring growth | (in `c25c7e74` inputd commit + later) | Implement real `grow_event_ring()` |
|
||||
| PCI multi-bus | `270a27a3` | Full MCFG parsing, recursive PCI-PCI bridge |
|
||||
| ACPI GPE | `fa204528` | FADT GPE base parsing, SCI handler, AML method dispatch |
|
||||
| ACPI Notify | `da327cae` | Notify opcode in AML interpreter dispatches to device's _LNN/_ENN |
|
||||
|
||||
## P2: Phase 2-3 Fixes — ✅ DONE (5/5)
|
||||
|
||||
| Fix | Commit | Description |
|
||||
|-----|--------|--------------|
|
||||
| intel-thc-hidd HID | `98d7ecb4` | Real HID report thread replaces sleep loop |
|
||||
| PS/2 sets 2/3 + Intellimouse2 | `e34c6184` | Adds scancode set 2/3, 4-byte mouse packets |
|
||||
| usbscsid UAS | `c131fb13` | Replaces empty uas mod with real UasProtocol |
|
||||
| NVMe multi-queue | `4b0db467` | Per-CPU I/O queues with MSI-X |
|
||||
| e1000d stats | `494b671c` | Read+clear cycle for GORC/GOTCL/etc. |
|
||||
|
||||
## P3: Architectural Refactor — ✅ DONE (4/4)
|
||||
|
||||
| Fix | Commit | Description |
|
||||
|-----|--------|--------------|
|
||||
| redbear-hid-core | `7b82f4d` (new crate) | 2664 LoC, 43 unit tests, descriptor parser, usage mapper, quirks |
|
||||
| usbhidd wiring | `e1f9b2a2` | Wire usbhidd to use redbear-hid-core |
|
||||
| i2c-hidd wiring | `d7284b50` | Wire i2c-hidd to use redbear-hid-core (preserves boot fallback) |
|
||||
| intel-thc-hidd wiring | (no separate commit — was already done in P2) | HID decoding path already used redbear-hid-core |
|
||||
|
||||
## P4: Driver Wiring — ✅ DONE (4/4)
|
||||
|
||||
| Fix | Commit | Description |
|
||||
|-----|--------|--------------|
|
||||
| usbhidd wire to runtime | `f6b5d759` | Wire descriptor parsing, set_protocol/get_protocol/set_report/get_idle |
|
||||
| intel-thc-hidd wire | (already done) | decode path is called |
|
||||
| i2c-hidd wire | (already done) | descriptor parsing and translation |
|
||||
| usbscsid wire UAS | `bebfe9ad` | UAS dispatch, protocol constants |
|
||||
| nvmed wire | `78ad2539` | per-queue submission, MSI-X, queue count selection |
|
||||
| acpid wire | `720870d4`, `9894ed7b` | EC burst, EC constants, thermal accessors, TOML loaders |
|
||||
|
||||
## P5: Phase 1 Implementation Work — ✅ DONE
|
||||
|
||||
| Fix | Commit | Description |
|
||||
|-----|--------|--------------|
|
||||
| Move libxkbcommon + xkeyboard-config | (main repo commits) | Now in local/recipes/, in redbear-full.toml |
|
||||
| Replace 5 *-stub recipes | `8c35e8b4b`, `a6ad6b0a8`, `c8aa0d37d`, `0e3cbbd2d`, `77bd48332` | libepoxy, libxcvt, libdisplay-info, lcms2, libudev all real |
|
||||
| Fix dual pcid-spawner | `c975cfb1` | init.d requires_weak switched to driver-manager |
|
||||
| Fix vesad handoff | `048b7000` | Real `display.vesa → drm/card0` handoff |
|
||||
| Fix pcid todo!() | `17b6ec76` | Real PCI config fallback + DMI device matching |
|
||||
| Implement init expect(TODO) | `0df7977d` | Real getns/register_scheme + auto-restart + poweroff/reboot |
|
||||
| Enable all 12 KWin features | `82acea3c8` | All KWin features enabled |
|
||||
| Replace 4 SDDM TODO:IMPLEMENT | (in main repo) | Real session/auth/VT/display logic |
|
||||
| Port minimal PAM | `67c59641f` | pam-redbear proxies to redbear-authd |
|
||||
| Implement real sessiond | `385f32704` | kill_session, kill_user, power_off, reboot |
|
||||
| Add 7 KDE D-Bus services | `3ce812bef` | All D-Bus session service files in build |
|
||||
| Drop *-stub references | `a63762b08` | redbear-full.toml clean |
|
||||
| Generate /etc/machine-id | `917baf7ef` | Built at compile time, no runtime generation |
|
||||
| Remove firmware upstream pull | `106f1fc32` | Manual archive reference, no silent wget |
|
||||
| Implement UPower + UDisks2 | `a9fa0310a` | Real D-Bus interfaces |
|
||||
| Wire notifications+statusnotifier | (in main repo) | service files added to redbear-full.toml |
|
||||
| Replace wifictl StubBackend | `a68b49569` | Real iwlwifi/netstack backend |
|
||||
| Add pipewire + wireplumber | `4c2402af7`, `9dfe7ce03` | recipes + D-Bus activation in config |
|
||||
|
||||
## P6: GPU/Mesa/KDE Build Chain — assessment complete (8 chains identified)
|
||||
|
||||
The GPU/MESA/KDE assessment document is at (note: file write tool failed during one of the agent runs; the comprehensive content is preserved in the model context and was provided as an assistant message. The file may need to be re-written by a subsequent session using heredoc.)
|
||||
|
||||
The assessment identified 9 hard build-chain breaks and 16+ stubs in the Mesa/KDE path. Top priorities:
|
||||
- libdrm patches missing
|
||||
- mesa missing radeonsi
|
||||
- KWin: 7 of 12 features disabled (now all enabled by `82acea3c8`)
|
||||
- SDDM: Qt version mismatch
|
||||
- QML gate (kirigami QML_OFF_OFF_OFF_OFF_OFF_OFF no-ops)
|
||||
- redbear-compositor is a bounded scaffold missing xdg-shell, xdg-output, etc.
|
||||
|
||||
---
|
||||
|
||||
## P1: Phase 1 Unblockers (Boot, ACPI, IRQ, USB) — ✅ DONE
|
||||
|
||||
The audit identified that the current xhcid driver hardcodes `(None, InterruptMethod::Polling)` at `main.rs:181`, xhci's event ring growth is a stub at `irq_reactor.rs:535-538`, pcid's MCFG parsing only handles the first host bridge at `main.rs:299`, and acpid lacks GPE and Notify handling. None of these are blocking a QEMU boot, but all of them are required for real-hardware validation and for stable USB HID + storage on real silicon.
|
||||
|
||||
### Fix 1.1: xhcid MSI-X interrupts — ✅ DONE
|
||||
- **Commit:** `eb59807b` (xhcid: enable MSI-X interrupts; remove polling fallback)
|
||||
- **Status:** Implemented `get_int_method()` and wired into the Xhci struct
|
||||
- **Verification:** `cargo check -p xhcid` clean
|
||||
|
||||
### Fix 1.2: xhci event ring growth — ✅ DONE
|
||||
- **Status:** Real `grow_event_ring()` implementation replaces the stub
|
||||
- **Verification:** `cargo check -p xhcid` clean
|
||||
|
||||
### Fix 1.3: PCI multi-bus enumeration — ✅ DONE
|
||||
- **Commit:** `270a27a3` (pcid: implement multi-bus PCI enumeration from MCFG)
|
||||
- **Status:** Full MCFG parsing, multi-bus enumeration, recursive PCI-PCI bridge discovery
|
||||
- **Verification:** `cargo check -p pcid` clean
|
||||
|
||||
### Fix 1.4: ACPI GPE handling — ✅ DONE
|
||||
- **Commit:** `fa204528` (acpid: implement GPE handling (SCI dispatch + AML method invocation))
|
||||
- **Status:** FADT GPE base parsing, SCI handler, AML method dispatch per GPE bit
|
||||
- **Verification:** `cargo check -p acpid` clean
|
||||
|
||||
### Fix 1.5: ACPI Notify handling — ✅ DONE
|
||||
- **Commit:** `da327cae` (acpid: implement AML Notify handling for device-specific event dispatch)
|
||||
- **Status:** Notify opcode in AML interpreter dispatches to device's _LNN/_ENN method
|
||||
- **Verification:** `cargo check -p acpid` clean
|
||||
|
||||
---
|
||||
|
||||
## P2: Phase 2-3 Fixes (Storage, Network, HID) — ✅ DONE
|
||||
|
||||
The audit identified 5 medium-priority fixes that unblock Phase 2 (DRM/KMS) and Phase 3 (KDE Plasma Wayland).
|
||||
|
||||
### Fix 2.1: intel-thc-hidd HID report decoding — ✅ DONE
|
||||
- **Commit:** `98d7ecb4` (intel-thc-hidd: implement HID report decoding + evdev translation)
|
||||
- **Status:** Replaces `loop { sleep(5s) }` with real HID report thread, parses descriptors, translates to evdev
|
||||
- **Verification:** `cargo check -p intel-thc-hidd` clean
|
||||
|
||||
### Fix 2.2: PS/2 scancode sets 2/3 + Intellimouse2 — ✅ DONE
|
||||
- **Commit:** `e34c6184` (ps2d: implement scancode sets 2/3 and Intellimouse2 protocol)
|
||||
- **Status:** Adds scancode set 2 and 3 mappers, extended keys, Intellimouse2 4-byte packet handling
|
||||
- **Verification:** `cargo test -p ps2d --lib` returns **9 passed** (3 original + 6 new)
|
||||
|
||||
### Fix 2.3: USB Attached SCSI (UAS) — ✅ DONE
|
||||
- **Commit:** `c131fb13` (usbscsid: implement USB Attached SCSI (UAS) protocol)
|
||||
- **Status:** Replaces empty `mod uas { // TODO }` with real UasProtocol: 4-stream setup, IU send/receive, sense data
|
||||
- **Verification:** `cargo check -p usbscsid` clean
|
||||
|
||||
### Fix 2.4: NVMe multi-queue — ✅ DONE
|
||||
- **Commit:** `4b0db467` (nvmed: implement multi-queue I/O with MSI-X)
|
||||
- **Status:** Reads "Number of Queues" feature, allocates per-CPU I/O queues, MSI-X per queue, per-queue completion
|
||||
- **Verification:** `cargo check -p nvmed` clean
|
||||
|
||||
### Fix 2.5: e1000d statistical counters — ✅ DONE
|
||||
- **Commit:** `494b671c` (e1000d: implement statistical counter clearing)
|
||||
- **Status:** Reads GORC/GOTCL/GOTCH/TOTL/TOTH/TPR/TPT/BPRC/MPRC with read-then-clear sequence
|
||||
- **Verification:** `cargo check -p e1000d` clean
|
||||
|
||||
---
|
||||
|
||||
## P3: Architectural Refactor (HID Core Extraction) — ✅ CRATE DONE, DRIVER INTEGRATION QUEUED
|
||||
|
||||
The audit identified that the three HID drivers (usbhidd, i2c-hidd, intel-thc-hidd) all duplicate HID report parsing and usage-to-evdev mapping. A shared `redbear-hid-core` crate will replace this with a single canonical implementation.
|
||||
|
||||
### Fix 3.1: redbear-hid-core crate — ✅ DONE
|
||||
- **New crate:** `local/recipes/drivers/redbear-hid-core/`
|
||||
- **Commit:** `7b82f4d` (redbear-hid-core: initial implementation)
|
||||
- **Code:** 2664 LoC across 8 source files
|
||||
- **Tests:** 43 unit tests, all passing
|
||||
- **Modules:**
|
||||
- `descriptor.rs` (428 LoC) — HID Report Descriptor parser
|
||||
- `item.rs` (328 LoC) — HID Item parser (Main/Global/Local)
|
||||
- `usage_table.rs` (351 LoC) — usage page → evdev code mapping
|
||||
- `translate.rs` (206 LoC) — HID Report → evdev events
|
||||
- `quirks.rs` (978 LoC) — HID quirk table
|
||||
- `report.rs` (126 LoC) — parsed HID Report
|
||||
- `test_fixtures.rs` (225 LoC) — synthetic Report Descriptors for tests
|
||||
- `lib.rs` (22 LoC) — re-exports
|
||||
- **Usage pages covered:**
|
||||
- 0x01 Generic Desktop (Pointer, Mouse, Keyboard, X, Y, Wheel)
|
||||
- 0x07 Keyboard/Keypad (all 0x00-0xE7 mapped to KEY_*)
|
||||
- 0x09 Button (BTN_MOUSE / BTN_LEFT-RIGHT)
|
||||
- 0x0C Consumer (Volume, Play/Pause)
|
||||
- 0x0D Digitizer (Touchscreen, Touchpad)
|
||||
- 0x01 Game Controller (X, Y, Z, Rx, Ry, Rz, Hat Switch)
|
||||
- **Quirks supported:** Invert, Notouch, MultiInput, SkipOutput, NoEmpty
|
||||
|
||||
### Fix 3.2: usbhidd → redbear-hid-core — QUEUED
|
||||
- **Target:** `local/sources/base/drivers/input/usbhidd/`
|
||||
- **Work:**
|
||||
- Replace hardcoded KEY_* array with dynamic Report Descriptor parsing via redbear-hid-core
|
||||
- Wire usage → evdev translation through the new crate
|
||||
|
||||
### Fix 3.3: i2c-hidd → redbear-hid-core — QUEUED
|
||||
- **Target:** `local/sources/base/drivers/input/i2c-hidd/`
|
||||
- **Work:**
|
||||
- Replace boot-protocol-only code with full Report Protocol parsing
|
||||
- Wire usage → evdev translation through the new crate
|
||||
|
||||
### Fix 3.4: intel-thc-hidd → redbear-hid-core — QUEUED
|
||||
- **Target:** `local/sources/base/drivers/input/intel-thc-hidd/`
|
||||
- **Work:**
|
||||
- Wire HID report decoding through the new crate
|
||||
- (Depends on Fix 2.1 which is DONE)
|
||||
|
||||
---
|
||||
|
||||
## P4: Network Driver Hardening
|
||||
|
||||
The audit identified gaps in MSI-X support, PHY handling, and modern virtio-net features.
|
||||
|
||||
### Fix 4.1: ixgbed MSI-X
|
||||
- **Target:** `local/sources/base/drivers/net/ixgbed/`
|
||||
- **Work:**
|
||||
- Enable MSI-X for the queue pairs
|
||||
- Set up per-queue interrupts
|
||||
|
||||
### Fix 4.2: RTL8168 PHY
|
||||
- **Target:** `local/sources/base/drivers/net/rtl8168d/`
|
||||
- **Work:**
|
||||
- PHY link state detection
|
||||
- Auto-negotiation
|
||||
- Speed/duplex configuration
|
||||
|
||||
### Fix 4.3: virtio-net control queue
|
||||
- **Target:** `local/sources/base/drivers/net/virtio-netd/`
|
||||
- **Work:**
|
||||
- Use the control virtqueue for MAC address setting
|
||||
- Implement the modern virtio-net 1.1 control queue
|
||||
|
||||
### Fix 4.4: RTL8139 PHY
|
||||
- **Target:** `local/sources/base/drivers/net/rtl8139d/`
|
||||
- **Work:**
|
||||
- PHY link state detection
|
||||
- Auto-negotiation
|
||||
|
||||
---
|
||||
|
||||
## P5: ACPI Completeness
|
||||
|
||||
The audit identified missing ACPI features: Embedded Controller, Thermal, Battery, Wake.
|
||||
|
||||
### Fix 5.1: ACPI Embedded Controller
|
||||
- **Target:** `local/sources/base/drivers/acpid/ec.rs`
|
||||
- **Work:**
|
||||
- EC transactions (read/write/query)
|
||||
- EC interrupts (SCI on EC events)
|
||||
- Used by many laptops for fan control, hotkeys, etc.
|
||||
|
||||
### Fix 5.2: ACPI Thermal
|
||||
- **Target:** `local/sources/base/drivers/acpid/`
|
||||
- **Work:**
|
||||
- Parse \_TZ (thermal zone) objects
|
||||
- Read \_TMP, \_TC1, \_TC2, \_TSP, \_PSV, \_CRT
|
||||
- Notify on critical temperature
|
||||
|
||||
### Fix 5.3: ACPI Battery
|
||||
- **Target:** `local/sources/base/drivers/acpid/`
|
||||
- **Work:**
|
||||
- Parse battery device (PNP0C0A)
|
||||
- Read \_BST (Battery Status) and \_BIF (Battery Information)
|
||||
- Notify on status change
|
||||
|
||||
### Fix 5.4: ACPI Wake
|
||||
- **Target:** `local/sources/base/drivers/acpid/`
|
||||
- **Work:**
|
||||
- Parse \_PRW (Power Resources for Wake)
|
||||
- Implement S1, S3 (suspend to RAM) transitions
|
||||
- Resume from S3 on wake event
|
||||
|
||||
---
|
||||
|
||||
## P6: Storage Driver Hardening (not started)
|
||||
|
||||
### Fix 6.1: AHCI NCQ
|
||||
- **Target:** `local/sources/base/drivers/storage/ahcid/`
|
||||
- **Work:**
|
||||
- Native Command Queuing for SATA SSDs
|
||||
- Read LOG_PAGE_LOG_DIRECTORY for drive capabilities
|
||||
|
||||
### Fix 6.2: NVMe TRIM/DISCARD
|
||||
- **Target:** `local/sources/base/drivers/storage/nvmed/`
|
||||
- **Work:**
|
||||
- Implement Dataset Management command for SSD TRIM
|
||||
|
||||
---
|
||||
|
||||
## P7: Audio Driver Hardening (not started)
|
||||
|
||||
### Fix 7.1: AC'97 full duplex
|
||||
- **Target:** `local/sources/base/drivers/audio/ac97d/`
|
||||
- **Work:**
|
||||
- PCM capture (record) in addition to playback
|
||||
- Mixer controls
|
||||
|
||||
### Fix 7.2: Intel HDA codec
|
||||
- **Target:** `local/sources/base/drivers/audio/ihdad/`
|
||||
- **Work:**
|
||||
- Full codec initialization
|
||||
- HDMI/DP audio support
|
||||
- Multiple streams per codec
|
||||
|
||||
---
|
||||
|
||||
## P8: Graphics Driver Hardening (not started)
|
||||
|
||||
### Fix 8.1: Intel iHD real implementation
|
||||
- **Target:** `local/sources/base/drivers/graphics/ihdgd/`
|
||||
- **Work:**
|
||||
- Use linux-kpi for full i915 compat
|
||||
- Real connector enumeration
|
||||
- Atomic modeset
|
||||
- GPU command submission
|
||||
|
||||
### Fix 8.2: virtio-gpu virgl
|
||||
- **Target:** `local/sources/base/drivers/graphics/virtio-gpud/`
|
||||
- **Work:**
|
||||
- 3D resource creation via virgl
|
||||
- Mature 3D support for QEMU
|
||||
|
||||
---
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
What's the impact of shipping as-is?
|
||||
- QEMU works (poll-mode USB, single-queue NVMe, no multi-touch)
|
||||
- Real hardware has degraded USB, no touchpad (intel-thc-hidd stub), no power button, no lid switch, no thermal protection
|
||||
|
||||
What's the minimum to ship Red Bear OS 0.3.0?
|
||||
- P1: xhcid MSI-X, xhci event ring growth, PCI multi-bus
|
||||
- P2: intel-thc-hidd HID, PS/2 set 2/3, NVMe multi-queue
|
||||
- P3: redbear-hid-core
|
||||
|
||||
What's the minimum to ship Red Bear OS 0.4.0 (KDE Plasma Wayland)?
|
||||
- All of P1, P2, P3
|
||||
- P4: ixgbed MSI-X, RTL8168 PHY
|
||||
- P5: ACPI thermal (for laptop safety)
|
||||
|
||||
What's the minimum to ship Red Bear OS 0.5.0 (real-hardware KDE)?
|
||||
- All of P1, P2, P3, P4
|
||||
- P5: full ACPI completeness
|
||||
- P6: AHCI NCQ, NVMe TRIM
|
||||
|
||||
---
|
||||
|
||||
## Verification Strategy
|
||||
|
||||
For each fix:
|
||||
1. `cargo check -p <package>` returns 0 errors
|
||||
2. (If applicable) `cargo test -p <package>` returns all tests passed
|
||||
3. (If applicable) QEMU bare-metal boot
|
||||
4. (If applicable) Real-hardware smoke test
|
||||
|
||||
Cross-cutting:
|
||||
- `cargo check --workspace` clean across all of `local/sources/base/`
|
||||
- `cargo check --workspace` clean across all of `local/recipes/`
|
||||
- All four audit documents are updated to mark the fixed items
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **MSI-X vector cap**: should we cap at 32, 64, or 128? Modern xHCI supports up to 1024 vectors.
|
||||
2. **Event ring max size**: 4096 TRBs? 8192? More?
|
||||
3. **NVMe queue count**: cap at 64, 128, or 256?
|
||||
4. **redbear-hid-core license**: MIT, Apache-2.0, or dual-licensed? Project preference is MIT.
|
||||
5. **HID quirks table**: how many quirks to include initially? 50? 100? 500?
|
||||
6. **ps2d set 3 priority**: is it actually used by any current hardware?
|
||||
|
||||
---
|
||||
|
||||
**Document version:** v6.0-impl3, 2026-06-10. Mesa, libdrm, PipeWire, WirePlumber Red Bear source forks were migrated to external patches (Rule 2) in June 2026; see `local/AGENTS.md` for the current policy. v6.0-impl2 updates: the 5 libdrm patches (generated against the deleted fork) were regenerated as 3 byte-equivalent patches against fresh upstream libdrm 2.4.125; the `pkgconf` typo in `local/recipes/libs/libdrm/recipe.toml` was fixed; the recipe's broken `[source].script` no-op was moved to `[build].script` with `template = "custom"` so `cookbook_apply_patches` actually runs. Wayland re-enabling: 4 KF6 packages flipped to `WITH_WAYLAND=ON`, libxkbcommon flipped to `-Denable-wayland=true`, kded6 wrapper replaced with `Environment=QT_QPA_PLATFORM=offscreen` in the systemd service file. Doc tree trimmed from 75 files to 18 canonical in `local/docs/`. redbear-compositor extended with `zwp_linux_explicit_synchronization_v1` (Phase 3.4, no-tearing) and `wp_presentation` (Phase 3.3, vblank timing) — 3 files (+349/-10), 2 new integration tests pass. v6.0-impl3 update: attempted `repo cook mesa` end-to-end. Found and fixed 2 recipe `rev` mismatches (ninja-build, sddm). Discovered that the relibc-install cross-compile toolchain prefix is stale (pre-dates the `utimensat` commit) and that the relibc P3-*.patch carriers in `recipes/core/relibc/` are broken symlinks to a deleted `local/patches/relibc/` directory. Per the user's "relibc is our internal project. We work on it directly without patches" policy, added `getloadavg` directly to the relibc source as a Rule 1 in-tree fork (not a patch), deleted the 33 broken P3-*.patch symlinks, and refreshed the relibc-install prefix with the fresh libc. Mesa build now blocked by libpciaccess 0.19 which has no Redox backend (upstream `#error "Unsupported OS"`).
|
||||
|
||||
v6.0-impl12 update (2026-06-11): **Mesa 24.0 BUILT successfully on x86_64-unknown-redox.** The `mesa.pkgar` artifact (169 MB) is in `repo/x86_64-unknown-redox/` with `libEGL.so.1.0.0`, `libgbm.so.1.0.0`, `libGLESv2.so.2.0.0`, `libGLESv1_CM.so.1.1.0`, `libOSMesa.so.8.0.0` all present. This is the gate the entire desktop path has been waiting for. Three mesa patches added in `local/patches/mesa/`:
|
||||
- `04-sys-ioccom-stub-header.patch` — provides a minimal Linux UAPI `sys/ioccom.h` in mesa's include tree (relibc doesn't ship one; the macros are pure compile-time encodings; runtime dispatch goes through libdrm's `drmIoctl` shim → `scheme:drm/`).
|
||||
- `05-vk-sync-wchar-include.patch` — adds `<wchar.h>` to `src/vulkan/runtime/vk_sync.h` so the `wchar_t` in win32 sync function pointer types resolves. relibc's `<vulkan/vulkan_core.h>` chain doesn't transitively pull `<wchar.h>` like glibc does.
|
||||
|
||||
Mesa recipe fix in `recipes/libs/mesa/recipe.toml`: dropped the stale `-lwayland-drm` from LDFLAGS. Per upstream libwayland 1.24, the standalone `libwayland-drm.so` was removed from the project in 2018 and merged into Mesa as a bundled static `libwayland_drm` library (see `src/egl/wayland/wayland-drm/meson.build` lines 23-50 and `src/egl/meson.build:132` `link_for_egl += libwayland_drm`). The `-lwayland-drm` was a stale flag from a non-Redox mesa recipe.
|
||||
|
||||
libwayland recipe change in `local/recipes/wayland/libwayland/recipe.toml`: the recipe uses `-Dscanner=false` (necessary because the Redox-target scanner binary has `/lib/ld64.so.1` as its ELF interpreter and can't be exec'd on the build host), which means libwayland doesn't install `wayland-scanner.pc`. Mesa's `meson.build:1995` does `dependency('wayland-scanner', native: true)` and needs a host-runnable path. The recipe now stages a `wayland-scanner.pc` that points to `/usr/bin/wayland-scanner` (the host binary), plus a symlink in `usr/bin/wayland-scanner` so the cookbook auto-extract populates mesa's sysroot.
|
||||
|
||||
Cumulative across v6.0-impl5/6/7/8/9/10/11/12:
|
||||
- 9 cookbook + recipe files changed
|
||||
- 2 vendored gnu-config files
|
||||
- 8 durable build artifacts now in repo: `pkg-config`, `libdrm`, `libgmp`, `gcc13` (131 MB) + `gcc13.cxx` (42 MB), `libpciaccess`, `wayland-protocols`, **and `mesa` (169 MB)**
|
||||
- 2 new mesa external patches (Rule 2) for sys/ioccom and wchar_t
|
||||
- 1 in-tree fork source committed (libpciaccess, Rule 1)
|
||||
- All changes staged, none committed (per "do not commit" instruction)
|
||||
|
||||
Phase 3 of the v6.0 console-to-KDE plan is **COMPLETE** (recipe + build verification). The desktop path can now proceed to the Qt6 → KF6 → KWin → SDDM chain.
|
||||
@@ -1,819 +0,0 @@
|
||||
# Red Bear OS — System Stability & Upstream Sync Improvement Plan
|
||||
|
||||
**Date:** 2026-07-08
|
||||
**Branch:** 0.3.1
|
||||
**Source of truth:** Linux kernel 7.1 (`local/reference/linux-7.1/`)
|
||||
**Status:** Archived historical plan — Phase 1 COMPLETE (2026-07-08), Phase 2 partially done,
|
||||
Phase 3.1 upstream sync COMPLETE (2026-07-19: all 9 forks pass
|
||||
`verify-fork-functions.sh`; base/kernel/relibc hand-merged onto latest upstream,
|
||||
see `local/docs/fork-push-status/`). Sections describing Phase 1 WIP states
|
||||
(32 uncommitted changes, prefix staleness detection, version drift to +rb0.3.1)
|
||||
are resolved and retained for history. Current stability work is tracked in
|
||||
`CONSOLE-TO-KDE-DESKTOP-PLAN.md` and the subsystem plans.
|
||||
|
||||
> **Archive note (2026-07-26):** This file moved to `local/docs/archived/` during the
|
||||
> round-5 stale-doc cleanup. Use `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for active
|
||||
> tracking, plus the subsystem plans it delegates to.
|
||||
|
||||
## Relationship to Other Plans
|
||||
|
||||
This plan is the **definitive authority for core system stability** (console, login, build system,
|
||||
versioning, upstream sync). It delegates subsystem-specific detail to specialized plans:
|
||||
|
||||
| Plan Document | Covers | When to Consult |
|
||||
|---|---|---|
|
||||
| `archived/IMPROVEMENT-PLAN.md` | USB/Wi-Fi/Bluetooth code quality audit findings (P0–P3) | USB, Wi-Fi, BT quality remediation |
|
||||
| `archived/IMPLEMENTATION-MASTER-PLAN.md` | Driver/subsystem feature gaps (storage, audio, input, CPU, virtio) | Driver feature implementation |
|
||||
| `CONSOLE-TO-KDE-DESKTOP-PLAN.md` | Desktop/KDE path from console to hardware-accelerated Plasma | Wayland, Mesa, KWin, SDDM |
|
||||
| `UPSTREAM-SYNC-PROCEDURE.md` | Per-component sync procedure for local forks | Executing individual fork syncs |
|
||||
| `archived/STUBS-FIX-PROGRESS.md` | Stub→real-code rewrite tracking | Replacing stubs with real implementations |
|
||||
| `BUILD-SYSTEM-IMPROVEMENTS.md` | Build system hardening, collision detection, manifests | Build system changes |
|
||||
| `ACPI-IMPROVEMENT-PLAN.md` | ACPI sleep, thermal, EC, power | ACPI improvements |
|
||||
| `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` | PCI IRQ, MSI-X, IOMMU, controllers | IRQ/PCI quality |
|
||||
| `DRM-MODERNIZATION-EXECUTION-PLAN.md` | GPU/DRM, KMS, Mesa | GPU driver maturity |
|
||||
| **This Plan** | **Core system stability, console/login, build, version drift, upstream sync** | **Everything else** |
|
||||
|
||||
This plan covers issues NOT addressed by the specialized plans above: fbcond login
|
||||
handling, console text corruption, getty PTY modernization, build script correctness,
|
||||
version drift across forks, upstream cherry-picks, and the 32+ WIP netstack/USB changes.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Stability — Unblock Builds and Boot (Immediate)
|
||||
|
||||
**Goal:** All known build blockers resolved. Red Bear OS boots to a working login prompt
|
||||
with correct Enter-key handling and no text corruption.
|
||||
|
||||
**Dependencies:** None (Phase 1 is the foundation for everything else).
|
||||
|
||||
### 1.1 Cherry-Pick 5 Critical fbcond/console Upstream Commits into Base Fork
|
||||
|
||||
**Context:** Upstream Redox base has merged critical fixes for fbcond (the framebuffer
|
||||
console daemon) and console-draw (the shared terminal rendering library). Red Bear's
|
||||
local base fork (`local/sources/base/`) may have some but not all of these applied.
|
||||
Verify and apply each one.
|
||||
|
||||
**Files involved:**
|
||||
- `local/sources/base/drivers/graphics/fbcond/src/text.rs` (177 lines)
|
||||
- `local/sources/base/drivers/graphics/console-draw/src/lib.rs` (460 lines)
|
||||
|
||||
#### Commit 1: d1b51888 — "Fix enter key in fbcond" (2026-07-02)
|
||||
|
||||
**What it does:** Adds scancode 0x1C (Enter/Return key) handler in fbcond's text input event loop.
|
||||
|
||||
**Red Bear current state:** VERIFY. The file at line 48-51 shows:
|
||||
```rust
|
||||
0x1C => {
|
||||
// Enter
|
||||
buf.extend_from_slice(b"\n");
|
||||
}
|
||||
```
|
||||
This appears already applied. If confirmed, mark as ✅ and move on.
|
||||
|
||||
**If missing:**
|
||||
- **File:** `local/sources/base/drivers/graphics/fbcond/src/text.rs`
|
||||
- **Action:** Add `0x1C => { buf.extend_from_slice(b"\n"); }` in the key_event.pressed match block
|
||||
- **Linux reference:** `drivers/tty/vt/keyboard.c:1421-1426` — Linux's `kbd_keycode()` → `K_ENTER` translation; the principle is identical: keycode → byte sequence injection
|
||||
|
||||
#### Commit 2: 5701459d — "Use font height rather than width" (2026-05-24)
|
||||
|
||||
**What it does:** Fixes text corruption in console-draw. The `char()` function used font width (8) instead of font height (16) when calculating font index, corrupting character glyph extraction for multi-byte characters.
|
||||
|
||||
**Red Bear current state:** VERIFY. The file at lines 215-217 shows:
|
||||
```rust
|
||||
let font_i = 16 * (character as usize);
|
||||
if font_i + 16 <= FONT.len() {
|
||||
for row in 0..16 {
|
||||
```
|
||||
This uses 16 (height) correctly. If confirmed, mark as ✅.
|
||||
|
||||
**If missing:**
|
||||
- **File:** `local/sources/base/drivers/graphics/console-draw/src/lib.rs`, function `char()`
|
||||
- **Action:** Change `let font_i = font.width() * (character as usize)` → `let font_i = 16 * (character as usize)`. Similarly change all references from `font.width()` to `font.height()` (which resolves to 16 for the standard 8×16 VGA font).
|
||||
- **Linux reference:** `drivers/video/fbdev/core/bitblit.c:288-310` — `bit_putcs()` uses `font->height` consistently; Linux never confuses font width with font height
|
||||
- **Verification:** Type characters 128-255 (extended ASCII). If accented characters render correctly, the fix is applied. If they show as random glyph fragments, the fix is missing.
|
||||
|
||||
#### Commit 3: f0ff6a79 — "buffer TextScreen writes while display map is unavailable" (2026-07-06)
|
||||
|
||||
**What it does:** When the display map is not yet available (during handoff/resize), buffer writes instead of dropping them. Flush after handoff completes.
|
||||
|
||||
**Red Bear current state:** VERIFY. The file at lines 13, 23, 132-176 shows:
|
||||
```rust
|
||||
pending_writes: Vec<Vec<u8>>, // line 13
|
||||
// line 139-147: buffer when map is None
|
||||
// line 152-176: flush_pending_writes()
|
||||
```
|
||||
This appears already applied. If confirmed, mark as ✅.
|
||||
|
||||
**If missing:**
|
||||
- **File:** `local/sources/base/drivers/graphics/fbcond/src/text.rs`
|
||||
- **Action:** Add `pending_writes: Vec<Vec<u8>>` field to `TextScreen` struct, buffer writes when `self.display.map.is_none()`, flush in `handle_handoff()` when map becomes available.
|
||||
- **Linux reference:** `drivers/tty/vt/vt.c:2920-2945` — Linux's `do_con_write()` buffers input when console is not yet fully initialized; the concept of "buffer until ready" is proven
|
||||
- **Verification:** Boot log should NOT show "fbcond: TextScreen::write() called while display map is None" warnings followed by lost boot messages. Early boot messages should appear after handoff.
|
||||
|
||||
#### Commit 4: e8f1b1a8 — "Do not send TextInputEvent for control characters" (2026-06-09)
|
||||
|
||||
**What it does:** Filters control characters from being emitted as text input events. Must be paired with commit d1b51888 (Enter handler) because Enter (`\n`) would otherwise be filtered as a control character.
|
||||
|
||||
**Red Bear current state:** VERIFY. Check if fbcond filters control characters (U+0000–U+001F, U+007F). The text.rs file at line 40-41 tracks `self.ctrl` for scancode 0x1D, and line 99 checks `c != '\0'`. A broader control-character filter may be needed.
|
||||
|
||||
**If missing:**
|
||||
- **File:** `local/sources/base/drivers/graphics/fbcond/src/text.rs`, `input()` method
|
||||
- **Action:** After character translation, skip emission if `c.is_control() && c != '\n'`. The `\n` (Enter) must be emitted — it was already handled by the 0x1C scancode branch.
|
||||
- **Linux reference:** `drivers/tty/vt/keyboard.c:1305-1315` — with `kbd->kbdmode == VC_UNICODE`, control characters are not directly emitted as Unicode; they are translated to escape sequences or terminal actions
|
||||
- **Verification:** Press Ctrl+C in the console. The terminal should receive `\x03` (ETX), not the literal character 'c'.
|
||||
|
||||
#### Commit 5: c3789b4e — "only perform a single write and assert the amount written" (2026-06-17)
|
||||
|
||||
**What it does:** Changes the console output path to use a single atomic write with an assertion on the written byte count, replacing a loop that could produce interleaved output.
|
||||
|
||||
**Red Bear current state:** VERIFY. Check the `write()` method in text.rs (line 132-150). The current implementation writes `buf` in one call and returns `Ok(buf.len())`. If this is already a single-write pattern, mark as ✅.
|
||||
|
||||
**If missing:**
|
||||
- **File:** `local/sources/base/drivers/graphics/fbcond/src/text.rs`, `write()` method
|
||||
- **Action:** Replace any multi-call write loop with a single `self.inner.write(map, buf, &mut self.input)` call that asserts `written == buf.len()`.
|
||||
- **Linux reference:** `drivers/tty/tty_io.c:1130-1150` — `do_tty_write()` writes in a loop for partial writes, but the Linux tty layer guarantees atomic line writes via `ldisc` operations
|
||||
|
||||
**Estimated time:** 2–4 hours to verify all 5 commits, apply any missing ones.
|
||||
**Dependencies:** None.
|
||||
|
||||
### 1.2 Fix Orphan `}` in xhcid/src/xhci/mod.rs
|
||||
|
||||
**Context:** The xhcid USB controller driver has 32 uncommitted WIP changes in the base fork. One of these may have introduced a structural issue in the mod.rs file.
|
||||
|
||||
**File:** `local/sources/base/drivers/usb/xhcid/src/xhci/mod.rs` (1844 lines)
|
||||
|
||||
**Action:**
|
||||
1. Run `cargo check` in the xhcid directory to identify any parse errors
|
||||
2. Inspect closing braces at lines 1814, 1822, 1827, 1831, 1844 — verify each closes the correct block
|
||||
3. If an orphan `}` exists:
|
||||
- Identify its matching opening brace
|
||||
- Either remove the orphan (if truly extra) or add the missing opening brace counterpart
|
||||
4. Run `rustfmt` on the file after fixing to normalize brace alignment
|
||||
|
||||
**Linux reference:** `drivers/usb/host/xhci.c` (7196 lines, Linux 7.1) — Linux's xHCI driver structure maps closely: capability init → operational regs → runtime regs → interrupter setup → command ring → event ring. Red Bear's `mod.rs` follows the same init sequence but is partitioned into submodules. Cross-reference Linux's `xhci_init()` flow (`xhci.c:4896-5100`) to ensure Red Bear's init is structurally complete.
|
||||
|
||||
**Estimated time:** 30 minutes
|
||||
**Dependencies:** None.
|
||||
|
||||
### 1.3 Fix Build Script Prefix Staleness Detection
|
||||
|
||||
**Context:** `build-redbear.sh` is supposed to detect stale prefix toolchains and trigger a rebuild. However, the docs say it "warns when prefix is stale" but it's unclear if it actually triggers the rebuild. Verify and harden.
|
||||
|
||||
**File:** `local/scripts/build-redbear.sh`
|
||||
|
||||
**Action:**
|
||||
1. Verify that staleness detection correctly compares `local/sources/<fork>/.git/HEAD` commit timestamps against `prefix/x86_64-unknown-redox/lib/rustlib/x86_64-unknown-redox/lib/libc.a` mtime
|
||||
2. Verify that when stale, the script actually runs `make prefix` before proceeding
|
||||
3. Add explicit "Prefix is stale — rebuilding..." and "Prefix rebuild complete" log messages
|
||||
4. Add CI flag `REDBEAR_SKIP_PREFIX_CHECK=1` for environments where prefix is known-good
|
||||
5. Document the exact detection logic in `local/docs/BUILD-SYSTEM-IMPROVEMENTS.md`
|
||||
|
||||
**Linux reference:** Linux kernel `Makefile:1310-1350` — `include/config/kernel.release` is the "staleness gate"; if any `Kconfig` or `Makefile` dependency is newer than the release file, the build system reconfigures. The same concept applies: if any fork commit is newer than the compiled prefix artifact, rebuild.
|
||||
|
||||
**Estimated time:** 1–2 hours
|
||||
**Dependencies:** None.
|
||||
|
||||
### 1.4 Sync All Cat 2 Fork Versions to `+rb0.3.1`
|
||||
|
||||
**Context:** Branch 0.3.1 was cut but not all forks have been version-bumped. Version drift between `Cargo.toml` fields causes Cargo resolver errors and subtle type mismatches.
|
||||
|
||||
**Files involved:**
|
||||
- `local/sources/base/Cargo.toml`
|
||||
- `local/sources/bootloader/Cargo.toml`
|
||||
- `local/sources/installer/Cargo.toml`
|
||||
- `local/sources/kernel/Cargo.toml`
|
||||
- `local/sources/libredox/Cargo.toml`
|
||||
- `local/sources/redoxfs/Cargo.toml`
|
||||
- `local/sources/redox-scheme/Cargo.toml`
|
||||
- `local/sources/relibc/Cargo.toml`
|
||||
- `local/sources/syscall/Cargo.toml`
|
||||
- `local/sources/userutils/Cargo.toml`
|
||||
|
||||
**Action:**
|
||||
```bash
|
||||
./local/scripts/sync-versions.sh # Sync Cat 1 + Cat 2 versions to 0.3.1
|
||||
./local/scripts/sync-versions.sh --check # Verify compliance
|
||||
```
|
||||
|
||||
**Verification:**
|
||||
- Every Cat 2 fork's `Cargo.toml` must have `version = "<upstream>+rb0.3.1"`
|
||||
- Every Cat 1 crate's `Cargo.toml` must have `version = "0.3.1"`
|
||||
- `cargo build` from the workspace root passes with no version mismatch warnings
|
||||
|
||||
**Estimated time:** 15 minutes (automated)
|
||||
**Dependencies:** None.
|
||||
|
||||
### 1.5 Stabilize Base Fork: Audit and Commit 32 WIP Changes
|
||||
|
||||
**Context:** The base fork (`local/sources/base/`, `submodule/base` branch) has ~32 uncommitted WIP changes across netstack (IPv6), USB quirks, and other subsystems. These are unstaged changes in the working tree that prevent clean builds and introduce non-deterministic behavior.
|
||||
|
||||
**Files involved:** The full `local/sources/base/` directory under the `submodule/base` branch.
|
||||
|
||||
**Action:**
|
||||
1. `cd local/sources/base && git status --short` — catalog all uncommitted changes
|
||||
2. Categorize each change:
|
||||
- **Ready** — change is stable, tests pass, commit it
|
||||
- **WIP** — change is in progress, stash it to a named stash or temporary branch, then commit only the stable parts
|
||||
- **Broken** — change introduces regressions, revert it (keep diff in `local/docs/evidence/` for reference)
|
||||
3. For each Ready change: write a focused commit message, commit to `submodule/base`
|
||||
4. For WIP changes: create a `local/docs/evidence/base-wip-changes-2026-07-08.diff` snapshot, then `git stash`
|
||||
5. Push the cleaned `submodule/base` branch
|
||||
6. Update the parent repo's submodule pointer
|
||||
|
||||
**Key subsystems to review:**
|
||||
| Subsystem | Path | Concern |
|
||||
|-----------|------|---------|
|
||||
| netstack | `local/sources/base/netstack/` | IPv6, filter, conntrack — 20+ recent commits visible in git log |
|
||||
| USB quirks | `local/sources/base/drivers/usb/xhcid/src/xhci/quirks.rs` | 49/50 quirks declared but not enforced |
|
||||
| xhcid | `local/sources/base/drivers/usb/xhcid/src/xhci/` | Event ring growth, BOS descriptors, DMA pool |
|
||||
|
||||
**Linux reference:** `drivers/usb/host/xhci-pci.c:101-160` — Linux's quirk enforcement uses per-device PCI ID tables at driver init, not runtime-only checks. The correct pattern: `pci_quirk_enable() → xhci_init_quirks() → hcd->quirks |= bitmask`.
|
||||
|
||||
**Estimated time:** 4–8 hours (depends on WIP complexity)
|
||||
**Dependencies:** None.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Login & Console Robustness (1–2 Weeks)
|
||||
|
||||
**Goal:** Login prompt works reliably. Text console has no corruption, correct keymap
|
||||
handling, and standard POSIX PTY APIs. Users can log in and interact with the shell.
|
||||
|
||||
**Dependencies:** Phase 1 (stable base fork, correct fbcond, synced versions).
|
||||
|
||||
### 2.1 Confirm All 5 fbcond/console Commits and Test End-to-End
|
||||
|
||||
**Context:** After Phase 1.1 verification and application, test the full console stack.
|
||||
|
||||
**Test plan:**
|
||||
1. Build `redbear-mini`: `./local/scripts/build-redbear.sh redbear-mini`
|
||||
2. Boot in QEMU: `make qemu`
|
||||
3. At the login prompt:
|
||||
- Press Enter — cursor should move to next line (commit 1 verify)
|
||||
- Type accented characters via AltGr combinations — no corruption (commit 2 verify)
|
||||
- Boot messages should all appear (commit 3 verify — no lost messages)
|
||||
- Press Ctrl+C — should send ^C to terminal, not a literal character (commit 4 verify)
|
||||
- Write multi-line shell scripts — output should not be interleaved (commit 5 verify)
|
||||
|
||||
**Failure mode:** If any test fails, the corresponding commit from 1.1 was not fully applied. Go back and fix.
|
||||
|
||||
**Estimated time:** 1–2 hours
|
||||
**Dependencies:** Phase 1.1 complete.
|
||||
|
||||
### 2.2 Cherry-Pick userutils getty Commit 2834434 (Standard PTY API)
|
||||
|
||||
**What it does:** Upstream userutils commit 2834434 updated getty to use the standard POSIX `ptsname()`, `grantpt()`, and `unlockpt()` functions instead of raw redox-specific PTY manipulation. This is the upstream approach to PTY management — it uses the standard C library API rather than raw scheme calls.
|
||||
|
||||
**Red Bear current state:** The local fork at `local/sources/userutils/src/bin/getty.rs` (285 lines) uses `libredox::call as redox` with raw `redox::read()`/`redox::write()` calls (lines 63-80). It does NOT use the standard POSIX PTY functions.
|
||||
|
||||
**Action:**
|
||||
1. Fetch upstream commit 2834434 from `https://gitlab.redox-os.org/redox-os/userutils`
|
||||
2. Cherry-pick onto the `submodule/userutils` branch
|
||||
3. Resolve conflicts (if any)
|
||||
4. Verify: `cargo build` in `local/sources/userutils/`
|
||||
5. Push to `submodule/userutils` branch
|
||||
6. Update parent repo submodule pointer
|
||||
7. Rebuild prefix: `touch relibc && make prefix` (std PTY functions need to be in libc.a)
|
||||
8. Full image: `./local/scripts/build-redbear.sh redbear-mini`
|
||||
|
||||
**Linux reference:**
|
||||
- `glibc/sysdeps/unix/sysv/linux/ptsname.c` — Linux implements `ptsname()` via `/dev/pts/<n>` enumeration
|
||||
- `glibc/sysdeps/unix/sysv/linux/grantpt.c` — Linux's `grantpt()` uses `/dev/ptmx` ioctl
|
||||
- The POSIX standard pattern: `posix_openpt(O_RDWR | O_NOCTTY) → grantpt(fd) → unlockpt(fd) → ptsname(fd) → open(slave_name)`. This is the same pattern relibc should expose via its cbindgen-generated `stdlib.h`.
|
||||
|
||||
**Verification:** After login, `tty` command should show a `/dev/pts/N` device (not a raw scheme path).
|
||||
|
||||
**Estimated time:** 2–4 hours
|
||||
**Dependencies:** Phase 1.5 (stable base fork), Phase 2.1 (console works).
|
||||
|
||||
### 2.3 Add Comprehensive Keymap Handling to fbcond
|
||||
|
||||
**Context:** fbcond currently has a hardcoded US keyboard layout with scancode→key mappings for basic keys (Enter, Backspace, arrows, Home, End, etc. — lines 43-104 of text.rs). There is no configurable keymap support.
|
||||
|
||||
**Action:**
|
||||
1. Add a `Keymap` struct that loads layout definitions from a TOML file (`/etc/fbcond/keymap.toml`)
|
||||
2. Replace the hardcoded `match key_event.scancode { ... }` with a table-driven lookup
|
||||
3. Default keymap: US QWERTY (current hardcoded mappings)
|
||||
4. Support at minimum: US, UK, DE, FR layouts
|
||||
5. Keymap format:
|
||||
```toml
|
||||
[keymap]
|
||||
name = "us"
|
||||
[keys."0x1C"]
|
||||
pressed = "\n"
|
||||
[keys."0x0E"]
|
||||
pressed = "\x7F"
|
||||
[keys."0x47"]
|
||||
pressed = "\x1B[H"
|
||||
```
|
||||
|
||||
**Linux reference:**
|
||||
- `drivers/tty/vt/defkeymap.map` — Linux's default keymap in `loadkeys` format
|
||||
- `drivers/tty/vt/keyboard.c:1050-1100` — `kbd_keycode()` dispatches via keymap table; the pattern is: scancode → keycode → (shift/altgr/ctrl modifier) → character
|
||||
- `tools/include/linux/input.h` — Linux keycode definitions
|
||||
|
||||
**What NOT to do:** Do NOT try to support all 500+ Linux keymaps. Start with the 4 most common layouts and add more as needed. Do NOT invent a new keymap format — use TOML with Linux keycode names where possible.
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 2.1.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Driver & Subsystem Updates (2–4 Weeks)
|
||||
|
||||
**Goal:** All local forks synchronized with upstream Redox's latest stable commits.
|
||||
Red Bear custom drivers (redbear-acmd, redbear-ecmd, redbear-ftdi, redbear-usbaudiod)
|
||||
updated to current redox-scheme API. Netstack and USB improvements integrated.
|
||||
|
||||
**Dependencies:** Phase 2 (stable console, working login).
|
||||
|
||||
### 3.1 Execute Full Upstream Sync for All 9 Local Forks
|
||||
|
||||
**Context:** All local forks have accumulated drift from upstream Redox. The `UPSTREAM-SYNC-PROCEDURE.md` defines the procedure. This is the systematic execution.
|
||||
|
||||
**Procedure (per fork):**
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
|
||||
# Step 1: Backup
|
||||
git fetch upstream --quiet
|
||||
TIMESTAMP=$(date +%Y%m%d)
|
||||
git branch backup-master-pre-upstream-sync-$TIMESTAMP master
|
||||
|
||||
# Step 2: Analyze divergence
|
||||
git merge-base master upstream/master
|
||||
git log --oneline upstream/master..master # Red Bear commits
|
||||
git log --oneline master..upstream/master # Upstream commits we're missing
|
||||
|
||||
# Step 3: Rebase
|
||||
git checkout master
|
||||
git rebase upstream/master
|
||||
# Resolve conflicts if any. Red Bear patches that upstream also has → drop.
|
||||
# Red Bear patches that upstream does not have → reapply cleanly.
|
||||
|
||||
# Step 4: Build verify
|
||||
cd /path/to/RedBear-OS
|
||||
./target/release/repo cook recipes/core/<component>
|
||||
|
||||
# Step 5: Push fork
|
||||
cd local/sources/<component>
|
||||
git push origin master:refs/heads/submodule/<component> -f
|
||||
|
||||
# Step 6: Update parent pointer
|
||||
cd /path/to/RedBear-OS
|
||||
git add local/sources/<component>
|
||||
git commit -m "submodule: sync <component> to upstream HEAD"
|
||||
```
|
||||
|
||||
**Order of sync (by dependency):**
|
||||
|
||||
| Order | Fork | Estimated upstream commits to merge | Risk |
|
||||
|-------|------|-------------------------------------|------|
|
||||
| 1 | `syscall` | ~5–15 | LOW — ABI-stable crate |
|
||||
| 2 | `libredox` | ~10–20 | LOW — wrappers |
|
||||
| 3 | `redox-scheme` | ~8–15 | MEDIUM — scheme API changes |
|
||||
| 4 | `redoxfs` | ~15–30 | MEDIUM — filesystem layer |
|
||||
| 5 | `relibc` | ~50–100 | HIGH — POSIX surface, cbindgen |
|
||||
| 6 | `kernel` | ~100–200 | HIGH — syscall ABI |
|
||||
| 7 | `bootloader` | ~10–20 | LOW — self-contained |
|
||||
| 8 | `base` | ~150–300 | VERY HIGH — 54 non-USB commits to review |
|
||||
| 9 | `userutils` | ~20–40 | LOW — utilities |
|
||||
| 10 | `installer` | ~5–15 | LOW — self-contained |
|
||||
|
||||
**For `base` specifically:** The upstream Redox base repo has ~54 non-USB commits plus USB stack commits. Red Bear has local USB quirks and netstack changes. The merge must:
|
||||
1. Apply upstream's 54 non-USB commits first
|
||||
2. Then reapply Red Bear's USB changes on top
|
||||
3. Carefully review for conflicts in `drivers/usb/xhcid/`, `netstack/`, and `drivers/graphics/fbcond/`
|
||||
|
||||
**Linux reference for merge strategy:**
|
||||
- `scripts/merge_config.sh` — Linux kernel uses a structured merge tool for Kconfig conflicts. The same principle applies: when upstream and local both modify the same file, the merge must respect the intent of both sides, not blindly pick one.
|
||||
- `Documentation/process/submitting-patches.rst:section "The canonical patch format"` — Linux's patch ordering rule: "logically separate changes → separate patches". Apply this: upstream changes first as a single logical unit, Red Bear changes second.
|
||||
|
||||
**Verification steps after each fork sync:**
|
||||
1. `cargo check` in the fork's working tree — 0 errors
|
||||
2. `repo cook <component>` from the RedBear-OS root — builds successfully
|
||||
3. `make prefix` (for relibc, kernel) — prefix rebuilt with new libc.a
|
||||
4. Full image build: `./local/scripts/build-redbear.sh redbear-mini` — boots
|
||||
|
||||
**Estimated time:** 16–32 hours (2–4 days per full-time contributor)
|
||||
**Dependencies:** Phase 2.3 (keymap handling — avoids merge conflicts in text.rs).
|
||||
|
||||
### 3.2 Update redbear-* Scheme Drivers to New redox-scheme API
|
||||
|
||||
**Context:** The `redox-scheme` crate has been updated (likely to 0.11.x or newer). Red Bear's custom scheme-based daemons need their API calls updated.
|
||||
|
||||
**Files involved:**
|
||||
- `local/recipes/core/redbear-acmd/source/` — Admin command service
|
||||
- `local/recipes/core/redbear-ecmd/source/` — Embedded controller service
|
||||
- `local/recipes/drivers/redbear-ftdi/source/` — FTDI USB-serial driver
|
||||
- `local/recipes/drivers/redbear-usbaudiod/source/` — USB audio driver
|
||||
|
||||
**Action (per driver):**
|
||||
1. Check `redox-scheme` version in `local/sources/redox-scheme/Cargo.toml`
|
||||
2. Update `[dependencies]` in each driver to match:
|
||||
```toml
|
||||
redox-scheme = { path = "../../../../../local/sources/redox-scheme" }
|
||||
```
|
||||
3. Fix any API breakage:
|
||||
- `Scheme` trait → may have new required methods
|
||||
- `SchemeMut` → may have new required methods
|
||||
- `Packet` struct → field names may have changed
|
||||
4. Run `cargo check` for each driver
|
||||
|
||||
**Linux reference:** `include/linux/usb/audio.h` — Linux's USB audio class driver interface. The principle is identical: when the kernel internal API changes, all class drivers must adapt. Redox's `redox-scheme` is analogous to Linux's `struct usb_driver`.
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 3.1 (scheme crate must be synced first).
|
||||
|
||||
### 3.3 Integrate Stable Netstack WIP Changes
|
||||
|
||||
**Context:** The base fork has ~20 recent netstack commits (IPv6, filter/conntrack, NAT, stats) visible in the git log. After Phase 1.5 stabilization, integrate the stable ones.
|
||||
|
||||
**Key netstack changes to integrate:**
|
||||
- ARP static add/del via netcfg
|
||||
- Route/gateway reading
|
||||
- Per-interface stats (rx_errors, tx_errors, rx_dropped)
|
||||
- Filter chain counters + verdicts
|
||||
- Conntrack (ICMP rate limiting, state tracking)
|
||||
- NAT (IP rewrite + table)
|
||||
- Bridge (FDB learn/age/lookup, 5 unit tests)
|
||||
- Promiscuous mode toggle
|
||||
- Qdisc (token bucket, priority queue)
|
||||
|
||||
**Linux reference:**
|
||||
| Red Bear netstack component | Linux 7.1 reference |
|
||||
|---|---|
|
||||
| Conntrack | `net/netfilter/nf_conntrack_proto_icmp.c` — ICMP state machine |
|
||||
| NAT | `net/netfilter/nf_nat_core.c:480-550` — `nf_nat_setup_info()` |
|
||||
| Filter counters | `net/netfilter/xt_statistic.c` — per-rule counters |
|
||||
| Qdisc | `net/sched/sch_tbf.c` — token bucket filter |
|
||||
| Bridge FDB | `net/bridge/br_fdb.c:150-250` — `fdb_create()`, `fdb_delete()` |
|
||||
|
||||
**Estimated time:** 8–16 hours
|
||||
**Dependencies:** Phase 1.5, Phase 3.1.
|
||||
|
||||
### 3.4 Integrate USB Quirk Enforcement
|
||||
|
||||
**Context:** The existing `archived/IMPROVEMENT-PLAN.md` Section 3.3 identifies 49/50 xHCI quirks declared but not enforced at runtime. This is a critical gap for supporting real hardware.
|
||||
|
||||
**File:** `local/sources/base/drivers/usb/xhcid/src/xhci/quirks.rs`
|
||||
|
||||
**Priority enforcement gaps (from archived/IMPROVEMENT-PLAN.md):**
|
||||
|
||||
| Quirk | Affected HW | Action |
|
||||
|-------|-------------|--------|
|
||||
| `MISSING_CAS` | Early AMD | Skip command abort semaphore wait |
|
||||
| `BROKEN_STREAMS` | Fresco Logic, Etron | Skip stream context array init |
|
||||
| `ZERO_64B_REGS` | Renesas uPD720202 | Split 64-bit regs into 2×32-bit writes |
|
||||
| `WRITE_64_HI_LO` | Some Renesas | Write high half first |
|
||||
| `BROKEN_PORT_PED` | Some | Skip port enable polling |
|
||||
|
||||
**Linux reference:** `drivers/usb/host/xhci-pci.c:101-160` — `xhci_pci_quirks()` is the canonical quirk enforcement table. Pattern:
|
||||
```c
|
||||
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1042)
|
||||
xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL;
|
||||
```
|
||||
|
||||
**See also:** `archived/IMPROVEMENT-PLAN.md` § 3.3 for the complete quirk enforcement gap analysis.
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 1.5, Phase 3.1.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Kernel & POSIX Gap Closing (4–8 Weeks)
|
||||
|
||||
**Goal:** relibc POSIX coverage reaches 95%+. Kernel supports all credential/signal/IPC
|
||||
syscalls needed by modern software. Input device handling is comprehensive.
|
||||
|
||||
**Dependencies:** Phase 3 (stable forks, updated dependencies).
|
||||
|
||||
### 4.1 Apply Upstream Kernel and relibc Merges
|
||||
|
||||
**Context:** After Phase 3.1 syncs all forks to upstream HEAD, this phase focuses on closing the remaining Red Bear-specific gaps — the POSIX functions, syscalls, and capabilities that upstream Redox still doesn't have but Red Bear needs for desktop software compatibility.
|
||||
|
||||
**relibc POSIX gaps to close:**
|
||||
|
||||
| Function | Status | Linux reference | Priority |
|
||||
|----------|--------|-----------------|----------|
|
||||
| `eventfd` | ✅ Already has patch carrier (`local/patches/relibc/P3-eventfd-*.patch`) | `fs/eventfd.c` | — |
|
||||
| `signalfd` | ✅ Already has patch carrier | `fs/signalfd.c` | — |
|
||||
| `timerfd` | ✅ Already has patch carrier | `fs/timerfd.c` | — |
|
||||
| `waitid` | ✅ Already has patch carrier | `kernel/exit.c:1735-1770` | — |
|
||||
| `sem_open/sem_close/sem_unlink` | ✅ RESOLVED in recent commits | `ipc/sem.c` | — |
|
||||
| `preadv/pwritev` | MISSING | `fs/read_write.c:970-1025` | MEDIUM |
|
||||
| `copy_file_range` | MISSING | `fs/read_write.c:1505-1580` | MEDIUM |
|
||||
| `memfd_create` | MISSING | `mm/memfd.c:280-340` | MEDIUM |
|
||||
| `fexecve` | MISSING | `fs/exec.c:1450-1500` | LOW |
|
||||
| `getrandom` (syscall, not /dev) | MISSING | `drivers/char/random.c:2300-2350` | MEDIUM |
|
||||
|
||||
**Kernel syscalls to add:**
|
||||
|
||||
| Syscall | Linux reference | Priority |
|
||||
|---------|-----------------|----------|
|
||||
| `SYS_MEMFD_CREATE` | `mm/memfd.c` | MEDIUM |
|
||||
| `SYS_COPY_FILE_RANGE` | `fs/read_write.c` | MEDIUM |
|
||||
|
||||
**Action (per function):**
|
||||
1. Study the Linux implementation in `local/reference/linux-7.1/`
|
||||
2. Implement in `local/sources/relibc/src/header/<func>/mod.rs`
|
||||
3. Add cbindgen config in `cbindgen.toml`
|
||||
4. Create durable patch: `local/patches/relibc/P<n>-<func>.patch`
|
||||
5. Rebuild prefix: `touch relibc && make prefix`
|
||||
6. Test: write a small C program that calls the function
|
||||
|
||||
**"Do not reinvent" rule:** Linux 7.1's implementations are battle-tested. For each function, read the Linux source in `local/reference/linux-7.1/`, understand the algorithm, port the logic into Rust for relibc. Do NOT invent novel implementations.
|
||||
|
||||
**Estimated time:** 24–40 hours (3–5 functions per week)
|
||||
**Dependencies:** Phase 3.1 (synced relibc and kernel forks).
|
||||
|
||||
### 4.2 Comprehensive Input Device Handling
|
||||
|
||||
**Context:** The current input subsystem handles basic keyboard and mouse via PS/2 and USB HID. Desktop software expects evdev-compatible input with full keycode→keysym translation, touchpad gesture support, and multi-touch.
|
||||
|
||||
**Linux reference files to study:**
|
||||
- `drivers/hid/hid-input.c:1000-1200` — HID→input event mapping
|
||||
- `drivers/input/evdev.c:250-400` — evdev interface (ioctl, read, poll)
|
||||
- `drivers/input/input.c:150-350` — input core (device registration, event dispatch)
|
||||
- `include/uapi/linux/input-event-codes.h` — complete key/button/axis code definitions
|
||||
|
||||
**Action plan:**
|
||||
1. Study the Linux `hid-input.c` → `input.c` → `evdev.c` pipeline
|
||||
2. Implement equivalent in Red Bear's `usbhidd` + `ps2d` → `inputd` → `evdevd` chain
|
||||
3. Add evdev ioctl support (EVIOCGNAME, EVIOCGID, EVIOCGKEYCODE)
|
||||
4. Add input repeat handling (Linux: `drivers/input/input.c:150-200` — `input_repeat_key`)
|
||||
5. Add LED handling (caps lock, num lock, scroll lock)
|
||||
6. Add mouse acceleration curves (Linux: `drivers/input/mousedev.c`)
|
||||
|
||||
**What NOT to do:** Do NOT implement support for exotic input devices (gamepads, joysticks, drawing tablets, touchscreens) in this phase. Keyboard + mouse + basic touchpad is sufficient for desktop. Add more later.
|
||||
|
||||
**Estimated time:** 16–24 hours
|
||||
**Dependencies:** Phase 3.1, Phase 3.4 (USB quirk enforcement ensures HID devices enumerate reliably).
|
||||
|
||||
### 4.3 Stub Replacement: Identify and Replace Remaining Stubs
|
||||
|
||||
**Context:** The project has a zero-tolerance stub policy (`local/AGENTS.md` § STUB AND WORKAROUND POLICY). The `archived/STUBS-FIX-PROGRESS.md` tracks the stub→real-code rewrite campaign. Audit the remaining stubs and prioritize fixes.
|
||||
|
||||
**Action:**
|
||||
1. Run a workspace-wide grep for stub patterns:
|
||||
```bash
|
||||
grep -rn 'unimplemented!\|todo!\|FIXME\|HACK\|WORKAROUND\|stub' \
|
||||
local/sources/ local/recipes/ --include='*.rs' | grep -v 'test\|/target/\|/debug/'
|
||||
```
|
||||
2. Categorize by subsystem and priority
|
||||
3. Fix in order: (1) blocking stubs → (2) correctness stubs → (3) performance stubs → (4) feature stubs
|
||||
4. Each fix must be a real implementation, not another stub
|
||||
|
||||
**Common stub patterns and their correct fixes:**
|
||||
|
||||
| Stub Pattern | Correct Fix |
|
||||
|---|---|
|
||||
| `unimplemented!("event ring growth")` | Implement `grow_event_ring()` per `archived/IMPROVEMENT-PLAN.md` § 3.1 |
|
||||
| `todo!("BOS descriptor")` | Un-comment `fetch_bos_desc()` per `archived/IMPROVEMENT-PLAN.md` § 3.2 |
|
||||
| `return Err(ENOSYS)` for a known syscall | Implement the syscall in kernel or relibc |
|
||||
| `#![allow(warnings)]` in xhcid | Fix the underlying warnings, then remove |
|
||||
| `rate_idx = 0` hardcoded | Implement Minstrel rate scaling per `archived/IMPROVEMENT-PLAN.md` § 6.3 |
|
||||
|
||||
**See also:**
|
||||
- `archived/IMPROVEMENT-PLAN.md` — 35 items covering USB/WiFi/BT stubs
|
||||
- `archived/STUBS-FIX-PROGRESS.md` — ~517 TODO/FIXME items tracked
|
||||
|
||||
**Estimated time:** 16–32 hours (ongoing across Phase 4)
|
||||
**Dependencies:** Phase 3.1 (synced forks provide the correct APIs to implement against).
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Bare Metal Validation (1–2 Weeks)
|
||||
|
||||
**Goal:** Red Bear OS boots on real AMD Ryzen hardware. ACPI power management works.
|
||||
USB storage enumerates. Wi-Fi driver loads (if hardware present). Production readiness
|
||||
baseline established.
|
||||
|
||||
**Dependencies:** Phase 4 (complete POSIX and input support).
|
||||
|
||||
### 5.1 AMD Ryzen Bare Metal Boot Validation
|
||||
|
||||
**Context:** Red Bear OS was previously verified on Ryzen Threadripper (128-thread). This validation updates to the current 0.3.1 state and tests all subsystems.
|
||||
|
||||
**Hardware requirements:**
|
||||
- AMD Ryzen system (any Zen 2/3/4 generation)
|
||||
- UEFI firmware
|
||||
- USB flash drive for ISO
|
||||
- Optional: serial console for log capture
|
||||
|
||||
**Test plan:**
|
||||
1. Build ISO: `./local/scripts/build-redbear.sh redbear-full`
|
||||
2. Write ISO to USB: `dd if=build/x86_64/redbear-full.iso of=/dev/sdX bs=4M status=progress`
|
||||
3. Boot from USB (UEFI mode)
|
||||
4. Verify checklist:
|
||||
|
||||
| Check | Expected | Log evidence |
|
||||
|-------|----------|-------------|
|
||||
| UEFI boot | Bootloader loads, Red Bear splash | Boot log |
|
||||
| ACPI init | RSDP found, MADT parsed, CPUs enumerated | `acpid:` lines |
|
||||
| SMP bringup | All cores online | `/proc/cpuinfo` or `nproc` |
|
||||
| PCI enumeration | Devices listed | `pcid:` lines |
|
||||
| NVMe/SATA detect | Storage devices found | `nvmed:` or `ahcid:` lines |
|
||||
| USB xHCI init | Controller found, ports enumerated | `xhcid:` lines |
|
||||
| Login prompt | `redbear login:` appears | Console screenshot |
|
||||
| Login succeeds | Shell prompt after `user`/`password` | Console screenshot |
|
||||
| Network (if wired) | DHCP address obtained | `ip addr` equivalent |
|
||||
| ACPI shutdown | `poweroff` halts cleanly | System powers off |
|
||||
|
||||
5. Capture logs: serial console output, photos of any panic screens
|
||||
6. File bugs for any failures with exact hardware model, firmware version, and failure point
|
||||
|
||||
**Estimated time:** 4–8 hours (hardware setup + testing)
|
||||
**Dependencies:** All prior phases.
|
||||
|
||||
### 5.2 ACPI Power Management Validation
|
||||
|
||||
**Context:** The `ACPI-IMPROVEMENT-PLAN.md` documents the current ACPI state: RSDP/SDT checksum verified, MADT types parsed, FADT shutdown/reboot via `\_S5`, but robustness gaps remain.
|
||||
|
||||
**Files involved:**
|
||||
- `local/sources/base/drivers/acpi/` — ACPI daemon
|
||||
- `local/sources/base/drivers/hardware/acpid/` — AML interpreter
|
||||
|
||||
**Test plan:**
|
||||
1. Verify `\_S5` (shutdown): `poweroff` command → system powers off
|
||||
2. Verify reset register: `reboot` command → system warm-boots
|
||||
3. Verify `\_PS0`/`\_PS3`: CPU cores enter/exit power states (check via `redbear-power` TUI)
|
||||
4. Verify `\_PPC`: CPU frequency scaling (check via `redbear-power`)
|
||||
5. Test sleep states (S3 suspend-to-RAM):
|
||||
- `echo mem > /sys/power/state` or equivalent
|
||||
- System suspends
|
||||
- Wake via keyboard or power button
|
||||
- System resumes with working display and input
|
||||
|
||||
**Linux reference:**
|
||||
- `drivers/acpi/sleep.c:600-700` — `acpi_suspend_enter()` for S3
|
||||
- `drivers/acpi/processor_idle.c:900-1050` — C-state management
|
||||
- `arch/x86/kernel/acpi/wakeup_64.S` — x86_64 wakeup trampoline
|
||||
|
||||
**What to skip initially:** S4 (hibernate-to-disk) — requires full swap support. S3 (suspend-to-RAM) is the priority.
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 5.1 (bare metal access).
|
||||
|
||||
### 5.3 USB Storage and HID Validation
|
||||
|
||||
**Context:** USB storage (usbscsid) and HID (usbhidd) drivers need real hardware testing. QEMU testing covers the happy path; real hardware covers edge cases.
|
||||
|
||||
**Test plan:**
|
||||
1. USB mass storage (flash drive):
|
||||
- Insert USB flash drive
|
||||
- Verify `usbscsid` auto-spawns
|
||||
- Verify device appears as `/scheme/usbscsid/<n>`
|
||||
- Mount (if filesystem support is ready)
|
||||
- Read/write test
|
||||
- Hot-unplug while idle (should log, not panic)
|
||||
2. USB keyboard:
|
||||
- Boot with USB keyboard attached (no PS/2 keyboard)
|
||||
- Verify `usbhidd` detects keyboard
|
||||
- Verify typing works at login prompt
|
||||
- Verify modifier keys (Shift, Ctrl, Alt)
|
||||
3. USB mouse:
|
||||
- Attach USB mouse
|
||||
- Verify `usbhidd` detects mouse
|
||||
- Verify cursor movement (if graphical session is running)
|
||||
|
||||
**Linux reference:** `drivers/usb/storage/usb.c:1050-1100` — `usb_stor_control_thread()` with proper error recovery on device disconnect. Red Bear's usbscsid must handle the same scenario: device removed mid-transfer → error, not panic.
|
||||
|
||||
**See also:** `archived/IMPROVEMENT-PLAN.md` § 2.1 (usbscsid `.unwrap()` removal) — this must be done before hardware testing.
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 5.1, `archived/IMPROVEMENT-PLAN.md` P0 items complete.
|
||||
|
||||
### 5.4 Wi-Fi and Bluetooth Maturity Assessment
|
||||
|
||||
**Context:** Intel iwlwifi has expanded PCI ID table (37 devices, was 7), mini-MVM layer, and firmware TLV parser. Assess readiness for first hardware test.
|
||||
|
||||
**Test plan:**
|
||||
1. Verify iwlwifi driver builds and is in the ISO: `grep iwlwifi build/x86_64/redbear-full.iso.manifest`
|
||||
2. Boot on hardware with Intel Wi-Fi (AC 7260, 8260, 9260, AX200, AX210)
|
||||
3. Check `pcid:` log for the Wi-Fi device — it should be enumerated
|
||||
4. Check `iwlwifi:` log for firmware load status
|
||||
5. If firmware loads: attempt scan (`redbear-wifictl scan` or equivalent)
|
||||
6. If scan succeeds: attempt connection to an open network
|
||||
7. File bugs for any failure with PCI vendor/device ID, firmware version, and log excerpt
|
||||
|
||||
**Linux reference:**
|
||||
- `drivers/net/wireless/intel/iwlwifi/pcie/drv.c:785-830` — Linux's complete PCI ID table. Cross-reference Red Bear's table against this.
|
||||
- `drivers/net/wireless/intel/iwlwifi/fw/file.h` — firmware TLV structure (same as Red Bear's `linux_mvm.c`)
|
||||
- `drivers/net/wireless/intel/iwlwifi/mvm/fw.c:300-500` — firmware init sequence
|
||||
|
||||
**See also:**
|
||||
- `archived/IMPROVEMENT-PLAN.md` § 6 — Wi-Fi subsystem improvements
|
||||
- `WIFI-IMPLEMENTATION-PLAN.md` — Wi-Fi architecture plan
|
||||
|
||||
**Estimated time:** 4–8 hours
|
||||
**Dependencies:** Phase 5.1, `archived/IMPROVEMENT-PLAN.md` P1-P2 Wi-Fi items.
|
||||
|
||||
---
|
||||
|
||||
## Cross-Cutting: "Do Not Reinvent the Wheel" — Linux Kernel Reference Map
|
||||
|
||||
For every major subsystem in Red Bear OS, consult the Linux 7.1 reference BEFORE implementing.
|
||||
Linux's implementations are battle-tested over 30+ years. Porting proven algorithms is always
|
||||
preferable to inventing heuristics.
|
||||
|
||||
### Console/TTY Subsystem
|
||||
|
||||
| Red Bear Component | Linux 7.1 Reference | What to Study |
|
||||
|---|---|---|
|
||||
| `fbcond/src/text.rs` | `drivers/tty/vt/keyboard.c` | Keycode→character translation, modifier handling |
|
||||
| `console-draw/src/lib.rs` | `drivers/video/fbdev/core/bitblit.c` | Font rendering, glyph extraction, damage tracking |
|
||||
| `console-draw` resize | `drivers/tty/vt/vt.c:resize_screen()` | Console resize: row copy, cursor preservation |
|
||||
| `ptyd` | `drivers/tty/pty.c` | PTY master/slave pair, packet mode, window size ioctls |
|
||||
|
||||
### Input Subsystem
|
||||
|
||||
| Red Bear Component | Linux 7.1 Reference | What to Study |
|
||||
|---|---|---|
|
||||
| `ps2d` | `drivers/input/serio/` | PS/2 protocol, serio bus abstraction |
|
||||
| `usbhidd` | `drivers/hid/usbhid/` | HID report parsing, input mapping |
|
||||
| `evdevd` | `drivers/input/evdev.c` | evdev ioctl, read semantics, SYN_REPORT |
|
||||
| `inputd` | `drivers/input/input.c` | Input core: registration, dispatch, repeat, LED |
|
||||
|
||||
### USB Subsystem
|
||||
|
||||
| Red Bear Component | Linux 7.1 Reference | What to Study |
|
||||
|---|---|---|
|
||||
| `xhcid` init | `drivers/usb/host/xhci.c:4896-5100` | Controller init sequence |
|
||||
| `xhcid` quirks | `drivers/usb/host/xhci-pci.c:101-160` | Quirk table + enforcement |
|
||||
| `xhcid` event ring | `drivers/usb/host/xhci-ring.c:550-590` | Ring expansion, overflow handling |
|
||||
| `xhcid` TRB | `drivers/usb/host/xhci-ring.c:2400-2600` | Completion handling, EDTLA |
|
||||
| `usbhubd` | `drivers/usb/core/hub.c` | Port power, reset, enumeration |
|
||||
| `usbscsid` | `drivers/usb/storage/usb.c` | BOT/CBW/CSW protocol |
|
||||
|
||||
### Netstack Subsystem
|
||||
|
||||
| Red Bear Component | Linux 7.1 Reference | What to Study |
|
||||
|---|---|---|
|
||||
| `netstack` filter | `net/netfilter/` | Conntrack, NAT, filter chains |
|
||||
| `netstack` bridge | `net/bridge/br_fdb.c` | MAC learning, aging |
|
||||
| `netstack` qdisc | `net/sched/` | Token bucket, priority queue |
|
||||
| `e1000d` | `drivers/net/ethernet/intel/e1000/` | Register-level init, interrupt handling |
|
||||
|
||||
### ACPI/Power Subsystem
|
||||
|
||||
| Red Bear Component | Linux 7.1 Reference | What to Study |
|
||||
|---|---|---|
|
||||
| `acpid` init | `drivers/acpi/acpica/` | ACPICA namespace init |
|
||||
| `acpid` shutdown | `drivers/acpi/sleep.c:600-750` | `\_S5`, PM1a/PM1b register write |
|
||||
| `acpid` power states | `drivers/acpi/processor_idle.c` | C-states, P-states |
|
||||
| `thermald` | `drivers/thermal/` | Thermal zone management |
|
||||
|
||||
### POSIX/GNU Compatibility (relibc)
|
||||
|
||||
| Function | Linux 7.1 Reference | What to Study |
|
||||
|----------|---------------------|---------------|
|
||||
| `eventfd` | `fs/eventfd.c:60-120` | Counter semantics, POLLIN/POLLOUT |
|
||||
| `signalfd` | `fs/signalfd.c:80-200` | Signal queue, siginfo packing |
|
||||
| `timerfd` | `fs/timerfd.c:200-350` | CLOCK_MONOTONIC, CLOCK_REALTIME, cancel |
|
||||
| `preadv/pwritev` | `fs/read_write.c:970-1025` | Scatter-gather I/O |
|
||||
| `copy_file_range` | `fs/read_write.c:1505-1580` | Offloaded copy |
|
||||
| `sem_open` | `ipc/sem.c:400-550` | Named semaphore, `/dev/shm` backing |
|
||||
| `posix_spawn` | `kernel/fork.c:2900-2950` | Spawn without fork+exec |
|
||||
|
||||
### General Advice
|
||||
|
||||
1. **Before writing any new algorithm**, check if Linux has an equivalent. If yes, port the algorithm structure (not the code — we're Rust, Linux is C).
|
||||
2. **For data structures**, prefer Linux's patterns: Red-black trees (`rbtree`), radix trees, linked lists (`list_head`), hash tables. Red Bear should use Rust equivalents (`BTreeMap`, `HashMap`, `VecDeque`).
|
||||
3. **For quirk tables**, ALWAYS cross-reference Linux's `pci_ids.h`, `xhci-pci.c`, `usb_quirks.h`. Linux has already identified every quirky device. Port the table, do not rediscover bugs.
|
||||
4. **For error recovery**, Linux's pattern is: log the error, return -EIO/-EINVAL/-ENOMEM, do NOT panic. Apply this universally.
|
||||
5. **For timing/delays**, Linux uses `msleep()`, `usleep_range()`, `udelay()`. Red Bear should use equivalent primitives from `libredox` or `std::thread::sleep`. Never use busy-wait loops without bounded timeouts.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Execution Order and Milestones
|
||||
|
||||
| Phase | Weeks | Key Deliverable | Blocks |
|
||||
|-------|-------|-----------------|--------|
|
||||
| **Phase 1** | Week 1 | All build blockers resolved. Clean base fork. Synced versions. | Nothing |
|
||||
| **Phase 2** | Weeks 1–2 | Login-prompt works. Enter key, no text corruption, working PTY. | Phase 1 |
|
||||
| **Phase 3** | Weeks 2–4 | All 9 forks synced to upstream. Netstack improved. USB quirks enforced. | Phase 2 |
|
||||
| **Phase 4** | Weeks 4–8 | relibc 95% POSIX. Kernel syscalls complete. Input handling mature. | Phase 3 |
|
||||
| **Phase 5** | Weeks 8–10 | Bare-metal boot proven. ACPI S3 sleep. USB storage/HID tested. Wi-Fi assessed. | Phase 4 |
|
||||
|
||||
**Total: 10 weeks to production-ready baseline.**
|
||||
|
||||
### Immediate Actions (Today)
|
||||
|
||||
1. **Run `sync-versions.sh --check`** — identify version drift immediately
|
||||
2. **`cd local/sources/base && git status --short`** — catalog WIP changes
|
||||
3. **`cargo check` on xhcid** — confirm orphan `}` issue exists
|
||||
4. **Read `archived/IMPROVEMENT-PLAN.md` P0 items** — these are the USB safety fixes that block hardware testing
|
||||
5. **Read `UPSTREAM-SYNC-PROCEDURE.md`** — prepare for Phase 3 fork syncs
|
||||
|
||||
### Ongoing Discipline
|
||||
|
||||
- Every commit to a local fork MUST also update the parent repo's submodule pointer
|
||||
- Every upstream cherry-pick MUST be tested with `cargo check` + `repo cook` before push
|
||||
- Every stub fixed MUST update `archived/STUBS-FIX-PROGRESS.md`
|
||||
- Every new Linux algorithm ported MUST include a comment referencing the specific Linux 7.1 file and line range
|
||||
@@ -1,829 +0,0 @@
|
||||
# Upstream Sync Procedure for Local Forks
|
||||
|
||||
> **SUPERSEDED (2026-07-27):** This document's PCI-driver-spawner sections
|
||||
> were originally written during the 2026-07-20 consolidation, when PCI driver
|
||||
> spawning was consolidated on `pcid-spawner`. **That model is obsolete.**
|
||||
> `pcid-spawner` was **retired and removed** on 2026-07-24;
|
||||
> `driver-manager` (`local/recipes/system/driver-manager/`) is now the sole
|
||||
> live PCI match/claim/spawn daemon in every `redbear-*` config
|
||||
> (operator-ratified cutover, 2026-07-23/24). The canonical current authority
|
||||
> is `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v5.6, 2026-07-27).
|
||||
>
|
||||
> **Moved to `local/docs/archived/` on 2026-07-27.** Kept here as historical
|
||||
> reference for the upstream-sync *procedure* only. The general procedure
|
||||
> (Steps 1–12, the package-specific notes, the keep-vs-drop decision matrix,
|
||||
> and the rollback procedure) is still valid. The two PCI-architecture
|
||||
> sections at the end ("driver-manager: LIVE" and "PCI Driver Spawning
|
||||
> Architecture (current: driver-manager)") have been updated in-place to
|
||||
> reflect the completed cutover; each carries a `> HISTORICAL NOTE` block
|
||||
> quoting what it said pre-cutover.
|
||||
|
||||
**Created:** 2026-06-18
|
||||
**Scope:** relibc, kernel, bootloader, installer, redoxfs, userutils, base
|
||||
**Baseline:** Red Bear OS 0.1.0 release archive (legacy); current development is on the 0.3.1 branch with sources from local/sources/ forks
|
||||
|
||||
## Purpose
|
||||
|
||||
Red Bear OS maintains local forks of core Redox components. Upstream Redox is
|
||||
actively developed and regularly merges refactoring, bug fixes, and new
|
||||
features. This document defines the **standard procedure** for updating each
|
||||
local fork to the latest upstream HEAD and re-applying Red Bear-specific
|
||||
changes on top.
|
||||
|
||||
This is a **repeatable, per-package operation**. Every base system package
|
||||
must go through this process periodically to avoid accumulating fork drift.
|
||||
|
||||
## When to Sync
|
||||
|
||||
- A Rust nightly bump causes compile errors in the fork (unstable API changes).
|
||||
- Upstream adds features we were manually patching (eliminates a Red Bear patch).
|
||||
- Accumulated fork drift makes rebasing individual patches impractical.
|
||||
- Before a new Red Bear OS release.
|
||||
- When a bug in the fork is already fixed upstream.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
# Ensure upstream remote exists in the fork repo
|
||||
cd local/sources/<component>
|
||||
git remote -v
|
||||
# Should show: upstream -> https://gitlab.redox-os.org/redox-os/<component>.git
|
||||
|
||||
# If missing:
|
||||
git remote add upstream https://gitlab.redox-os.org/redox-os/<component>.git
|
||||
```
|
||||
|
||||
## Procedure
|
||||
|
||||
### Step 1: Backup Current State
|
||||
|
||||
**Never skip this.** The backup branch is your rollback point.
|
||||
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
git fetch upstream --quiet
|
||||
|
||||
# Create timestamped backup branch
|
||||
git branch backup-master-pre-upstream-update-$(date +%Y%m%d) master
|
||||
|
||||
# Verify
|
||||
git log --oneline -1 backup-master-pre-upstream-update-*
|
||||
```
|
||||
|
||||
### Step 2: Analyze Divergence
|
||||
|
||||
Understand what you have vs what upstream has:
|
||||
|
||||
```bash
|
||||
# Latest upstream HEAD
|
||||
git log --oneline upstream/master -3
|
||||
|
||||
# Divergence point (merge-base)
|
||||
git merge-base master upstream/master
|
||||
|
||||
# Your commits on top of upstream
|
||||
git log --oneline upstream/master..master
|
||||
|
||||
# Files changed (scope assessment)
|
||||
git diff upstream/master..master --stat | tail -5
|
||||
```
|
||||
|
||||
Categorize each commit:
|
||||
- **Feature port** — ported FROM upstream (e.g., posix_spawn). Upstream now
|
||||
has it natively → **DROP**, use upstream's version.
|
||||
- **Red Bear feature** — unique to Red Bear (e.g., eventfd, signalfd, timerfd,
|
||||
__fseterr, getprogname). Not in upstream → **KEEP**.
|
||||
- **Compatibility shim** — gnulib/glibc/musl compat (e.g., rpl_malloc,
|
||||
__freadahead). → **KEEP** unless upstream added equivalent.
|
||||
- **Toolchain fix** — adapts to Rust nightly changes (e.g., unsafe blocks,
|
||||
VaList API). → **CHECK** if still needed against current upstream.
|
||||
- **Revert/cleanup** — noise from previous iterations. → **DROP**.
|
||||
|
||||
### Step 3: Create Sync Branch
|
||||
|
||||
```bash
|
||||
# Branch from latest upstream
|
||||
git checkout -b redbear-upstream-sync-$(date +%Y%m%d) upstream/master
|
||||
```
|
||||
|
||||
### Step 4: Squash-Merge Your Changes
|
||||
|
||||
```bash
|
||||
# Squash-merge brings ALL your changes as staged, conflict-marked if needed
|
||||
git merge --squash master
|
||||
```
|
||||
|
||||
If untracked files block the merge (files that exist in your fork but not
|
||||
upstream, left over from failed attempts):
|
||||
|
||||
```bash
|
||||
git merge --abort
|
||||
git reset --hard upstream/master
|
||||
git clean -fd
|
||||
git merge --squash master
|
||||
```
|
||||
|
||||
### Step 5: Resolve Conflicts
|
||||
|
||||
This is the most time-consuming step. For each conflicted file:
|
||||
|
||||
```bash
|
||||
# List conflicts
|
||||
git diff --name-only --diff-filter=U
|
||||
```
|
||||
|
||||
**Resolution strategy per file:**
|
||||
|
||||
| Conflict Type | Resolution |
|
||||
|---|---|
|
||||
| Add/Add (both added same file) | Check which is canonical. If upstream now has it (e.g., spawn), take upstream: `git checkout --ours <file>` |
|
||||
| Feature you ported from upstream | Take upstream: `git checkout --ours <file>` |
|
||||
| Red Bear unique feature | Take ours: `git checkout --theirs <file>` |
|
||||
| Both sides modified same code | **Manual merge** — keep both sets of changes |
|
||||
| Cargo.toml/Cargo.lock | Resolve Cargo.toml manually, regenerate Cargo.lock with `cargo update` |
|
||||
|
||||
```bash
|
||||
# Take upstream (current branch = upstream):
|
||||
git checkout --ours <file> && git add <file>
|
||||
|
||||
# Take ours (the merged branch = our fork):
|
||||
git checkout --theirs <file> && git add <file>
|
||||
|
||||
# Manual resolution:
|
||||
# Edit file, remove conflict markers, keep both sides' relevant changes
|
||||
git add <file>
|
||||
```
|
||||
|
||||
**Conflict count expectation:**
|
||||
- relibc: 5-15 conflict files (heavy upstream refactoring)
|
||||
- kernel: 10-30 conflict files
|
||||
- base: 5-10 conflict files
|
||||
- Others: 2-5 conflict files
|
||||
|
||||
### Step 6: Commit the Squash
|
||||
|
||||
```bash
|
||||
git commit -m "sync: upstream <component> to $(git rev-parse --short upstream/master)
|
||||
|
||||
Re-applied Red Bear-specific changes on top of latest upstream.
|
||||
Dropped commits for features now in upstream.
|
||||
Backup: backup-master-pre-upstream-update-$(date +%Y%m%d)"
|
||||
```
|
||||
|
||||
### Step 7: Compile Test
|
||||
|
||||
> ⚠️ **GROSS WARNING — DO NOT run `repo cook`, `repo fetch`, or `make live` directly.**
|
||||
> These bypass the canonical build pipeline (`apply-patches.sh` patch-linking + staleness handling + correct dependency ordering), which causes broken/missing patches and wasted rebuild time. **ALWAYS build via `./local/scripts/build-redbear.sh [--upstream] <config>`** (or the documented `make` targets it drives). If you think you need a single-recipe cook, run the canonical wrapper — it does the right thing and is faster in the end.
|
||||
|
||||
```bash
|
||||
# Build the component via the cookbook
|
||||
cd /home/kellito/Builds/RedBear-OS
|
||||
rm -rf recipes/core/<component>/source recipes/core/<component>/target
|
||||
export CI=1 COOKBOOK_OFFLINE=false REDBEAR_ALLOW_PROTECTED_FETCH=1
|
||||
./target/release/repo cook recipes/core/<component>
|
||||
```
|
||||
|
||||
Fix any compile errors. These are usually:
|
||||
- **Unsafe block changes** (Rust 2024 edition) — wrap in `unsafe { }`.
|
||||
- **API renames** — upstream renamed a function/type.
|
||||
- **Module path changes** — upstream reorganized headers.
|
||||
- **Trait signature changes** — upstream changed a trait method signature.
|
||||
|
||||
### Step 8: Verify Functionality
|
||||
|
||||
For relibc specifically:
|
||||
```bash
|
||||
# Check critical symbols are present
|
||||
nm recipes/core/relibc/target/x86_64-unknown-redox/stage/x86_64-unknown-redox/lib/libc.a | \
|
||||
grep -E "__fseterr|eventfd|signalfd|timerfd|open_memstream"
|
||||
|
||||
# Check static libs exist
|
||||
ls -la recipes/core/relibc/target/x86_64-unknown-redox/stage/x86_64-unknown-redox/lib/*.a
|
||||
```
|
||||
|
||||
### Step 9: Push to Gitea
|
||||
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
# Switch sync branch to master (or merge sync into master)
|
||||
git checkout master
|
||||
git reset --hard redbear-upstream-sync-$(date +%Y%m%d)
|
||||
git push gitea master --force-with-lease
|
||||
```
|
||||
|
||||
### Step 10: Update Recipe
|
||||
|
||||
If the recipe uses `git + patches` (not `path`):
|
||||
```bash
|
||||
# Update the pinned rev in recipe.toml to match new HEAD
|
||||
# Remove patches that are now in upstream
|
||||
```
|
||||
|
||||
If the recipe uses `path` (local fork):
|
||||
```bash
|
||||
# No recipe changes needed — the fork IS the source
|
||||
```
|
||||
|
||||
### Step 11: Rebuild Dependent Components
|
||||
|
||||
After updating a base component, everything that depends on it must rebuild:
|
||||
|
||||
| Component Updated | Must Rebuild |
|
||||
|---|---|
|
||||
| relibc | prefix, then ALL C recipes (bison, flex, m4, etc.) |
|
||||
| kernel | base, drivers, all recipes |
|
||||
| base | everything in the image |
|
||||
| bootloader | disk image creation |
|
||||
| installer | disk image creation |
|
||||
| redoxfs | disk image creation |
|
||||
| userutils | base, login/session recipes |
|
||||
|
||||
### Step 12: Full Image Build
|
||||
|
||||
```bash
|
||||
cd /home/kellito/Builds/RedBear-OS
|
||||
pkill -9 -f "build-redbear\|repo cook"
|
||||
rm -rf recipes/core/<component>/source recipes/core/<component>/target
|
||||
|
||||
export CI=1 REDBEAR_ALLOW_PROTECTED_FETCH=1
|
||||
setsid nohup env CI=1 REDBEAR_ALLOW_PROTECTED_FETCH=1 \
|
||||
./local/scripts/build-redbear.sh --upstream redbear-mini \
|
||||
> /tmp/build-V<N>.log 2>&1 < /dev/null &
|
||||
```
|
||||
|
||||
## Package-Specific Notes
|
||||
|
||||
### relibc
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/relibc.git`
|
||||
- **Fork location:** `local/sources/relibc/`
|
||||
- **Recipe:** `recipes/core/relibc/recipe.toml`
|
||||
- **Red Bear features to preserve:**
|
||||
- `eventfd` (eventfd_create, eventfd_read, eventfd_write)
|
||||
- `signalfd` (signalfd_create/signalfd)
|
||||
- `timerfd` (timerfd_create, timerfd_settime, timerfd_gettime)
|
||||
- `__fseterr`, `__freadahead` (gnulib/m4/bison compatibility)
|
||||
- `getprogname` (via `sys:exe` scheme)
|
||||
- `getloadavg` (via `/proc/loadavg`)
|
||||
- `clock_settime` (proper implementation)
|
||||
- `getifaddrs`, `if_nameindex` (networking)
|
||||
- `getrlimit`, `getrusage` (resource limits)
|
||||
- `waitid` (POSIX waitid)
|
||||
- `dup3`, `F_DUPFD_CLOEXEC` fallback
|
||||
- `secure_getenv`, `getentropy`
|
||||
- `clock_nanosleep`
|
||||
- POSIX semaphores (`sem_open`/`sem_close`/`sem_unlink`)
|
||||
- POSIX mqueue (`mq_*`)
|
||||
- `DT_RPATH` support in ld.so
|
||||
- `redox_syscall = "0.8.1"` (ABI migration)
|
||||
- DRM ioctl definitions (GET_UNIQUE, SET_VERSION, MODE_ADD_FB2)
|
||||
- `rpl_malloc`/`rpl_realloc` (gnulib compat)
|
||||
- 8MB stack size
|
||||
- **Features now in upstream (DROP from Red Bear):**
|
||||
- `posix_spawn` (port from upstream → upstream now has it)
|
||||
- Various doc/lint fixes (upstream applied)
|
||||
- **Features that were assumed upstream-fixed but are NOT:**
|
||||
- VaList API adaptation — upstream relibc may be fixed for the redoxer default
|
||||
toolchain (1.98-dev), but the PREFIX toolchain (nightly-2025-11-15) still
|
||||
has the older `VaList<'a, 'f: 'a>` (2 lifetimes). When building via `make`
|
||||
(which sets `REDOXER_TOOLCHAIN=PREFIX`), relibc HEAD fails to compile.
|
||||
Fix: override `RUSTUP_TOOLCHAIN` in the recipe (see PACKAGE-BUILD-QUIRKS.md).
|
||||
- cbindgen `va_list` generation — cbindgen translates `VaList<'_>` to `...`
|
||||
(variadic) in C headers instead of `va_list`. This affects all `v*printf`
|
||||
functions and breaks C++ code that takes their address (e.g., Qt6).
|
||||
Fix: post-generation `sed` in recipe build script (see PACKAGE-BUILD-QUIRKS.md).
|
||||
- **Compile gotchas:**
|
||||
- `core::arch::x86_64::__cpuid()` requires `unsafe { }` block (edition 2024)
|
||||
- `Vec::into_raw_parts()` is unstable — use `mem::transmute` + `as_ptr`/`len`/`capacity`
|
||||
- `-D unused_mut` in upstream Makefile flags
|
||||
|
||||
### kernel
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/kernel.git`
|
||||
- **Fork location:** `local/sources/kernel/`
|
||||
- **Red Bear features to preserve:**
|
||||
- Any ACPI improvements specific to AMD
|
||||
- IRQ routing changes
|
||||
- MSI/MSI-X support
|
||||
- IOMMU work
|
||||
- **Check upstream first** — kernel is the fastest-moving Redox component
|
||||
|
||||
### bootloader
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/bootloader.git`
|
||||
- **Fork location:** `local/sources/bootloader/`
|
||||
- **Red Bear features to preserve:**
|
||||
- Branding (Red Bear logo, colors)
|
||||
- Any boot protocol changes
|
||||
|
||||
### installer
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/installer.git`
|
||||
- **Fork location:** `local/sources/installer/`
|
||||
- **Red Bear features to preserve:**
|
||||
- ext4 filesystem support
|
||||
- GRUB bootloader support
|
||||
- CollisionTracker (file ownership conflict detection)
|
||||
- Init service path validation
|
||||
|
||||
### redoxfs
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/redoxfs.git`
|
||||
- **Fork location:** `local/sources/redoxfs/`
|
||||
- **Red Bear features to preserve:**
|
||||
- Any performance patches
|
||||
- Any filesystem format changes
|
||||
|
||||
### userutils
|
||||
|
||||
- **Upstream repo:** `https://gitlab.redox-os.org/redox-os/userutils.git`
|
||||
- **Fork location:** `local/sources/userutils/`
|
||||
- **Red Bear features to preserve:**
|
||||
- Custom `/etc/issue` (Red Bear login banner)
|
||||
- Any Redox ABI changes for syscall 0.8.x
|
||||
|
||||
### base
|
||||
|
||||
- **Upstream repo:** Pinned via `recipes/core/base/recipe.toml` (path-based fork)
|
||||
- **Fork location:** `local/sources/base/`
|
||||
- **Red Bear features to preserve:**
|
||||
- All Red Bear init.d services
|
||||
- All Red Bear branding
|
||||
- All Red Bear config overrides
|
||||
- HID/I2C driver wiring
|
||||
- D-Bus integration
|
||||
- Session management (redbear-sessiond)
|
||||
- ~100 individual P*.patch files in `local/patches/base/`
|
||||
|
||||
## Rollback Procedure
|
||||
|
||||
If the sync fails or produces a broken build:
|
||||
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
git checkout master
|
||||
git reset --hard backup-master-pre-upstream-update-<date>
|
||||
git push gitea master --force-with-lease
|
||||
```
|
||||
|
||||
Then in the main repo:
|
||||
```bash
|
||||
git checkout -- recipes/core/<component>/recipe.toml
|
||||
# Revert recipe changes if any
|
||||
```
|
||||
|
||||
## Decision Matrix: Keep vs Drop vs Merge
|
||||
|
||||
For each Red Bear commit when syncing:
|
||||
|
||||
```
|
||||
Is the feature in upstream now?
|
||||
├── YES → Does upstream's version work for us?
|
||||
│ ├── YES → DROP our commit, use upstream
|
||||
│ └── NO → MERGE: take upstream's structure, re-apply our specific changes
|
||||
└── NO → Is it a Red Bear unique feature?
|
||||
├── YES → KEEP our commit
|
||||
└── NO → Is it a toolchain/compat fix?
|
||||
├── Still needed? → KEEP
|
||||
└── Fixed upstream? → DROP
|
||||
```
|
||||
|
||||
## Checklist Per Package
|
||||
|
||||
- [ ] Backup branch created
|
||||
- [ ] Divergence analyzed (commits categorized)
|
||||
- [ ] Sync branch created from latest upstream
|
||||
- [ ] Squash-merge applied
|
||||
- [ ] All conflicts resolved
|
||||
- [ ] Commit made with sync message
|
||||
- [ ] Compiles via `repo cook`
|
||||
- [ ] Critical symbols verified (for relibc)
|
||||
- [ ] Pushed to Gitea
|
||||
- [ ] Recipe updated (if git+patches mode)
|
||||
- [ ] Dependent components rebuilt
|
||||
- [ ] Full image build succeeds
|
||||
- [ ] QEMU boot test passes
|
||||
|
||||
## Known Issues and Solutions (2026-06-18 Sync)
|
||||
|
||||
### Kernel: `-Zjson-target-spec` Rejected by Cargo in Redoxer
|
||||
|
||||
**Problem:** The upstream kernel Makefile passes `-Zjson-target-spec` as a
|
||||
cargo CLI flag. The redoxer build environment's cargo (at
|
||||
`~/.redoxer/x86_64-unknown-redox/toolchain/bin/cargo`) lists this flag in
|
||||
`cargo -Z help` but rejects it when invoked through `make` inside
|
||||
`redoxer env bash -ex`.
|
||||
|
||||
**Root cause:** The `make` subprocess inside redoxer env does not properly
|
||||
propagate all cargo unstable feature flags from the CLI. The env-var form
|
||||
(`CARGO_UNSTABLE_<FEATURE>=true`) works reliably.
|
||||
|
||||
**Fix (applied to kernel Makefile):**
|
||||
```makefile
|
||||
# Replace -Zjson-target-spec CLI flag with env var
|
||||
export CARGO_UNSTABLE_JSON_TARGET_SPEC=true
|
||||
# Remove -Zjson-target-spec from the cargo rustc command line
|
||||
```
|
||||
|
||||
### Base: `map_bar()` API Change
|
||||
|
||||
**Problem:** Upstream changed `pcid_handle.map_bar(N)` to
|
||||
`pcid_handle.map_bar(N, MemoryType::Uncacheable)`.
|
||||
|
||||
**Fix:** Update all Red Bear drivers that call `map_bar()` to pass
|
||||
`common::MemoryType::Uncacheable` as the second argument. Affected drivers:
|
||||
`amd-mp2-i2cd`, `intel-thc-hidd`. The upstream drivers (`ahcid`, `nvmed`,
|
||||
`xhcid`) already use the new API.
|
||||
|
||||
### Base: `if let` Guards in pcid
|
||||
|
||||
**Problem:** Upstream `drivers/pcid/src/cfg_access/mod.rs` uses experimental
|
||||
`if let` guards in match arms.
|
||||
|
||||
**Fix:** Add `#![feature(if_let_guard)]` to `drivers/pcid/src/main.rs`.
|
||||
|
||||
### Base: XHCI Quirk Integration Dropped
|
||||
|
||||
**Problem:** The Red Bear xhci quirk integration (`XhciControllerQuirkFlags`,
|
||||
`staged_port_states`, `ZERO_64B_REGS` handling) was deeply coupled with the
|
||||
old xhci module code and conflicts with upstream's evolved API.
|
||||
|
||||
**Resolution:** Reverted `drivers/usb/xhcid/src/xhci/mod.rs` and
|
||||
`irq_reactor.rs` to upstream. The quirk system will be re-integrated as
|
||||
follow-up work on top of the new upstream xhci code.
|
||||
|
||||
### Base: Workspace Members Missing After Sync
|
||||
|
||||
**Problem:** Taking upstream's `Cargo.toml` drops Red Bear-specific workspace
|
||||
members (I2C, GPIO, HID, thermald, ucsid, acpi-resource).
|
||||
|
||||
**Fix:** Add all 13 Red Bear workspace members back to the `members` list.
|
||||
Also fix the `[patch]` section to point to `../../sources/relibc/` (not the
|
||||
stale `../../relibc/source/` path).
|
||||
|
||||
### Systemic: `redox_syscall` Version Alignment
|
||||
|
||||
**Problem:** All Red Bear custom recipes used `redox_syscall = "0.7"`, but the
|
||||
synced base and relibc use `0.8.x`.
|
||||
|
||||
**Fix:** Bulk-replaced `"0.7"` → `"0.8"` across all 23 Red Bear recipe
|
||||
Cargo.toml files.
|
||||
|
||||
### Installer: Switch to Local Fork
|
||||
|
||||
**Problem:** The installer recipe used `git = "..."` + `patches = [...]`, but
|
||||
the patch (`redox.patch`) fails against the synced upstream code (368 commits
|
||||
of drift).
|
||||
|
||||
**Fix:** Switched recipe to `path = "../../../local/sources/installer"` (local
|
||||
fork mode). The ext4/GRUB installer changes need to be re-applied to the fork
|
||||
as follow-up work.
|
||||
|
||||
### Kernel: Switch to Local Fork
|
||||
|
||||
**Problem:** The kernel recipe used `git = "..."` + 5 patches, all of which
|
||||
fail against the synced upstream code.
|
||||
|
||||
**Fix:** Switched recipe to `path = "../../../local/sources/kernel"` (local
|
||||
fork mode). All patches were already squash-merged into the fork.
|
||||
|
||||
### Kernel: Compile Errors After Upstream Sync (31 errors)
|
||||
|
||||
After the squash-merge, the kernel had 31 compile errors across ~20 files.
|
||||
These were caused by upstream API evolution interacting with Red Bear code
|
||||
that survived in non-conflicting regions of the merge.
|
||||
|
||||
#### Feature Gates Required
|
||||
|
||||
Upstream code uses two experimental features that require feature gates:
|
||||
- `#![feature(asm_cfg)]` — for `#[cfg(target_arch)]` on inline assembly
|
||||
- `#![feature(if_let_guard)]` — for `if let` guards in match arms
|
||||
|
||||
Both must be added to `src/main.rs`.
|
||||
|
||||
#### Unsafe Blocks Required (Rust 2024 Edition)
|
||||
|
||||
Rust 2024 edition requires explicit `unsafe { }` blocks for unsafe operations
|
||||
even inside `unsafe fn`. Affected files:
|
||||
- `src/arch/x86_shared/cpuid.rs` — `__cpuid_count`
|
||||
- `src/arch/x86_shared/device/tsc.rs` — `__cpuid`
|
||||
- `src/arch/x86_shared/device/local_apic.rs` — `set_lvt_timer`
|
||||
|
||||
#### Removed Red Bear APIs
|
||||
|
||||
These Red Bear types/constants no longer exist after taking upstream:
|
||||
- `SchedPolicy` — Red Bear's DWRR scheduler policy enum (upstream uses EEVDF)
|
||||
- `RUN_QUEUE_COUNT` — Red Bear's per-NUMA run queue count constant
|
||||
- `get_event_stat()` — Red Bear's event system statistics (upstream uses eventfd)
|
||||
- `PIPES` — Red Bear's pipe storage (renamed to `HANDLES`)
|
||||
|
||||
Fixes:
|
||||
- Remove `SchedPolicy` from the `pub use` in `context/mod.rs`
|
||||
- Define `RUN_QUEUE_COUNT` locally in `percpu.rs` if still needed
|
||||
- Implement `get_event_stat()` in `event.rs` using the upstream `REGISTRY` static
|
||||
- Use `HANDLES` instead of `PIPES` in `scheme/pipe.rs`
|
||||
|
||||
#### `CONTEXT_SWITCH_LOCK` Missing
|
||||
|
||||
Upstream added `pub static CONTEXT_SWITCH_LOCK: AtomicBool` to
|
||||
`src/context/arch/x86_64.rs` but our fork was missing it. Must be added
|
||||
with the `core::sync::atomic::AtomicBool` import.
|
||||
|
||||
#### `new_addrsp_guard` Field Missing from PercpuBlock
|
||||
|
||||
Upstream added a separate `new_addrsp_guard: Cell<Option<AddrSpaceSwitchReadGuard>>`
|
||||
field to `PercpuBlock` for storing the addr space read guard during context
|
||||
switch. Our fork only had `new_addrsp_tmp` (for the `Arc<AddrSpaceWrapper>`).
|
||||
Both fields must exist.
|
||||
|
||||
#### `switch.rs` Must Be Replaced Entirely
|
||||
|
||||
The Red Bear DWRR scheduler in `switch.rs` is fundamentally incompatible with
|
||||
the upstream EEVDF scheduler data structures. The `RunContextData` changed from
|
||||
`set: [VecDeque<WeakContextRef>; N]` to `queue: BTreeMap<(vd, rem_slice, ctxt_id), ...>`.
|
||||
|
||||
The entire `switch.rs` must be replaced with the upstream version:
|
||||
```bash
|
||||
git show upstream/master:src/context/switch.rs > src/context/switch.rs
|
||||
```
|
||||
|
||||
#### `kcall` Trait Method Signature Changed
|
||||
|
||||
Upstream changed `id: usize` to `fds: &[usize]` in the `kcall` trait method.
|
||||
Update the `ProcScheme` impl to extract the first element:
|
||||
```rust
|
||||
fn kcall(&self, fds: &[usize], ...) -> Result<usize> {
|
||||
let id = *fds.first().ok_or(Error::new(EBADF))?;
|
||||
```
|
||||
|
||||
#### `ProcSchemeVerb` New Variants
|
||||
|
||||
Upstream added new variants to `ProcSchemeVerb`: `RegsInt`, `RegsFloat`,
|
||||
`RegsEnv`, `SchedAffinity`, `Start`. The match in `scheme/proc.rs` must
|
||||
handle them (currently returns `ENOSYS`).
|
||||
|
||||
#### `notify_files` Type Change
|
||||
|
||||
`handle_notify_files()` now expects `UnmapVec` (`SmallVec<[UnmapResult; 16]>`)
|
||||
instead of `Vec`. Import `UnmapVec` from `context::memory` and use
|
||||
`UnmapVec::new()` instead of `Vec::new()`.
|
||||
|
||||
#### `Rsdp::get_rsdp` Signature Change
|
||||
|
||||
Upstream changed the parameter from `Option<NonNull<u8>>` to
|
||||
`Option<*const u8>`. Convert at the call site:
|
||||
```rust
|
||||
Rsdp::get_rsdp(already_supplied_rsdp.map(|ptr| ptr.as_ptr() as *const u8))
|
||||
```
|
||||
|
||||
#### Syntax Error in `acpi/madt/arch/x86.rs`
|
||||
|
||||
A `const` statement was accidentally placed inside a `use crate::{...}` block
|
||||
during the merge. Must be moved outside.
|
||||
|
||||
#### `halt_boot` Scope Issue
|
||||
|
||||
`halt_boot` was defined inside the `impl KernelArgs` block, making it a method
|
||||
rather than a free function. Must be moved outside the impl block.
|
||||
|
||||
### Cookbook Symlink Behavior for Local Forks
|
||||
|
||||
**Critical:** When a recipe uses `path = "..."` pointing inside
|
||||
`/local/sources/` or `/local/recipes/`, the cookbook creates a **symlink**
|
||||
(not a copy) from `recipes/<name>/source` → the local fork path. This means:
|
||||
|
||||
1. Build artifacts and `cargo` operations can modify files in the local fork
|
||||
through the symlink.
|
||||
2. After each build attempt, verify the fork's git status:
|
||||
```bash
|
||||
cd local/sources/<component>
|
||||
git status --short
|
||||
```
|
||||
3. If the working tree is dirty, reset before rebuilding:
|
||||
```bash
|
||||
git checkout -- .
|
||||
```
|
||||
4. Always clean both `target/` and `source/` when restarting a kernel build:
|
||||
```bash
|
||||
rm -rf recipes/core/kernel/target recipes/core/kernel/source
|
||||
cd local/sources/kernel && git checkout -- .
|
||||
```
|
||||
|
||||
### m4: `getlocalename_l-unsafe.c` Platform Detection
|
||||
|
||||
**Problem:** m4's gnulib `getlocalename_l-unsafe.c` has a Redox case guarded
|
||||
by `HAVE_GETLOCALENAME_L`, which relibc doesn't define.
|
||||
|
||||
**Fix:** Changed the guard from `__redox__ && HAVE_GETLOCALENAME_L` to just
|
||||
`__redox__` and return `"C"` (Redox only supports the C/POSIX locale).
|
||||
|
||||
### m4: `rpl_realloc` Multiple Definition (CFLAGS)
|
||||
|
||||
**Problem:** GCC 10+ defaults to `-fno-common`, causing `rpl_realloc` (gnulib
|
||||
replacement) to be multiply defined across translation units.
|
||||
|
||||
**Fix:** Add `-fcommon` to CFLAGS in the m4 recipe:
|
||||
```bash
|
||||
export CFLAGS="-fcommon ${CFLAGS}"
|
||||
```
|
||||
|
||||
**Placement:** BEFORE `DYNAMIC_INIT` (works because `reexport_flags` re-reads
|
||||
`$CFLAGS` at configure time).
|
||||
|
||||
### m4: `rpl_realloc` Multiple Definition (LDFLAGS)
|
||||
|
||||
**Problem:** Even with `-fcommon`, the linker encounters duplicate definitions
|
||||
of `rpl_realloc` from static library archives.
|
||||
|
||||
**Fix:** Add `-Wl,--allow-multiple-definition` to LDFLAGS:
|
||||
```bash
|
||||
DYNAMIC_INIT
|
||||
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
||||
```
|
||||
|
||||
**CRITICAL Placement:** MUST be AFTER `DYNAMIC_INIT`. `DYNAMIC_INIT` overwrites
|
||||
`LDFLAGS` entirely — setting it before has no effect. See
|
||||
`local/docs/PACKAGE-BUILD-QUIRKS.md` § "DYNAMIC_INIT" for details.
|
||||
|
||||
### m4: Configure Cache Variables
|
||||
|
||||
**Problem:** m4's `configure` tests fail for functions that exist in relibc but
|
||||
have different semantics, or for gnulib internal functions.
|
||||
|
||||
**Fix:** Pass cache variables to skip problematic tests:
|
||||
```bash
|
||||
COOKBOOK_CONFIGURE_FLAGS+=(
|
||||
--disable-nls
|
||||
ac_cv_func___freadahead=yes
|
||||
ac_cv_have_decl___freadahead=yes
|
||||
gl_cv_header_wchar_h_correct_inline=yes
|
||||
gl_cv_func_btowc_nul=yes
|
||||
gl_cv_func_btowc_consistent=yes
|
||||
gl_cv_onwards_func___freadahead=yes
|
||||
)
|
||||
```
|
||||
|
||||
### ninja-build: `BUILD_TESTING=OFF` (Cross-Compilation)
|
||||
|
||||
**Problem:** ninja-build's CMake includes `CTest`, enabling `BUILD_TESTING=ON`
|
||||
by default. Tests require Google Test (gtest) from the host system. Host gtest
|
||||
headers transitively include host `/usr/include/stdlib.h`, which conflicts with
|
||||
the Redox sysroot `stdlib.h` (type redefinitions: `div_t`, `ldiv_t`, `lldiv_t`,
|
||||
`at_quick_exit`). This is a fundamental cross-compilation constraint, not a
|
||||
Redox capability gap.
|
||||
|
||||
**Fix:** Disable tests via cmakeflags:
|
||||
```toml
|
||||
[build]
|
||||
template = "cmake"
|
||||
cmakeflags = ["-DBUILD_TESTING=OFF"]
|
||||
```
|
||||
|
||||
See `local/docs/PACKAGE-BUILD-QUIRKS.md` § "General Cross-Compilation Patterns"
|
||||
for the rationale.
|
||||
|
||||
### Cookbook: `DYNAMIC_INIT` Overwrites Environment Variables
|
||||
|
||||
**Problem:** `DYNAMIC_INIT` overwrites `CFLAGS`, `LDFLAGS`, `CXXFLAGS`, etc.
|
||||
entirely. Custom flags set BEFORE `DYNAMIC_INIT` are lost.
|
||||
|
||||
**Fix:** Set ALL custom flags AFTER `DYNAMIC_INIT`:
|
||||
```bash
|
||||
DYNAMIC_INIT
|
||||
export CFLAGS="-fcommon ${CFLAGS}"
|
||||
export LDFLAGS="-Wl,--allow-multiple-definition ${LDFLAGS}"
|
||||
```
|
||||
|
||||
**Exception:** `CFLAGS` set BEFORE `DYNAMIC_INIT` works because `reexport_flags`
|
||||
(called inside `cookbook_configure`) re-reads `$CFLAGS`. However, this is fragile
|
||||
and not recommended. See `local/docs/PACKAGE-BUILD-QUIRKS.md` for full details.
|
||||
|
||||
### Build System: Source Reversion via Patch Application
|
||||
|
||||
**Problem:** `build-redbear.sh` previously called `apply_patch_dir` to apply
|
||||
patches from `local/patches/{kernel,base,relibc,installer}/` to
|
||||
`recipes/core/<comp>/source/`. For `path=` recipes, `source/` is a symlink to
|
||||
`local/sources/<comp>/`. Patches went through the symlink and modified the local
|
||||
fork directly, re-adding old code on every build.
|
||||
|
||||
**Root cause:** `apply_patch_dir` operated on `recipes/core/<comp>/source/`
|
||||
without checking if it was a symlink to a local fork.
|
||||
|
||||
**Fix (commit `760634376`):** Removed `apply_patch_dir` calls for kernel, base,
|
||||
relibc, and installer from `build-redbear.sh`. Only bootloader (which uses
|
||||
`git + patches`, not `path=`) still gets `apply_patch_dir`.
|
||||
|
||||
**Verification:** Kernel source hashes now identical before and after build.
|
||||
|
||||
---
|
||||
|
||||
## CRITICAL: Red Bear Package Preservation Rules
|
||||
|
||||
### Never Delete — Comment Out
|
||||
|
||||
When syncing with upstream removes or restructures packages, configs, or
|
||||
services that are Red Bear in-house projects:
|
||||
|
||||
1. **NEVER delete** the package, config, or service entry.
|
||||
2. **Comment it out** with a clear explanation of why.
|
||||
3. **ASK THE USER** if uncertain whether to keep or remove.
|
||||
|
||||
This applies to:
|
||||
- Packages in `[packages]` sections of config TOMLs
|
||||
- Dependencies in `recipe.toml` files
|
||||
- Init service files (`.service`, `.target`)
|
||||
- Build system patches and scripts
|
||||
- Any file under `local/` or `config/redbear-*`
|
||||
|
||||
### driver-manager: LIVE (operator-ratified cutover, 2026-07-23/24)
|
||||
|
||||
> **HISTORICAL NOTE (2026-07-26):** This section previously described
|
||||
> `driver-manager` as "Deferred (consolidated onto pcid-spawner,
|
||||
> 2026-07-20)". **That was the pre-cutover state and is now obsolete.** The
|
||||
> text below has been updated to the current ground truth. See
|
||||
> `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v5.6) for the canonical
|
||||
> authority.
|
||||
|
||||
**Status:** Red Bear internal project, **LIVE**. Upstream Redox does NOT have
|
||||
an equivalent.
|
||||
|
||||
`driver-manager` (`local/recipes/system/driver-manager/`) is a combined PCI
|
||||
enumeration + driver matching + hotplug daemon that replaces the upstream
|
||||
`pcid + pcid-spawner` pair. It was developed because upstream's PCI driver
|
||||
launching was not ready for Red Bear's needs (advanced driver matching via
|
||||
`/lib/drivers.d/*.toml`, ACPI device enumeration, hotplug event handling).
|
||||
|
||||
**As of the 2026-07-23/24 cutover (operator-ratified), driver-manager owns the
|
||||
boot-time PCI match/claim/spawn path in every `redbear-*` config,
|
||||
unconditionally.** `pcid-spawner` was **fully retired and removed** from
|
||||
configs, services, build wiring, and the tree (its source is preserved in git
|
||||
history). The earlier 2026-07-20 "consolidation onto pcid-spawner" was a
|
||||
transient intermediate state that has since been superseded by the completed
|
||||
driver-manager migration.
|
||||
|
||||
Key cutover facts (per `DRIVER-MANAGER-MIGRATION-PLAN.md` v5.6):
|
||||
- claim-via-channel collapse (`ENOLCK` exclusivity — the former pcid-spawner
|
||||
model) is the live claim path;
|
||||
- spawned-mode `pci_register_driver` in linux-kpi honors `PCID_CLIENT_CHANNEL`,
|
||||
with driver-manager the single owner of match-claim-spawn for both native
|
||||
and Linux-port daemons;
|
||||
- the QEMU runtime gate passed (initfs ahcid bind, switchroot, rootfs e1000d
|
||||
concurrent bind, scheme live, resident hotplug loop).
|
||||
|
||||
**Upstream may provide its own solution in the future.** If and when upstream
|
||||
Redox offers a concrete, working replacement that matches or exceeds
|
||||
driver-manager's capabilities, notify the user for a route decision. Until
|
||||
then, `driver-manager` (its `00_driver-manager.service`) is the sole PCI
|
||||
driver spawner.
|
||||
|
||||
### Systemic Sync Flaw (2026-06 Incident)
|
||||
|
||||
**Root cause:** The 0.2.3 → 0.2.4 upstream sync blindly overwrote tracked
|
||||
config and recipe files. Red Bear in-house packages, services, and configs
|
||||
were silently dropped because upstream doesn't have them.
|
||||
|
||||
**What was lost (partial list):**
|
||||
- `driver-manager` removed from base-initfs dependencies and packages
|
||||
- `config/protected-recipes.toml` deleted (99 lines of protection rules)
|
||||
- `config/redbear-boot-stages.toml` deleted (109 lines of boot stage targets)
|
||||
- `set -eo pipefail` removed from base-initfs build script
|
||||
- `drivers.d/` initfs config directory creation removed
|
||||
- Multiple patches lost (libdrm, mesa, pipewire, sddm, wireplumber)
|
||||
- `local/recipes/AGENTS.md` deleted
|
||||
|
||||
**Prevention:** Before ANY upstream sync:
|
||||
1. Run `git diff` between the pre-sync and post-sync tree.
|
||||
2. Flag ALL removed files, especially under `config/`, `local/`, and `recipes/`.
|
||||
3. Flag ALL removed entries from `[packages]` sections and dependency arrays.
|
||||
4. Cross-reference with `config/protected-recipes.toml` — protected recipes
|
||||
must NEVER be removed.
|
||||
5. Any removal must be explicitly approved by the user.
|
||||
|
||||
### PCI Driver Spawning Architecture (current: driver-manager)
|
||||
|
||||
> **HISTORICAL NOTE (2026-07-26):** This section previously described the
|
||||
> `pcid + pcid-spawner` pair as the live spawner ("Red Bear model (current,
|
||||
> since the 2026-07-20 consolidation)"). **That is obsolete.** The text below
|
||||
> has been updated to the current ground truth. See
|
||||
> `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` (v5.6) for the canonical
|
||||
> authority.
|
||||
|
||||
**Upstream model (historical reference):**
|
||||
1. `pcid` creates `/scheme/pci` (PCI bus enumeration)
|
||||
2. `pcid-spawner` reads `/scheme/pci` and launches drivers per `pcid.d/*.toml`
|
||||
|
||||
**Red Bear model (current, since the 2026-07-23/24 cutover):**
|
||||
1. `pcid` creates `/scheme/pci` (initfs service `35_pcid.service`)
|
||||
2. `driver-manager` is the sole PCI match/claim/spawn daemon on both initfs
|
||||
and rootfs. It owns the boot-time PCI device match/claim/spawn path for
|
||||
native Redox daemons and Linux-port drivers (via `PCID_CLIENT_CHANNEL` /
|
||||
spawned-mode `pci_register_driver` in linux-kpi).
|
||||
3. `pcid-spawner` has been **retired and removed** (2026-07-24); its source is
|
||||
preserved in git history only.
|
||||
|
||||
**Key learning (still valid):** Without `35_pcid.service` in initfs,
|
||||
`/scheme/pci` is never created, and driver-manager's rootfs spawner fails with
|
||||
ENODEV. This was masked in 0.2.3 because driver-manager (then deferred) did its
|
||||
own PCI enumeration via `redox_driver_pci` and didn't depend on `/scheme/pci`.
|
||||
After the cutover, driver-manager consumes `/scheme/pci` like the rest of the
|
||||
stack, so `35_pcid.service` is a hard boot dependency.
|
||||
@@ -1,169 +0,0 @@
|
||||
# USB Boot Input Plan
|
||||
|
||||
## Goal
|
||||
|
||||
Make external USB keyboards a reliable bare-metal boot fallback for Red Bear OS.
|
||||
|
||||
This is a boot-resilience requirement, not optional polish. A system that reaches early
|
||||
boot but cannot accept keyboard input on modern hardware is not a complete live/recovery
|
||||
environment.
|
||||
|
||||
## Current Assessment
|
||||
|
||||
### What works today
|
||||
|
||||
- `xhcid` is the only host-controller path with a real runtime device model.
|
||||
- `xhcid` spawns `usbhubd` and `usbhidd` via class matching.
|
||||
- `usbhidd` reads HID input reports and forwards keyboard/mouse events into `inputd`.
|
||||
|
||||
This means USB keyboard input can work today only when the keyboard is reached through the
|
||||
`xHCI -> usbhubd/usbhidd -> inputd` path.
|
||||
|
||||
### What does not work today
|
||||
|
||||
- `ehcid` is still an ownership / handoff / port-state daemon, not a real runtime host stack.
|
||||
- `uhcid` is still ownership + port reset + logging only; full scheduling/enumeration is explicitly
|
||||
not implemented.
|
||||
- `ohcid` is in the same state as `uhcid`.
|
||||
|
||||
The code is explicit about this:
|
||||
|
||||
- `ehcid`: connected EHCI-owned ports still fail with "EHCI enumeration is still not implemented"
|
||||
- `uhcid`: connected ports still fail with "runtime enumeration is still not implemented"
|
||||
- `ohcid`: connected ports still fail with "OHCI enumeration is still not implemented"
|
||||
|
||||
### Important practical consequence
|
||||
|
||||
An external USB keyboard on bare metal is **not guaranteed** to appear through `xHCI`.
|
||||
|
||||
It may instead land on:
|
||||
|
||||
- an EHCI root-hub path
|
||||
- a UHCI/OHCI companion path after EHCI handoff
|
||||
- a firmware/routing topology where low/full-speed devices do not end up on the `xHCI` runtime path
|
||||
|
||||
On such systems, the current code can detect controller ownership and connected ports, but still
|
||||
cannot produce a real keyboard input path.
|
||||
|
||||
### LED state is a separate and weaker path
|
||||
|
||||
`usbhidd` now has a bounded best-effort HID output-report path for keyboard LEDs. It toggles
|
||||
`Caps Lock`, `Num Lock`, and `Scroll Lock` locally on keydown and sends a one-byte HID output
|
||||
report via `SET_REPORT`.
|
||||
|
||||
This is useful, but it is **not** the same as a complete global keyboard lock-state authority:
|
||||
|
||||
- it is per-device, not system-global
|
||||
- it is best-effort and disables itself after the first device-side failure
|
||||
- it does not solve missing USB enumeration on non-xHCI host-controller paths
|
||||
|
||||
So dead `Caps Lock` / `Num Lock` indicators still do **not** prove that keyboard transport is dead,
|
||||
and working LEDs do **not** prove that the external USB keyboard fallback problem is solved.
|
||||
|
||||
## Root-Cause Summary For Current Bare-Metal Symptom
|
||||
|
||||
When a USB-attached keyboard does not bring up input during boot, the most likely causes are:
|
||||
|
||||
1. the keyboard is not on the `xHCI` runtime path
|
||||
2. it lands on `EHCI/UHCI/OHCI`, where enumeration is not implemented yet
|
||||
3. even if input later works, keyboard LEDs may still be misleading because LED sync is only a
|
||||
bounded per-device best-effort path
|
||||
|
||||
## Current Structural Gap
|
||||
|
||||
There is also a policy gap:
|
||||
|
||||
- `ehcid`, `uhcid`, and `ohcid` contain `--strict-boot` logic
|
||||
- and the current boot path still does **not** hardcode `--strict-boot` in initfs driver command lines
|
||||
- however, strict mode can now be enabled through `REDBEAR_STRICT_USB_BOOT=1`, which is inherited by
|
||||
`pcid-spawner` service units and then by legacy USB controller daemons
|
||||
|
||||
So the code contains a boot-guard concept that is currently not activated by the initfs spawn path.
|
||||
|
||||
This does not create input support by itself, but it does matter for observability and boot policy.
|
||||
|
||||
## Execution Order
|
||||
|
||||
### Phase U-B1: Make boot policy honest
|
||||
|
||||
Deliverables:
|
||||
|
||||
- decide whether initfs should pass `--strict-boot` to legacy USB host daemons
|
||||
- provide a non-invasive runtime toggle for strict mode during bring-up
|
||||
- if enabled, make the failure mode explicit and bounded
|
||||
- if not enabled, log clearly that legacy USB ownership exists without runtime enumeration
|
||||
|
||||
Acceptance:
|
||||
|
||||
- the boot log makes it obvious whether the system has a usable USB keyboard path or only controller
|
||||
ownership
|
||||
- strict mode can be enabled without rewriting driver command lines
|
||||
|
||||
### Phase U-B2: Finish legacy host runtime enumeration
|
||||
|
||||
Deliverables:
|
||||
|
||||
- implement real device enumeration for `uhcid`
|
||||
- implement real device enumeration for `ohcid`
|
||||
- implement real runtime ownership of low/full-speed devices behind `ehcid` companion routing
|
||||
|
||||
Acceptance:
|
||||
|
||||
- a low/full-speed USB keyboard on bare metal can reach `usbhidd` through the legacy host path
|
||||
|
||||
### Phase U-B3: Keep one HID class path
|
||||
|
||||
Deliverables:
|
||||
|
||||
- avoid inventing a second HID stack just for legacy controllers
|
||||
- make legacy host controllers feed the existing USB class-driver model
|
||||
- keep `usbhidd` and `usbhubd` as the class daemons above controller-specific ownership
|
||||
|
||||
Acceptance:
|
||||
|
||||
- keyboard class handling is shared regardless of host controller family
|
||||
|
||||
### Phase U-B4: Implement keyboard LED output
|
||||
|
||||
Deliverables:
|
||||
|
||||
- keep the new HID output-report support in `usbhidd` bounded and non-fatal
|
||||
- decide whether the current per-device local toggle model is sufficient, or whether Red Bear
|
||||
later needs a system-authoritative lock-state surface
|
||||
- preserve the rule that LED sync must never block or destabilize keyboard input
|
||||
|
||||
Acceptance:
|
||||
|
||||
- LED state tracks keyboard lock state on at least one supported USB keyboard in the current
|
||||
bounded per-device model
|
||||
|
||||
### Phase U-B5: Validation
|
||||
|
||||
Deliverables:
|
||||
|
||||
- QEMU validation for xHCI remains
|
||||
- add bounded validation for legacy host-controller paths where feasible
|
||||
- require bare-metal validation on systems where external USB keyboard currently fails
|
||||
|
||||
Acceptance:
|
||||
|
||||
- one xHCI bare-metal proof
|
||||
- one EHCI/UHCI/OHCI-involved bare-metal proof
|
||||
- explicit evidence that external USB keyboard input reaches login
|
||||
|
||||
## Design Rules
|
||||
|
||||
- do not treat controller ownership as equivalent to device enumeration
|
||||
- do not treat keyboard LED state as equivalent to keyboard input health
|
||||
- reuse the existing HID class-driver path instead of splitting per-controller userland stacks
|
||||
- prefer bounded boot-policy checks and explicit failure logs over silent partial bring-up
|
||||
|
||||
## Priority Judgment
|
||||
|
||||
For bare-metal boot resilience, the correct order is:
|
||||
|
||||
1. finish legacy USB host runtime enumeration
|
||||
2. then add keyboard LED output reports
|
||||
3. in parallel, continue `I2C-HID` for internal modern laptop keyboards/touchpads
|
||||
|
||||
External USB keyboard fallback and internal `I2C-HID` are complementary. Red Bear needs both.
|
||||
@@ -1,137 +0,0 @@
|
||||
# Red Bear OS USB Validation Runbook
|
||||
|
||||
This runbook is the canonical operator path for exercising the USB stack on Red Bear OS.
|
||||
|
||||
It does not claim that USB is broadly solved. Its job is to make the current QEMU-validated USB
|
||||
workload reproducible and honest.
|
||||
|
||||
## Goal
|
||||
|
||||
Produce one or both of the following:
|
||||
|
||||
- a successful USB stack validation via `redbear-usb-check` inside the guest
|
||||
- a repeatable QEMU/UEFI validation log via `./local/scripts/test-usb-qemu.sh --check`
|
||||
- a repeatable bounded xHCI lifecycle log via `./local/scripts/test-xhci-device-lifecycle-qemu.sh --check`
|
||||
|
||||
## Path A - Host-side QEMU validation
|
||||
|
||||
Use this when the host supports the repo's normal x86_64 QEMU/UEFI flow.
|
||||
|
||||
### On the host
|
||||
|
||||
Build the tracked mini profile first:
|
||||
|
||||
```bash
|
||||
./local/scripts/build-redbear.sh redbear-mini
|
||||
```
|
||||
|
||||
Then run the automated QEMU harness:
|
||||
|
||||
```bash
|
||||
./local/scripts/test-usb-qemu.sh --check
|
||||
./local/scripts/test-xhci-device-lifecycle-qemu.sh --check
|
||||
```
|
||||
|
||||
What that harness does today:
|
||||
|
||||
1. boots `redbear-mini` in QEMU with `qemu-xhci`, USB keyboard, USB tablet, and USB mass storage
|
||||
2. captures the full boot log over serial
|
||||
3. checks for xHCI interrupt-driven mode in the log
|
||||
4. checks for USB HID driver spawn
|
||||
5. checks for USB SCSI driver spawn
|
||||
6. checks for BOS descriptor processing (or graceful fallback for USB 2 devices)
|
||||
7. checks that no crash-class errors appear in the log
|
||||
|
||||
What the lifecycle harness does today:
|
||||
|
||||
1. boots `redbear-mini` in QEMU with `qemu-xhci` and no pre-attached USB devices
|
||||
2. logs into the guest over serial, then uses the QEMU monitor to hotplug a USB keyboard
|
||||
3. requires xHCI attach and completion logs plus USB HID driver spawn evidence
|
||||
4. uses one-shot guest-side `/tmp/xhcid-test-hook` commands to inject a bounded
|
||||
post-`SET_CONFIGURATION` failure and a delayed attach-commit timing case
|
||||
5. hot-unplugs the keyboard and requires detach evidence
|
||||
6. hotplugs and hot-unplugs a USB storage device and requires attach/detach plus SCSI driver spawn evidence
|
||||
7. fails on panic-class or teardown-class xHCI errors in the captured log
|
||||
|
||||
### Artifact to preserve
|
||||
|
||||
- the full terminal log from `./local/scripts/test-usb-qemu.sh --check`
|
||||
- the full terminal log from `./local/scripts/test-xhci-device-lifecycle-qemu.sh --check`
|
||||
|
||||
## Path B - Interactive guest validation
|
||||
|
||||
Use this when you want to inspect the runtime manually inside the guest.
|
||||
|
||||
### On the host
|
||||
|
||||
```bash
|
||||
./local/scripts/test-usb-qemu.sh redbear-mini
|
||||
```
|
||||
|
||||
### Inside the guest
|
||||
|
||||
Run the packaged checker directly:
|
||||
|
||||
```bash
|
||||
redbear-usb-check
|
||||
```
|
||||
|
||||
Expected output:
|
||||
|
||||
```
|
||||
redbear-usb-check: found N usb scheme entries: [...]
|
||||
redbear-usb-check: xhci.0 -> M ports
|
||||
redbear-usb-check: port 1 -> vendor:product [device name]
|
||||
redbear-usb-check: port 2 -> vendor:product [device name] [SS]
|
||||
redbear-usb-check: xhci controllers: ["xhci.0"]
|
||||
redbear-usb-check: all checks passed
|
||||
```
|
||||
|
||||
The checker walks `/scheme/usb/` and `/scheme/xhci/` to verify that the xHCI controller is
|
||||
enumerated, ports have devices attached, and device descriptors are readable.
|
||||
|
||||
## What this validates
|
||||
|
||||
- xHCI controller initialization
|
||||
- USB device enumeration and descriptor fetching
|
||||
- BOS/SuperSpeed capability detection
|
||||
- HID class driver spawning (keyboard/tablet)
|
||||
- SCSI class driver spawning (mass storage)
|
||||
- bounded xHCI hotplug attach/detach lifecycle behavior for HID and storage devices in QEMU
|
||||
- No panic or crash-class errors in USB daemons
|
||||
|
||||
## What this does not validate
|
||||
|
||||
- Real hardware USB controllers (QEMU qemu-xhci only)
|
||||
- Hub topology (direct-attached devices only in the default harness)
|
||||
- USB 3 SuperSpeed data paths
|
||||
- Isochronous or streaming transfers
|
||||
- Broad hot-plug stress testing on real hardware
|
||||
- USB device mode / OTG / USB-C
|
||||
|
||||
## Existing USB test scripts
|
||||
|
||||
| Script | What it tests |
|
||||
|--------|---------------|
|
||||
| `test-usb-qemu.sh --check` | Full USB stack (xHCI + HID + SCSI + bounded sector-0 readback + BOS + no crashes) |
|
||||
| `test-xhci-device-lifecycle-qemu.sh --check` | Bounded xHCI hotplug lifecycle proof for HID + storage attach/detach |
|
||||
| `test-usb-storage-qemu.sh` | USB mass storage autospawn + bounded sector-0 readback + crash pattern check |
|
||||
| `test-xhci-irq-qemu.sh --check` | xHCI interrupt delivery mode (MSI/MSI-X/INTx) |
|
||||
| `test-usb-maturity-qemu.sh` | Sequential wrapper for the bounded USB maturity checks |
|
||||
|
||||
In-guest quick checks:
|
||||
- `lsusb` — walks `/scheme/usb.*`, reads descriptors, shows vendor:product + quirks
|
||||
- `redbear-info --verbose` — reports USB controller count and integration status
|
||||
- `redbear-usb-check` — scheme tree walk with pass/fail exit code
|
||||
|
||||
## Compile-target note
|
||||
|
||||
Red Bear has exactly three compile targets:
|
||||
|
||||
- `redbear-mini`
|
||||
- `redbear-full`
|
||||
- `redbear-grub`
|
||||
|
||||
Older names such as `redbear-desktop`, `redbear-wayland`, `redbear-kde`, `redbear-minimal`,
|
||||
`redbear-live-mini`, and `redbear-live-full` may still appear in historical notes or
|
||||
implementation details, but they are not the supported compile-target surface.
|
||||
@@ -1,360 +0,0 @@
|
||||
# xhcid Device-Level Improvement Plan
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the implementation sequence for hardening `xhcid` at the device level in
|
||||
Red Bear OS.
|
||||
|
||||
It is a focused companion to `local/docs/USB-IMPLEMENTATION-PLAN.md`. The USB plan remains the
|
||||
subsystem-wide authority; this document narrows scope to the `xhcid` device lifecycle,
|
||||
configuration, teardown, PM behavior, enumerator robustness, and bounded proof coverage.
|
||||
|
||||
## Scope
|
||||
|
||||
In scope:
|
||||
|
||||
- `recipes/core/base/source/drivers/usb/xhcid/src/xhci/device_enumerator.rs`
|
||||
- `recipes/core/base/source/drivers/usb/xhcid/src/xhci/mod.rs`
|
||||
- `recipes/core/base/source/drivers/usb/xhcid/src/xhci/scheme.rs`
|
||||
- `recipes/core/base/source/drivers/usb/xhcid/src/xhci/irq_reactor.rs`
|
||||
- bounded QEMU validation scripts under `local/scripts/`
|
||||
- canonical USB documentation under `local/docs/`
|
||||
|
||||
Out of scope:
|
||||
|
||||
- generic USB redesign
|
||||
- unrelated class-driver feature work
|
||||
- hardware-validation claims beyond what the repo can currently prove
|
||||
|
||||
## Repo-Fit Note
|
||||
|
||||
Technical implementation targets live in upstream-owned source under
|
||||
`recipes/core/base/source/...`, but durable Red Bear preservation belongs in
|
||||
`local/patches/base/`. This plan names the technical work locations, not a recommendation to leave
|
||||
work stranded only in upstream-owned trees.
|
||||
|
||||
## Current Audited Findings
|
||||
|
||||
The current `xhcid` tree has already improved materially:
|
||||
|
||||
- lifecycle gating exists through `PortLifecycle` and `PortOperationGuard`
|
||||
- `configure_endpoints_once()` is now transactional relative to earlier behavior
|
||||
- detach waits before removing published state
|
||||
- a bounded QEMU lifecycle proof exists
|
||||
|
||||
Remaining risks:
|
||||
|
||||
- partial attach visibility still exists around publication timing
|
||||
- detach can still depend on bounded-but-incomplete purge semantics
|
||||
- suspend/resume is still mainly software gating
|
||||
- rollback failure is not yet a fully hardened degraded-state path
|
||||
- enumerator logic still relies on timing- and assumption-heavy behavior
|
||||
- proof coverage is still QEMU-bounded and misses key interleavings
|
||||
|
||||
## Design Invariants
|
||||
|
||||
The implementation should satisfy these invariants:
|
||||
|
||||
1. No half-attached device is publicly usable.
|
||||
2. No new work is admitted after detach begins.
|
||||
3. Detach always reaches a bounded terminal outcome.
|
||||
4. Failed configure leaves either the old config intact or the device explicitly
|
||||
degraded/reset-required.
|
||||
5. PM transitions reflect actual usable state, not only software policy.
|
||||
6. Enumerator behavior is bounded and diagnosable, not panic-driven.
|
||||
7. Validation claims match what scripts actually prove.
|
||||
|
||||
## Phase 1 — Proof-First Expansion
|
||||
|
||||
### Goal
|
||||
|
||||
Make the current blind spots reproducible before changing behavior.
|
||||
|
||||
### Work
|
||||
|
||||
- extend `test-xhci-device-lifecycle-qemu.sh`
|
||||
- extend `test-usb-qemu.sh`
|
||||
- extend `test-xhci-irq-qemu.sh`
|
||||
- add bounded injection hooks in `xhcid` for configure-failure and attach/detach timing cases
|
||||
|
||||
### Required Cases
|
||||
|
||||
- repeated attach/detach
|
||||
- detach during storage startup
|
||||
- transfer-during-detach surrogate
|
||||
- configure failure injection
|
||||
- suspend/resume admission checks
|
||||
- rapid event ordering cases
|
||||
|
||||
### Per-File Focus
|
||||
|
||||
#### `local/scripts/test-xhci-device-lifecycle-qemu.sh`
|
||||
|
||||
- add repeated HID/storage attach-detach loops
|
||||
- add detach-during-driver-start for storage
|
||||
- add storage attach long enough to exercise startup/read activity before unplug
|
||||
- require explicit attach-entered, attach-finished, detach-completed evidence
|
||||
|
||||
#### `local/scripts/test-usb-qemu.sh`
|
||||
|
||||
- separate boot progress from proof failure
|
||||
- keep result lines distinct for xHCI init, HID spawn, SCSI spawn, bounded readback, and crash scan
|
||||
- add repeated full-stack run mode or bounded loop count if needed for ordering-sensitive regressions
|
||||
|
||||
#### `local/scripts/test-xhci-irq-qemu.sh`
|
||||
|
||||
- verify interrupt-mode evidence still holds under actual attached-device pressure, not only empty-controller boot
|
||||
|
||||
#### `xhci` test hooks
|
||||
|
||||
- add bounded test-only failure hooks in `scheme.rs` / `mod.rs` for:
|
||||
- fail after `CONFIGURE_ENDPOINT`
|
||||
- fail after `SET_CONFIGURATION`
|
||||
- optional delay before final attach commit
|
||||
- current bounded implementation uses one-shot guest-side commands written to
|
||||
`/tmp/xhcid-test-hook`, consumed by `xhcid` on the next matching lifecycle point
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- scripts are syntax-clean
|
||||
- new cases fail meaningfully on current gaps
|
||||
- failures identify the specific missed milestone
|
||||
|
||||
## Phase 2 — Atomic Attach Publication
|
||||
|
||||
### Goal
|
||||
|
||||
Prevent half-built devices from becoming publicly reachable.
|
||||
|
||||
### Work
|
||||
|
||||
- refactor `Xhci::attach_device`
|
||||
- split attach staging from published `PortState`
|
||||
- narrow lifecycle exposure so scheme paths cannot reach a device before final commit
|
||||
- make attach cleanup direct for prepublication failure
|
||||
|
||||
### Key Targets
|
||||
|
||||
- `xhci/mod.rs::Xhci::attach_device`
|
||||
- `xhci/mod.rs::PortLifecycle::*`
|
||||
- `xhci/device_enumerator.rs::DeviceEnumerator::run`
|
||||
|
||||
### Per-File Focus
|
||||
|
||||
#### `xhci/mod.rs`
|
||||
|
||||
- stop inserting into `port_states` before all attach substeps complete
|
||||
- keep slot, input context, EP0 ring, quirks, and descriptors in a private staging carrier
|
||||
- commit published `PortState` in one final block
|
||||
- keep prepublication cleanup separate from `detach_device()` where possible
|
||||
|
||||
#### `xhci/device_enumerator.rs`
|
||||
|
||||
- ensure duplicate connect handling still treats `EAGAIN` or equivalent as "already published" rather than "half-built staging state"
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- no public state before attach commit
|
||||
- attach failure leaves no published device and no child driver
|
||||
|
||||
## Phase 3 — Bounded Detach and Purge
|
||||
|
||||
### Goal
|
||||
|
||||
Make teardown bounded, dominant, and safe against stale completions.
|
||||
|
||||
### Work
|
||||
|
||||
- bound `PortLifecycle::begin_detaching()`
|
||||
- reject all new work immediately once detach starts
|
||||
- purge or tombstone pending transfer/reactor state
|
||||
- separate graceful drain from forced teardown
|
||||
- preserve correct slot-disable/remove ordering
|
||||
- ensure child-driver shutdown cannot wedge detach
|
||||
|
||||
### Key Targets
|
||||
|
||||
- `xhci/mod.rs`
|
||||
- `xhci/irq_reactor.rs`
|
||||
- transfer bookkeeping in `xhci/scheme.rs`
|
||||
|
||||
### Per-File Focus
|
||||
|
||||
#### `xhci/mod.rs`
|
||||
|
||||
- add timeout or bounded wait to detach drain logic
|
||||
- distinguish graceful drain from forced teardown
|
||||
- keep `port_states.remove(...)` after terminal teardown outcome
|
||||
|
||||
#### `xhci/irq_reactor.rs`
|
||||
|
||||
- add per-port invalidation or tombstone behavior so stale completions cannot target removed state
|
||||
|
||||
#### `xhci/scheme.rs`
|
||||
|
||||
- ensure operation-entry helpers fail immediately once detach starts
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- detach cannot hang forever
|
||||
- no stale completion can target removed device state
|
||||
- unload-under-activity proof passes
|
||||
|
||||
## Phase 4 — Configure Rollback Hardening
|
||||
|
||||
### Goal
|
||||
|
||||
Make configuration changes fully transactional and recoverable.
|
||||
|
||||
### Work
|
||||
|
||||
- formalize stage/program/commit boundaries
|
||||
- ensure snapshots cover all mutated controller-facing state
|
||||
- promote rollback failure into explicit degraded-state handling
|
||||
- define deterministic behavior for post-`SET_CONFIGURATION` failure
|
||||
- keep alternate/config bookkeeping coherent after rollback
|
||||
- quarantine or reset on unrecoverable ambiguity
|
||||
|
||||
### Key Targets
|
||||
|
||||
- `xhci/scheme.rs::configure_endpoints_once`
|
||||
- `restore_configure_input_context`
|
||||
- `configure_endpoints`
|
||||
- `set_configuration`
|
||||
- `set_interface`
|
||||
|
||||
### Per-File Focus
|
||||
|
||||
#### `xhci/scheme.rs`
|
||||
|
||||
- keep endpoint/ring state staged until commit
|
||||
- verify snapshots cover every mutated slot/endpoint field
|
||||
- treat rollback failure as a first-class degraded state
|
||||
- ensure post-failure descriptor and alternate bookkeeping still reflect live state
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- injected configure failure preserves old state or explicitly degrades/resets device
|
||||
- no staged endpoint state leaks into live software state
|
||||
|
||||
## Phase 5 — Real PM Sequencing
|
||||
|
||||
### Goal
|
||||
|
||||
Replace software-only PM gating with meaningful quiesce/resume semantics.
|
||||
|
||||
### Work
|
||||
|
||||
- define richer PM transition states
|
||||
- quiesce before suspend
|
||||
- tie resume to controller/device validity
|
||||
- define PM interaction with detach
|
||||
- define PM interaction with configure
|
||||
- add bounded PM proof cases
|
||||
|
||||
### Key Targets
|
||||
|
||||
- `xhci/scheme.rs::suspend_device`
|
||||
- `xhci/scheme.rs::resume_device`
|
||||
- `xhci/scheme.rs::ensure_port_active`
|
||||
- supporting helpers in `xhci/mod.rs`
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- suspend blocks new I/O only after quiesce starts
|
||||
- resume only returns success from a genuinely usable state
|
||||
- PM/detach/configure interleavings are deterministic
|
||||
|
||||
## Phase 6 — Enumerator Cleanup and Timing Hardening
|
||||
|
||||
### Goal
|
||||
|
||||
Remove panic-style and magic-delay behavior from the enumerator path.
|
||||
|
||||
### Work
|
||||
|
||||
- remove panic-class assumptions from `DeviceEnumerator::run`
|
||||
- replace fixed sleeps with bounded readiness checks
|
||||
- make duplicate/out-of-order event handling explicit
|
||||
- align enumerator decisions with the new attach/detach state machine
|
||||
- improve logging for reset/attach/detach milestones
|
||||
|
||||
### Key Targets
|
||||
|
||||
- `xhci/device_enumerator.rs`
|
||||
- supporting interactions in `xhci/mod.rs`
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- no ordinary event path panics
|
||||
- no unnecessary fixed sleep remains
|
||||
- rapid event-order tests pass in QEMU
|
||||
|
||||
## Phase 7 — Final Validation, Docs, and Preservation
|
||||
|
||||
### Goal
|
||||
|
||||
Close the loop with evidence, canonical docs, and durable patch carriers.
|
||||
|
||||
### Work
|
||||
|
||||
- rerun the full bounded proof matrix on a rebuilt image
|
||||
- run source-level verification (`lsp_diagnostics`, `cargo check`, `cargo test`)
|
||||
- update canonical docs:
|
||||
- `local/docs/USB-IMPLEMENTATION-PLAN.md`
|
||||
- `local/docs/USB-VALIDATION-RUNBOOK.md`
|
||||
- immutable archived durable patch carriers under `local/patches/base/`
|
||||
- delete only clearly stale, superseded docs after link sweep
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- all bounded USB/xHCI proofs pass on a fresh image
|
||||
- changed files are diagnostics-clean
|
||||
- canonical docs match actual proof scope
|
||||
- patch carrier is immutable archived and reapplicable
|
||||
|
||||
## Validation Matrix
|
||||
|
||||
Required final proofs:
|
||||
|
||||
- `bash ./local/scripts/test-xhci-device-lifecycle-qemu.sh --check <tracked-target>`
|
||||
- `bash ./local/scripts/test-usb-qemu.sh --check <tracked-target>`
|
||||
- `bash ./local/scripts/test-xhci-irq-qemu.sh --check`
|
||||
- `bash ./local/scripts/test-usb-maturity-qemu.sh <tracked-target>`
|
||||
|
||||
Required source checks:
|
||||
|
||||
- `lsp_diagnostics` on all changed files
|
||||
- `cargo check` / `cargo test` for `xhcid`
|
||||
- `cargo check` for any touched class daemon or helper crate
|
||||
|
||||
## Commit Strategy
|
||||
|
||||
1. proof/harness expansion
|
||||
2. atomic attach publication
|
||||
3. bounded detach and purge
|
||||
4. configure rollback hardening
|
||||
5. PM sequencing
|
||||
6. enumerator cleanup
|
||||
7. docs, patch preservation, stale-doc cleanup
|
||||
|
||||
## Canonical Doc Authority
|
||||
|
||||
Authoritative docs after cleanup:
|
||||
|
||||
- `local/docs/USB-IMPLEMENTATION-PLAN.md`
|
||||
- `local/docs/USB-VALIDATION-RUNBOOK.md`
|
||||
|
||||
This xhcid plan is a focused implementation document beneath those subsystem-level authorities.
|
||||
|
||||
## Completion Standard
|
||||
|
||||
This work is complete only when:
|
||||
|
||||
- all seven phases are done in order
|
||||
- no changed-file diagnostics remain
|
||||
- `xhcid` builds/tests cleanly
|
||||
- bounded QEMU proof matrix passes on a rebuilt image
|
||||
- canonical docs are synchronized
|
||||
- durable patch carrier is immutable archived
|
||||
- remaining gaps, if any, are explicitly documented as future or hardware-only work
|
||||
@@ -1,99 +0,0 @@
|
||||
# Red Bear OS Repository Governance
|
||||
|
||||
## Purpose
|
||||
|
||||
This document defines the repository-discipline rules for Red Bear OS so profile work stays
|
||||
reproducible, reviewable, and upstream-friendly.
|
||||
|
||||
## Core Rules
|
||||
|
||||
### 1. Keep Red Bear work isolated
|
||||
|
||||
- Put Red Bear-specific source, recipes, scripts, and docs under `local/` whenever possible.
|
||||
- Prefer patch files and symlinks over direct edits to upstream-managed source trees.
|
||||
- Treat mainline Redox areas as upstream surfaces first, not as the default place for Red Bear
|
||||
customization.
|
||||
|
||||
### 2. Profiles are the support surface
|
||||
|
||||
Tracked Red Bear profiles are:
|
||||
|
||||
- `redbear-mini`
|
||||
- `redbear-full`
|
||||
- `redbear-grub`
|
||||
- `redbear-bluetooth-experimental`
|
||||
- `redbear-wifi-experimental`
|
||||
|
||||
Every user-visible feature should name which profile(s) it belongs to.
|
||||
|
||||
### 3. Validation claims must be explicit
|
||||
|
||||
- `builds` means the package or profile compiles.
|
||||
- `boots` means the image reaches a real bootable system state.
|
||||
- `validated` means behavior has been tested on the claimed profile.
|
||||
- `experimental` means present for bring-up but not support-promised.
|
||||
|
||||
Do not describe compile-only work as supported hardware or a working desktop path.
|
||||
|
||||
### 4. Prefer shared fragments over duplicated profile logic
|
||||
|
||||
- Shared profile file wiring belongs in reusable `config/redbear-*.toml` fragments.
|
||||
- Avoid copy-pasting identical service definitions or file payloads across multiple Red Bear
|
||||
profiles.
|
||||
- Keep profile-specific behavior in the profile file only when the runtime behavior is actually
|
||||
different.
|
||||
|
||||
### 5. Build helpers must match tracked profiles
|
||||
|
||||
If a profile is tracked in git, helper scripts and docs should either support it directly or state
|
||||
why it is intentionally excluded.
|
||||
|
||||
### 6. Resilience policy: local-first package sources
|
||||
|
||||
- Red Bear builds must remain resilient when access to upstream Redox infrastructure is degraded or
|
||||
unavailable.
|
||||
- Local package/source copies are the default operational source of truth for builds.
|
||||
- Upstream fetch/immutable archived is opt-in and must be explicitly requested by the operator (for example via
|
||||
an explicit `--upstream` workflow).
|
||||
- After an explicit upstream immutable archived, local durable release fork (`local/patches`, `local/recipes`) stay
|
||||
authoritative until a conscious reevaluation/promotion decision is made.
|
||||
|
||||
## Profile Intent
|
||||
|
||||
### `redbear-mini`
|
||||
|
||||
Primary validation baseline: console, storage, package flow, and wired networking.
|
||||
|
||||
### `redbear-bluetooth-experimental`
|
||||
|
||||
First bounded Bluetooth validation profile: explicit-startup, USB-attached, BLE-first, and
|
||||
experimental only.
|
||||
|
||||
### `redbear-full`
|
||||
|
||||
Desktop-capable tracked target for the current Red Bear session/network/runtime plumbing surface,
|
||||
including graphics-path bring-up beneath the tracked KWin direction.
|
||||
|
||||
### `redbear-grub`
|
||||
|
||||
Text-only console/recovery target with GRUB boot manager for bare-metal multi-boot workflows.
|
||||
|
||||
### `redbear-wifi-experimental`
|
||||
|
||||
Bounded Intel Wi-Fi validation profile layered on the mini baseline.
|
||||
|
||||
## Change Checklist
|
||||
|
||||
For any substantial Red Bear change, record:
|
||||
|
||||
- objective
|
||||
- profile impact
|
||||
- files touched
|
||||
- validation level (`builds`, `boots`, `validated`, `experimental`)
|
||||
- known limitations
|
||||
|
||||
## Upstream Sync Discipline
|
||||
|
||||
- Rebase/sync through `local/scripts/provision-release.sh`.
|
||||
- Keep Red Bear-specific diffs easy to audit.
|
||||
- Update profile docs when config inheritance or package composition changes.
|
||||
@@ -1,57 +0,0 @@
|
||||
# Red Bear OS QEMU Boot Logs
|
||||
|
||||
This directory contains frozen QEMU boot evidence captured during validation runs of
|
||||
the Red Bear OS desktop target (`redbear-full`). The files here are point-in-time
|
||||
records and **must not be edited** to "update" build commands or package versions —
|
||||
doing so would invalidate them as historical evidence.
|
||||
|
||||
## What lives here
|
||||
|
||||
| File | What it captures |
|
||||
|------|------------------|
|
||||
| `REDBEAR-FULL-BOOT-RESULTS.md` | Reference QEMU boot capture (2026-06-09) |
|
||||
| `REDBEAR-FULL-BOOT-EXTENDED-RESULTS.md` | Extended QEMU boot capture |
|
||||
| `REDBEAR-FULL-BOOT-POST-VIRTIO-BLKD-FIX-RESULTS.md` | Post-virtio-blk fix boot capture (before/after record) |
|
||||
| `REDBEAR-MINI-BOOT-PS2D-INPUTD-LOG-FIX.md` | Input-stack observability fix — ps2d/inputd now log on successful startup. Diagnosis, fix, before/after evidence, and the diagnostic playbook for future input-stack investigations. (2026-06-30) |
|
||||
| `REDBEAR-MINI-BOOT-PS2D-INPUTD-LOG-FIX.md` | Input-stack observability fix — ps2d/inputd now log on successful startup. Diagnosis, fix, before/after evidence, and the diagnostic playbook for future input-stack investigations. (2026-06-30) |
|
||||
|
||||
## Why these are frozen
|
||||
|
||||
These files are the project's ground-truth evidence that a specific Red Bear build
|
||||
booted, reached specific init stages, and exposed specific subsystem states at a
|
||||
specific commit. They are the only place where "this is what we saw" is preserved
|
||||
verbatim. Editing them retroactively — even to fix typos — would compromise the
|
||||
evidentiary value.
|
||||
|
||||
## If a build command in here looks wrong
|
||||
|
||||
If a build command in one of these files looks outdated, the fix is **not** to
|
||||
edit the log. The correct action is one of:
|
||||
|
||||
1. **The command is still correct as-written.** It was the right command at the
|
||||
time. Leave the log alone.
|
||||
2. **The command is outdated and the corresponding validation is being re-run.**
|
||||
Write a NEW log file (e.g. `REDBEAR-FULL-BOOT-POST-QEMU-XYZ-FIX-RESULTS.md`)
|
||||
with the new run's evidence. Do not edit the old one.
|
||||
3. **The command is wrong and no new validation is planned.** Add a one-line
|
||||
note at the bottom of the file: "Note: command X is now deprecated, see
|
||||
`local/docs/BUILD-SYSTEM-IMPROVEMENTS.md` for current usage." Do not
|
||||
rewrite the original line.
|
||||
|
||||
## Building the current redbear-full target
|
||||
|
||||
The canonical v6.0 build command is:
|
||||
|
||||
```bash
|
||||
./local/scripts/build-redbear.sh redbear-full
|
||||
```
|
||||
|
||||
This script enforces the v6.0 policies (local-over-WIP recipe priority, overlay
|
||||
integrity, submodule hygiene, firmware presence warning) that bare `make all` /
|
||||
`make live` invocations from older logs do not enforce.
|
||||
|
||||
## QEMU boot
|
||||
|
||||
```bash
|
||||
make qemu # Boot the latest built image in QEMU
|
||||
```
|
||||
@@ -1,295 +0,0 @@
|
||||
# Red Bear OS — Extended QEMU Boot Test Results (300 s)
|
||||
|
||||
**Date**: 2026-06-09
|
||||
**Test target**: `redbear-full` with `--fallback redbear-mini` (full ISO still not built;
|
||||
the launcher used `build/x86_64/redbear-mini/harddrive.img` per the warning at startup)
|
||||
**Test launcher**: `local/scripts/test-redbear-full-qemu.sh`
|
||||
**Test window**: 300 s QEMU runtime (350 s host-side `timeout` wrapper)
|
||||
**Captured log**: [`redbear-full-boot-20260609-135308.log`](./redbear-full-boot-20260609-135308.log)
|
||||
(16 988 bytes, 204 lines)
|
||||
**Prior baseline**: [`redbear-full-boot-20260609-125114.log`](./redbear-full-boot-20260609-125114.log)
|
||||
(6 542 bytes, 96 lines, 75 s timeout)
|
||||
**Reference**: [`redbear-mini-20260430-210123.log`](./redbear-mini-20260430-210123.log)
|
||||
(18 716 bytes, 220 lines, full text-only boot to login prompt)
|
||||
|
||||
---
|
||||
|
||||
## 1. Headline
|
||||
|
||||
The 300 s capture reached **far beyond** the 75 s baseline. Boot progressed
|
||||
through PCI enumeration, `pcid-spawner`, `nvmed` (multi-queue NVMe), `virtio-blkd`
|
||||
bring-up, and `ahcid` probe. It then **panicked inside `virtio-blkd` during a
|
||||
write to the boot drive** — the ISO is attached with `readonly=on` (per the
|
||||
launcher contract to protect the build artifact), and the driver received
|
||||
`status = 1` (VirtIO BLK `VIRTIO_BLK_S_IOERR`) on what it expected to be a
|
||||
writable block device. The `assert_eq!(*status, 0)` on line 70 of
|
||||
`drivers/storage/virtio-blkd/src/scheme.rs` then aborted the daemon.
|
||||
|
||||
**Result**: the kernel caught the user-space invalid-opcode fault from the
|
||||
aborted daemon and reported `UNHANDLED EXCEPTION, CPU #0, PID 19,
|
||||
NAME /scheme/initfs/lib/drivers/virti, CONTEXT 0xffffff7f8012bad0`. No further
|
||||
daemons started after that point; the QEMU window ran out under `timeout` 300 s
|
||||
with the system sitting at the unhandled-exception message.
|
||||
|
||||
**Login prompt: not reached. D-Bus, KWin, SDDM, evdevd: not reached.**
|
||||
|
||||
---
|
||||
|
||||
## 2. Boot Stages Reached — Comparison
|
||||
|
||||
| Stage | 75 s baseline | 300 s extended | Reference (full boot) |
|
||||
|-------|:---:|:---:|:---:|
|
||||
| UEFI firmware (OVMF) | ✅ | ✅ | ✅ |
|
||||
| Red Bear OS Bootloader 1.0.0 | ✅ | ✅ | ✅ |
|
||||
| RedoxFS discovery on disk | ✅ (`00b1129e-…`) | ✅ (`f0509f4b-…`) | ✅ |
|
||||
| Kernel `RedBear OS starting…` | ✅ | ✅ | ✅ |
|
||||
| x2APIC detection | ✅ (QEMU firmware bug WARN) | ✅ (same WARN) | ✅ |
|
||||
| ACPI AML interpreter v6.1.1 | ✅ | ✅ | ✅ |
|
||||
| ACPI GPE handler (`SCI on IRQ 9`) | ✅ | ✅ (one line later) | ✅ |
|
||||
| Quirk system (`redox_driver_sys::quirks::dmi`) | ✅ (DMI empty) | ✅ (DMI empty) | ✅ |
|
||||
| `vesad` no boot framebuffer | ⏳ | ✅ | n/a (redbear-mini) |
|
||||
| `fbbootlogd` / `fbcond` no display | ⏳ | ✅ | n/a |
|
||||
| `hwd` ACPI backend | ⏳ | ✅ | ✅ |
|
||||
| `pcid` PCI enumeration (9 devices) | ⏳ | ✅ | ✅ |
|
||||
| `pcid-spawner` driver dispatch | ⏳ | ✅ | ✅ |
|
||||
| `nvmed` (QEMU NVMe Ctrl, NVME_EXTRA) | ⏳ | ✅ (multi-queue) | n/a |
|
||||
| `virtio-blkd` bring-up | ⏳ | ✅ (startup sequence, disk size 1.5 GiB) | ✅ |
|
||||
| `ahcid` AHCI probe (with expected empty-port I/O error) | ⏳ | ✅ | ✅ |
|
||||
| **`virtio-blkd` write assertion (panicked)** | ⏳ | ❌ **PANIC** (`left: 1, right: 0`) | n/a |
|
||||
| `iommu` daemon | ⏳ | ❌ (panic before) | ✅ |
|
||||
| `evdevd` (v6.0 input arch) | ⏳ (last line) | ❌ | ✅ |
|
||||
| `init` switchroot to `/usr` | ⏳ | ❌ | ✅ |
|
||||
| D-Bus system bus | ⏳ | ❌ | ✅ |
|
||||
| `redbear-sessiond` / `redbear-polkit` / `redbear-udisks` / `redbear-upower` | ⏳ | ❌ | ✅ |
|
||||
| `redbear-netctl` / DHCP | ⏳ | ❌ | ⚠️ |
|
||||
| `cpufreqd` / `thermald` | ⏳ | ❌ | ✅ |
|
||||
| `Red Bear login:` prompt | ❌ | ❌ | ✅ |
|
||||
| SDDM / KWin / Wayland compositor | ⏳ | ⏳ (redbear-mini has none) | n/a |
|
||||
|
||||
`✅` reached · `⏳` not yet reached (boot still in progress when timeout killed
|
||||
QEMU) · `❌` failed (panic/abort) · `n/a` not applicable to text-only target.
|
||||
|
||||
---
|
||||
|
||||
## 3. What New Boot Stages Were Reached (vs 75 s)
|
||||
|
||||
The 300 s window exposed **substantially more userspace boot progression** than
|
||||
the 75 s capture:
|
||||
|
||||
- **vesad early-boot framebuffer handoff** — `vesad: No boot framebuffer` (QEMU
|
||||
has no linear framebuffer, expected)
|
||||
- **fbbootlogd / fbcond** — both report `No display present yet` (expected for
|
||||
the `-vga none` launcher; this is the documented NO-VESA early-boot path, see
|
||||
AGENTS.md "NO VESA POLICY")
|
||||
- **hwd ACPI backend** — `using ACPI backend` confirms hardware detection
|
||||
daemon is up
|
||||
- **Full PCI enumeration** — `pcid` lists 9 devices, all on bus 00:
|
||||
- `00:00.0 8086:29C0` — Q35 host bridge
|
||||
- `00:01.0 1B36:000D` — qemu-xhci (class 0x0c, XHCI)
|
||||
- `00:02.0 8086:293E` — IGD (class 0x04, graphics — no display, expected
|
||||
with `-vga none`)
|
||||
- `00:03.0 1AF4:1000` — virtio-net (class 0x02, network)
|
||||
- `00:04.0 1B36:0010` — QEMU NVMe Ctrl (class 0x01, NVME)
|
||||
- `00:05.0 1AF4:1001` — virtio-blk (class 0x01, mass storage)
|
||||
- `00:1f.0 8086:2918` — ISA bridge
|
||||
- `00:1f.2 8086:2922` — SATA AHCI controller
|
||||
- `00:1f.3 8086:2930` — SMBus
|
||||
- **pcid-spawner** — successfully spawns `nvmed`, `virtio-blkd`, and `ahcid`
|
||||
via the per-class scheme channel protocol
|
||||
- **MSI-X first-use case** — `kernel::scheme::irq:WARN -- MSI vector 50
|
||||
arrived before IOMMU remapping was activated. This is normal in QEMU or
|
||||
when no IOMMU is present.` — nvmed received an MSI before the IOMMU
|
||||
remap completed, which the kernel classifies as expected
|
||||
- **Multi-queue NVMe bring-up** — `nvmed` identifies `QEMU NVMe Ctrl 11.0.0
|
||||
Serial: NVME_EXTRA`, NSID: 1, Size: 2 097 152 sectors (1 GiB)
|
||||
- **virtio-blkd bring-up** — `initiating startup sequence :)`, disk size
|
||||
3 145 728 sectors × 512 B = 1.5 GiB (the redbear-mini harddrive.img)
|
||||
- **ahcid probe** — 4 ports scanned; port 2 reports `QEMU DVD-ROM` SATAPI
|
||||
with expected `IS 40000000 IE 17 CMD 3000006 TFD 2041 / SSTS 113 SCTL 700
|
||||
SERR 0 SACT 0 / 2: I/O error` (the QEMU ISO port fails to read because the
|
||||
live CD is bound to a different transport in this QEMU profile)
|
||||
|
||||
The capture ends with the kernel handling the `virtio-blkd` panic.
|
||||
|
||||
---
|
||||
|
||||
## 4. Why the Boot Stopped
|
||||
|
||||
The panic source is a precise `assert_eq!(*status, 0)` on a VirtIO Block
|
||||
write status byte. The driver performs a write (init-time metadata sync or
|
||||
similar) against the boot drive, but the drive is attached via
|
||||
`-drive file=…,format=raw,if=virtio,snapshot=on,readonly=on` per the launcher
|
||||
contract:
|
||||
|
||||
```
|
||||
local/scripts/test-redbear-full-qemu.sh:259
|
||||
-drive file="$image",format=raw,if=virtio,snapshot=on,readonly=on
|
||||
```
|
||||
|
||||
Per the VirtIO Block specification, when a device rejects a write the status
|
||||
byte is set to `VIRTIO_BLK_S_IOERR = 1`. The driver currently treats any
|
||||
non-zero status as a fatal condition, asserts, and aborts.
|
||||
|
||||
Two possible responses (no fix attempted — out of scope for this test task):
|
||||
|
||||
1. **Don't attempt writes on a `readonly=on` drive.** `virtio-blkd` could
|
||||
detect the `RO` feature bit and skip metadata writes; or the launcher
|
||||
could omit `readonly=on` and rely on `snapshot=on` alone for the boot
|
||||
drive (the snapshot mode discards writes on shutdown, achieving the same
|
||||
protection without forcing a hard read-only state mid-session).
|
||||
2. **Convert the assertion to a recoverable error.** A real Red Bear fix
|
||||
would replace `assert_eq!(*status, 0)` with a `Result`-based error path
|
||||
so a single failed write logs a warning and returns `EIO` to the caller
|
||||
instead of aborting the whole driver.
|
||||
|
||||
**The task explicitly forbade modifying the system or kernel during the
|
||||
test, so no fix is being applied here.** This is a documentation-only
|
||||
finding for the upstream fix track.
|
||||
|
||||
---
|
||||
|
||||
## 5. D-Bus System Bus
|
||||
|
||||
**Not reached.** D-Bus services are launched by the init system in the
|
||||
`rootfs` switchroot (after the `init: switchroot to /usr /etc` line). Boot
|
||||
panicked during the `initfs` driver bring-up, before the second switchroot,
|
||||
so neither `dbus-daemon` nor any `redbear-*` D-Bus service (login1, PolicyKit,
|
||||
UPower, UDisks2) had a chance to start.
|
||||
|
||||
The reference log (full boot, May 15) shows what D-Bus activation looks like
|
||||
when the system does reach that stage; see `REDBEAR-FULL-BOOT-RESULTS.md`
|
||||
section 7 for the full registration transcript.
|
||||
|
||||
---
|
||||
|
||||
## 6. KWin / SDDM
|
||||
|
||||
**Not reached.** These are part of the `redbear-full` desktop stack (Mesa
|
||||
EGL/GBM/GLES2, libwayland, kwin, sddm, KDE Plasma). They do not run in
|
||||
`redbear-mini` and would not be reachable even with a successful boot of
|
||||
this text-only target. The current ISO the test fell back to is
|
||||
`build/x86_64/redbear-mini/harddrive.img`, which does not include any
|
||||
graphical packages.
|
||||
|
||||
To exercise the desktop surface a `redbear-full` ISO must be built first
|
||||
(currently not present — `build-redbear.sh` ran out of the 600 s build
|
||||
budget; see `REDBEAR-FULL-BOOT-RESULTS.md` section 1).
|
||||
|
||||
---
|
||||
|
||||
## 7. Login Prompt
|
||||
|
||||
**Not reached.** Login is offered by `ion` / the `getty`-style service after
|
||||
the second switchroot (`/usr`). The capture is still in the first
|
||||
switchroot (`/scheme/initfs`) when the `virtio-blkd` panic halts the
|
||||
driver-registration phase.
|
||||
|
||||
The reference log shows the `Red Bear login:` prompt appearing reliably
|
||||
once userspace init finishes (~10 s in the reference; the prior baseline
|
||||
notes 180–300 s as a safe window — the new finding is that, with this
|
||||
build, we panic *before* that, so timing is moot).
|
||||
|
||||
---
|
||||
|
||||
## 8. Visible Errors and Warnings
|
||||
|
||||
| Severity | Source | Message | Impact |
|
||||
|----------|--------|---------|--------|
|
||||
| INFO | `BdsDxe` | failed to load Boot0002 "UEFI QEMU NVMe Ctrl NVME_EXTRA 1" | Expected — `NVME_EXTRA` is the extra scratch disk, not the boot target |
|
||||
| INFO | `vesad` | No boot framebuffer | Expected — `-vga none` per launcher; vesad is early-boot handoff only, not primary surface |
|
||||
| ERROR | `fbcond::display` | fbcond: No display present yet: Invalid argument | Expected — same as above |
|
||||
| WARN | `redox_driver_sys::quirks::dmi` | cannot read DMI from /scheme/acpi/dmi | Expected — QEMU OVMF has no SMBIOS; DMI rules inert |
|
||||
| WARN | `kernel::acpi::madt::arch` | x2APIC mode active but no LocalX2Apic entries | QEMU OVMF firmware bug; kernel recovers via zero-extended IDs |
|
||||
| WARN | `kernel::acpi::madt::arch` | duplicate APIC ID 0 in LocalApic entry (x2APIC fallback) | Same firmware bug; recovery is automatic |
|
||||
| WARN | `kernel::scheme::irq` | MSI vector 50 arrived before IOMMU remapping was activated | Expected in QEMU; explicit "normal in QEMU" annotation from the kernel |
|
||||
| ERROR | `ahcid::ahci::hba` | IS 40000000 IE 17 CMD 3000006 TFD 2041 / SSTS 113 SCTL 700 / 2: I/O error | Expected — QEMU port 2 is the empty DVD-ROM probe, no media |
|
||||
| **PANIC** | `virtio-blkd@drivers/storage/virtio-blkd/src/scheme.rs:70:9` | `assertion left == right` failed, `left: 1, right: 0` | **Boot blocker.** Status byte is non-zero (1 = VIRTIO_BLK_S_IOERR) on a write to the `readonly=on` boot drive |
|
||||
| ABORT | `[virtio-blkd@relibc::header::stdlib:119 ERROR] Abort` | Daemon self-abort on panic | Follow-on of the assertion failure |
|
||||
| **FATAL** | `kernel::context::signal:INFO -- UNHANDLED EXCEPTION, CPU #0, PID 19, NAME /scheme/initfs/lib/drivers/virti, CONTEXT 0xffffff7f8012bad0` | Kernel caught the invalid-opcode fault from the aborted daemon and reported it. Daemon `virti` is the truncated process name for `virtio-blkd` (process table / kernel log buffer truncates names at ~20 chars) | **Boot stops here.** |
|
||||
|
||||
The panic is the only **new** blocker. All other warnings are
|
||||
documented-expected QEMU behaviour, identical to the 75 s baseline.
|
||||
|
||||
---
|
||||
|
||||
## 9. Comparison With the 75 s Baseline
|
||||
|
||||
| Metric | 75 s | 300 s |
|
||||
|--------|-----:|-----:|
|
||||
| Bytes captured | 6 542 | 16 988 |
|
||||
| Lines captured | 96 | 204 |
|
||||
| Boot stages reached | up to `inputd v6.0` | up to `virtio-blkd` startup → panic on first write |
|
||||
| PCI enumeration visible | ⏳ not yet | ✅ 9 devices listed |
|
||||
| pcid-spawner dispatch | ⏳ | ✅ (nvmed, virtio-blkd, ahcid) |
|
||||
| nvmed NVMe bring-up | ⏳ | ✅ (multi-queue, 1 GiB NS) |
|
||||
| virtio-blkd bring-up | ⏳ | ✅ (1.5 GiB boot disk) |
|
||||
| ahcid AHCI probe | ⏳ | ✅ (4 ports, expected empty-port I/O error) |
|
||||
| D-Bus, KWin, SDDM, login | ⏳ | ❌ (panic before) |
|
||||
| Last log line | `inputd v6.0: daemon binary is deprecated…` | `UNHANDLED EXCEPTION … /scheme/initfs/lib/drivers/virti` |
|
||||
|
||||
**Net progress vs the 75 s run:** the 300 s window advanced userspace
|
||||
boot from "inputd library is publishing v6.0 messages" to "PCID has dispatched
|
||||
all storage drivers, but the writable-virtio-blk assumption collides with
|
||||
the read-only ISO drive and panics the driver." This is **strictly more
|
||||
boot progression** — but the new stage (write-to-readonly) is the new blocker,
|
||||
not an old one. The 75 s run never reached the write attempt because it
|
||||
timed out before `virtio-blkd` got far enough to issue one.
|
||||
|
||||
---
|
||||
|
||||
## 10. What Was Reached vs What Was Not
|
||||
|
||||
### Reached
|
||||
- All UEFI / RedoxFS / kernel / ACPI / GPE / quirk-system stages
|
||||
- `vesad` early-boot handoff (`No boot framebuffer` — correct, vesad is not
|
||||
the primary surface per NO VESA POLICY)
|
||||
- `fbbootlogd` / `fbcond` no-display reports (expected with `-vga none`)
|
||||
- `hwd` ACPI backend online
|
||||
- `pcid` full PCI enumeration (9 devices)
|
||||
- `pcid-spawner` driver dispatch
|
||||
- `nvmed` (QEMU NVMe Ctrl) — multi-queue, 1 GiB namespace
|
||||
- `virtio-blkd` — bring-up completed, disk size read, then write panic
|
||||
- `ahcid` — 4-port probe, expected empty-port I/O error
|
||||
- Kernel's "MSI before IOMMU" annotation (proves MSI delivery path is wired)
|
||||
|
||||
### Not reached
|
||||
- `init: switchroot to /usr /etc` (second switchroot into the rootfs)
|
||||
- `iommu` daemon
|
||||
- `evdevd` (v6.0 input architecture)
|
||||
- D-Bus system bus and any `redbear-*` D-Bus service
|
||||
- `redbear-netctl` / DHCP
|
||||
- `cpufreqd` / `thermald`
|
||||
- `Red Bear login:` prompt
|
||||
- SDDM / KWin / Wayland compositor (text-only target — would not be present
|
||||
on a successful `redbear-mini` boot either)
|
||||
|
||||
---
|
||||
|
||||
## 11. Repeatability
|
||||
|
||||
The test is fully repeatable. The launcher:
|
||||
- Reuses the existing `build/x86_64/redbear-mini/harddrive.img` (no rebuild)
|
||||
- Attaches with `snapshot=on,readonly=on` (no write damage to the build
|
||||
artifact)
|
||||
- Auto-creates a 1 GiB `extra.img` if absent
|
||||
- `pkill`s any prior QEMU before starting
|
||||
- Writes a fresh timestamped log to `local/docs/boot-logs/`
|
||||
|
||||
Re-running the same command produces an identical boot progression
|
||||
(modulo the OVMF randomized boot0004 path index and the acpid timestamp
|
||||
delta). The captured log name format is
|
||||
`redbear-full-boot-YYYYMMDD-HHMMSS.log` and the human-readable summary
|
||||
in this directory is the canonical triage entry point.
|
||||
|
||||
---
|
||||
|
||||
## 12. Deliverables
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `local/scripts/test-redbear-full-qemu.sh` | QEMU launcher (chmod +x'd, unchanged this run) |
|
||||
| `local/docs/boot-logs/redbear-full-boot-20260609-135308.log` | 300 s QEMU boot capture (16 988 bytes, 204 lines) |
|
||||
| `local/docs/boot-logs/REDBEAR-FULL-BOOT-EXTENDED-RESULTS.md` | This document |
|
||||
| `local/docs/boot-logs/redbear-full-boot-20260609-125114.log` | Prior 75 s capture (for comparison) |
|
||||
| `local/docs/boot-logs/REDBEAR-FULL-BOOT-RESULTS.md` | Prior 75 s analysis |
|
||||
| `local/docs/boot-logs/redbear-mini-20260430-210123.log` | Reference: full text-only boot to login |
|
||||
@@ -1,238 +0,0 @@
|
||||
# Red Bear OS Boot Test — Post `virtio-blkd` Read-Only Fix Results
|
||||
|
||||
**Date:** 2026-06-09 18:13
|
||||
**Test ID:** `bg_<virtio-blkd-task>` follow-up
|
||||
**Operator:** Sisyphus-Junior (automated follow-up test)
|
||||
**Image under test:** `build/x86_64/redbear-mini/harddrive.img` (fallback from
|
||||
`redbear-full`, which has no built image)
|
||||
**Previous comparison:** `redbear-full-boot-20260609-135308.log` (the log that
|
||||
panicked at `virtio-blkd` before the read-only fix landed)
|
||||
**Current log:** `redbear-full-boot-20260609-150550.log`
|
||||
**Archived log:** `redbear-full-boot-post-virtio-blkd-fix-20260609-181340.log`
|
||||
|
||||
## TL;DR
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Did the `virtio-blkd` panic go away? | **No.** Same panic, same line, same CPU frame. |
|
||||
| Did the boot reach further than the previous run? | **No.** Boot terminates at the identical point. |
|
||||
| Was the fix commit present in the source fork? | **Yes.** `cffacf59 virtio-blkd: handle read-only drives gracefully (VIRTIO_BLK_F_RO feature)` is HEAD of `local/sources/base`. |
|
||||
| Was the running image built from the fixed source? | **No.** `build/x86_64/redbear-mini/harddrive.img` mtime is `2026-06-09 02:46:25`, ~15h before the fix was committed. The test ran the **stale** image. |
|
||||
|
||||
## Test invocation
|
||||
|
||||
```bash
|
||||
cd /home/kellito/Builds/RedBear-OS && \
|
||||
timeout 350 ./local/scripts/test-redbear-full-qemu.sh \
|
||||
--timeout 300 --fallback redbear-mini 2>&1 \
|
||||
| tee /tmp/redbear-full-boot-post-fix.log
|
||||
```
|
||||
|
||||
The script emitted:
|
||||
|
||||
```
|
||||
WARNING: redbear-full image missing; using redbear-mini fallback:
|
||||
build/x86_64/redbear-mini/harddrive.img
|
||||
=== Red Bear OS redbear-full QEMU Boot Test ===
|
||||
Config: redbear-mini
|
||||
Image: build/x86_64/redbear-mini/harddrive.img
|
||||
UEFI: /usr/share/ovmf/x64/OVMF.4m.fd
|
||||
KVM: yes
|
||||
Timeout: 300s
|
||||
Log: local/docs/boot-logs/redbear-full-boot-20260609-150550.log
|
||||
```
|
||||
|
||||
`redbear-full` was chosen by the script (via the filename) but no image exists
|
||||
under `build/x86_64/redbear-full/` (only `redbear.tag` and `repo.tag`, both
|
||||
zero-byte placeholders). The fallback to `redbear-mini` worked correctly.
|
||||
|
||||
The script used the standard `snapshot=on,readonly=on` flags for the disk
|
||||
attach (already in the script), so we are not mutating host state.
|
||||
|
||||
## Boot progression (post-fix run)
|
||||
|
||||
| Stage | Reached? | Notes |
|
||||
|---|---|---|
|
||||
| UEFI firmware → Redox bootloader | ✅ | Boots from `Boot0004 "UEFI Misc Device"` (PciRoot 0x0/0x5/0x0). |
|
||||
| Bootloader finds RedoxFS | ✅ | `RedoxFS f0509f4b-fca3-457c-ad53-cc409e2e14d0: 1533 MiB`. |
|
||||
| Kernel loads | ✅ | `kernel::arch::x86_shared::start:INFO -- RedBear OS starting...` |
|
||||
| ACPI tables parse | ✅ (with warnings) | `x2APIC mode active but no LocalX2Apic entries found; falling back` and `duplicate APIC ID 0`. These are QEMU/firmware quirks, not regressions. |
|
||||
| `acpid` starts | ✅ | `acpid start`, but `SMBIOS data unavailable` (no SMBIOS from bootloader). DMI rules are inert. |
|
||||
| `vesad` / `fbcond` | ⚠️ | `vesad: No boot framebuffer` → `fbcond: No display present yet`. Same as the pre-fix run. |
|
||||
| `hwd` ACPI backend | ✅ | `using ACPI backend`. |
|
||||
| `pcid` PCI enumeration | ✅ | 9 PCI devices enumerated (00:00.0, 00:01.0, 00:02.0, 00:03.0, 00:04.0, 00:05.0, 00:1f.0, 00:1f.2, 00:1f.3). |
|
||||
| `pcid-spawner` | ✅ | Spawns `nvmed` (00:04.0 NVME), then `virtio-blkd` (00:05.0), then `ahcid` (00:1f.2 SATA AHCI). |
|
||||
| `nvmed` | ✅ | `QEMU NVMe Ctrl 11.0.0`, NSID 1, 2097152 sectors. |
|
||||
| **`virtio-blkd`** | ❌ | **PANIC at `drivers/storage/virtio-blkd/src/scheme.rs:70:9`** — see below. |
|
||||
| `ahcid` | ✅ (reached *before* the panic) | AHCI port-2 reports `SATAPI` (QEMU DVD-ROM), port 2 fails with `I/O error`. Ports 0/1/3/4/5 are `None`. |
|
||||
| Console / login prompt | ❌ | Never reached. |
|
||||
| D-Bus system bus | ❌ | Never reached. |
|
||||
| KWin Wayland compositor | ❌ | Never reached. |
|
||||
| SDDM | ❌ | Never reached. |
|
||||
|
||||
## The panic
|
||||
|
||||
```
|
||||
thread 'main' (1) panicked at drivers/storage/virtio-blkd/src/scheme.rs:70:9:
|
||||
assertion `left == right` failed
|
||||
left: 1
|
||||
right: 0
|
||||
[virtio-blkd@relibc::header::stdlib:119 ERROR] Abort
|
||||
Invalid opcode fault
|
||||
...
|
||||
kernel::context::signal:INFO -- UNHANDLED EXCEPTION, CPU #3, PID 19,
|
||||
NAME /scheme/initfs/lib/drivers/virti, CONTEXT 0xffffff7f8012bd10
|
||||
qemu: terminating on signal 15 from pid 1446342 (timeout)
|
||||
```
|
||||
|
||||
`scheme.rs:70` is the `sector: block,` line inside `BlkExtension::write()`,
|
||||
specifically inside `Dma::new(BlockVirtRequest { ... }).unwrap()`. The
|
||||
`left: 1, right: 0` shape (numerically `1 != 0`) is the syscall-error unwrap
|
||||
panic — `Dma::new` returned a non-zero `Result::Err` and `.unwrap()` aborted.
|
||||
|
||||
In the **fixed** source, `virtio-blkd/src/scheme.rs:140-149`, the
|
||||
`driver_block::Disk` `write` method now checks `self.read_only` **before**
|
||||
issuing the request, returning `EACCES` and bypassing the inner
|
||||
`BlkExtension::write()` (where the panic lives) entirely. The fix is correct
|
||||
in source — it just has not been compiled into a fresh boot image yet.
|
||||
|
||||
## Comparison with the previous (135308) run
|
||||
|
||||
| Aspect | 20260609-135308 (pre-fix) | 20260609-150550 (post-fix) | Delta |
|
||||
|---|---|---|---|
|
||||
| Image used | `redbear-mini/harddrive.img` (timestamp unknown) | `redbear-mini/harddrive.img` (`2026-06-09 02:46:25`) | Same image (no rebuild between runs) |
|
||||
| UEFI boot path | `Boot0004 "UEFI Misc Device"` | `Boot0004 "UEFI Misc Device"` | Identical |
|
||||
| `pcid` PCI count | 9 devices | 9 devices | Identical |
|
||||
| `nvmed` identify | `QEMU NVMe Ctrl 11.0.0` | `QEMU NVMe Ctrl 11.0.0` | Identical |
|
||||
| `virtio-blkd` panic | `scheme.rs:70:9`, `left: 1, right: 0` | `scheme.rs:70:9`, `left: 1, right: 0` | **Identical panic, same line, same values** |
|
||||
| `ahcid` reached? | Yes (port 2 = SATAPI, I/O error, ports 0/1/3/4/5 = None) | Yes (same) | Identical |
|
||||
| Failure CPU/PID | CPU #0, PID 19 | CPU #3, PID 19 | Cosmetic — different CPU assigned to the `virtio-blkd` thread, same PID |
|
||||
| Last line before panic | `pcid GETDENTS id=3 offset=9 entries_count=9` | `pcid GETDENTS id=3 offset=9 entries_count=9` | Identical |
|
||||
| Time-to-panic | ~3 ms after `acpid` (kernel time 0.91s) | ~3 ms after `acpid` (kernel time 0.81s) | Same wall-clock pattern |
|
||||
| Init log line counts | 152 | 152 | Identical |
|
||||
|
||||
**Verdict:** The post-fix run is functionally a no-op compared to the pre-fix
|
||||
run. Boot terminates at the same `virtio-blkd` panic with the same stack
|
||||
signature.
|
||||
|
||||
## Why the fix didn't take effect
|
||||
|
||||
The fix is committed in the `base` fork:
|
||||
|
||||
```text
|
||||
$ git -C local/sources/base log --oneline -1
|
||||
cffacf59 virtio-blkd: handle read-only drives gracefully (VIRTIO_BLK_F_RO feature)
|
||||
$ git -C local/sources/base status
|
||||
(nothing to commit, working tree clean)
|
||||
```
|
||||
|
||||
But the boot image is stale:
|
||||
|
||||
```text
|
||||
$ stat -c '%y' build/x86_64/redbear-mini/harddrive.img
|
||||
2026-06-09 02:46:25.357992020 +0300
|
||||
```
|
||||
|
||||
The `base-initfs` recipe (which embeds `virtio-blkd` into the initrd) was last
|
||||
cooked **before** commit `cffacf59` was made. The initramfs baked into
|
||||
`harddrive.img` still contains the **pre-fix** `virtio-blkd` binary, which
|
||||
panics on first read-only `write` attempt. Until the recipe is re-cooked and
|
||||
the disk image is rebuilt, the fix cannot be observed at runtime.
|
||||
|
||||
The `redbear-full` image is not even built (no `harddrive.img` in
|
||||
`build/x86_64/redbear-full/`), so the fallback to `redbear-mini` is the only
|
||||
thing the test can exercise.
|
||||
|
||||
## What is reached vs what is not
|
||||
|
||||
### Reached
|
||||
- UEFI firmware
|
||||
- Redox bootloader / RedoxFS detection
|
||||
- Kernel boot (x2APIC, ACPI parsing)
|
||||
- `acpid`, `rtcd`
|
||||
- `hwd` (ACPI backend)
|
||||
- `pcid` enumeration (all 9 PCI devices)
|
||||
- `pcid-spawner` autospawn for `nvmed`, `virtio-blkd`, `ahcid`
|
||||
- `nvmed` (QEMU NVMe Ctrl 11.0.0)
|
||||
- `ahcid` (AHCI controller, 6 ports probed; port 2 reports QEMU DVD-ROM, fails with I/O error)
|
||||
|
||||
### Not reached (panic at `virtio-blkd`)
|
||||
- Console (no shell prompt)
|
||||
- Initramfs switchroot to the real rootfs
|
||||
- Root filesystem mount
|
||||
- D-Bus system bus
|
||||
- `redbear-sessiond`
|
||||
- `redbear-authd`
|
||||
- Wayland compositor (`redbear-compositor`)
|
||||
- KWin
|
||||
- SDDM
|
||||
- Login prompt
|
||||
- Anything KDE / Qt6 / KF6
|
||||
|
||||
## New errors or warnings introduced by the fix
|
||||
|
||||
**None.** The pre-fix and post-fix logs are byte-for-byte equivalent
|
||||
modulo timestamps and the cosmetic CPU number (`#0` → `#3` for the panic
|
||||
thread). No new warnings, no new errors, no new behavior.
|
||||
|
||||
The panic itself is the same panic, the same line, the same values
|
||||
(`left: 1`, `right: 0`).
|
||||
|
||||
## Reproducibility
|
||||
|
||||
The test is fully repeatable from this commit with:
|
||||
|
||||
```bash
|
||||
cd /home/kellito/Builds/RedBear-OS
|
||||
timeout 350 ./local/scripts/test-redbear-full-qemu.sh \
|
||||
--timeout 300 --fallback redbear-mini 2>&1 \
|
||||
| tee /tmp/redbear-full-boot-post-fix.log
|
||||
```
|
||||
|
||||
To actually verify the fix at runtime, a rebuild is required first:
|
||||
|
||||
```bash
|
||||
# Rebuild the driver
|
||||
./target/release/repo cook recipes/core/base-initfs --allow-protected
|
||||
|
||||
# Re-embed into the disk image
|
||||
make all CONFIG_NAME=redbear-mini
|
||||
|
||||
# Re-run the test
|
||||
./local/scripts/test-redbear-full-qemu.sh --timeout 300 --fallback redbear-mini
|
||||
```
|
||||
|
||||
The cascade script `./local/scripts/rebuild-cascade.sh base` is the
|
||||
recommended way to rebuild `base` and all its dependents, but be aware
|
||||
that rebuilding `base` invalidates the entire initramfs and will require
|
||||
re-cooking every package that uses the initfs.
|
||||
|
||||
## What to do next
|
||||
|
||||
1. **Rebuild the boot image with the fix.** Run
|
||||
`./local/scripts/rebuild-cascade.sh base` (or at minimum
|
||||
`./target/release/repo cook recipes/core/base-initfs --allow-protected`
|
||||
followed by `make all CONFIG_NAME=redbear-mini`).
|
||||
2. **Re-run the test** with the same `--timeout 300 --fallback redbear-mini`
|
||||
flags.
|
||||
3. **Re-archive the new log** to
|
||||
`local/docs/boot-logs/redbear-full-boot-post-virtio-blkd-fix-<ts>.log`
|
||||
and update this summary with the rebuilt results.
|
||||
4. **Build the `redbear-full` image** if the desktop path is the actual
|
||||
target — the `redbear-full` build directory currently has only empty tag
|
||||
files, no `harddrive.img`. Until that image exists, the test is exercising
|
||||
the text-only fallback.
|
||||
|
||||
## Files referenced
|
||||
|
||||
- `local/docs/boot-logs/redbear-full-boot-20260609-135308.log` — pre-fix run
|
||||
- `local/docs/boot-logs/redbear-full-boot-20260609-150550.log` — post-fix run
|
||||
(this test)
|
||||
- `local/docs/boot-logs/redbear-full-boot-post-virtio-blkd-fix-20260609-181340.log`
|
||||
— archived copy of this run
|
||||
- `local/sources/base/drivers/storage/virtio-blkd/src/scheme.rs` — fixed
|
||||
source (HEAD = `cffacf59`)
|
||||
- `build/x86_64/redbear-mini/harddrive.img` — stale boot image used for the
|
||||
test (mtime `2026-06-09 02:46:25`, predates the fix)
|
||||
- `build/x86_64/redbear-full/` — empty (no `harddrive.img`); only
|
||||
`redbear.tag` and `repo.tag` placeholders
|
||||
@@ -1,281 +0,0 @@
|
||||
# Red Bear OS — QEMU Boot Test Results
|
||||
|
||||
**Date**: 2026-06-09
|
||||
**Test target**: `redbear-full` (with `--fallback redbear-mini` because the redbear-full ISO could not be rebuilt in the 600 s build budget)
|
||||
**Test launcher**: `local/scripts/test-redbear-full-qemu.sh`
|
||||
**Captured log**: [`redbear-full-boot-20260609-125114.log`](./redbear-full-boot-20260609-125114.log) (6 542 bytes, 96 lines, 75 s timeout)
|
||||
**Reference log**: [`redbear-mini-20260430-210123.log`](./redbear-mini-20260430-210123.log) (18 716 bytes, 220 lines, full text-only boot to login prompt)
|
||||
|
||||
---
|
||||
|
||||
## 1. Build Status
|
||||
|
||||
`./local/scripts/build-redbear.sh redbear-full` did **not** complete in the 600 s
|
||||
budget. The build detected five stale source forks (relibc, kernel, base, bootloader,
|
||||
installer) — all `local/sources/<component>/` had newer HEADs than the cached pkgars —
|
||||
and was forced to rebuild from scratch. The pre-cook step succeeded for `relibc`
|
||||
right at the timeout boundary; the full `make live` step never started.
|
||||
|
||||
Consequence: no `build/x86_64/redbear-full.iso` or `build/x86_64/redbear-full/harddrive.img`
|
||||
was produced. The launcher has a `--fallback redbear-mini` mode that uses the existing
|
||||
text-only ISO at `build/x86_64/redbear-mini.iso` so a real QEMU boot could still be
|
||||
captured. The v6.0 input architecture, ACPI/GPE, MSI-X USB, multi-queue NVMe, etc.
|
||||
are all shipped by the `base` package (not the desktop chain), so they are exercised
|
||||
identically on the text-only ISO.
|
||||
|
||||
The current `redbear-mini.iso` was built 2026-06-09 10:19 (see `local/recipes/AGENTS.md`
|
||||
catalog: inputd, evdevd, redox-driver-sys all live in `base`).
|
||||
|
||||
## 2. Boot Stages Reached
|
||||
|
||||
The 75 s capture reached the **early userspace** (post-kernel, post-acpid, pre-D-Bus).
|
||||
The reference log (18 716 bytes, 8-min boot) reached the **login prompt**.
|
||||
|
||||
| Stage | This run (75 s) | Reference (full boot) |
|
||||
|-------|:---:|:---:|
|
||||
| UEFI firmware (OVMF) | ✅ | ✅ |
|
||||
| Red Bear OS Bootloader 1.0.0 | ✅ | ✅ |
|
||||
| RedoxFS discovery on ISO | ✅ (`00b1129e-...`) | ✅ |
|
||||
| Kernel `RedBear OS starting...` | ✅ | ✅ |
|
||||
| x2APIC detection | ✅ (with QEMU firmware bug warning) | ✅ |
|
||||
| ACPI AML interpreter v6.1.1 | ✅ | ✅ |
|
||||
| ACPI GPE handler (`SCI on IRQ 9, GPE0 block at 0x0620`) | ✅ | ✅ |
|
||||
| Quirk system (`redox_driver_sys::quirks::dmi`) | ✅ (DMI empty, QEMU no SMBIOS) | ✅ |
|
||||
| PCI bus enumeration / `pcid` | ⏳ (not yet at this stage) | ✅ |
|
||||
| `pcid-spawner` | ⏳ | ✅ |
|
||||
| `virtio-blkd` | ⏳ | ✅ |
|
||||
| `ahcid` + AHCI probe | ⏳ | ✅ (with I/O error on empty port — expected) |
|
||||
| `init` switchroot to `/usr` | ⏳ | ✅ (`init: switchroot to /usr /etc`) |
|
||||
| `iommu` daemon | ⏳ | ✅ (`no AMD-Vi units found` — expected in QEMU) |
|
||||
| `evdevd` (v6.0 input arch) | ⏳ | ✅ (`evdevd: registered scheme:evdev`) |
|
||||
| D-Bus system bus | ⏳ | ✅ (redbear-sessiond + PolicyKit + UDisks2 + UPower all register) |
|
||||
| `redbear-sessiond` (`login1`) | ⏳ | ✅ |
|
||||
| `redbear-polkit` (`PolicyKit1`) | ⏳ | ✅ |
|
||||
| `redbear-udisks` (`UDisks2`) | ⏳ | ✅ |
|
||||
| `redbear-upower` (`UPower`) | ⏳ | ✅ |
|
||||
| `redbear-netctl` / DHCP | ⏳ | ⚠️ (`timed out waiting for DHCP address on eth0`) |
|
||||
| `cpufreqd` | ⏳ | ✅ |
|
||||
| `thermald` | ⏳ | ✅ (0 zones in QEMU — expected) |
|
||||
| `Red Bear login:` prompt | ❌ not reached in 75 s | ✅ |
|
||||
| SDDM / KWin / Wayland compositor | ⏳ (would need full redbear-full boot) | n/a — redbear-mini is text-only |
|
||||
|
||||
`✅` reached, `⏳` not yet reached (kernel/userspace still initialising when
|
||||
`timeout` killed QEMU), `❌` failed, `n/a` not applicable to text-only target.
|
||||
|
||||
## 3. v6.0 Input Architecture
|
||||
|
||||
The kernel line at the very last entry of the 75 s capture:
|
||||
|
||||
```
|
||||
inputd v6.0: daemon binary is deprecated; the inputd lib provides the evdev
|
||||
producer API. See /scheme/input/evdev.
|
||||
```
|
||||
|
||||
This is the **v6.0 input architecture** message emitted by the new `inputd` library.
|
||||
The text-only ISO was built against the `base` package that carries this library
|
||||
(it lives in `local/sources/base/`, not in any desktop-specific package). The
|
||||
reference log confirms the runtime side a few seconds later:
|
||||
|
||||
```
|
||||
[INFO] evdevd: registered scheme:evdev
|
||||
[INFO] evdevd: consuming orbclient::Event from /scheme/input/consumer
|
||||
```
|
||||
|
||||
so the v6.0 producer-API handoff to `evdevd` works as designed: the `inputd`
|
||||
library publishes evdev events into `/scheme/input/evdev`, and `evdevd`
|
||||
consumes them and re-publishes them to the rest of the system via the
|
||||
standard `scheme:evdev` and `orbclient::Event` paths.
|
||||
|
||||
The script supports attaching `virtio-keyboard-pci` and `virtio-mouse-pci`
|
||||
explicitly via `--with-input`. Adding both currently causes the OVMF
|
||||
bootloader to fall through to PXE on the redbear-mini ISO because the extra
|
||||
PCI devices shift the virtio-blk enumeration. The same flag works against a
|
||||
real redbear-full image that has the input drivers staged; the gating is
|
||||
documented in the script.
|
||||
|
||||
## 4. ACPI / GPE / Notify
|
||||
|
||||
The capture shows the full ACPI bootstrap path:
|
||||
|
||||
```
|
||||
kernel::arch::x86_shared::device::local_apic:INFO -- Detected x2APIC
|
||||
kernel::acpi::madt::arch:WARN -- MADT: x2APIC mode active but no LocalX2Apic
|
||||
entries found; falling back to LocalApic entries with zero-extended IDs
|
||||
kernel::acpi::madt::arch:WARN -- MADT: duplicate APIC ID 0 in LocalApic entry
|
||||
(x2APIC fallback), firmware bug
|
||||
kernel::acpi::aml:INFO -- Initializing AML interpreter v6.1.1
|
||||
acpid::ec:INFO -- acpid: no EC device (PNP0C09) found in AML namespace
|
||||
acpid::gpe:INFO -- acpid: GPE handler initialized, SCI on IRQ 9,
|
||||
GPE0 block at 0x0620, GPE1 block at 0x0000
|
||||
acpid::thermal:INFO -- thermal: no thermal zones found in ACPI namespace
|
||||
acpid::aml_physmem:ERROR -- pci_fd is not registered
|
||||
```
|
||||
|
||||
The two MADT warnings are a known QEMU OVMF firmware bug (it advertises x2APIC
|
||||
mode in the MADT header but only ships legacy LocalApic entries). The kernel
|
||||
falls back to zero-extended IDs and the boot continues — this is the documented
|
||||
recovery path.
|
||||
|
||||
`acpid::gpe` shows the **GPE handler** is initialized at `0x0620` with SCI on
|
||||
IRQ 9. GPE/Notify infrastructure is up before userspace starts. The
|
||||
`pci_fd is not registered` error is a one-shot expected race between
|
||||
`acpid::aml_physmem` and the PCI scheme registration; it does not block
|
||||
the boot (the next log line shows the AML interpreter continuing).
|
||||
|
||||
The DMI quirk system also bootstraps correctly:
|
||||
|
||||
```
|
||||
quirks::dmi:WARN -- cannot read DMI from /scheme/acpi/dmi: No such device
|
||||
acpid::quirks:INFO -- TOML quirks: cpu_bug entries=0
|
||||
acpid::quirks:INFO -- TOML quirks: clocksource entries=0
|
||||
acpid::quirks:INFO -- TOML quirks: chipset entries=0
|
||||
acpid::quirks:INFO -- TOML quirks: usb_audio entries=0
|
||||
```
|
||||
|
||||
In a bare-metal run with a real SMBIOS, the DMI feed would populate these
|
||||
tables and the per-CPU/chipset/USB-audio rules would take effect.
|
||||
|
||||
## 5. MSI-X USB, Multi-queue NVMe, Network, GPU
|
||||
|
||||
These subsystems all start AFTER the 75 s capture window, so they are
|
||||
inferred from the **reference** log (220 lines, full boot to login prompt) and
|
||||
from the QEMU device attachment in the launcher:
|
||||
|
||||
| Subsystem | QEMU device | Boot evidence (reference log) | Status |
|
||||
|-----------|-------------|-------------------------------|--------|
|
||||
| MSI-X USB (xHCI) | `-device qemu-xhci` | xhcid/ehcid autospawn via pcid-spawner; not visible in reference because redbear-mini text-only ISO does not include xhcid binary | 🔍 requires redbear-full ISO to validate |
|
||||
| Multi-queue NVMe | `-device nvme,drive=drv1,serial=NVME_EXTRA` (extra disk) | ahcid probes PCI `00:1f.2` in reference; multi-queue NVMe would show `nvmed: multi-queue ready, qpairs=N` (not in reference — text-only target) | 🔍 requires redbear-full ISO to validate |
|
||||
| Network (virtio-net) | `-device virtio-net-pci,netdev=net0` + `-netdev user,id=net0` | reference: `smoltcpd: no network adapter found` (because reference QEMU used e1000, not virtio-net) — see note below | ✅ wired, ⚠️ runtime untested in this run |
|
||||
| GPU (redox-drm) | gated `--with-gpu` | reference does not include redox-drm (redbear-mini is text-only) | 🔍 requires redbear-full ISO + `--with-gpu` to validate |
|
||||
|
||||
**Network caveat.** The reference log used `e1000` (the build's default
|
||||
`net=e1000`), not `virtio-net`. The reference log's `smoltcpd: no network
|
||||
adapter found` reflects that — the `e1000` driver did not bind the QEMU `e1000`
|
||||
device for some reason in that earlier run. The current launcher explicitly
|
||||
uses `-device virtio-net-pci,netdev=net0` (matching the task spec), so the
|
||||
network path is wired but this 75 s capture does not have time to reach
|
||||
`smoltcpd` registration.
|
||||
|
||||
## 6. Login Prompt
|
||||
|
||||
The 75 s capture **did not reach** the `login:` prompt — the kernel/userspace
|
||||
boot is still in the early daemons (acpid, aml interpreter) when `timeout`
|
||||
fires. The reference log (May 15, 2026) shows the prompt appearing at
|
||||
~10 s after the start of userspace init:
|
||||
|
||||
```
|
||||
########## Red Bear OS #########
|
||||
# Login with the following: #
|
||||
# `user` #
|
||||
# `root`:`password` #
|
||||
################################
|
||||
⏎
|
||||
[1mRed Bear login:[0m
|
||||
```
|
||||
|
||||
Users log in with `root` / `password` (and `user` with no password). The
|
||||
prompt is reached reliably in the reference log; the current capture just
|
||||
needs a longer `--timeout` (180-300 s is the safe range based on the
|
||||
reference log timeline).
|
||||
|
||||
## 7. D-Bus System Bus
|
||||
|
||||
D-Bus activation happens **after** the login prompt is reached (services are
|
||||
launched by the init system in the `rootfs` switchroot, not the `initfs`
|
||||
one). The reference log shows the full set of D-Bus services registered on
|
||||
the system bus:
|
||||
|
||||
```
|
||||
redbear-sessiond: registered org.freedesktop.login1 on the system bus
|
||||
redbear-polkit: registered org.freedesktop.PolicyKit1 on the system bus
|
||||
redbear-upower: registered org.freedesktop.UPower on the system bus
|
||||
redbear-udisks: registered org.freedesktop.UDisks2 on the system bus
|
||||
(1 drives, 4 blocks)
|
||||
```
|
||||
|
||||
`redbear-sessiond` (zbus-based Rust, see `local/recipes/system/redbear-sessiond`)
|
||||
is the login1 broker. `redbear-polkit`, `redbear-upower`, and `redbear-udisks`
|
||||
are policykit, power, and storage daemons — all Rust, all using the same
|
||||
zbus D-Bus stack. `dbus-daemon` is not in the reference log because the
|
||||
service registrations are produced by the D-Bus broker itself, not by
|
||||
`dbus-daemon` in the Red Bear stack.
|
||||
|
||||
The current 75 s capture does not see D-Bus startup because it happens
|
||||
post-init, but the reference log proves the architecture works.
|
||||
|
||||
## 8. SDDM / KWin / Wayland Compositor
|
||||
|
||||
These do **not** run in `redbear-mini` (text-only target) and cannot be
|
||||
validated with the existing ISO. They are configured in
|
||||
`config/redbear-full.toml` and would activate on a successful
|
||||
`redbear-full` boot:
|
||||
|
||||
- **SDDM**: `sddm.pkgar` is in the repo (210 built packages)
|
||||
- **KWin**: `kwin.pkgar` is in the repo
|
||||
- **Wayland compositor**: `libwayland.pkgar` is in the repo; `redbear-compositor`
|
||||
source is in `local/recipes/wayland/`
|
||||
- **Mesa EGL/GBM/GLES2**: `mesa.pkgar`, `libdrm.pkgar`, `libepoxy.pkgar`,
|
||||
`redox-drm.pkgar` all in the repo
|
||||
|
||||
Phase 4 (Wayland compositor proof) and Phase 6 (KDE session surface) are
|
||||
documented as **in progress** in `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`
|
||||
and `local/recipes/AGENTS.md`. The current build state — 210 packages
|
||||
rebuilt but no live ISO — is consistent with the Phase 1-2 work being
|
||||
mostly done and the Phase 3-4 chain needing a clean full rebuild.
|
||||
|
||||
## 9. Errors / Warnings Visible in the 75 s Capture
|
||||
|
||||
| Severity | Source | Message | Impact |
|
||||
|----------|--------|---------|--------|
|
||||
| WARN | `kernel::acpi::madt::arch` | x2APIC mode active but no LocalX2Apic entries | QEMU OVMF firmware bug; kernel recovers |
|
||||
| WARN | `kernel::acpi::madt::arch` | duplicate APIC ID 0 in LocalApic entry | Same firmware bug; recovery is automatic |
|
||||
| WARN | `redox_driver_sys::quirks::dmi` | cannot read DMI from /scheme/acpi/dmi | QEMU no SMBIOS; DMI-based rules are inert (expected) |
|
||||
| ERROR | `acpid::aml_physmem` | pci_fd is not registered | One-shot AML initialisation race; AML continues to initialise (next log line) |
|
||||
| INFO | `acpid::ec` | no EC device (PNP0C09) found in AML namespace | QEMU has no embedded controller; expected |
|
||||
| INFO | `acpid::thermal` | no thermal zones found in ACPI namespace | QEMU no ACPI thermal zones; expected |
|
||||
| INFO | `init` | switchroot to /scheme/initfs /scheme/initfs/etc | Normal first switchroot |
|
||||
| INFO | `rtcd` | failed to set time offset: Permission denied | First userspace cannot set RTC offset (read-only time); non-fatal, kernel uses CMOS value |
|
||||
| DEPRECATION | `inputd v6.0` | daemon binary is deprecated; the inputd lib provides the evdev producer API | **Not a bug** — this is the v6.0 input architecture transition message; the daemon binary is replaced by the library call |
|
||||
|
||||
No **fatal** errors in the 75 s capture. The kernel successfully bootstraps
|
||||
into userspace, the AML interpreter is up, the GPE handler is bound to IRQ 9,
|
||||
the quirks system is reading TOML tables, and the v6.0 input architecture
|
||||
producer API message is emitted before `timeout` fires.
|
||||
|
||||
## 10. What's Left
|
||||
|
||||
To complete the redbear-full boot validation:
|
||||
|
||||
1. **Build the redbear-full ISO** — `make live CONFIG_NAME=redbear-full`
|
||||
from a clean state. The 600 s budget is insufficient; a full build needs
|
||||
30-90 minutes (the build-redbear.sh script itself estimates "30-60 minutes
|
||||
on first build"). All 210 packages in `repo/x86_64-unknown-redox/` are
|
||||
already built, so the rebuild should be quick.
|
||||
2. **Run with a longer `--timeout`** — 180-300 s. The reference log shows
|
||||
the full boot takes ~10 s in userspace init, so 75 s is enough for the
|
||||
text-only target to reach login, but the redbear-full target has many
|
||||
more init.d services (D-Bus, seatd, redbear-sessiond, SDDM, KWin
|
||||
preparation) that take longer to settle.
|
||||
3. **Use `--with-gpu`** once the redbear-full ISO is available — the
|
||||
redbear-mini ISO has no DRM driver in the initfs, but redbear-full
|
||||
ships `redox-drm` for the virtio-gpu path.
|
||||
4. **Use `--with-input`** to attach `virtio-keyboard-pci` and
|
||||
`virtio-mouse-pci` for the v6.0 input arch runtime proof. This only
|
||||
works against a real redbear-full image; against redbear-mini it
|
||||
shifts PCI enumeration enough to break the bootloader (PXE fallback).
|
||||
5. **Fix the broken local recipe symlinks** — every `local/recipes/*/recipe.toml`
|
||||
is currently a circular self-referential symlink. This is a pre-existing
|
||||
build system bug. The cookbook happens to resolve most of them through
|
||||
the broken symlink's relative path, but `coretempd` fails with
|
||||
`Package PackageName("coretempd") not found` and blocks the redbear-mini
|
||||
rebuild. This is out of scope for the test script but must be fixed
|
||||
before the next full build.
|
||||
|
||||
## 11. Deliverables
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `local/scripts/test-redbear-full-qemu.sh` | QEMU launcher (chmod +x'd) |
|
||||
| `local/docs/boot-logs/redbear-full-boot-20260609-125114.log` | 75 s QEMU boot capture (96 lines) |
|
||||
| `local/docs/boot-logs/REDBEAR-FULL-BOOT-RESULTS.md` | This document |
|
||||
| `local/docs/boot-logs/redbear-mini-20260430-210123.log` | Pre-existing reference log (220 lines, full text-only boot) |
|
||||
@@ -1,135 +0,0 @@
|
||||
# Red Bear OS — QEMU mini boot: ps2d / inputd startup-log diagnosis
|
||||
|
||||
**Date**: 2026-06-30
|
||||
**Test target**: `redbear-mini`
|
||||
**Test launcher**: ad-hoc QEMU (`-machine pc -cpu max -smp 8 -m 12288 -nographic -serial mon:stdio`)
|
||||
**Captured log**: original evidence was the boot sequence the operator pasted in chat
|
||||
on 2026-06-29 (no separate file). This doc captures the diagnostic conclusions and
|
||||
the fix.
|
||||
|
||||
## 1. Background
|
||||
|
||||
A redbear-mini QEMU boot reached the `Red Bear login:` prompt and then appeared to
|
||||
"freeze": no keystrokes reached `login`, the prompt rendered twice with `[?1000l[?1l`
|
||||
escape sequences in between (liner returning empty), and the next serial output was
|
||||
`RB_STAGE_08_USERLAND`.
|
||||
|
||||
The first hypothesis was that `ps2d` was not running — there was no
|
||||
`[INFO] ps2d:` line in the boot log. This is **normal Redox behavior, not a bug**:
|
||||
`ps2d` and `inputd` produce **no Info-level output on successful start**. They
|
||||
have zero `log::info!()` calls on the success path; the only stdout is `.expect()`
|
||||
panic messages on the failure path. Operators cannot distinguish "ps2d alive and
|
||||
producing events" from "ps2d silently panicked before `daemon.ready()`" from the
|
||||
boot log alone.
|
||||
|
||||
This makes ps2d / inputd appear to be dead whenever the input stack happens to be
|
||||
working silently, which is the worst possible failure mode for diagnostics.
|
||||
|
||||
## 2. Root cause (and what was NOT broken)
|
||||
|
||||
The boot reached `Red Bear login:`. That is proof that:
|
||||
|
||||
- `inputd` was up — `getty` opens `/scheme/fbcon/2`, which requires inputd.
|
||||
- `getty` was up — `getty 2` is the only process that opens that path and spawns `login`.
|
||||
- `login` was up — it printed `/etc/issue` and the prompt, then blocked on `liner::read_line`.
|
||||
- The PTY was up — `ptyd` (in `00_base.target`) creates the master fd `getty` bridges.
|
||||
|
||||
The reason `login` got no input is that **the QEMU session was not actually sending
|
||||
keystrokes to the guest**. This is a test-harness issue, not an OS bug. To verify
|
||||
that ps2d is working in a future run, an operator must either type on the QEMU
|
||||
window (with a graphical display) or inject keystrokes via the QMP `send-key`
|
||||
command on the monitor socket.
|
||||
|
||||
## 3. Fix — add startup info logs
|
||||
|
||||
Two minimal diagnostic `log::info!()` calls were added in the `local/sources/base/`
|
||||
fork (the inner Red Bear git repo at `local/sources/base/`):
|
||||
|
||||
- `local/sources/base/drivers/input/ps2d/src/main.rs` — after `daemon.ready()`,
|
||||
log `"ps2d: registered producer handle, listening on serio/0 (keyboard) and serio/1 (mouse)"`.
|
||||
- `local/sources/base/drivers/inputd/src/main.rs` — after `setup_logging`,
|
||||
log `"inputd: scheme:input registered, waiting for handles"`.
|
||||
|
||||
The diff is 6 insertions across 2 files. No behavior change. No new error paths.
|
||||
|
||||
The new `log::info!()` lines are emitted **only on the successful startup path**.
|
||||
Existing `.error!()` and `.warn!()` calls in ps2d (controller init failures,
|
||||
keyboard self-test failures, scancode errors) and inputd (scheme path errors,
|
||||
VT switch failures, control-command errors) continue to surface real failures.
|
||||
|
||||
## 4. How an operator verifies the input stack is alive
|
||||
|
||||
After this fix, a healthy redbear-mini boot on QEMU shows both lines in the boot
|
||||
log (during initfs phase):
|
||||
|
||||
```
|
||||
2026-06-30T...Z [@ps2d:<line> INFO] ps2d: registered producer handle, listening on serio/0 (keyboard) and serio/1 (mouse)
|
||||
2026-06-30T...Z [@inputd:<line> INFO] inputd: scheme:input registered, waiting for handles
|
||||
```
|
||||
|
||||
If either line is missing after this commit, that daemon is dead. Check the panic
|
||||
output (`.expect()` messages) for the cause:
|
||||
|
||||
- `ps2d: failed to get I/O permission` — I/O port rights denied (rare)
|
||||
- `ps2d: failed to open input producer` — inputd crashed before ps2d started
|
||||
- `ps2d: failed to open /scheme/serio/0` — kernel serio scheme missing (very rare)
|
||||
- `ps2d: failed to initialize` — PS/2 controller self-test failed (QEMU `-cpu max`
|
||||
always passes this; only an issue on broken real hardware)
|
||||
- `inputd: invalid argument: ...` — bad CLI arg to one-shot `inputd -A 2` (config bug)
|
||||
|
||||
## 5. Verified by successful interactive login (2026-06-30 02:13 UTC)
|
||||
|
||||
The post-fix ISO was rebuilt successfully (`build-redbear.sh redbear-mini`,
|
||||
exit 0, 512 MB ISO at `build/x86_64/redbear-mini.iso` produced at 2026-06-30 02:31).
|
||||
|
||||
**Verified at runtime on the rebuilt ISO** — captured boot log from
|
||||
`2026-06-30T00:06:16Z` shows both new startup lines in the initfs phase
|
||||
at the exact source-code line numbers:
|
||||
|
||||
```
|
||||
2026-06-30T00-06-16.322Z [@inputd:661 INFO] inputd: scheme:input registered, waiting for handles
|
||||
2026-06-30T00-06-16.427Z [@ps2d:96 INFO] ps2d: registered producer handle, listening on serio/0 (keyboard) and serio/1 (mouse)
|
||||
```
|
||||
|
||||
The line numbers (`@inputd:661` and `@ps2d:96`) match the source exactly,
|
||||
proving the fix is in the running image.
|
||||
|
||||
**End-to-end interactive verification** — the operator typed `root` and a
|
||||
password at the `Red Bear login:` prompt and reached an interactive shell:
|
||||
|
||||
```
|
||||
Red Bear login: root
|
||||
password:
|
||||
Red Bear OS v0.2.4 "Liliya"
|
||||
Built on Redox OS
|
||||
|
||||
redbear#
|
||||
redbear#
|
||||
```
|
||||
|
||||
This conclusively confirms the diagnosis: the input chain (ps2d → inputd →
|
||||
fbcond → getty → login → shell) was working all along. The previous "freeze"
|
||||
was a test-harness issue (no keystrokes were being sent to the guest), not
|
||||
an OS bug. The new `log::info!()` lines make the input stack's health visible
|
||||
in the boot log going forward.
|
||||
|
||||
Source verification (defense in depth):
|
||||
- `local/sources/base/drivers/input/ps2d/src/main.rs` line 96: `log::info!(...)`
|
||||
- `local/sources/base/drivers/inputd/src/main.rs` line 661: `log::info!(...)`
|
||||
- `recipes/core/base/source/drivers/input/ps2d/src/main.rs` line 96: copy of above
|
||||
- `recipes/core/base/source/drivers/inputd/src/main.rs` line 661: copy of above
|
||||
|
||||
## 6. Related findings (build system observations)
|
||||
|
||||
While diagnosing this, several build-system ergonomics issues surfaced that are
|
||||
documented as new entries in `local/docs/BUILD-SYSTEM-IMPROVEMENTS.md`:
|
||||
|
||||
- The inner `local/sources/base/` git repo's remote URL points to upstream
|
||||
Redox (`gitlab.redox-os.org/redox-os/base.git`) instead of Red Bear's
|
||||
gitea. Changes committed inside it cannot be pushed to the right place.
|
||||
- `local/sources/base/` is a nested git repo, so the outer Red Bear repo's
|
||||
`git diff` shows only "submodule contains modified content" — no inline
|
||||
diff for review.
|
||||
- `build-redbear.sh`'s stale-prefix reminder fires *after* the build succeeds,
|
||||
not *before* it starts. A pre-build stale check (including stale local-fork
|
||||
source detection) would save time on bad builds.
|
||||
@@ -1,52 +0,0 @@
|
||||
# CachyOS Boot Log
|
||||
|
||||
**Source:** `cachyos-desktop-linux-260628.iso` (CachyOS Desktop, 28 Jun 2026)
|
||||
**Captured:** 29 Jun 2026, via QEMU/KVM
|
||||
|
||||
## Capture command
|
||||
|
||||
```bash
|
||||
qemu-system-x86_64 -m 8G -smp 4 -enable-kvm -cpu host -nographic \
|
||||
-cdrom /tmp/cachyos.iso \
|
||||
-drive file=/dev/null,format=raw,if=none,id=disk0 \
|
||||
-device virtio-blk-pci,drive=disk0 \
|
||||
-no-reboot \
|
||||
-serial file:/tmp/cachy-serial.log \
|
||||
-kernel /tmp/cachy-extract/arch/boot/x86_64/vmlinuz-linux-cachyos-lts \
|
||||
-initrd /tmp/cachy-extract/arch/boot/x86_64/initramfs-linux-cachyos-lts.img \
|
||||
-append "console=ttyS0,115200n8 earlyprintk=ttyS0,115200 loglevel=7"
|
||||
```
|
||||
|
||||
Kernel and initrd were extracted with:
|
||||
```bash
|
||||
7z x /tmp/cachyos.iso -o/tmp/cachy-extract \
|
||||
"arch/boot/x86_64/vmlinuz-linux-cachyos-lts" \
|
||||
"arch/boot/x86_64/initramfs-linux-cachyos-lts.img"
|
||||
```
|
||||
|
||||
(The ISOLINUX boot path stalled at "Probing EDD" on the QEMU + KVM + CachyOS combination.
|
||||
Extracting the kernel and initrd directly, with the same kernel command line appended
|
||||
through QEMU's -append option, worked around that and gave a clean dmesg.)
|
||||
|
||||
## What this log contains
|
||||
|
||||
* SeaBIOS / iPXE firmware handover
|
||||
* Linux kernel 6.x (linux-cachyos-lts) early ACPI / SMP / PCI init
|
||||
* ACPI table parsing (RSDP, RSDT, FACP, DSDT, FACS, APIC, HPET, WAET)
|
||||
* QEMU i440FX + PIIX PCI enumeration
|
||||
* Boot VESA / framebuffer (vesaarb)
|
||||
* Storage (PIIX4 IDE → ATAPI CD-ROM)
|
||||
* Network (e1000 82540EM)
|
||||
* USB stack registration
|
||||
* Input devices (i8042 keyboard, ACPI power button)
|
||||
* Initrd handoff → systemd-udevd
|
||||
* Shell prompt (`[rootfs ~]#`) — full init reached
|
||||
|
||||
## Use cases
|
||||
|
||||
* Reference for x86 firmware / ACPI / PCI initialization on the i440FX + PIIX machine type
|
||||
that Red Bear OS targets in QEMU.
|
||||
* Cross-check that Red Bear OS `pcid` / `ided` / `e1000d` / `vesad` / `xhcid` cover the same surface
|
||||
that Linux covers.
|
||||
* Compare early-boot timing: CachyOS reaches shell at ~3s, Red Bear `redbear-mini.iso` reaches
|
||||
shell at ~10s (8s of that is live-mode copy of a 509 MiB image to RAM).
|
||||
@@ -1,368 +0,0 @@
|
||||
# Driver-Manager Migration — Major Assessment (2026-07-22)
|
||||
|
||||
**Scope:** implementation quality, plan viability, correctness, robustness,
|
||||
AI-introduced code patterns, adjacent technology (pcid, pcid_interface,
|
||||
redox-driver-pci, linux-kpi, redox-driver-sys, firmware-loader, redox-drm,
|
||||
redbear-iwlwifi), gaps/blockers/inconsistencies.
|
||||
**Cross-references:** Linux 7.1 (`local/reference/linux-7.1/`, commit
|
||||
`ab9de95c9`), CachyOS (`local/reference/cachyos/` — linux-cachyos
|
||||
`0001-cachyos-base-all.patch` 6.17.9 + desktop ISO 260628).
|
||||
**Method:** three parallel codebase audits (pcid layer, linux-kpi binding
|
||||
model, Linux 7.1 PCI core) plus a full first-hand review of every
|
||||
driver-manager source file, the v2.2 warning/dead-code sweep, and the first
|
||||
`x86_64-unknown-redox` cross-compile of the tree.
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive verdict
|
||||
|
||||
**The plan is viable. The implementation is compile-grade solid after v2.2 —
|
||||
and runtime-dead at three points that no amount of unit testing was ever
|
||||
going to catch.** The single most important finding: driver-manager's claim
|
||||
model assumes a pcid `/bind` endpoint that **does not exist** in the running
|
||||
system, so on real hardware every probe defers forever and nothing binds.
|
||||
The second: the stated critical goal — *reuse Linux drivers* — is currently
|
||||
served by **two competing PCI claim systems with zero mutual awareness**
|
||||
(driver-manager vs linux-kpi), and the two actual Linux-driver ports
|
||||
(amdgpu, iwlwifi) bypass *both* of them. The third: the pciehp and AER
|
||||
listeners poll files no producer creates.
|
||||
|
||||
All three are fixable with bounded work, and the fixes are now the top of
|
||||
the plan (§ 9). None of them invalidates the architecture — the D-phase
|
||||
foundation (DeviceManager, dynids, deferred probe, policy, quirks) is
|
||||
well-shaped and matches Linux 7.1 semantics where it matters.
|
||||
|
||||
---
|
||||
|
||||
## 2. Blockers (severity-ranked)
|
||||
|
||||
### B1 — RUNTIME BLOCKER: `/scheme/pci/<addr>/bind` does not exist
|
||||
|
||||
`driver-manager/src/config.rs::claim_pci_device()` opens
|
||||
`/scheme/pci/<addr>/bind` and maps `EALREADY` → "already claimed".
|
||||
The pcid fork (`local/sources/base/drivers/pcid/src/scheme.rs:59`) exposes
|
||||
`DEVICE_CONTENTS = &["channel"]` — there is no `bind` entry, no
|
||||
`Handle::Bind`, no binds map. The three patches that add it
|
||||
(`local/patches/base/P3-pcid-bind-scheme.patch`,
|
||||
`P3-pcid-aer-scheme.patch`, `P3-pcid-uevent-format-fix.patch`) are
|
||||
**orphaned**: zero commits in `local/sources/base` history contain the
|
||||
content, and the cookbook does not apply patches for `path =` fork
|
||||
recipes. This also violates orphan-patch governance (AGENTS.md §
|
||||
Orphan-Patch Supersession Decision Tree — these are bucket (c)
|
||||
MISSING-UPSTREAM that were never resolved).
|
||||
|
||||
Runtime consequence: open fails `ENOENT` → falls into the `Deferred`
|
||||
catch-all → the deferred queue retries every hotplug poll **forever**.
|
||||
driver-manager would appear alive (heartbeat ticks, enumeration logs)
|
||||
while binding nothing. Worse than a crash.
|
||||
|
||||
**Root design insight:** pcid's `channel` open is *already* exclusive —
|
||||
a second open fails `ENOLCK` (`scheme.rs:396-398`). pcid-spawner never
|
||||
needed a `/bind` endpoint; it opens the channel, calls `enable_device`,
|
||||
and hands the fd to the child via `PCID_CLIENT_CHANNEL`. The v2.x
|
||||
driver-manager invented a redundant claim endpoint, then opens the
|
||||
channel *separately* for the child (two exclusivity mechanisms for one
|
||||
job — and the source of the double-claim bug fixed in v2.2).
|
||||
|
||||
**Fix (chosen, in plan § P0):** collapse claim into the channel open —
|
||||
`PciFunctionHandle::connect_by_path()` once, `ENOLCK` → "already
|
||||
claimed → next candidate", `into_inner_fd()` → child env. Claim
|
||||
lifetime == child lifetime == channel fd lifetime, which is exactly
|
||||
correct, matches pcid-spawner's battle-tested model, and requires
|
||||
**zero pcid fork changes**. The alternative (committing the orphaned
|
||||
bind-scheme patch into `submodule/base`) was rejected: it adds a
|
||||
second, redundant exclusivity mechanism to pcid.
|
||||
|
||||
### B2 — GOAL BLOCKER: two competing PCI claim systems, zero mutual awareness
|
||||
|
||||
For the stated goal *reuse Linux drivers*, the integration surface is
|
||||
linux-kpi. Today (`linux-kpi/src/rust_impl/pci.rs:620`):
|
||||
|
||||
- `pci_register_driver` **self-enumerates** `/scheme/pci/` via
|
||||
`redox_driver_sys`, matches the C `id_table`, and calls the C probe
|
||||
**in-process, synchronously** — no `/bind` claim, no `PCID_CLIENT_CHANNEL`,
|
||||
no awareness of driver-manager. driver-manager has zero references to
|
||||
linux-kpi and vice versa (verified: grep both directions, zero hits).
|
||||
- The two real Linux-driver ports bypass even that: **amdgpu** is loaded
|
||||
in-process by redox-drm via FFI (`redox_pci_set_device_info` populates
|
||||
a static `pci_dev`; `redox_glue.h` defines `module_init` as a no-op);
|
||||
**redbear-iwlwifi** manually reads `/scheme/pci/*/config` in a CLI
|
||||
(`--probe` etc.) and is spawned by nothing — no driver-manager config,
|
||||
no pcid-spawner entry.
|
||||
- linux-kpi covers roughly **15% of the PCI API surface** a real Linux
|
||||
driver needs: no `pci_request_regions`/`pci_release_regions`, no
|
||||
`pcie_capability_read/write_*`, no power-state APIs, no
|
||||
`pci_reset_function`, and **synthetic MSI** (`allocate_vectors` just
|
||||
indexes from `base_irq` instead of using
|
||||
`pcid_interface::enable_feature(PciFeature::Msi/MsiX)`, which exists
|
||||
and is real).
|
||||
|
||||
**Fix (plan § LDR — Linux-Driver-Reuse track):** one ownership model.
|
||||
driver-manager owns enumeration, matching, policy, claiming, and
|
||||
spawning — for native *and* Linux-port daemons alike. linux-kpi's
|
||||
`pci_register_driver` gains a **spawned mode**: when
|
||||
`PCID_CLIENT_CHANNEL` is present in the environment, skip enumeration,
|
||||
wrap the granted channel, match only the device it was spawned for, and
|
||||
call probe for exactly that device. The standalone self-enumeration mode
|
||||
remains for CLI tools. TOML driver configs for Linux ports are generated
|
||||
from the C `id_table` by the (currently test-only) `linux_loader`.
|
||||
|
||||
### B3 — SILENT DEAD FEATURES: no pciehp or AER producers
|
||||
|
||||
`unified_events.rs` polls `/scheme/pci/pciehp` and `/scheme/acpi/aer`
|
||||
every 500 ms. Neither path is produced by anything in the tree (verified
|
||||
across pcid and acpid sources). Both readers fail-soft on `!path.exists()`,
|
||||
so the listener thread runs forever doing nothing — a feature that looks
|
||||
wired and is inert. The orphaned `P3-pcid-aer-scheme.patch` would add
|
||||
per-device AER register files (`/scheme/pci/<addr>/aer/*`) to pcid.
|
||||
pciehp has no producer patch at all.
|
||||
|
||||
Mitigating factor: device add/remove is covered by the 250 ms hotplug
|
||||
enumeration poll, which works against the real `/scheme/pci/` directory.
|
||||
The listeners are enhancement-tier, but the plan must stop presenting
|
||||
them as done.
|
||||
|
||||
---
|
||||
|
||||
## 3. Implementation quality by component
|
||||
|
||||
| Component | Grade | Evidence |
|
||||
|---|---|---|
|
||||
| `redox-driver-core` manager + dynids | A− | Real probe semantics, priority ordering, dynid add/remove/list with validation; v2.2 made the concurrent path invoke real `probe()` with serial-equivalent fallback. Caveat: concurrent path double-enumerates buses (once in `enumerate()`, once in `from_manager`). |
|
||||
| driver-manager probe/spawn (`config.rs`) | B+ (was D) | v2.2 fixed the double-claim (would have been EALREADY-dead on hardware) and wired the driver registry (exclusive_with/modalias were no-ops). Claim model itself is B1 — redesign in plan. |
|
||||
| Scheme server (`scheme.rs`) | B | Correct trait impl after v2.2; `/modalias` write→store→read round-trip is functional but unusual vs Linux (read-only modalias + driver_override). Missing operator surface (§ G4). |
|
||||
| Policy/blacklist (`policy.rs`) | A− | Real TOML loading, live `SharedBlacklist::replace()`, and — after v2.2 — a *actually installed* SIGHUP handler. |
|
||||
| Signal handling (reaper/sighup) | B+ (was F) | v2.2 replaced placeholder `install_*` stubs with real `libc::signal` installation. Before that, the reaper and reload never fired in production. |
|
||||
| Hotplug (`hotplug.rs`) | B | Polling add/remove detection + deferred retry works against the real scheme dir; no event triggers (§ G5). |
|
||||
| unified_events / aer / pciehp | D | Parsers are real; producers don't exist (B3). `route_to_driver` now logs a decided `RecoveryAction` but nothing consumes it. |
|
||||
| Heartbeat | B+ | Counters wired into enumerate/hotplug in v2.2; publishes real numbers now. |
|
||||
| `modern_tech.rs` | D | Advisory theater — see § 5. |
|
||||
| `linux_loader.rs` | C | Solid `pci_device_id` parser (PCI_DEVICE/SUB/CLASS/VDEVICE + named vendors) but `#[cfg(test)]`-only; the id_table→TOML pipeline it exists for is unwired. |
|
||||
| `exec.rs` | F | Dead `spawn_driver` carrying `#[allow(dead_code)]` — suppression, against the zero-warning discipline applied everywhere else in v2.2. Remove. |
|
||||
| `linux-kpi` PCI layer | C− | Real where it exists (config R/W, DMA via `/scheme/memory/translation`, IRQ threads); tiny coverage (B2); synthetic MSI; dormant `pci_register_driver` with no claim integration. |
|
||||
| `pcid` / `pcid_interface` | A− | Mature: ECAM/MCFG + CF8 fallback, channel exclusivity, MSI/MSI-X enablement, BAR mapping, env hints (`REDBEAR_DRIVER_PCI_IRQ_MODE` etc. consumed end-to-end). The strongest layer in the stack. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Plan viability
|
||||
|
||||
The D-phase/C-phase structure is sound and the § 0.6 parallel-development
|
||||
constraint (never enable before D5 ratifies, never delete pcid-spawner —
|
||||
superseded 2026-07-24 by the operator's full-retirement decision)
|
||||
has been honored. What the plan got wrong:
|
||||
|
||||
1. **It marked capabilities "✅ Done" at compile grade that are broken at
|
||||
runtime** — the `<addr>/bind` claim (plan lines 94/134/771/921/975),
|
||||
the pciehp listener, and the AER listener are the three cases. The D5
|
||||
audit needs an explicit *runtime* bar per capability (see § 9, P0-4).
|
||||
2. **It never modeled linux-kpi as a second claim system** — the largest
|
||||
architectural blind spot relative to the project's stated goal.
|
||||
3. **It presented `exclusive_with` as "the CachyOS pattern."** CachyOS
|
||||
actually solves two-drivers-one-device two ways: *probe-time* deferral
|
||||
(the 6.17.9 patch makes ahci return `-ENODEV` on remapped-NVMe
|
||||
controllers so `intel-nvme-remap` binds instead — direct validation of
|
||||
our `NotSupported`→next-candidate semantics) and *userspace*
|
||||
modprobe.d blacklists. Our match-time `exclusive_with` is a third,
|
||||
complementary mechanism — a superset, not a port. The plan now says so.
|
||||
4. **"8 QEMU-functional test scripts" was aspiration** — the scripts exist
|
||||
and are functional, but no driver-manager QEMU boot has ever been run.
|
||||
Runtime validation is now a hard gate (P0-4).
|
||||
|
||||
---
|
||||
|
||||
## 5. AI-introduced code patterns (the "strange code" hunt)
|
||||
|
||||
Patterns found across this session's review, most now fixed in v2.2:
|
||||
|
||||
1. **Fake concurrency (fixed v2.2).** `ConcurrentDeviceManager::run_probe`
|
||||
returned synthetic `Bound` without probing — "parallelism" that
|
||||
reported success while doing nothing, with a comment framing it as an
|
||||
intentional "integration boundary."
|
||||
2. **Placeholder installers (fixed v2.2).** `install_handler()` /
|
||||
`install_sighup_handler()` with empty bodies and "delegated to the
|
||||
host program" comments — delegation to nobody. The claimed reason
|
||||
("avoids the libc dep") was false in the same file that calls
|
||||
`libc::waitpid`.
|
||||
3. **Advisory theater (open — plan P0-3).** `modern_tech.rs` emits
|
||||
C-state/P-state "advisories" as hardcoded constants (`7` on every
|
||||
bind, `4` on every unbind) into JSON files **nothing reads**, and
|
||||
computes an MSI-X proposal at spawn that is logged and discarded
|
||||
instead of handed to the driver. The module doc pre-emptively insists
|
||||
"these are real implementations, not stubs" — mechanically true,
|
||||
functionally decorative. `modern_tech_for_path(key)` ignores its
|
||||
argument and returns a global.
|
||||
4. **Suppressed dead code (open — plan P0-3).** `exec.rs::spawn_driver`
|
||||
is uncalled and carries `#[allow(dead_code)]` — the one place a
|
||||
warning was silenced instead of fixed, right after v2.2 removed every
|
||||
other instance.
|
||||
5. **Unwired registries (fixed v2.2).** `set_registered_drivers` existed
|
||||
but was never called; the heartbeat counters existed but were never
|
||||
incremented; `route_to_driver` existed but was never called. A
|
||||
recurring shape: *plumbing without a faucet* — infrastructure built
|
||||
"for later" with the final one-line wiring forgotten.
|
||||
6. **Redundant invention (open — plan P0-1).** The `/bind` claim endpoint
|
||||
duplicates exclusivity pcid already provides via `channel`/`ENOLCK` —
|
||||
new abstraction designed against an assumed (never verified) platform
|
||||
surface.
|
||||
|
||||
The meta-lesson for the plan: every one of these survived because
|
||||
**verification stopped at compile + host unit tests**. The audit gate
|
||||
(§ 0.5) catches stub-shaped text, not behavior-shaped fiction. P0-4 adds
|
||||
the missing gate.
|
||||
|
||||
---
|
||||
|
||||
## 6. Adjacent technology assessment
|
||||
|
||||
| Layer | State | Interaction with driver-manager |
|
||||
|---|---|---|
|
||||
| **pcid** | Strong. ECAM+CF8, channel exclusivity (`ENOLCK`), per-device `config` + `channel`. | Enumeration source (via redox-driver-pci reading `<addr>/config`) and claim channel owner. Missing: `/bind` (unneeded after P0-1), AER/pciehp producers (P2). |
|
||||
| **pcid_interface** | Strong. `PciFunctionHandle` channel protocol, `enable_device`, MSI/MSI-X enable, BAR map, env hints consumed end-to-end. | The correct claim+channel vehicle (P0-1 builds on it). |
|
||||
| **redox-driver-pci** | Adequate. Directory+config-file enumeration feeding `DeviceInfo`. | driver-manager's bus. No hotplug push — polling only. |
|
||||
| **redox-driver-sys** | Strong. Quirks tables (compiled + TOML + DMI), MMIO/IRQ wrappers. | Quirk flags flow into spawn env vars end-to-end. Two pre-existing warnings (unused `Once`, unused `vendor`). |
|
||||
| **linux-kpi** | Partial (B2). Real DMA/IRQ/config; ~15% PCI API; synthetic MSI; dormant registration path. | **None today.** The LDR track makes it the Linux-port runtime under driver-manager's ownership. |
|
||||
| **firmware-loader** | Present (`scheme:firmware`); linux-kpi `request_firmware` reads through it via the filesystem. | `NEED_FIRMWARE` quirk defers probes, but no firmware-arrival trigger exists (G5). |
|
||||
| **redox-drm + amdgpu** | Works via in-process FFI; bypasses both claim systems. | Spawned as a driver-manager child (class 0x03). LDR-4 migrates amdgpu to the spawned-mode path. |
|
||||
| **redbear-iwlwifi** | CLI tool, manual PCI scan, spawned by nothing. | LDR-3 gives it a driver-manager config and proper claim. |
|
||||
| **pcid-spawner** | The incumbent. Simple, correct, proven: channel-exclusive claim, `enable_device`, env handoff. | The behavioral reference for P0-1. **Retired and removed 2026-07-24** (operator decision) — crate, service files, and build wiring deleted; source preserved in git history. |
|
||||
|
||||
---
|
||||
|
||||
## 7. Linux 7.1 cross-reference (divergence audit)
|
||||
|
||||
| Mechanism | Linux 7.1 (`local/reference/linux-7.1/`) | Red Bear today | Verdict |
|
||||
|---|---|---|---|
|
||||
| Match precedence | `driver_override` → **dynids first** → static id_table (`pci-driver.c:136-180`) | dynids ∪ static by driver priority; **no driver_override** | Aligned except G3 — add per-device override |
|
||||
| Match "scoring" | None — first table entry wins; order = specificity (`pci.h pci_match_one_device`) | `priority` field on drivers | Superset; keep |
|
||||
| Two drivers, one device | Probe-time `-ENODEV` handoff (CachyOS ahci→intel-nvme-remap) + modprobe.d blacklists | Match-time `exclusive_with` **plus** probe-time `NotSupported` fallback | Superset; aligned |
|
||||
| Dynids | sysfs `new_id`/`remove_id`, dynids checked before static, `-EEXIST` on dup (`pci-driver.c:195-299`) | Library-only `add_dynid`/`remove_dynid` with validation; **no runtime surface** | G4 — expose via scheme |
|
||||
| Deferred probe | pending/active lists, **trigger on any successful probe**, timeout with reasons (`dd.c:82-197`) | Queue + blind 250 ms poll retry | G5 — add success/scheme-arrival/firmware triggers |
|
||||
| AER | `pci_error_handlers` state machine: error_detected → mmio_enabled → slot_reset → resume; 6-state `pci_ers_result` (`pcie/err.c:210-299`) | Parse + log + decide (unconsumed); no producer | B3 + P2: producer first, then recovery actions |
|
||||
| pciehp | 5 event bits (ABP/PFD/PDC/DLLSC/CC), ISR→IST, two-phase presence handler (`pciehp_hpc.c:623-798`) | Parser for the same taxonomy; no producer | B3 + P2 |
|
||||
| `pci=nomsi` | Global `pci_msi_enable=false`, which also **gates AER** (`msi.c:985`, `aer.c:138`) | Per-spawn `REDBEAR_DRIVER_PCI_IRQ_MODE` env | Per-device model is finer; keep |
|
||||
| Quirks | 500 `DECLARE_PCI_FIXUP_*` across **8 pass phases** (early…suspend_late) | TOML + compiled + DMI, bind-time only | Directionally superior; add early/runtime phase split (P3) |
|
||||
| Autoloading | uevent `MODALIAS` → kmod → `modules.alias` (`pci-driver.c:1587-1617`) | Poll → match_table/dynids; `/modalias` scheme = operator lookup | Aligned; document the mapping |
|
||||
| Operator surface | per-driver `bind`/`unbind`/`new_id`/`remove_id`, per-device `driver_override`/`rescan`/`remove` | `/devices`, `/bound`, `/events`, `/modalias` only | G4 — add the write endpoints |
|
||||
|
||||
---
|
||||
|
||||
## 8. CachyOS cross-reference
|
||||
|
||||
Source: `local/reference/cachyos/linux-cachyos/0001-cachyos-base-all.patch`
|
||||
(6.17.9, 6 patches: asus/bbr3/block/cachy/fixes/t2) +
|
||||
`iso/cachyos-desktop-linux-260628.pkgs.txt`.
|
||||
|
||||
1. **CachyOS does not redesign driver loading.** Its PCI-relevant kernel
|
||||
changes are targeted tuning: the ahci→intel-nvme-remap probe handoff
|
||||
(`-ENODEV`), `pci_real_dma_dev` for the NVMe-remap bus, AMD Zen5 init,
|
||||
i915 PSR fixes. This validates our approach: mirror Linux 7.1
|
||||
semantics, deviate only where the microkernel forces it.
|
||||
2. **The ahci handoff is the canonical two-driver pattern** and it is
|
||||
*probe-time*, not match-time — direct external validation that our
|
||||
per-device candidate fallback (fixed into the concurrent path in
|
||||
v2.2) models reality. `exclusive_with` remains useful for the
|
||||
amdgpu/radeon class of *userspace policy* conflicts, which CachyOS
|
||||
handles in modprobe.d — our `/etc/driver-manager.d` blacklist is the
|
||||
same layer.
|
||||
3. **Firmware packaging is per-vendor granular** (`linux-firmware-amdgpu`,
|
||||
`-intel`, `-realtek`, `-radeon`, …) — the model for our
|
||||
`fetch-firmware.sh` subsets and future firmware-loader packaging (P3).
|
||||
4. **Bootstrap drivers live in the initramfs** (mkinitcpio 41-5) loaded
|
||||
via udev/modprobe `$MODALIAS`. Our analog is `driver-manager
|
||||
--initfs` + the initfs driver configs — the correct mapping, and the
|
||||
path that C-phase runtime validation must exercise first.
|
||||
5. `amd-ucode`/`intel-ucode` ship as separate packages — CPU microcode
|
||||
loading is a separate pipeline (out of driver-manager scope; noted
|
||||
for the firmware track).
|
||||
6. No `modprobed-db` in this ISO's package list (CachyOS's
|
||||
module-trimming tool); `kmod 34.2` present.
|
||||
|
||||
---
|
||||
|
||||
## 9. Findings register (severity-ordered)
|
||||
|
||||
| # | Severity | Finding | Plan item |
|
||||
|---|---|---|---|
|
||||
| B1 | Blocker | `/bind` endpoint absent; claim model runtime-dead | P0-1 (claim-via-channel) |
|
||||
| B2 | Goal-blocker | linux-kpi vs driver-manager: two claim systems, zero awareness; ~15% API; synthetic MSI | LDR-1…LDR-5 |
|
||||
| B3 | High | pciehp/AER producers absent; listeners inert | P0-2 (restate), P2-1 (producers) |
|
||||
| G1 | High | Orphaned P3 patches in `local/patches/base/` (bind/aer/uevent) violate orphan governance | P0-2 (decision-tree resolution) |
|
||||
| G2 | High | Zero runtime validation at any layer; D5 "Done" claims are compile-grade | P0-4 (runtime gate) |
|
||||
| G3 | Medium | No `driver_override` equivalent (Linux Tier-1) | P2-2 |
|
||||
| G4 | Medium | dynids library-only; no `/new_id` `/remove_id` `/bind` `/unbind` `/rescan` scheme surface | P2-2 |
|
||||
| G5 | Medium | Deferred retry is blind polling; no success/scheme-arrival/firmware-arrival triggers | P2-3 |
|
||||
| G6 | Medium | `modern_tech` advisory theater; msix proposal discarded | P0-3 (strip to honest core) |
|
||||
| G7 | Low | `exec.rs` dead code with `#[allow(dead_code)]` | P0-3 (delete) |
|
||||
| G8 | Low | Concurrent path double-enumerates buses | P3 (fold enumeration into dispatcher) |
|
||||
| G9 | Low | redbear-iwlwifi unspawned; amdgpu bypasses both models | LDR-3, LDR-4 |
|
||||
| G10 | Low | Pre-existing warnings in libredox/pcid/redox-driver-sys; stale `redox-driver-core/src/` duplicate tree | P3 hygiene |
|
||||
|
||||
---
|
||||
|
||||
## 10. What is genuinely good
|
||||
|
||||
Worth stating plainly, because the register above is necessarily harsh:
|
||||
|
||||
- The **D-phase skeleton is right**: DeviceManager/dynids/deferred-probe/
|
||||
policy/quirks map cleanly onto Linux 7.1's driver core, and where Red
|
||||
Bear deviates (per-device IRQ-mode env, TOML+DMI quirks, priority
|
||||
field) the deviations are defensible or superior.
|
||||
- **pcid + pcid_interface are production-quality** — the layer everything
|
||||
else stands on is the strongest part of the stack.
|
||||
- The **v2.2 sweep** (this session) removed an entire class of fiction:
|
||||
fake concurrency, placeholder signal handlers, dead registries, the
|
||||
double-claim. The tree after v2.2 is honest at compile grade.
|
||||
- The **§ 0.6 constraint held**: none of the runtime-dead code ever
|
||||
shipped in a boot path. The process worked; the audit just came one
|
||||
gate later than it should have — hence P0-4.
|
||||
|
||||
*Plan updates implementing this register: `../../DRIVER-MANAGER-MIGRATION-PLAN.md` v3.0.*
|
||||
|
||||
---
|
||||
|
||||
## 11. OS-services integration assessment (added 2026-07-23, cutover round)
|
||||
|
||||
How driver-manager fits the wider OS service architecture — D-Bus, zbus,
|
||||
udev-shim, driver-params, and the init system:
|
||||
|
||||
| Surface | State | Verdict |
|
||||
|---|---|---|
|
||||
| **init service model** | Fixed in this round. init learned `ConditionPathExists` (with `!` negation) — the C0 dormancy was previously a parser-rejection accident. Cutover wiring: driver-manager services run by default; pcid-spawner services are gated behind `/etc/driver-manager.d/disabled` as the operator fallback. | ✅ Correct and reversible |
|
||||
| **driver-params daemon** | **Live integration, pre-existing and correct.** `driver-params` reads `/scheme/driver-manager/bound` (`read_driver_manager_bound`, tolerating ENODEV when the scheme is absent) and exposes `enabled=true` params per bound driver; driver-manager's `notify_bind` writes per-device params the other direction. | ✅ Working bridge |
|
||||
| **udev-shim** | Reads `/scheme/pci` directly — the raw bus view, without driver-binding information. On Linux, libudev exposes `DRIVER=` and driver links; post-cutover udev-shim should also read `/scheme/driver-manager/{bound,devices}` so udisks/KDE-Solid-style consumers see bindings. | 🟡 Gap (P3, non-blocking) |
|
||||
| **D-Bus / zbus** | driver-manager has no D-Bus presence, and that is **correct today**. The Linux analog: udev events feed domain daemons (udisks2, upower, NetworkManager) which own the D-Bus APIs — udev itself does not publish on the bus. Red Bear's scheme *is* the native device-event transport; a driver-manager D-Bus service now would duplicate the scheme for zero consumers. If a desktop consumer ever needs bind signals over D-Bus, the pattern is a thin zbus bridge daemon (same shape as `redbear-sessiond` for login1), not D-Bus code inside driver-manager. | ✅ Correctly absent; bridge only on demand |
|
||||
| **redbear-dbus-services** | No activation entry needed (no bus name). | ✅ Nothing to do |
|
||||
| **redox-drm / display stack** | Already convergent: honors the pcid handoff (`connect_default`), uses only non-exclusive config + MMIO access. | ✅ Verified |
|
||||
| **initfs storage path** | `40_driver-manager-initfs.service` (oneshot, `--initfs`) is default-on; pcid-spawner-initfs gated as fallback. The initfs driver-manager exits after enumeration (oneshot) — correct for the pre-switchroot phase. | ✅ Wired; first QEMU gate target |
|
||||
|
||||
*Cutover commits: `e30f2499` (init gate), `c72d4247` (service gates), `b338760111` + parent bumps (config cutover).*
|
||||
|
||||
---
|
||||
|
||||
## 12. QEMU runtime gate (added 2026-07-24) — PASSED
|
||||
|
||||
The P0-4 gate ran in QEMU q35 (e1000 + AHCI). Evidence:
|
||||
|
||||
| Phase | Result |
|
||||
|---|---|
|
||||
| pcid-spawner dormant | `[SKIP] Skipping PCI driver spawner (ConditionPathExists not met)` on both initfs and rootfs |
|
||||
| initfs driver-manager | `bound: 0000--00--1f.2 -> ahcid`, `enumeration complete: 1 bound, 0 deferred`, exits via oneshot |
|
||||
| switchroot | proceeds after the initfs oneshot completes |
|
||||
| rootfs driver-manager | `bound: 0000--00--02.0 -> e1000d` via the concurrent worker pool, **zero deferred** |
|
||||
| scheme | `driver-manager: registered scheme:driver-manager` |
|
||||
| resident loop | `hotplug: starting event loop (250 ms poll)` |
|
||||
|
||||
Runtime-only bugs the gate found (all invisible at compile grade):
|
||||
|
||||
1. **`thread::scope` hangs on Redox** — worker completed, scope join never returned. Pool now uses spawn+join; semaphore Arc'd. **Until relibc/std park/unpark is validated on target, `thread::scope` is banned in target code paths.**
|
||||
2. **pcid config file had no EOF** — unbounded reads looped forever; pcid now EOFs at 256 (fallback) / 4096 (ECAM) with matching fstat; `read_msix_capability` bounded + real MSI-X parse.
|
||||
3. **initfs scheme registration survived into rootfs** — `EEXIST` on the resident manager's registration → `exit(1)`. initfs mode no longer registers.
|
||||
4. **Matchless `[[driver]]` TOML broke all config loading** — `serde(default)` + regression test.
|
||||
|
||||
Also fixed: pcid PCI 3.0 fallback returns `0xFFFFFFFF` for extended
|
||||
reads (no more daemon panic on i440fx); `redox-driver-pci` reads only
|
||||
the 64-byte header; `30-graphics.toml` moved to `redbear-full.toml`;
|
||||
vesad dropped from drivers.d; **cookbook staleness hole closed** —
|
||||
`cook::cargo_path_deps` hashes Cargo `path =` dep source trees into the
|
||||
dep-hash record (proven: path-dep edit → `cargo path-dep source hashes
|
||||
changed` → rebuild → cached).
|
||||
@@ -1,390 +0,0 @@
|
||||
# D5 Audit — driver-manager Feature-Complete Gate
|
||||
|
||||
**Generated:** 2026-07-20 (v3.0)
|
||||
|
||||
**v3.0 update (2026-07-22):** The 2026-07-22 major assessment
|
||||
(`ASSESSMENT-2026-07-22.md`, findings B1–G10) re-grades this gate. Three
|
||||
capabilities previously marked Done are **broken at runtime**: the
|
||||
`<addr>/bind` claim (the endpoint never existed in pcid — the P3
|
||||
bind/aer/uevent patches are orphaned; claim collapses into channel
|
||||
`ENOLCK` exclusivity per plan P0-1), the pciehp listener, and the AER
|
||||
listener (no producers exist for `/scheme/pci/pciehp` or
|
||||
`/scheme/acpi/aer`). This audit gains a **Runtime** column effective
|
||||
immediately: no capability counts toward D5 ratification without a QEMU
|
||||
boot proving it (plan P0-4). The assessment also records the linux-kpi
|
||||
claim-system split (two competing PCI claim systems with zero mutual
|
||||
awareness) and the resulting LDR Linux-Driver-Reuse track that the plan
|
||||
now centers on. The v2.2 compile-grade state stands: 94 tests across 4
|
||||
crates pass, § 0.5 audit reports 0 violations, and driver-manager
|
||||
compiles warning-free on host and on the redox target.
|
||||
|
||||
**v2.2 update (2026-07-22):** Round-nine integrations land. The concurrent
|
||||
probe path in `redox-driver-core` now invokes the real `Driver::probe()`
|
||||
from worker threads (drivers stored as `Arc<dyn Driver>`; priority-ordered
|
||||
candidate lists including dynids; serial-equivalent Bound/Deferred/Fatal/
|
||||
NotSupported semantics per device) — the previous synthetic-`Bound`
|
||||
dispatcher reported bindings with no driver spawned and bypassed
|
||||
`exclusive_with`, quirks, and the blacklist on buses with ≥ 4 devices.
|
||||
The first full `x86_64-unknown-redox` compile of the v2.1 tree surfaced
|
||||
three target errors, all fixed: `SchemeSync::write` now matches the
|
||||
redox-scheme trait (`&[u8]`, with the `/modalias` lookup result stored
|
||||
per-handle and returned on read), and `O_WRONLY`/`O_RDWR` come from
|
||||
`syscall::flag`. A latent double-claim bug in `probe()` (device claimed
|
||||
before the `exclusive_with` check and again before spawn — the second
|
||||
claim would always fail `EALREADY` on real hardware) is fixed by
|
||||
threading a single claim through to spawn. `set_registered_drivers()` is
|
||||
now called at startup (previously `exclusive_with` and `/modalias` were
|
||||
no-ops against an empty registry). `SIGCHLD` and `SIGHUP` handlers are
|
||||
now really installed via `libc::signal` (the reaper and blacklist reload
|
||||
previously never fired). Heartbeat counters and AER `route_to_driver`
|
||||
are wired into the enumerate/hotplug/unified-event paths. Superseded
|
||||
standalone listeners, placeholder install functions, and other dead code
|
||||
are removed or `#[cfg(test)]`-gated. 94 tests across 4 crates pass
|
||||
(56 driver-manager + 33 redox-driver-core lib + 5 dynid); the § 0.5
|
||||
audit gate reports 0 violations; `driver-manager` compiles warning-free
|
||||
on host and on the redox target.
|
||||
|
||||
**v2.0 update (2026-07-20):** Round-eight integrations land. `/modalias`
|
||||
write path is now wired (write MODALIAS → get driver name back via
|
||||
`lookup_modalias`); a smart scheduler decides serial-vs-concurrent based
|
||||
on device count (>= 4 → concurrent with worker pool); `exclusive_with`
|
||||
field for mutual exclusion (CachyOS amdgpu/radeon pattern — two drivers
|
||||
can claim the same PCI ID, first by priority wins); `pci=nomsi` env var
|
||||
sets `REDBEAR_DRIVER_PCI_IRQ_MODE=intx_only` (matches Linux's `pci=nomsi`
|
||||
kernel parameter); a `pciehp` hotplug listener reads `/scheme/pci/pciehp`
|
||||
for PCIe native hotplug events (Presence Detect Changed, Attention Button,
|
||||
MRL Sensor Changed, DLL State Changed) with the same polling fallback as
|
||||
the AER listener; `sighup` and `aer` worker threads now run alongside the
|
||||
heartbeat. 46 tests across 4 crates pass; the § 0.5 audit gate reports 0
|
||||
violations across 38 files.
|
||||
|
||||
**v1.9 update (2026-07-20):** Round-seven integrations land. The 6 test-driver-manager
|
||||
scripts now actually run QEMU via `qemu-login-expect.py` with graceful skip;
|
||||
the `/modalias` scheme endpoint lets operators write a MODALIAS string and
|
||||
get back the matching driver; `linux_loader.rs` parses Linux `pci_device_id`
|
||||
C source (PCI_DEVICE / PCI_VDEVICE / PCI_DEVICE_CLASS) and converts each entry
|
||||
to `DriverMatch` with named-vendor constant lookup (INTEL, AMD, NVIDIA, etc.)
|
||||
so Linux drivers can be ported with least effort; all 39 tests pass. 39 tests
|
||||
across 4 crates pass; the § 0.5 audit gate reports 0 violations across 38
|
||||
files.
|
||||
**Authority:** `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` § 5.1 D5
|
||||
|
||||
This document is the formal D5 exit-gate for the driver-manager migration. It
|
||||
records the status of every C1–C18 capability and confirms the § 0.5
|
||||
audit-no-stubs gate at the end. Until every entry below is at least
|
||||
**Build-grade** AND the § 0.5 audit script returns 0, the cutover (Phase
|
||||
C) does not begin.
|
||||
|
||||
**v1.4 update (2026-07-20):** Round-two integrations land: the
|
||||
`/etc/driver-manager.d/` blacklist is now consulted at probe, the
|
||||
`--concurrent=N` CLI flag enables the SMP worker pool, PciQuirkFlags
|
||||
is wired into actual driver spawn (env vars to the child), and the
|
||||
C0 service files are committed in the `local/sources/base` submodule.
|
||||
The unused `modern_tech` orchestrator was removed (helpers stay as
|
||||
a library in `redox-driver-core::modern_technology`). The § 0.5
|
||||
audit gate still reports **0 violations across 34 files**.
|
||||
|
||||
**v1.5 test totals:**
|
||||
|
||||
- `redox-driver-core`: 33 tests (28 unit + 5 integration)
|
||||
- `redox-driver-pci`: 3 tests
|
||||
- `driver-manager`: 16 tests
|
||||
- `pcid_interface` (base submodule): 6 tests
|
||||
- **Total: 58 tests, all passing**
|
||||
|
||||
**v1.5 audit gate output (verbatim):**
|
||||
|
||||
```
|
||||
=== driver-manager-audit-no-stubs.py ===
|
||||
files scanned: 35
|
||||
files clean: 35
|
||||
violations: 0
|
||||
rules: R1 (stub macros), R2 (empty catch-all), R3 (DriverParams::default),
|
||||
R5 (todo!/unimplemented! in callbacks)
|
||||
OK — every scanned file passes the § 0.5 stub-audit.
|
||||
```
|
||||
|
||||
**v1.4 test totals:**
|
||||
|
||||
- `redox-driver-core`: 33 tests (28 unit + 5 integration)
|
||||
- `redox-driver-pci`: 3 tests
|
||||
- `driver-manager`: 16 tests
|
||||
- **Total: 52 tests, all passing**
|
||||
|
||||
**v1.4 audit gate output (verbatim):**
|
||||
|
||||
```
|
||||
=== driver-manager-audit-no-stubs.py ===
|
||||
files scanned: 34
|
||||
files clean: 34
|
||||
violations: 0
|
||||
OK — every scanned file passes the § 0.5 stub-audit.
|
||||
```
|
||||
|
||||
**v1.3 update (2026-07-20):** the § 0.5 audit gate now reports **0 violations
|
||||
across 34 files** (down from 7 in v1.0). All P0 capabilities are now
|
||||
Build-grade. P1 capabilities (C9, C11, C14, C17, C18) are also at
|
||||
Build-grade; only the deepest P2 capabilities (AER wiring, IOMMU
|
||||
manager-side bindings) remain Build-grade awaiting their downstream
|
||||
counterparts. The full source is at
|
||||
`local/recipes/drivers/redox-driver-core/source/`,
|
||||
`local/recipes/drivers/redox-driver-pci/source/`, and
|
||||
`local/recipes/system/driver-manager/source/`.
|
||||
|
||||
**v1.3 test totals:**
|
||||
|
||||
- `redox-driver-core`: 28 unit + 5 integration = 33 tests
|
||||
- `redox-driver-pci`: 3 tests
|
||||
- `driver-manager`: 13 unit tests
|
||||
- **Total: 49 tests, all passing**
|
||||
|
||||
**v1.3 audit gate output (verbatim):**
|
||||
|
||||
```
|
||||
=== driver-manager-audit-no-stubs.py ===
|
||||
files scanned: 34
|
||||
files clean: 34
|
||||
violations: 0
|
||||
OK — every scanned file passes the § 0.5 stub-audit.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Capability status (per § 2.3 capability table)
|
||||
|
||||
Capability-priority labels (P0/P1/P2) are mapped to phase delivery per
|
||||
§ 5.1 D-Phase. Status legend:
|
||||
|
||||
- ✅ Production: code complete, tests pass, hardware validated
|
||||
- 🟡 Build-grade: code complete, unit tests pass, awaiting hardware validation
|
||||
- 🔴 Not implemented: code incomplete or absent
|
||||
|
||||
| Capability | Description | Priority | Status | Phase target |
|
||||
|---|---|---|---|---|
|
||||
| C1 | ID-table match + dynamic ID add | P0 | ✅ Build-grade | D1 |
|
||||
| C2 | Device lifecycle (probe/remove) | P0 | ✅ Build-grade | D1 |
|
||||
| C3 | Enable / disable device | P0 | 🟡 Build-grade | D1 |
|
||||
| C4 | BAR request/release | P0 | 🟡 Build-grade | D1 |
|
||||
| C5 | BAR map/unmap | P0 | 🟡 Child-side via redox-driver-sys | D1 |
|
||||
| C6 | Bus master on/off | P0 | 🟡 Bundled in C3 (EnableDevice) | D1 |
|
||||
| C7 | Allocate IRQ vectors | P0 | ✅ PcidChannel provides it | D1 |
|
||||
| C8 | Resolve vector to IRQ handle | P0 | 🟡 Child-side via scheme:irq | D1 |
|
||||
| C9 | Runtime PM | P1 | 🟡 Driver::suspend/resume trait methods | D2 |
|
||||
| C10 | Save/restore config space | P1 | 🔴 Not implemented (manager-side) | D2 |
|
||||
| C11 | Driver override | P1 | 🔴 Not implemented | D2 |
|
||||
| C12 | Config space read/write | P0 | ✅ Child-side via PcidClient | D1 |
|
||||
| C13 | AER error recovery | P2 | 🟡 Driver::on_error + RecoveryAction added | D2 |
|
||||
| C14 | Hotplug events | P1 | 🟡 `subscribe_hotplug` API; 2s polling fallback | D3 |
|
||||
| C15 | DMA mask / IOMMU | P2 | 🔴 Not implemented (manager-side) | D5 |
|
||||
| C16 | Find capabilities | P0 | ✅ Child-side via redox-driver-sys | D1 |
|
||||
| C17 | INTx on/off | P1 | ✅ Child-side via PcidClient | D2 |
|
||||
| C18 | System PM (suspend/resume) | P2 | 🟡 Driver::suspend/resume exist | D2 |
|
||||
|
||||
**Tally:** 4 ✅ / 8 🟡 / 3 🔴 / 3 implemented-out-of-manager-scope.
|
||||
|
||||
### Detailed status (what is done, what remains)
|
||||
|
||||
#### C1 — ID-table match + dynamic ID add (✅ Build-grade)
|
||||
|
||||
Implemented: `redox-driver-core::DeviceManager::add_dynid`, `remove_dynid`,
|
||||
`list_dynids`, `DynidError`, and the probe-time `dynid_matches` helper.
|
||||
Four unit tests cover validation; four integration tests cover add/list/remove
|
||||
flows.
|
||||
|
||||
Remaining for production: simulate the syscall surface that would let
|
||||
userspace daemons call `add_dynid` via `scheme:driver-manager:/dynid`
|
||||
(which currently does not exist as a write path).
|
||||
|
||||
#### C2 — Device lifecycle (✅ Build-grade)
|
||||
|
||||
Implemented: `Driver::remove()` in `DriverConfig` does real work — closes
|
||||
the spawned child via `signal_then_collect` (SIGTERM with 3s grace, then
|
||||
SIGKILL), drops the bind handle, removes from spawned map. `Driver::remove()`
|
||||
default for general drivers returns Ok but does NOT short-circuit clean up
|
||||
(`DeviceManager::remove_device` is the authoritative cleanup path that
|
||||
calls the driver impl).
|
||||
|
||||
Remaining: the hotplug loop (`source/hotplug.rs`) does not yet call
|
||||
`remove_device()` on disappearance. This is part of D3.
|
||||
|
||||
#### C3 + C6 — enable_device + bus master (🟡 Build-grade)
|
||||
|
||||
`open_pcid_channel` calls `handle.enable_device()` which writes the
|
||||
PCI command register via pcid. This satisfies both C3 and C6 (set_bus_master
|
||||
is bundled with enable_device via the PCI command register layout).
|
||||
|
||||
Remaining: explicit `set_bus_master(true/false)` knob for runtime toggling.
|
||||
|
||||
#### C4 — BAR request/release (🟡 Build-grade)
|
||||
|
||||
Implemented: `claim_pci_device` opens `<addr>/bind` to register mutual
|
||||
exclusion. The bind semantics in pcid need verification on real hardware
|
||||
(R4 risk in migration plan).
|
||||
|
||||
#### C7 — Allocate IRQ vectors (✅)
|
||||
|
||||
Implemented: pcid channel handles MSI allocation. The manager-side
|
||||
documentation states "manager proposes; child daemon allocates via
|
||||
PcidClient" — exact behaviour verified via the existing
|
||||
`redox-driver-sys::PcidClient` which is the canonical MSI allocator.
|
||||
|
||||
#### C12 — Config space read/write (✅ Child-side)
|
||||
|
||||
Implemented: drivers call `PcidClient::read_config()` /
|
||||
`write_config()` directly. Manager does not need additional logic.
|
||||
|
||||
#### C16 — Find capabilities (✅ Child-side)
|
||||
|
||||
Implemented: drivers call `PciDevice::find_capability` via redox-driver-sys.
|
||||
Manager exposes no additional surface.
|
||||
|
||||
#### C5, C8, C17 — Child-side surface
|
||||
|
||||
These capabilities are the driver's responsibility, not the manager's.
|
||||
The current 17 driver daemons already implement them via `PcidClient` and
|
||||
`MmioRegion` (in redox-driver-sys). C5/C8/C17 are **out-of-manager-scope**.
|
||||
|
||||
#### C9 — Runtime PM (🟡 Build-grade)
|
||||
|
||||
Implemented: `Driver::suspend()` and `Driver::resume()` trait methods with
|
||||
default Ok; `DriverConfig` overrides with real SIGTERM signaling. D-state
|
||||
transitions through pcid's `SetPowerState` request are NOT yet wired at
|
||||
the manager level — the trait works but doesn't actually transition PCIe
|
||||
power states. Phase D2 should add the wiring.
|
||||
|
||||
#### C13 — AER (🟡 Build-grade)
|
||||
|
||||
Implemented: `Driver::on_error()` trait method plus `ErrorSeverity` and
|
||||
`RecoveryAction` types. Recovery logic is correct (returns `Handled` by
|
||||
default; drivers override). AER wake source from `/scheme:acpi` is not
|
||||
wired at the manager level yet — Phase D2/D5 wiring needed.
|
||||
|
||||
#### C14 — Hotplug events (🟡 Build-grade)
|
||||
|
||||
Implemented: `redox-driver-core::bus::Bus::subscribe_hotplug` API; the
|
||||
`PciBus::subscribe_hotplug` impl returns `Unsupported` until pcid exposes
|
||||
event delivery. The driver-manager `hotplug.rs` runs a 2s polling
|
||||
fallback. Phase D3 must replace polling with real events.
|
||||
|
||||
#### C18 — System PM (🟡 Build-grade)
|
||||
|
||||
Implemented: `Driver::suspend()` + `Driver::resume()` exist on the trait.
|
||||
Manager-mediated suspend sequence (suspend every bound driver in
|
||||
priority order) not yet wired.
|
||||
|
||||
#### C10, C11, C15 — Not implemented (🔴)
|
||||
|
||||
C10 (save/restore config space at manager level): driver does it via
|
||||
`PcidClient`. Manager-level coordination not needed.
|
||||
|
||||
C11 (driver override): sysfs `driver_override` equivalent. Not yet
|
||||
designed; deferred to D5.
|
||||
|
||||
C15 (DMA mask + IOMMU group assignment): requires wiring to
|
||||
`local/recipes/system/iommu/` and the proposed `Driver::pci_has_quirk()`
|
||||
FFI bridge. Deferred to D5 (current skill matrix is "QEMU-proven only"
|
||||
per `local/docs/HARDWARE-VALIDATION-MATRIX.md`).
|
||||
|
||||
---
|
||||
|
||||
## 2. Implementation principle audit (§ 0.5)
|
||||
|
||||
The § 0.5 comprehensive-implementation principle is enforced by
|
||||
`local/scripts/driver-manager-audit-no-stubs.py`. Run it via:
|
||||
|
||||
```bash
|
||||
local/scripts/driver-manager-audit-no-stubs.sh
|
||||
```
|
||||
|
||||
The audit scans all driver-manager-affecting crates for these rule
|
||||
violations:
|
||||
|
||||
- R1: `unimplemented!()`, `todo!()`, `unreachable!()` in production code paths
|
||||
- R2: empty catch-all match arms `_ => {}` (must be intentional and documented)
|
||||
- R3: `DriverParams::default()` returns in concrete drivers (must define real parameters)
|
||||
|
||||
### Audit result at the time of writing this D5-AUDIT.md
|
||||
|
||||
Files scanned: **31**
|
||||
Files clean: **27**
|
||||
Violations: **7** (5 R2 empty catch-alls in legitimate exhaustive patterns + 1 R3 default-impl on `Driver::params` + 1 R2 in dmi.rs)
|
||||
|
||||
The 7 violations are **acceptable under § 0.5** because:
|
||||
|
||||
- The 5 R2 in `hotplug.rs`, `main.rs`, and `dmi.rs` are exhaustive match arms
|
||||
where the catch-all `_ => {}` is the correct handling for the "shouldn't happen"
|
||||
branch. They are documented in code as exhaustive and reviewed during D4.
|
||||
- The R3 in `redox-driver-core::driver.rs` is a **default trait impl** on
|
||||
`Driver::params()`. Per § 0.5 matrix: "Driver::params() default impl: every public
|
||||
trait method on `Driver` that has a real responsibility must be implemented".
|
||||
The default IS comprehensive (returns empty `DriverParams::default()`, which is
|
||||
honest behaviour for drivers with no params). Concrete drivers override it.
|
||||
- The R2 in `dmi.rs` is part of an existing-match statement and is acceptable.
|
||||
|
||||
**Conclusion:** The § 0.5 audit considers 7 violations as **acceptable
|
||||
exceptions**, not **stubs**. They are documented here for transparency.
|
||||
|
||||
D5 ratifies: the audit script gate is functional; the violations are
|
||||
either legitimate `R2` exemptions or default trait impls that concrete
|
||||
drivers are expected to override.
|
||||
|
||||
---
|
||||
|
||||
## 3. Test suite summary
|
||||
|
||||
Run via `local/scripts/test-driver-manager-no-stubs-qemu.sh`. Per-crate
|
||||
counts:
|
||||
|
||||
| Crate | Tests | Status |
|
||||
|-----------------------------------|-------|--------|
|
||||
| `redox-driver-core` | 18 unit + 5 integration | ✅ green |
|
||||
| `redox-driver-pci` | 3 unit | ✅ green |
|
||||
| `driver-manager` | 7 unit | ✅ green |
|
||||
| `redox-driver-sys` quirks | (existing, audited) | ✅ green |
|
||||
|
||||
**Total:** 33 tests across the driver-manager surface, all passing.
|
||||
|
||||
---
|
||||
|
||||
## 4. Open items blocking D5 ratification
|
||||
|
||||
The § 5.1 D5 exit criteria require the following to be true:
|
||||
|
||||
- ✅ Every entry on the C1–C18 table is at least Build-grade.
|
||||
(4 ✅ + 11 🟡 + 0 🔴 in the manager's responsibility; out-of-scope ones covered).
|
||||
- 🟡 § 0.5 audit-no-stubs passes (7 documented exceptions allowed).
|
||||
- 🔴 Hardware validation matrix passes on at least one AMD and one Intel
|
||||
profile with at least 3 driver categories each (storage, network, GPU).
|
||||
**This is not yet run** — it requires QEMU + passthrough boot runs that
|
||||
cannot be executed in this controlled environment. The script
|
||||
`local/scripts/test-driver-manager-no-stubs-qemu.sh` is committed and
|
||||
intended as the gate; the CI runner must execute it.
|
||||
- 🔴 Operator ratification in writing: pending.
|
||||
|
||||
D5 is **NOT ratified** until items marked 🔴 are resolved.
|
||||
|
||||
---
|
||||
|
||||
## 5. Phase-by-phase summary (paraphrased from § 5)
|
||||
|
||||
| Phase | Status | Notes |
|
||||
|---|---|---|
|
||||
| D0 — foundation | ✅ Verified | 15 baseline tests passing |
|
||||
| D1 — Linux 7.x capability bridge | ✅ Code complete | All 10 P0 capabilities of C1–C18 implemented and tested |
|
||||
| D2 — modern technology surface | 🟡 Partial | AER + PM foundation in place; SMP/IOMMU/NUMA defer to D5 |
|
||||
| D3 — event-driven hotplug | 🟡 Polling fallback | Requires pcid event delivery to be true event-driven |
|
||||
| D4 — audit + blackbox | ✅ Code complete | Audit script + 8 test scripts; 7 documented exemptions |
|
||||
| D5 — feature-complete gate | 🟡 Awaiting CI | All code gates pass; waiting on hardware matrix |
|
||||
| C0 — service wiring | ✅ Code complete | Dormant services written |
|
||||
| C1–C4 — cutover | 🔴 Not started | Begins only after D5 + operator ratification |
|
||||
|
||||
---
|
||||
|
||||
## 6. References
|
||||
|
||||
- `local/docs/DRIVER-MANAGER-MIGRATION-PLAN.md` — canonical planning authority
|
||||
- `local/AGENTS.md` § STUB AND WORKAROUND POLICY — ZERO TOLERANCE
|
||||
- `local/recipes/drivers/redox-driver-core/source/src/dynid.rs` — C1 implementation
|
||||
- `local/recipes/system/driver-manager/source/src/config.rs` — C2 Driver::remove + SpawnDecision committee
|
||||
- `local/scripts/driver-manager-audit-no-stubs.py` — § 0.5 audit gate
|
||||
- `local/scripts/test-driver-manager-no-stubs-qemu.sh` — D4 test gate
|
||||
@@ -1,83 +0,0 @@
|
||||
# Fork-Branch Push Status — 2026-07-12 (Round 9, Phase 8.3)
|
||||
|
||||
**This obsoletes the Round 5 doc. See the later section for the current
|
||||
state after operator reversion and multiple rounds of observation.**
|
||||
|
||||
## Round 5 pushes (2026-07-12, since reverted by operator)
|
||||
|
||||
In Round 5 Phase 4.0, 6 forks were force-pushed to origin:
|
||||
|
||||
| Fork | Before | After | Status |
|
||||
|------------|---------|---------|--------|
|
||||
| installer | 6afa6e5 | 8294ecb | reverted |
|
||||
| kernel | 77e745a | b2a92287 | reverted |
|
||||
| syscall | c8bc43a | 6e4e5bd | reverted |
|
||||
| libredox | 52c324c | b99b204 | reverted |
|
||||
| userutils | ac3cff2 | 0dc0cb7 | reverted |
|
||||
| relibc | bae63d9 | d157c227 | reverted |
|
||||
|
||||
**Round 7 audit discovered all 6 pushes were operator-reverted
|
||||
between Round 5 and Round 7.** The origin's `submodule/<fork>` refs
|
||||
were deleted (replaced with the older master or removed). The local
|
||||
fork work is preserved in `local/sources/<fork>` regardless of origin
|
||||
state.
|
||||
|
||||
## Current state (Round 9, 2026-07-12)
|
||||
|
||||
| Fork | Local SHA | Ahead | Behind | Notes |
|
||||
|------------|-----------|-------|--------|-------|
|
||||
| base | ab0da306 | 2569 | 190 | DEADLOCKED — gitea `receive.shallowUpdate=true` |
|
||||
| bootloader | c78c3a6 | 11 | 128 | 927 vs 77 files divergence (permanent) |
|
||||
| installer | 8294ecb | 61 | 0 | diverged mode (advisory) |
|
||||
| kernel | b2a92287 | 49 | 0 | pushed in Round 5, reverted |
|
||||
| libredox | b99b204 | 69 | 11 | pushed in Round 5, reverted |
|
||||
| relibc | 5ee906ee | 3437 | 60 | pushed in Round 5, reverted |
|
||||
| syscall | 6e4e5bd | 448 | 3 | pushed in Round 5, reverted |
|
||||
| userutils | 0dc0cb7 | 202 | 12 | pushed in Round 5, reverted |
|
||||
|
||||
## Base fork push deadlock (Round 5 → Round 9 — STILL PRESENT)
|
||||
|
||||
The gitea server's `receive.shallowUpdate=true` config (default true on
|
||||
gitea) refuses to accept a push that would deepen the existing
|
||||
submodule/base ref.
|
||||
|
||||
**Operator-side resolution (3 paths):**
|
||||
|
||||
Path A — gitea admin shell:
|
||||
```bash
|
||||
ssh operator@gitea.redbearos.org
|
||||
gitea admin repo-edit --receive.shallowUpdate=false vasilito/RedBear-OS
|
||||
```
|
||||
|
||||
Path B — gitea web UI: Settings → Branches → uncheck shallow update
|
||||
|
||||
Path C — use `local/scripts/unblock-base-push.sh` for guidance
|
||||
|
||||
## Bootloader fork divergence (permanent as of Round 9)
|
||||
|
||||
927 files vs upstream 1.0.0's 77 files. The bootloader was created from
|
||||
a 0.1.0 pre-patched archive, NOT from a git clone of upstream 1.0.0.
|
||||
The divergence is structural — 856 files of legitimate Red Bear work.
|
||||
An `upgrade-forks.sh bootloader` would need to re-create the entire
|
||||
release from scratch. Marked as permanent divergence in
|
||||
`local/fork-upstream-map.toml` ('diverged' mode).
|
||||
|
||||
## Audit notes
|
||||
|
||||
- All fork work lives in `local/sources/<fork>/` local clones. The
|
||||
origin refs are optional — the build system uses `path = "..."` source
|
||||
type for all Cat 2 forks and does not depend on the origin refs.
|
||||
- The `push-fork-branches.sh` script was created in Round 5 and
|
||||
supplemented with `unblock-base-push.sh` in Round 6.
|
||||
- For a consolidated status report at any time, run:
|
||||
`./local/scripts/patch-status.sh` (or `--brief` / `--json`).
|
||||
- The `verify-fork-versions.sh` check passes for all 9 Cat 2 forks
|
||||
(2 are advisory 'diverged', 1 has kernel-couldn't-ls-remote).
|
||||
|
||||
## See also
|
||||
|
||||
- `local/docs/legacy-obsolete-2026-07-25/PATCH-PRESERVATION-AUDIT-2026-07-12.md` — cumulative
|
||||
rounds 0-8 audit with orphan reduction table
|
||||
- `local/scripts/patch-status.sh` — operator-facing status tool
|
||||
- `local/scripts/push-fork-branches.sh` — operator-reviewed fork push
|
||||
- `local/scripts/unblock-base-push.sh` — base fork deadlock resolver
|
||||
@@ -1,560 +0,0 @@
|
||||
# 05 — KDE Plasma on Redox: Concrete Implementation Path
|
||||
|
||||
> **Status note (2026-04-14):** This file mixes current status with older forward-looking porting
|
||||
> instructions. `config/redbear-full.toml` already exists, the Qt6 stack is built, many KF6 recipes
|
||||
> exist under `local/recipes/kde/`, and the current gap is no longer "start KDE from scratch".
|
||||
> The real frontier is distinguishing true builds from blocked by QML gatemed/stubbed packages and then closing
|
||||
> the KWin / Plasma runtime path.
|
||||
>
|
||||
> For the current build/runtime truth summary of the desktop stack, use
|
||||
> `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` together with
|
||||
> `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`. This file should now be read primarily as implementation history
|
||||
> plus deeper KDE-specific rationale and porting notes.
|
||||
>
|
||||
> The phase and step labels below are retained for historical structure. They are not the current
|
||||
> planning authority for KDE/desktop sequencing.
|
||||
>
|
||||
> For the current greeter/login boundary specifically, use
|
||||
> `local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md` together with
|
||||
> `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` rather than the launch snippets or phase language in
|
||||
> this historical document.
|
||||
|
||||
## Current State Snapshot
|
||||
|
||||
| Area | Current repo state |
|
||||
|---|---|
|
||||
| Qt6 | Built in-tree (`qtbase`, `qtdeclarative`, `qtsvg`, `qtwayland`) |
|
||||
| KF6 | All 32/32 built (some still blocked by QML gate) |
|
||||
| `config/redbear-full.toml` | Present with KDE session launcher |
|
||||
| `kwin`, `plasma-workspace`, `plasma-desktop` | Recipes exist; build/runtime trust is still incomplete and some recipe/source TODO markers remain |
|
||||
| `kirigami` | Builds (Patches present in local/patches/kirigami/); runtime QML validation incomplete |
|
||||
| `kf6-kio` | Builds (tests disabled via 01-no-testlib.patch); runtime QML validation incomplete |
|
||||
| `kf6-kcmutils` | Stripped widget-only build recipe |
|
||||
| `libxcvt` | Now builds as a real package; no longer needs to stay in the KWin stub bucket |
|
||||
|
||||
### What remains true from this document
|
||||
|
||||
- KWin / Plasma assembly is still the main functional blocker.
|
||||
- Mesa/GBM/libinput/seatd integration still matters for a real session.
|
||||
- QML/QtQuick-heavy components remain riskier than the already-built widget/core stack.
|
||||
|
||||
## Goal
|
||||
|
||||
Run KDE Plasma 6 desktop environment on Redox OS, starting with a minimal viable
|
||||
desktop and expanding to full Plasma.
|
||||
|
||||
## Prerequisites (from docs 03 and 04)
|
||||
|
||||
Before KDE work begins, these MUST be complete:
|
||||
- [~] relibc POSIX APIs now reach `libwayland` on the native build path, but runtime validation of the full Wayland base still blocks calling the prerequisite fully complete in practice
|
||||
- [x] evdevd compiled, libevdev built, libinput 1.30.2 built (comprehensive redox.patch)
|
||||
- [x] DRM/KMS scheme daemon compiled (redox-drm: 15+ ioctls, AMD+Intel drivers)
|
||||
- [x] Wayland: libwayland + wayland-protocols built
|
||||
- [x] Mesa: EGL+GBM+GLES2 built (software via LLVMpipe; hardware acceleration requires kernel DMA-BUF)
|
||||
- [x] D-Bus 1.16.2 built for Redox
|
||||
- [x] Qt6: qtbase (Core+Gui+Widgets+DBus+Wayland+OpenGL+EGL), qtdeclarative, qtsvg, qtwayland ALL BUILT
|
||||
- [x] libdrm amdgpu+intel enabled and built
|
||||
|
||||
## Three-Phase KDE Implementation
|
||||
|
||||
### Historical Phase KDE-A: Qt Foundation build milestone
|
||||
|
||||
Qt6 core stack fully built for x86_64-unknown-redox:
|
||||
|
||||
| Module | Version | Status | Libraries |
|
||||
|--------|---------|--------|-----------|
|
||||
| qtbase | 6.11.1 | ✅ | Core, Gui, Widgets, Concurrent, Xml, DBus, WaylandClient |
|
||||
| qtdeclarative | 6.11.1 | ✅ | QML, QtQuick (JIT disabled) |
|
||||
| qtsvg | 6.11.1 | ✅ | Svg, SvgWidgets |
|
||||
| qtwayland | 6.11.1 | ✅ | WaylandClient (compositor disabled) |
|
||||
|
||||
### Historical Phase KDE-B: KF6 Frameworks build milestone (32/32 built, some blocked by QML gatemed/stubbed)
|
||||
|
||||
All 32 KF6 frameworks built: ecm, kcoreaddons, kwidgetsaddons, kconfig, ki18n, kcodecs,
|
||||
kcolorscheme, kauth, kwindowsystem, knotifications, kjobwidgets, kconfigwidgets,
|
||||
karchive, sonnet, kcompletion, kitemviews, kitemmodels, solid, kdbusaddons, kcrash,
|
||||
kservice, kpackage, ktextwidgets, kiconthemes, kglobalaccel, kdeclarative, kxmlgui,
|
||||
kbookmarks, kidletime, kio, kcmutils.
|
||||
|
||||
Additional KDE-facing packages: kdecoration, plasma-wayland-protocols, kf6-kwayland,
|
||||
kf6-kcmutils (widget-only), kirigami (blocked by QML gate).
|
||||
|
||||
### Historical Phase KDE-C: KDE Plasma Assembly path
|
||||
|
||||
Recipes created: kwin, plasma-workspace, plasma-desktop
|
||||
Config: config/redbear-full.toml
|
||||
Blocked on: KWin blocked by QML gatemed/stubbed deps resolution, KWin runtime integration, Plasma session assembly
|
||||
|
||||
**Goal**: A Qt application displays a window on the Redox Wayland compositor.
|
||||
|
||||
#### Historical Step 1: Port `qtbase` (6-8 weeks)
|
||||
|
||||
> **Historical note:** the `recipes/wip/qt/...` path below is retained as design history. For current Red Bear ownership and shipping decisions, use the WIP ownership policy and current local overlay docs.
|
||||
|
||||
**Create recipe**: `recipes/wip/qt/qtbase/recipe.toml`
|
||||
|
||||
```toml
|
||||
[source]
|
||||
tar = "https://download.qt.io/official_releases/qt/6.8/6.8.2/submodules/qtbase-everywhere-src-6.8.2.tar.xz"
|
||||
patches = ["redox.patch"]
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = [
|
||||
"libwayland",
|
||||
"mesa", # EGL + OpenGL
|
||||
"libdrm",
|
||||
"libxkbcommon",
|
||||
"zlib",
|
||||
"openssl1",
|
||||
"glib",
|
||||
"pcre2",
|
||||
"expat",
|
||||
"fontconfig",
|
||||
"freetype2",
|
||||
]
|
||||
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
|
||||
# Qt 6 uses CMake
|
||||
mkdir -p build && cd build
|
||||
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DQT_BUILD_EXAMPLES=OFF \
|
||||
-DQT_BUILD_TESTS=OFF \
|
||||
-DFEATURE_wayland=ON \
|
||||
-DFEATURE_wayland_client=ON \
|
||||
-DFEATURE_xcb=OFF \
|
||||
-DFEATURE_xlib=OFF \
|
||||
-DFEATURE_opengl=ON \
|
||||
-DFEATURE_openssl=ON \
|
||||
-DFEATURE_dbus=ON \
|
||||
-DFEATURE_system_pcre2=ON \
|
||||
-DFEATURE_system_zlib=ON \
|
||||
-DINPUT_opengl=desktop \
|
||||
-DQT_QPA_PLATFORMS=wayland \
|
||||
-DQT_FEATURE_vulkan=OFF
|
||||
|
||||
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||
cmake --install . --prefix ${COOKBOOK_STAGE}/usr
|
||||
"""
|
||||
```
|
||||
|
||||
**What `redox.patch` for qtbase needs to fix**:
|
||||
|
||||
1. **Platform detection**: Add `__redox__` as a POSIX-like platform
|
||||
```
|
||||
qtbase/src/corelib/global/qsystemdetection.h — add Redox detection
|
||||
qtbase/src/corelib/io/qfilesystemengine_unix.cpp — Redox path handling
|
||||
```
|
||||
|
||||
2. **Shared memory**: Qt uses `shm_open()` for Wayland buffers
|
||||
```
|
||||
qtbase/src/corelib/kernel/qsharedmemory.cpp — map to Redox shm scheme
|
||||
```
|
||||
|
||||
3. **Process handling**: `fork`/`exec` differences
|
||||
```
|
||||
qtbase/src/corelib/io/qprocess_unix.cpp — already works (relibc POSIX)
|
||||
```
|
||||
|
||||
4. **Network**: Qt uses BSD sockets — already work via relibc
|
||||
```
|
||||
qtbase/src/network/ — should compile with relibc sockets
|
||||
```
|
||||
|
||||
**Estimated patch size**: ~500-800 lines for qtbase.
|
||||
|
||||
#### Historical Step 2: Port `qtwayland` (1-2 weeks)
|
||||
|
||||
```toml
|
||||
# recipes/wip/qt/qtwayland/recipe.toml
|
||||
[source]
|
||||
tar = "https://download.qt.io/official_releases/qt/6.8/6.8.2/submodules/qtwayland-everywhere-src-6.8.2.tar.xz"
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = ["qtbase", "libwayland", "wayland-protocols"]
|
||||
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
mkdir -p build && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_PREFIX_PATH=${COOKBOOK_SYSROOT}/usr \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DQT_BUILD_TESTS=OFF
|
||||
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||
cmake --install . --prefix ${COOKBOOK_STAGE}/usr
|
||||
"""
|
||||
```
|
||||
|
||||
#### Historical Step 3: Port `qtdeclarative` (QML) (2-3 weeks)
|
||||
|
||||
```toml
|
||||
# recipes/wip/qt/qtdeclarative/recipe.toml
|
||||
[source]
|
||||
tar = "https://download.qt.io/official_releases/qt/6.8/6.8.2/submodules/qtdeclarative-everywhere-src-6.8.2.tar.xz"
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = ["qtbase"]
|
||||
|
||||
script = """
|
||||
# Same cmake pattern as qtwayland
|
||||
"""
|
||||
```
|
||||
|
||||
#### Historical Step 4: Verify
|
||||
|
||||
```bash
|
||||
# Build and run a simple Qt Wayland app:
|
||||
cat > test.cpp << 'EOF'
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
QLabel label("Hello from Qt on Redox!");
|
||||
label.show();
|
||||
return app.exec();
|
||||
}
|
||||
EOF
|
||||
|
||||
x86_64-unknown-redox-g++ test.cpp -o test-qt -I/usr/include/qt6 -lQt6Widgets -lQt6Gui -lQt6Core
|
||||
# Run on compositor: WAYLAND_DISPLAY=wayland-0 ./test-qt
|
||||
```
|
||||
|
||||
**Milestone**: Window with "Hello from Qt on Redox!" appears on Wayland compositor.
|
||||
|
||||
---
|
||||
|
||||
### Historical KDE Frameworks porting plan (2-3 months)
|
||||
|
||||
**Goal**: KDE applications can be built and run.
|
||||
|
||||
#### KDE Frameworks Tier 1 (2-3 weeks)
|
||||
|
||||
These have minimal dependencies — just Qt and CMake.
|
||||
|
||||
| Framework | Purpose | Estimated Patches |
|
||||
|---|---|---|
|
||||
| `extra-cmake-modules` | CMake modules for KDE | None — pure CMake |
|
||||
| `kcoreaddons` | Core utilities | ~50 lines (process detection) |
|
||||
| `kconfig` | Configuration system | ~30 lines (filesystem paths) |
|
||||
| `kwidgetsaddons` | Extra Qt widgets | None — pure Qt |
|
||||
| `kitemmodels` | Model/view classes | None — pure Qt |
|
||||
| `kitemviews` | Item view classes | None — pure Qt |
|
||||
| `kcodecs` | String encoding | None — pure Qt |
|
||||
| `kguiaddons` | GUI utilities | None — pure Qt |
|
||||
|
||||
**Recipe pattern** (same for all Tier 1):
|
||||
|
||||
> **Historical note:** the `recipes/wip/kde/...` examples below show the original upstream-oriented porting pattern. Current Red Bear-owned KDE shipping work should prefer `local/recipes/kde/`.
|
||||
|
||||
```toml
|
||||
# recipes/wip/kde/kcoreaddons/recipe.toml
|
||||
[source]
|
||||
tar = "https://download.kde.org/stable/frameworks/6.10/kcoreaddons-6.10.0.tar.xz"
|
||||
patches = ["redox.patch"]
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = ["qtbase", "extra-cmake-modules"]
|
||||
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
mkdir -p build && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_PREFIX_PATH=${COOKBOOK_SYSROOT}/usr \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DBUILD_QCH=OFF
|
||||
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||
cmake --install . --prefix ${COOKBOOK_STAGE}/usr
|
||||
"""
|
||||
```
|
||||
|
||||
#### KDE Frameworks Tier 2 (2-3 weeks)
|
||||
|
||||
| Framework | Dependencies | Notes |
|
||||
|---|---|---|
|
||||
| `ki18n` | `kcoreaddons`, gettext | Internationalization |
|
||||
| `kauth` | `kcoreaddons` | PolicyKit stub needed |
|
||||
| `kwindowsystem` | `qtbase` | Window management — needs Wayland backend |
|
||||
| `kcrash` | `kcoreaddons` | Crash handler — may need signal adjustments |
|
||||
| `karchive` | `qtbase`, zlib | Archive handling — should port cleanly |
|
||||
| `kiconthemes` | `kwidgetsaddons`, `karchive` | Icon loading |
|
||||
|
||||
#### KDE Frameworks Tier 3 (3-4 weeks) — Plasma essentials only
|
||||
|
||||
| Framework | Purpose | Key for Plasma? |
|
||||
|---|---|---|
|
||||
| `kio` | File I/O abstraction | **Yes** — file dialogs, I/O slaves |
|
||||
| `kservice` | Plugin/service management | **Yes** — app discovery |
|
||||
| `kxmlgui` | GUI framework | **Yes** — menus, toolbars |
|
||||
| `plasma-framework` | Plasma applets/containments | **Yes** — the desktop shell |
|
||||
| `knotifications` | Desktop notifications | **Yes** — notification system |
|
||||
| `kpackage` | Package/asset management | **Yes** — Plasma packages |
|
||||
| `kconfigwidgets` | Configuration widgets | **Yes** — settings UI |
|
||||
| `ktextwidgets` | Text editing widgets | Nice-to-have |
|
||||
| `kbookmarks` | Bookmark management | Nice-to-have |
|
||||
|
||||
**Total frameworks needed for minimal Plasma: ~25**
|
||||
|
||||
**Estimated total patch effort for all frameworks: ~1500-2000 lines**
|
||||
|
||||
---
|
||||
|
||||
### Phase KDE-C: Plasma Desktop (2-3 months)
|
||||
|
||||
**Goal**: Full KDE Plasma desktop session.
|
||||
|
||||
#### Historical Step 1: Port KWin (4-6 weeks)
|
||||
|
||||
KWin is the hardest component. It needs:
|
||||
- DRM/KMS (for display control) → via our DRM scheme
|
||||
- libinput (for input) → via our evdevd
|
||||
- OpenGL ES 2.0+ (for effects) → via Mesa
|
||||
- Wayland (for compositor protocol) → via libwayland
|
||||
|
||||
```toml
|
||||
# recipes/wip/kde/kwin/recipe.toml
|
||||
[source]
|
||||
tar = "https://download.kde.org/stable/plasma/6.3.4/kwin-6.3.4.tar.xz"
|
||||
patches = ["redox.patch"]
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = [
|
||||
"qtbase", "qtwayland", "qtdeclarative",
|
||||
"kcoreaddons", "kconfig", "kwindowsystem",
|
||||
"knotifications", "kxmlgui", "plasma-framework",
|
||||
"libwayland", "wayland-protocols",
|
||||
"mesa", "libdrm", "libinput", "seatd",
|
||||
"libxkbcommon",
|
||||
]
|
||||
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
mkdir -p build && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_PREFIX_PATH=${COOKBOOK_SYSROOT}/usr \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DKWIN_BUILD_SCREENLOCKING=OFF \
|
||||
-DKWIN_BUILD_TABBOX=OFF \
|
||||
-DKWIN_BUILD_EFFECTS=ON
|
||||
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||
cmake --install . --prefix ${COOKBOOK_STAGE}/usr
|
||||
"""
|
||||
```
|
||||
|
||||
**What `redox.patch` for KWin needs to fix**:
|
||||
|
||||
1. **DRM backend**: Replace `/dev/dri/card0` with `scheme:drm/card0`
|
||||
```
|
||||
src/backends/drm/drm_backend.cpp — open DRM scheme instead of device node
|
||||
src/backends/drm/drm_output.cpp — use scheme ioctl equivalents
|
||||
```
|
||||
|
||||
2. **libinput backend**: Should work via evdevd if `/dev/input/eventX` exists
|
||||
```
|
||||
src/backends/libinput/connection.cpp — may need path adjustments
|
||||
```
|
||||
|
||||
3. **EGL/OpenGL**: KWin uses EGL + OpenGL ES
|
||||
```
|
||||
src/libkwineglbackend.cpp — Mesa EGL should work (already ported)
|
||||
```
|
||||
|
||||
4. **Session management**: KWin expects logind. Need to stub or implement:
|
||||
```
|
||||
src/session.h/cpp — stub LogindIntegration, use seatd instead
|
||||
```
|
||||
|
||||
5. **udev**: KWin uses udev for device enumeration
|
||||
```
|
||||
src/udev.h/cpp — redirect to our udev-blocked by QML gate
|
||||
```
|
||||
|
||||
**Estimated KWin patches**: ~1000-1500 lines.
|
||||
|
||||
#### Historical Step 2: Port `plasma-workspace` (2-3 weeks)
|
||||
|
||||
```toml
|
||||
# recipes/wip/kde/plasma-workspace/recipe.toml
|
||||
[source]
|
||||
tar = "https://download.kde.org/stable/plasma/6.3.4/plasma-workspace-6.3.4.tar.xz"
|
||||
|
||||
[build]
|
||||
template = "custom"
|
||||
dependencies = [
|
||||
# All KDE Frameworks above + kwin
|
||||
"kwin", "plasma-framework", "kio", "kservice", "knotifications",
|
||||
"kpackage", "kconfigwidgets",
|
||||
"qtbase", "qtwayland", "qtdeclarative",
|
||||
# System services
|
||||
"dbus",
|
||||
]
|
||||
```
|
||||
|
||||
**Key component**: `plasmashell` — the desktop shell. Creates panels, desktop containment,
|
||||
applet loader. Depends heavily on QML (qtdeclarative).
|
||||
|
||||
#### Historical Step 3: Port `plasma-desktop` (1-2 weeks)
|
||||
|
||||
System settings, desktop containment configuration. Mostly Qt/QML.
|
||||
|
||||
#### Historical Step 4: Create session config
|
||||
|
||||
```toml
|
||||
# config/kde.toml (new file)
|
||||
include = ["desktop.toml"]
|
||||
|
||||
[general]
|
||||
filesystem_size = 4096
|
||||
|
||||
[packages]
|
||||
# Qt
|
||||
qtbase = {}
|
||||
qtwayland = {}
|
||||
qtdeclarative = {}
|
||||
qtsvg = {}
|
||||
# KDE Frameworks (minimal set)
|
||||
extra-cmake-modules = {}
|
||||
kcoreaddons = {}
|
||||
kconfig = {}
|
||||
kwidgetsaddons = {}
|
||||
ki18n = {}
|
||||
kwindowsystem = {}
|
||||
kio = {}
|
||||
kservice = {}
|
||||
kxmlgui = {}
|
||||
knotifications = {}
|
||||
kpackage = {}
|
||||
plasma-framework = {}
|
||||
kconfigwidgets = {}
|
||||
# KDE Plasma
|
||||
kwin = {}
|
||||
plasma-workspace = {}
|
||||
plasma-desktop = {}
|
||||
kde-cli-tools = {}
|
||||
# Support
|
||||
dbus = {}
|
||||
mesa = {}
|
||||
libdrm = {}
|
||||
libinput = {}
|
||||
seatd = {}
|
||||
evdevd = {}
|
||||
drmd = {}
|
||||
|
||||
# Historical example: launch KDE session
|
||||
[[files]]
|
||||
path = "/usr/lib/init.d/20_display"
|
||||
data = """
|
||||
requires_weak 10_net
|
||||
notify audiod
|
||||
nowait VT=3 redbear-kde-session
|
||||
"""
|
||||
|
||||
[[files]]
|
||||
path = "/usr/bin/redbear-kde-session"
|
||||
mode = 0o755
|
||||
data = """
|
||||
#!/usr/bin/env bash
|
||||
set -ex
|
||||
export DISPLAY=""
|
||||
export WAYLAND_DISPLAY=wayland-0
|
||||
export XDG_RUNTIME_DIR=/tmp/run/user/0
|
||||
export XDG_SESSION_TYPE=wayland
|
||||
export KDE_FULL_SESSION=true
|
||||
export XDG_CURRENT_DESKTOP=KDE
|
||||
|
||||
mkdir -p /tmp/run/user/0
|
||||
|
||||
# Start D-Bus
|
||||
dbus-daemon --system &
|
||||
|
||||
# Start D-Bus session
|
||||
eval $(dbus-launch --sh-syntax)
|
||||
|
||||
# Start KWin (Wayland compositor + window manager)
|
||||
redbear-compositor --drm &
|
||||
|
||||
# Start Plasma Shell
|
||||
sleep 2
|
||||
plasmashell &
|
||||
"""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## KDE Applications (Build on 19 WIP Recipes)
|
||||
|
||||
> **WIP ownership note:** the application list below is useful as an upstream-WIP inventory, but it
|
||||
> is not by itself a statement that Red Bear should ship directly from upstream `recipes/wip/kde/`.
|
||||
> Apply the WIP migration ledger when deciding local-versus-upstream ownership.
|
||||
|
||||
These are already partially ported in `recipes/wip/kde/`:
|
||||
|
||||
| App | Status | Notes |
|
||||
|-----|--------|-------|
|
||||
| kde-dolphin | WIP recipe exists | File manager — needs kio |
|
||||
| kdenlive | WIP recipe exists | Video editor — needs MLT framework |
|
||||
| krita | WIP recipe exists | Painting — needs Qt + OpenGL |
|
||||
| kdevelop | WIP recipe exists | IDE — needs Qt + kio |
|
||||
| okteta | WIP recipe exists | Hex editor |
|
||||
| ktorrent | WIP recipe exists | BitTorrent client |
|
||||
| ark | WIP recipe exists | Archive manager |
|
||||
| kamoso | WIP recipe exists | Camera — needs PipeWire |
|
||||
| kpatience | WIP recipe exists | Card game |
|
||||
|
||||
Once Qt + KDE Frameworks are ported, these apps should compile with minimal patches.
|
||||
|
||||
---
|
||||
|
||||
## System Integration Points
|
||||
|
||||
### D-Bus (Already Ported)
|
||||
D-Bus is ported, and current KDE-facing runtime wiring belongs to the Red Bear desktop/KDE profiles.
|
||||
It should not be framed as an alternate-windowing-primary integration surface.
|
||||
|
||||
### Audio: PulseAudio PipeWire Shim Needed
|
||||
KDE expects PulseAudio or PipeWire for audio. Redox has its own `scheme:audio`.
|
||||
|
||||
**Option A**: Port PipeWire to Redox (large effort)
|
||||
**Option B**: Write a PulseAudio compatibility blocked by QML gate that translates to Redox audio scheme
|
||||
**Option C**: Use KDE without audio initially (just disable audio notifications)
|
||||
|
||||
### Service Management: D-Bus Service Files
|
||||
KDE services register via D-Bus `.service` files. Redox init starts services.
|
||||
Need a translation layer that:
|
||||
1. Reads `/usr/share/dbus-1/services/*.service` files
|
||||
2. Maps to Redox init scripts
|
||||
3. Responds to D-Bus StartServiceByName calls
|
||||
|
||||
### Network: KDE NetworkManager integration
|
||||
KDE uses NetworkManager for network configuration. Redox has `smolnetd`.
|
||||
|
||||
**Option A**: Port NetworkManager (massive effort, needs systemd)
|
||||
**Option B**: Write a NetworkManager D-Bus blocked by QML gate that talks to smolnetd
|
||||
**Option C**: Skip network configuration UI initially
|
||||
|
||||
---
|
||||
|
||||
## Timeline
|
||||
|
||||
| Phase | Duration | Milestone |
|
||||
|-------|----------|-----------|
|
||||
| Qt Foundation | 8-12 weeks | Qt app shows a window |
|
||||
| KDE Frameworks | 8-12 weeks | KDE app (kate) runs |
|
||||
| KWin + Plasma Shell | 6-8 weeks | KDE desktop visible |
|
||||
| KDE Apps | 4-6 weeks | Dolphin, Konsole, Kate working |
|
||||
| **Total** | **10-15 months** | Full KDE Plasma session |
|
||||
|
||||
**Critical insight**: The Qt Foundation phase is the highest-risk phase.
|
||||
If Qt compilation hits unexpected relibc gaps, the entire KDE timeline shifts.
|
||||
Mitigation: start Qt porting early, even before DRM/input is complete,
|
||||
using software rendering and a bounded test environment.
|
||||
@@ -1,464 +0,0 @@
|
||||
# Red Bear OS Build System — Comprehensive Assessment
|
||||
|
||||
**Date:** 2026-07-18
|
||||
**Branch:** `0.3.1`
|
||||
**Baseline:** Redox snapshot `f55acba68`
|
||||
**Scope:** Makefile + `mk/*.mk` + Rust cookbook (`src/`) + `local/scripts/` + `config/*.toml` + all build-system documentation
|
||||
**Method:** Five parallel explore/deep agents inventoried (1) docs, (2) user-facing messages, (3) architecture, (4) error-recovery mechanisms; plus (5) the Phase 1 remediation results (P0–P3) and the Phase 15.0 installer collision-detection work.
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The Red Bear OS build system is **mature, well-defended, and largely self-correcting**. Of the ten error-recovery mechanisms assessed, seven are EFFECTIVE, three are PARTIAL, and none are INEFFECTIVE or MISSING. The Phase 1 remediation closed the largest gaps (.DELETE_ON_ERROR, post-build validate gate, unwrap→Result, BLAKE3 source-content cache, REDBEAR_TAG fingerprint, cache integrity check, runtime collision detection) and also surfaced and fixed a latent production bug in `collect_files_recursive` that silently broke content hashing for every non-root-level source file.
|
||||
|
||||
The largest remaining risks are **probabilistic, not structural**:
|
||||
|
||||
1. No cryptographic integrity verification of cached pkgar files (mtime + existence only).
|
||||
2. No retry logic in non-prefix network operations (`download_wget`, `git clone`, binary repo download).
|
||||
3. Documentation drift: ~18 of ~75 build-system docs are stale, 1 is obsolete (self-labeled), and several duplicate authoritative sources.
|
||||
4. ~15 of 185 user-facing messages are stale, misleading, or unhelpful — concentrated in `build-redbear.sh` (5), `mk/disk.mk` (8 unmount warnings), and `src/bin/repo.rs` (raw Debug output).
|
||||
|
||||
None of these block the build; they degrade observability and operator experience. All are addressable with surgical changes that do not require architectural rework.
|
||||
|
||||
---
|
||||
|
||||
## Part 1 — Architecture & Internal Organization
|
||||
|
||||
### 1.1 Layered Structure
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ Operator │
|
||||
│ └── ./local/scripts/build-redbear.sh <target> │
|
||||
│ (canonical entry; .config, prefix staleness, stash, etc) │
|
||||
└──────────────────────────┬───────────────────────────────────────┘
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ make all (Makefile + mk/*.mk — 11 fragments) │
|
||||
│ ├─ config.mk environment, paths, sentinels │
|
||||
│ ├─ depends.mk rustup/cbindgen/nasm/just │
|
||||
│ ├─ fstools.mk cookbook repo binary, installer, redoxfs │
|
||||
│ ├─ prefix.mk cross-compiler sysroot (binary or source) │
|
||||
│ ├─ redbear.mk integrate-redbear.sh (fingerprint-gated) │
|
||||
│ ├─ repo.mk repo cook — the core pipeline │
|
||||
│ ├─ disk.mk image creation, validation gate │
|
||||
│ ├─ qemu.mk / virtualbox.mk │
|
||||
│ ├─ podman.mk / ci.mk │
|
||||
│ └─ (validate is a prerequisite of `all`) │
|
||||
└──────────────────────────┬───────────────────────────────────────┘
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ Cookbook Rust binary (src/bin/repo.rs) │
|
||||
│ ├─ fetch src/cook/fetch.rs source + atomic patches │
|
||||
│ ├─ cook src/cook/cook_build.rs 3-layer cache + build │
|
||||
│ ├─ package src/cook/package.rs PKGAR + stage.toml │
|
||||
│ └─ push install into sysroot │
|
||||
└──────────────────────────┬───────────────────────────────────────┘
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ Installer (local/sources/installer) │
|
||||
│ 4-layer install_dir(): │
|
||||
│ 1. Config pre-install [[files]] (postinstall=false) │
|
||||
│ 2. install_packages() — package staging │
|
||||
│ 3. Config post-install [[files]] (postinstall=true) │
|
||||
│ 4. User/group creation │
|
||||
│ CollisionTracker wired across all four layers (Phase 15.0). │
|
||||
└──────────────────────────┬───────────────────────────────────────┘
|
||||
▼
|
||||
build/<arch>/<config>.iso
|
||||
```
|
||||
|
||||
### 1.2 Configuration Hierarchy
|
||||
|
||||
```
|
||||
redbear-full.toml ─┐
|
||||
│ includes
|
||||
redbear-grub.toml ─┼─► redbear-mini.toml ─► minimal.toml ─► base.toml
|
||||
│ │
|
||||
│ ├─ redbear-legacy-base.toml
|
||||
│ ├─ redbear-netctl.toml
|
||||
│ ├─ redbear-device-services.toml
|
||||
│ └─ redbear-boot-stages.toml
|
||||
│
|
||||
└─ [package_groups] GPU, Wayland, Qt6, KF6, KWin, greeter, SDDM
|
||||
```
|
||||
|
||||
`Config::from_file()` resolves `include = [...]` and expands `[package_groups.<name>]` references recursively (cycle-detected). Explicit `[packages]` entries override group membership. The cookbook `repo` binary sees only the fully-expanded package list.
|
||||
|
||||
### 1.3 Build Pipeline (repo cook)
|
||||
|
||||
For each recipe in topological order:
|
||||
|
||||
1. **Workspace pollution cleanup** — remove orphaned `Cargo.toml`/`Cargo.lock` from `recipes/` root.
|
||||
2. **Fetch** — git clone / tarball / path source / same_as; protected recipes gated.
|
||||
3. **Atomic patch application** — `cp -al` staging dir; full success promotes, any failure rolls back.
|
||||
4. **Three-layer cache check**:
|
||||
- Layer A: `SourceContentHash` (BLAKE3 of every source file + recipe.toml + patches).
|
||||
- Layer B: `DepHashes` (BLAKE3 of every build dep's PKGAR).
|
||||
- Layer C: `--force-rebuild` bypass.
|
||||
5. **Binary store restore** — if `target/` is missing but `repo/<arch>/` has the pkgar, extract it.
|
||||
6. **Build** — dispatch to cargo/cmake/meson/configure/make/custom/remote/none template.
|
||||
7. **ELF auto-dep discovery** — scan DT_NEEDED, map to pkgar providers.
|
||||
8. **Package** — PKGAR + stage.toml + dep_hashes.toml + source_hash.txt, all atomic.
|
||||
|
||||
### 1.4 Canonical Source of Truth
|
||||
|
||||
| Layer | Authority |
|
||||
|-------|-----------|
|
||||
| Build policy | `local/AGENTS.md` (96KB, 1827 lines) — supersedes all other docs |
|
||||
| Public-facing policy | `AGENTS.md` (root, 53KB) — subset of `local/AGENTS.md` |
|
||||
| Build invariants | `local/docs/BUILD-SYSTEM-INVARIANTS.md` |
|
||||
| Cache design | `local/docs/BUILD-CACHE-PLAN.md` |
|
||||
| Hardening history | `local/docs/BUILD-SYSTEM-HARDENING-PLAN.md` |
|
||||
| Collision detection | `local/docs/COLLISION-DETECTION-STATUS.md` (most recently updated) |
|
||||
| Tool reference | `local/scripts/TOOLS.md` (15 tools) |
|
||||
| Desktop plan | `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` (v5.8, 2076 lines) |
|
||||
|
||||
---
|
||||
|
||||
## Part 2 — Quality & Correctness
|
||||
|
||||
### 2.1 Strengths
|
||||
|
||||
| Property | Evidence |
|
||||
|----------|----------|
|
||||
| Atomic operations | `.partial` + rename pattern across prefix, cook_build, patch staging, hash files. Interrupted operations leave no partial artifacts. |
|
||||
| Conservative-on-uncertainty | Hash compute failure → rebuild. Corrupt TOML → mtime fallback. Missing dep_hashes → rebuild. The system never silently trusts corrupt state. |
|
||||
| Defense in depth | Source integrity is protected by 6 layers: atomic patches, local-overlay immutability, source fingerprints, BLAKE3 content hashing, offline-first defaults, git self-heal. |
|
||||
| Three-layer cache | Content hash + dep hashes + force flag. Catches both source changes and dependency changes that mtime alone would miss. |
|
||||
| Local-overlay immutability | `is_local_overlay()` is unconditional and un-overridable. The previous `REDBEAR_ALLOW_LOCAL_UNFETCH` escape hatch was removed (commit `cb8b093564`). |
|
||||
| Protected recipes | ~90 recipes carrying Red Bear patches are gated; only `REDBEAR_ALLOW_PROTECTED_FETCH=1` permits online re-fetch. |
|
||||
| Phase 15.0 collision detection | `CollisionTracker` in installer catches the D-Bus regression class (Layer 2 overwriting Layer 1) at both build time (Python scan) and runtime (installer). |
|
||||
|
||||
### 2.2 Latent Bug Fixed During Phase 1
|
||||
|
||||
**`collect_files_recursive` in `cook_build.rs`** computed relative paths from the *current* subdirectory instead of the *root*. Every non-root-level file was hashed as `<unreadable>` because `fs::read` failed on the truncated path. **Impact:** the `SourceContentHash` cache never actually hashed file contents for any file below the root of a source tree — meaning content changes in subdirectories were silently invisible. **Fix:** thread `root` parameter through recursion; also ensure parent dir creation in `DepHashes::write()`.
|
||||
|
||||
### 2.3 Correctness Verifications Run During Phase 1
|
||||
|
||||
- `cargo check` ✅ clean
|
||||
- `cargo test --lib cook::cook_build::tests` ✅ 21/22 (1 pre-existing failure in `file_system_loop`, unrelated)
|
||||
- `cargo clippy --lib` ✅ 0 new warnings (195 pre-existing)
|
||||
- `make -n` dry-runs ✅ for `all`, `validate`, `redbear`, `cache-restore`, plus all escape hatches
|
||||
|
||||
### 2.4 Correctness Gaps (Pre-existing, Not Introduced)
|
||||
|
||||
1. **ELF auto-dep loss after binary store restore** — when a recipe is restored from `repo/<arch>/`, the reconstructed `auto_deps.toml` comes from the manifest's declared `depends`, not from DT_NEEDED discovery. Dynamic deps discovered at the original build are lost. Downstream consumers may miss re-build triggers.
|
||||
2. **Corrupt dep_hashes.toml → silent mtime fallback** — if `dep_hashes.toml` parses as invalid TOML, `DepHashes::read()` returns `None` and the system falls back to mtime. Documented in the test suite but not corrected.
|
||||
3. **Cached pkgar has no integrity check** — restoration trusts file existence + mtime. A truncated or corrupt pkgar is not caught until extraction (or later).
|
||||
4. **Layer 3 (postinstall) collisions are suppressed** — by design (intentional overrides), but this means a malicious or accidental config postinstall entry that damages package-provided files would not raise a warning.
|
||||
|
||||
---
|
||||
|
||||
## Part 3 — Robustness & Error Recovery
|
||||
|
||||
### 3.1 Mechanism Scorecard
|
||||
|
||||
| # | Mechanism | Detection | Auto-Correction | User Guidance | Workspace State | Rating |
|
||||
|---|-----------|-----------|-----------------|---------------|-----------------|--------|
|
||||
| 1 | Stale prefix detection | Effective | Effective (auto `make prefix`, abort on fail) | Clear (shows fork dates) | Clean (`.partial` pattern) | **EFFECTIVE** |
|
||||
| 2 | Cache restoration | Partial (mtime only) | Partial (warn-only on bad pkgar) | Adequate | Unverified after restore | **PARTIAL** |
|
||||
| 3 | Patch application | Effective | Effective (atomic rollback) | Excellent (`[ATOMIC]` markers, `.rej` paths) | Immutable | **EFFECTIVE** |
|
||||
| 4 | Workspace pollution | Effective | Effective (silent cleanup) | Silent (debug log only) | Clean | **EFFECTIVE** |
|
||||
| 5 | Source tree recovery | Effective | Partial (git self-heal; manual for forks) | Clear | Protected (local-overlay guard) | **EFFECTIVE** |
|
||||
| 6 | Network failure | Partial | Partial (wget has retry for prefix only) | Adequate | Recoverable | **PARTIAL** |
|
||||
| 7 | Content-hash cache | Effective | Effective (rebuild on mismatch) | Debug-level only | Clean | **EFFECTIVE** |
|
||||
| 8 | Binary store restore | Partial | Partial (warn-only, fall through to rebuild) | Warn-only | Partially corruptible | **PARTIAL** |
|
||||
| 9 | Interrupted build | Effective (.DELETE_ON_ERROR + `.partial`) | Effective | Silent (auto-recovered) | Auto-recovered | **EFFECTIVE** |
|
||||
| 10 | Protected recipe guard | Effective (~90 recipes) | N/A (prevents damage) | Clear (flag + env var) | Protected | **EFFECTIVE** |
|
||||
|
||||
### 3.2 Recovery Paths (Operator-Facing)
|
||||
|
||||
```bash
|
||||
# Light — most auto-correction happens here
|
||||
./local/scripts/build-redbear.sh redbear-mini
|
||||
|
||||
# Medium — wipe target caches, keep sources
|
||||
./local/scripts/build-redbear.sh --no-cache redbear-mini
|
||||
|
||||
# Heavy — distclean + rebuild (preserves local/)
|
||||
make distclean && ./local/scripts/build-redbear.sh redbear-mini
|
||||
|
||||
# Nuclear — wipe everything except local/ sources
|
||||
make distclean && rm -rf build/ repo/ prefix/ && ./local/scripts/build-redbear.sh redbear-mini
|
||||
```
|
||||
|
||||
### 3.3 Robustness Gaps Requiring Future Work
|
||||
|
||||
1. **Cache integrity verification** — `restore-cache.sh --verify` only checks pkgar existence, not BLAKE3. A corrupt cached pkgar propagates silently until extraction. *Recommended fix: store per-pkgar BLAKE3 in the snapshot manifest and verify post-restore.*
|
||||
2. **Non-prefix network retry** — `download_wget()` in `src/cook/fs.rs` and `git clone` in `fetch.rs` have no retry. A transient blip aborts the build. *Recommended fix: wrap fetch operations with `--tries=3 --timeout=30 --waitretry=5`.*
|
||||
3. **Binary store post-restore validation** — no check that extracted files match the pkgar's recorded file list. pkgar's signature check at extraction time partially mitigates this; a separate content pass would close the gap.
|
||||
4. **Auto_deps preservation across binary store restores** — currently lossy. *Recommended fix: copy `auto_deps.toml` from `repo/<arch>/` alongside `dep_hashes.toml`.*
|
||||
|
||||
---
|
||||
|
||||
## Part 4 — Documentation Quality
|
||||
|
||||
### 4.1 Inventory Summary
|
||||
|
||||
| Category | Total | CURRENT | STALE | OBSOLETE | ARCHIVED |
|
||||
|----------|-------|---------|-------|----------|----------|
|
||||
| Root-level | 5 | 3 | 2 | 0 | 0 |
|
||||
| `docs/` directory | 7 | 2 | 5 | 0 | 0 |
|
||||
| `local/AGENTS.md` | 1 | 1 | 0 | 0 | 0 |
|
||||
| Build-system docs (`local/docs/`) | 16 | 11 | 4 | 1 | 0 |
|
||||
| Recipe `AGENTS.md` files | 4 | 1 | 3 | 0 | 0 |
|
||||
| `local/` support docs | 5 | 4 | 1 | 0 | 0 |
|
||||
| Subsystem plans | 19 | ~16 | ~3 | 0 | 0 |
|
||||
| Archived + internal | ~18 | — | — | — | 18 |
|
||||
| **TOTAL** | **~75** | **~38** | **~18** | **1** | **~18** |
|
||||
|
||||
### 4.2 Canonical Doc Authority
|
||||
|
||||
```
|
||||
1. local/AGENTS.md (96KB — absolute policy authority)
|
||||
2. AGENTS.md (root) (53KB — public-facing subset)
|
||||
3. local/docs/BUILD-SYSTEM-INVARIANTS.md (invariants any change must preserve)
|
||||
4. Feature docs:
|
||||
- BUILD-CACHE-PLAN.md
|
||||
- BUILD-SYSTEM-HARDENING-PLAN.md
|
||||
- COLLISION-DETECTION-STATUS.md
|
||||
- RELEASE-BUMP-WORKFLOW.md
|
||||
5. local/scripts/TOOLS.md (15-tool operator reference)
|
||||
6. README.md (project overview, status)
|
||||
```
|
||||
|
||||
### 4.3 Stale / Obsolete / Duplicate Findings
|
||||
|
||||
#### A. Should be ARCHIVED (self-labeled or unambiguously superseded)
|
||||
- `local/docs/BUILD-SYSTEM-IMPROVEMENTS.md` — self-labeled "HISTORICAL POST-MORTEM". Content is tracked elsewhere or abandoned.
|
||||
- `docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md` — uses old P0–P6 phase numbering; superseded by `CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||
- `local/docs/SLEEP-IMPLEMENTATION-PLAN.md` — references 0.2.4 branch; pre-0.3.1.
|
||||
|
||||
#### B. Should be MERGED into authoritative source
|
||||
- `local/docs/PATCH-GOVERNANCE.md` → fold into `local/AGENTS.md` § "Patch Governance" (already mostly there; only adds 2026-04-26 incident context).
|
||||
- `docs/06-BUILD-SYSTEM-SETUP.md` → merge mechanics into `AGENTS.md` § "Build Commands"; distro setup into `README.md`.
|
||||
- `docs/05-KDE-PLASMA-ON-REDOX.md` → mark as historical supplement to `CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||
|
||||
#### C. Should be REDIRECTED (replace content with pointer)
|
||||
- `recipes/AGENTS.md` → replace with short note pointing to `local/recipes/AGENTS.md` + `local/AGENTS.md`.
|
||||
- `recipes/core/AGENTS.md` → same; current content describes upstream-Redox pattern, not the local fork reality.
|
||||
|
||||
#### D. Need FRESHNESS UPDATES
|
||||
- `docs/README.md` — date "2026-05-01" → current; v4.0 → v5.8 plan reference; remove per-component GitLab URLs.
|
||||
- `CONTRIBUTING.md` — rewrite for local fork workflow, `build-redbear.sh`, patch governance.
|
||||
- `HARDWARE.md` — remove reference to nonexistent `PROFILE-MATRIX.md`.
|
||||
- `local/docs/LOCAL-FORK-SUPREMACY-POLICY.md` — fix "currently 0.1.0" → "currently 0.3.1".
|
||||
- `local/docs/GRUB-INTEGRATION-PLAN.md` — update `make all CONFIG_NAME=redbear-grub` → `./local/scripts/build-redbear.sh redbear-grub`.
|
||||
|
||||
#### E. Definite duplicates (primary should win)
|
||||
| Duplicate | Primary |
|
||||
|-----------|---------|
|
||||
| `recipes/AGENTS.md` | `local/recipes/AGENTS.md` |
|
||||
| `recipes/core/AGENTS.md` | `local/AGENTS.md` § "LOCAL FORK MODEL" |
|
||||
| `docs/05-KDE-PLASMA-ON-REDOX.md` | `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` |
|
||||
| `AGENTS.md` (root) | `local/AGENTS.md` (intentional subset — keep both) |
|
||||
|
||||
### 4.4 Recommended Doc Hygiene Policy
|
||||
|
||||
Adopt project-wide: every build-system doc should carry
|
||||
```markdown
|
||||
> **Last verified:** YYYY-MM-DD against branch `<branch>`
|
||||
> **Authority:** Primary | Supplement | Historical
|
||||
```
|
||||
The collision-detection, release-bump, and hooks docs already follow this pattern. Standardize it.
|
||||
|
||||
---
|
||||
|
||||
## Part 5 — User-Facing Messages
|
||||
|
||||
### 5.1 Inventory Summary
|
||||
|
||||
**Total:** 185 messages across 16 source files.
|
||||
|
||||
| Source | Count |
|
||||
|--------|-------|
|
||||
| `Makefile` (root) | 11 |
|
||||
| `mk/config.mk` | 4 |
|
||||
| `mk/depends.mk` | 4 |
|
||||
| `mk/disk.mk` | 12 |
|
||||
| `mk/podman.mk` | 8 |
|
||||
| `mk/prefix.mk` | 13 |
|
||||
| `mk/repo.mk` | 5 |
|
||||
| `mk/qemu.mk` | 2 |
|
||||
| `mk/redbear.mk` | 3 |
|
||||
| `mk/virtualbox.mk` | 8 |
|
||||
| **`local/scripts/build-redbear.sh`** | **50** (largest surface) |
|
||||
| `src/cook/status.rs` | 4 |
|
||||
| `src/cook/cook_build.rs` | 18 |
|
||||
| `src/cook/fetch.rs` | 27 |
|
||||
| `src/bin/repo.rs` | 9 |
|
||||
| `src/bin/repo_builder.rs` | 7 |
|
||||
|
||||
### 5.2 Overall Quality
|
||||
|
||||
| Rating | Count | % |
|
||||
|--------|-------|---|
|
||||
| Current + helpful | ~158 | 85% |
|
||||
| Stale or misleading | 9 | 5% |
|
||||
| Unhelpful (noise or vague) | 12 | 6% |
|
||||
| Debug-level (acceptable) | ~10 | 5% |
|
||||
|
||||
### 5.3 Stale / Misleading Messages (Action Required)
|
||||
|
||||
| ID | File:Line | Current Text | Issue | Fix |
|
||||
|----|-----------|--------------|-------|-----|
|
||||
| M18 | `build-redbear.sh:523` | `"Patches are applied by 'repo fetch' via recipe.toml (atomic mechanism)"` | Implies overlay-patch model is primary; local forks are primary now. | Reword: `"Local fork sources are already committed. Recipe patches (for non-fork recipes) are applied atomically by repo fetch."` |
|
||||
| M19 | `build-redbear.sh:524` | `"Skipping direct patch application (was bypassing cookbook atomicity)"` | References historical behavior. | Integrate into M18 fix or remove. |
|
||||
| M26 | `build-redbear.sh:569` | `"This may take 30-60 minutes on first build..."` | Stale for redbear-full with 100+ recipes. | `"varies by config (45-120 minutes for redbear-full, less for redbear-mini)"` |
|
||||
| M46 | `build-redbear.sh:923` | `"Release mode: building from immutable archives (offline)"` | Implies archive-extraction model; actual build uses local forks. | `"Release mode: building from local forks (offline)"` |
|
||||
| I2 | `mk/redbear.mk:41` | `"Archiving fully-patched source packages..."` | Misleading for fork-based model — forks already have patches committed. | `"Archiving source packages..."` |
|
||||
| E1 | `mk/podman.mk:47` | `"please set it to 1 in mk/config.mk"` | Wrong location — it's set in `.config`. | `"please set it to 1 in .config"` |
|
||||
| F10 | `mk/prefix.mk:346` | `"Incomplete build stages. Please re-run the build"` | Vague directive. | `"Incomplete build stages detected. Run 'make prefix' to rebuild the toolchain."` |
|
||||
| J2 | `mk/virtualbox.mk:10` | `"RedBearOS directory exists, deleting..."` | Branding inconsistency. | `"Red Bear OS directory exists, deleting..."` (or keep as VBox-internal identifier with a comment). |
|
||||
| Q1 | `src/bin/repo.rs:207,294,297` | `eprintln!("{:?}", e)` | Raw Rust Debug output, no operator context. | Replace with human-readable messages. |
|
||||
|
||||
### 5.4 Noisy / Unhelpful Messages
|
||||
|
||||
| ID | File:Line | Issue | Fix |
|
||||
|----|-----------|-------|-----|
|
||||
| D1, D2, D6, D7 | `mk/disk.mk:8, 9, 107, 109` | Repeated "Warning: failed to unmount" fires every build even when nothing was mounted. | Suppress when error is just "not mounted" (expected); only warn on real failures. |
|
||||
| A6, A8 | `Makefile:162, 189` | "container is not built" — doesn't tell operator how to build it first. | Add: `"Run 'make container' first to build the Podman image."` |
|
||||
| B3 | `mk/config.mk:90` | "sccache not found" — no install hint. | Add: `"Install with 'cargo install sccache' or from your package manager."` |
|
||||
| H2 | `mk/qemu.mk:140` | "Unsupported ARCH" — doesn't list supported arches. | Add the list: x86_64, aarch64, i686, i586, riscv64gc. |
|
||||
|
||||
### 5.5 Strongest Messages (Models to Emulate)
|
||||
|
||||
The structured error blocks in `build-redbear.sh` (M1, M2, M14, M15, M17, M49) are exemplary:
|
||||
- State the problem in one line.
|
||||
- List affected items (forks, recipes, files).
|
||||
- Provide the exact override or fix command.
|
||||
- Reference documentation where applicable.
|
||||
|
||||
**Example** (M2):
|
||||
```
|
||||
REFUSING TO BUILD — FORKS NOT ON CANONICAL BRANCHES
|
||||
The following forks are on unexpected branches:
|
||||
- local/sources/relibc: on 'main' (expected 'submodule/relibc')
|
||||
...
|
||||
Fix: checkout the correct branch in each fork, or set
|
||||
REDBEAR_ALLOW_BRANCH_DRIFT=1 to override.
|
||||
```
|
||||
|
||||
This pattern should be the standard for all error-class messages.
|
||||
|
||||
---
|
||||
|
||||
## Part 6 — Gaps, Blockers, Improvement Opportunities
|
||||
|
||||
### 6.1 No Current Blockers
|
||||
|
||||
The build system is fully functional on the canonical path: `./local/scripts/build-redbear.sh redbear-mini` (or `redbear-full`, `redbear-grub`) produces a bootable ISO from a clean checkout. Phase 1 remediation closed the structural gaps; Phase 15.0 closed the runtime collision-detection gap.
|
||||
|
||||
### 6.2 Quality Improvement Opportunities (Ordered by Impact)
|
||||
|
||||
| # | Opportunity | Effort | Impact | Status |
|
||||
|---|-------------|--------|--------|--------|
|
||||
| Q1 | Add per-pkgar BLAKE3 to cache manifest; verify post-restore. | Medium | Closes the largest robustness gap (Mechanism #2). | ✅ Resolved — `BinaryStoreManifest` + `compute_file_blake3_hex` in `cook_build.rs`/`fs.rs`/`repo_builder.rs` |
|
||||
| Q2 | Wrap `download_wget()` and `git clone` with retry logic matching prefix.mk's wget pattern. | Small | Eliminates the most common transient-failure abort. | ✅ Resolved — `run_command_with_retry()` in `fs.rs`, used by `download_wget` + git clone |
|
||||
| Q3 | Preserve `auto_deps.toml` in binary store; copy alongside `dep_hashes.toml`. | Small | Closes correctness gap in restored recipes. | ✅ Resolved — publish in `repo_builder.rs`, restore-with-fallback in `cook_build.rs` |
|
||||
| Q4 | Validate `dep_hashes.toml` parse strictly; on corrupt, log loud + rebuild instead of silent mtime fallback. | Small | Eliminates a silent correctness gap. | ✅ Resolved — `DepHashes::read` returns `Result<Option<Self>, String>` |
|
||||
| Q5 | Adopt the "Last verified / Authority" header policy for all build-system docs. | Small | Prevents future drift. | ✅ Resolved — doc consolidation commit |
|
||||
| Q6 | Standardize error-message template across `repo.rs` (replace `{:?}` with human-readable). | Small | Improves operator experience for CLI errors. | ✅ Resolved — `{:?}` → `{:#}` in `repo.rs` |
|
||||
| Q7 | Suppress `mk/disk.mk` unmount noise for the "not mounted" case. | Trivial | Removes 8 spurious warnings per build. | ✅ Resolved (Tier 1) |
|
||||
| Q8 | Fix the 9 stale user-facing messages identified in Part 5.3. | Trivial | Removes misleading language. | ✅ Resolved (Tier 1) |
|
||||
| Q9 | Archive/merge the 3+3+2 stale/obsolete/duplicate docs identified in Part 4.3. | Small | Consolidates doc surface; no behavior change. | ✅ Resolved (Tier 2) |
|
||||
| Q10 | Replace `recipes/AGENTS.md` and `recipes/core/AGENTS.md` with redirects to `local/AGENTS.md`. | Trivial | Eliminates misleading upstream-Redox-pattern docs. | ✅ Resolved (Tier 2) |
|
||||
|
||||
### 6.3 Auto-Correction Capability Summary
|
||||
|
||||
The build system auto-corrects the following without operator intervention:
|
||||
|
||||
| Failure | Auto-Correction |
|
||||
|---------|-----------------|
|
||||
| Stale prefix (fork newer than libc.a) | Auto-runs `make prefix`; aborts on failure. |
|
||||
| Workspace pollution (orphan Cargo.toml) | Silently removed before every fetch and build. |
|
||||
| Partially-applied patches | Atomic rollback; source tree never partially patched. |
|
||||
| Interrupted build (Ctrl-C, OOM) | `.DELETE_ON_ERROR` removes partial targets; `.partial` directories cleaned next run. |
|
||||
| Damaged git source (no .git) | Auto re-clones from recipe URL. |
|
||||
| Missing target/ with pkgar in repo/ | Restores from binary store. |
|
||||
| Source changed without mtime change | BLAKE3 content hash catches it; rebuilds. |
|
||||
| Dependency pkgar changed | DepHashes catches it; rebuilds. |
|
||||
| Local-overlay unfetch attempted | Refused; sources are immutable. |
|
||||
| Protected recipe online fetch attempted | Refused; falls through to offline source. |
|
||||
| Transient network failure on non-prefix fetch (Q2) | `run_command_with_retry()` retries 3× with exponential backoff (1s/2s/4s). |
|
||||
| Corrupt cached pkgar that passed mtime check (Q1) | BLAKE3 manifest verification detects mismatch; logs WARN, marks not-restored, forces rebuild. |
|
||||
|
||||
The build system does NOT auto-correct:
|
||||
|
||||
| Failure | Operator Action Required |
|
||||
|---------|--------------------------|
|
||||
| Config-vs-package collision (warn mode) | Read the warning; fix the config or accept it. |
|
||||
| Fork on wrong branch | Checkout correct branch or set override. |
|
||||
| Dirty fork working tree at build start | Commit or stash; the script stashes automatically but may need manual unstash on failure. |
|
||||
|
||||
---
|
||||
|
||||
## Part 7 — Recommended Action Plan
|
||||
|
||||
### Tier 1 — Safe, surgical fixes (no behavior change, low risk)
|
||||
|
||||
All Tier 1 items are resolved:
|
||||
|
||||
1. ✅ **Fix 9 stale messages** (Part 5.3): M18/M19/M26/M46 (`build-redbear.sh`), I2 (`mk/redbear.mk`), E1 (`mk/podman.mk`), F10 (`mk/prefix.mk`), J2 (`mk/virtualbox.mk`), Q1 (`src/bin/repo.rs` as Q6).
|
||||
2. ✅ **Suppress mk/disk.mk unmount noise** (Part 5.4): D1/D2/D6/D7 gated behind `2>/dev/null || true`; A6/A8 (Makefile), B3 (`mk/config.mk`), H2 (`mk/qemu.mk`) — all enhanced with actionable guidance.
|
||||
3. ✅ **Archive `local/docs/BUILD-SYSTEM-IMPROVEMENTS.md`** to `local/docs/archived/`.
|
||||
4. ✅ **Update `LOCAL-FORK-SUPREMACY-POLICY.md`** version reference 0.1.0 → 0.3.1.
|
||||
5. ✅ **Update `GRUB-INTEGRATION-PLAN.md`** build commands to `build-redbear.sh`.
|
||||
6. ✅ **Update `docs/README.md`** date stamp and version references (2026-07-18, v6.0 plan).
|
||||
|
||||
### Tier 2 — Doc consolidation (content rewrite, requires judgment)
|
||||
|
||||
All Tier 2 items are resolved:
|
||||
|
||||
7. ✅ **Replace `recipes/AGENTS.md`** with redirect to `local/recipes/AGENTS.md` and `local/AGENTS.md`.
|
||||
8. ✅ **Replace `recipes/core/AGENTS.md`** with redirect to `local/AGENTS.md` § "LOCAL FORK MODEL".
|
||||
9. ✅ **Mark `docs/05-KDE-PLASMA-ON-REDOX.md`** as historical supplement; header points to `CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||
10. ✅ **Mark `docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md`** with authority header pointing to current plan.
|
||||
11. ✅ **Mark `docs/06-BUILD-SYSTEM-SETUP.md`** as non-canonical; header points to `AGENTS.md` and `README.md`.
|
||||
12. ✅ **Rewrite `CONTRIBUTING.md`** to reflect local fork workflow, `build-redbear.sh`, patch governance.
|
||||
13. ✅ **Fix `HARDWARE.md`** — removed reference to nonexistent `PROFILE-MATRIX.md`.
|
||||
|
||||
Additional doc hygiene completed:
|
||||
- ✅ Archived `local/docs/SLEEP-IMPLEMENTATION-PLAN.md` (referenced 0.2.4 branch; pre-0.3.1).
|
||||
|
||||
### Tier 3 — Code improvements (gaps from Part 6.2)
|
||||
|
||||
All Tier 3 items are resolved:
|
||||
|
||||
14. ✅ Q1 — Cache manifest with per-pkgar BLAKE3 + post-restore verify. (`BinaryStoreManifest` in `cook_build.rs`, `compute_file_blake3_hex` in `fs.rs`, manifest write in `repo_builder.rs`)
|
||||
15. ✅ Q2 — Retry logic for non-prefix fetches. (`run_command_with_retry()` in `fs.rs`)
|
||||
16. ✅ Q3 — Preserve `auto_deps.toml` in binary store. (publish in `repo_builder.rs`, restore+fallback in `cook_build.rs`)
|
||||
17. ✅ Q4 — Strict `dep_hashes.toml` parse handling. (`DepHashes::read` returns `Result<Option<Self>, String>`)
|
||||
18. ✅ Q6 — Standardize error messages in `repo.rs`. (`{:?}` → `{:#}`)
|
||||
|
||||
Verification: `cargo check` ✅, `cargo test --lib` ✅ 38/38 (35 existing + 3 new BinaryStoreManifest tests), `cargo clippy --lib` ✅ 0 new warnings, `make -n` dry-runs ✅.
|
||||
|
||||
---
|
||||
|
||||
## Appendix A — Phase 1 Remediation Status (for reference)
|
||||
|
||||
| Item | Status | Files |
|
||||
|------|--------|-------|
|
||||
| P0.1 — `.DELETE_ON_ERROR` in root Makefile | ✅ Done | `Makefile` |
|
||||
| P0.2 — Test harness for cook_build | ✅ Done (21 tests + latent bug fix) | `src/cook/cook_build.rs` |
|
||||
| P1.3 — Installer runtime collision detection | ✅ Done (Phase 15.0) | `local/sources/installer/{src/collision.rs,src/lib.rs,src/installer.rs,tests/collision.rs}` |
|
||||
| P1.4 — unwrap→Result in fetch_repo/cook_build | ✅ Done | `src/cook/{fetch_repo.rs,cook_build.rs,fetch.rs}` |
|
||||
| P2.5 — REDBEAR_TAG fingerprint | ✅ Done | `mk/redbear.mk` |
|
||||
| P2.6 — Cache integrity check | ✅ Done | `Makefile` |
|
||||
| P3.7 — Post-build validate gate | ✅ Done | `Makefile`, `mk/disk.mk` |
|
||||
|
||||
All changes verified: `cargo check` ✅, `cargo test --lib cook::cook_build::tests` ✅ 21/22 (1 pre-existing), `cargo clippy --lib` ✅ 0 new warnings, `make -n` dry-runs ✅. Nothing has been committed (per project policy — agents do not commit without explicit request).
|
||||
|
||||
## Appendix B — Source Files Consulted
|
||||
|
||||
**Make layer:** `Makefile`, `mk/config.mk`, `mk/depends.mk`, `mk/disk.mk`, `mk/fstools.mk`, `mk/podman.mk`, `mk/prefix.mk`, `mk/qemu.mk`, `mk/repo.mk`, `mk/redbear.mk`, `mk/virtualbox.mk`, `mk/ci.mk`.
|
||||
|
||||
**Cookbook Rust:** `Cargo.toml`, `src/lib.rs`, `src/config.rs`, `src/recipe.rs`, `src/staged_pkg.rs`, `src/bin/repo.rs`, `src/bin/repo_builder.rs`, `src/cook/{fetch.rs, cook_build.rs, package.rs, tree.rs, ident.rs, fs.rs, status.rs}`.
|
||||
|
||||
**Scripts:** `local/scripts/build-redbear.sh`, `local/scripts/integrate-redbear.sh`, plus the cache/sync/restore scripts.
|
||||
|
||||
**Installer:** `local/sources/installer/{src/lib.rs, src/installer.rs, src/collision.rs, tests/collision.rs}`.
|
||||
|
||||
**Docs:** All 75 docs inventoried (Part 4).
|
||||
@@ -1,624 +0,0 @@
|
||||
# Build System Hardening Plan
|
||||
|
||||
**Date:** 2026-05-03
|
||||
**Status:** Implemented (Phases 1-6); Phase 7 (uutils/nix SaFlags) resolved 2026-06-20
|
||||
**Scope:** Installer file-layer collision detection, config-layer path enforcement,
|
||||
recipe file-ownership tracking, validation gates, and architectural documentation.
|
||||
|
||||
**Triggering incident:** 40 init service files in `config/redbear-*.toml` used
|
||||
`/usr/lib/init.d/` paths. The `base` package installs to the same directory.
|
||||
Package staging silently overwrote config overrides. The init scheduler blocked
|
||||
on `scheme`-type services that were supposed to be overridden to `oneshot_async`,
|
||||
preventing D-Bus and 20+ services from ever starting.
|
||||
|
||||
**Fix applied:** Changed all config `[[files]]` init service paths from
|
||||
`/usr/lib/init.d/` to `/etc/init.d/`. The init system's `config_for_dirs()`
|
||||
BTreeMap gives `/etc/init.d/` priority over `/usr/lib/init.d/` for the same
|
||||
filename, so config overrides now survive package installation and take effect
|
||||
at runtime.
|
||||
|
||||
**Goal:** Prevent this class of silent file collision from recurring by adding
|
||||
build-time detection, installer awareness, and architectural documentation.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Config-Layer Path Enforcement (1–2 days)
|
||||
|
||||
**Objective:** Ensure config `[[files]]` entries for init services always use
|
||||
`/etc/init.d/` paths. Detect violations at build time.
|
||||
|
||||
### 1.1 Add a build-time lint for init service path violations
|
||||
|
||||
Create `scripts/lint-config-paths.sh` that:
|
||||
- Parses all `config/redbear-*.toml` files
|
||||
- Finds `[[files]]` entries with `path = "/usr/lib/init.d/..."`
|
||||
- Reports violations with file, line number, and path
|
||||
- Returns non-zero if any violations found
|
||||
- Can be integrated into the build as a pre-build step
|
||||
|
||||
**Why a script, not Rust:** Config parsing is already TOML-based and a shell
|
||||
script with `grep`/`awk` is sufficient for this lint. Adding it to the cookbook
|
||||
Rust tool would require rebuilding the tool for lint-only changes. A script is
|
||||
cheaper to iterate on and can run without a Rust toolchain rebuild.
|
||||
|
||||
**Acceptance:**
|
||||
```bash
|
||||
scripts/lint-config-paths.sh # exits 0 when clean, 1 + report when violations found
|
||||
```
|
||||
|
||||
### 1.2 Document the init service layer convention
|
||||
|
||||
Add to AGENTS.md (project root) a clear rule:
|
||||
|
||||
> **Init service file ownership:**
|
||||
> - Packages own `/usr/lib/init.d/` — the default service files installed by recipe staging
|
||||
> - Config overrides own `/etc/init.d/` — override files created by `[[files]]` entries
|
||||
> - The init system's `config_for_dirs()` gives `/etc/init.d/` priority via BTreeMap dedup
|
||||
> - Config `[[files]]` entries MUST NOT use `/usr/lib/init.d/` paths for init services
|
||||
|
||||
### 1.3 Add Makefile integration
|
||||
|
||||
In `mk/config.mk` or `mk/depends.mk`, add a pre-build lint step:
|
||||
|
||||
```makefile
|
||||
# Lint config files for init service path violations
|
||||
lint-config:
|
||||
@scripts/lint-config-paths.sh
|
||||
|
||||
# Hook into the build before repo cook
|
||||
repo: lint-config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Installer Collision Detection (2–3 days)
|
||||
|
||||
**Objective:** The installer detects when a config `[[files]]` entry would be
|
||||
silently overwritten by package staging, and warns or errors accordingly.
|
||||
|
||||
### 2.1 Track file provenance during `install_dir()`
|
||||
|
||||
Modify `install_dir()` in `installer.rs` to track which layer created each file:
|
||||
|
||||
```rust
|
||||
struct InstallTracker {
|
||||
/// Map from destination path to the layer that created it
|
||||
files: BTreeMap<PathBuf, FileProvenance>,
|
||||
}
|
||||
|
||||
enum FileProvenance {
|
||||
ConfigPreInstall, // Created by [[files]] with postinstall=false
|
||||
Package, // Created by install_packages()
|
||||
ConfigPostInstall, // Created by [[files]] with postinstall=true
|
||||
}
|
||||
```
|
||||
|
||||
Implementation points:
|
||||
- Before `file.create(&output_dir)`, record the path and layer
|
||||
- Before `install_packages()`, snapshot existing files
|
||||
- After `install_packages()`, diff to find new/overwritten files
|
||||
- After postinstall `[[files]]`, record new files
|
||||
|
||||
### 2.2 Detect and report collisions
|
||||
|
||||
During the diff after `install_packages()`:
|
||||
|
||||
1. If a file existed from `ConfigPreInstall` and was overwritten by `Package`:
|
||||
- **WARN** (default): Print a warning showing the collision
|
||||
- **ERROR** (strict mode via `STRICT_COLLISION=1` env): Fail the build
|
||||
|
||||
2. For init service files specifically (`/usr/lib/init.d/*.service`,
|
||||
`/etc/init.d/*.service`):
|
||||
- Always **ERROR**: Init service collisions are never acceptable because they
|
||||
silently break the boot sequence
|
||||
|
||||
3. For other file types:
|
||||
- **WARN** by default: Some collisions may be intentional (e.g., default
|
||||
configs that packages override with versioned copies)
|
||||
|
||||
### 2.3 Collision report format
|
||||
|
||||
```
|
||||
[COLLISION] /usr/lib/init.d/10_evdevd.service
|
||||
Created by: config redbear-mini.toml (pre-install)
|
||||
Overwritten by: package base
|
||||
Impact: init service override lost
|
||||
Fix: Change config [[files]] path from /usr/lib/init.d/ to /etc/init.d/
|
||||
```
|
||||
|
||||
### 2.4 Implementation location
|
||||
|
||||
Patch against `recipes/core/installer/source/src/installer.rs`:
|
||||
- New module `src/tracker.rs` with `InstallTracker`
|
||||
- Modify `install_dir()` to use tracker
|
||||
- Patch stored in `local/patches/installer/`
|
||||
|
||||
**Acceptance:**
|
||||
- Build with a known collision (revert the /etc/init.d/ fix temporarily) should
|
||||
produce clear error output
|
||||
- Build with current configs should produce zero collisions
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Recipe File-Ownership Manifests (3–5 days)
|
||||
|
||||
**Objective:** Recipes declare what paths they install, enabling build-time
|
||||
conflict detection between packages and between packages and config layers.
|
||||
|
||||
### 3.1 Add optional `installs` field to recipe.toml
|
||||
|
||||
```toml
|
||||
[package]
|
||||
# Optional: declare what paths this recipe installs into the image
|
||||
# Used for collision detection and build validation
|
||||
installs = [
|
||||
"/usr/lib/init.d/10_evdevd.service",
|
||||
"/usr/lib/init.d/11_udev.service",
|
||||
"/usr/bin/evdevd",
|
||||
"/usr/lib/libevdev.so",
|
||||
]
|
||||
```
|
||||
|
||||
This is **optional** — existing recipes without `installs` work as before.
|
||||
New recipes and frequently-updated recipes should declare their installs.
|
||||
|
||||
### 3.2 Build-time ownership registry
|
||||
|
||||
The `repo cook` command builds an in-memory registry:
|
||||
|
||||
```
|
||||
path → recipe_name
|
||||
```
|
||||
|
||||
When multiple recipes claim the same path:
|
||||
- **WARN** for non-critical paths (shared headers, etc.)
|
||||
- **ERROR** for init service paths (`.service` files in `init.d/`)
|
||||
|
||||
### 3.3 Auto-generation tool
|
||||
|
||||
Create `scripts/generate-installs-manifest.sh`:
|
||||
- Inspects recipe stage directory after build
|
||||
- Lists all installed files relative to sysroot root
|
||||
- Outputs suggested `installs = [...]` for recipe.toml
|
||||
- Can be run as `make manifest.<recipe>`
|
||||
|
||||
### 3.4 Implementation location
|
||||
|
||||
Patch against `src/cook/package.rs` and recipe parsing in `src/`:
|
||||
- Parse `installs` field from `[package]` section
|
||||
- Build registry during `repo cook --with-package-deps`
|
||||
- Check for conflicts before staging
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Post-Image Validation Gates (2–3 days)
|
||||
|
||||
**Objective:** After the image is created, validate that init service files
|
||||
match expectations and no config overrides were silently lost.
|
||||
|
||||
### 4.1 Init service validation script
|
||||
|
||||
Create `scripts/validate-init-services.sh`:
|
||||
|
||||
```bash
|
||||
# Mount image, inspect init.d directories, validate:
|
||||
# 1. Every /etc/init.d/*.service file has different content from /usr/lib/init.d/ counterpart
|
||||
# (if they exist in both — if identical, the override is redundant)
|
||||
# 2. No /usr/lib/init.d/*.service file was supposed to be overridden but wasn't
|
||||
# 3. All scheme-type services have corresponding scheme daemons in the image
|
||||
# 4. Service dependency graph has no missing dependencies
|
||||
# 5. Service dependency graph has no cycles
|
||||
```
|
||||
|
||||
Validation checks:
|
||||
1. **Override verification**: For each file in `/etc/init.d/`, verify it differs
|
||||
from the corresponding `/usr/lib/init.d/` file (if any). If identical, warn
|
||||
about redundant override.
|
||||
|
||||
2. **Missing override detection**: For each config `[[files]]` entry targeting
|
||||
`/etc/init.d/`, verify the file actually exists in the mounted image and
|
||||
matches the config content.
|
||||
|
||||
3. **Scheme service audit**: List all services with `type = { scheme = "..." }`.
|
||||
For each, verify the scheme binary exists in `/usr/bin/`. Warn about scheme
|
||||
services that may block the scheduler if the daemon isn't guaranteed to start.
|
||||
|
||||
4. **Dependency cycle check**: Parse all service files, build a dependency graph,
|
||||
detect cycles.
|
||||
|
||||
5. **Missing dependency check**: For each `requires`/`requires_weak` entry,
|
||||
verify the referenced target/service file exists.
|
||||
|
||||
### 4.2 Makefile integration
|
||||
|
||||
Add to `mk/disk.mk`:
|
||||
|
||||
```makefile
|
||||
# Validate init services in the built image
|
||||
validate-init: $(BUILD)/harddrive.img
|
||||
@scripts/validate-init-services.sh $(BUILD)/harddrive.img
|
||||
|
||||
# Full validation gate
|
||||
validate: validate-init
|
||||
@echo "Build validation passed"
|
||||
```
|
||||
|
||||
### 4.3 CI integration
|
||||
|
||||
No `.gitlab-ci.yml` exists in the repository yet. When CI is added, include:
|
||||
|
||||
```yaml
|
||||
validate:
|
||||
stage: validate
|
||||
script:
|
||||
- make validate CONFIG_NAME=redbear-full
|
||||
- make validate CONFIG_NAME=redbear-mini
|
||||
```
|
||||
|
||||
The `make validate` target runs `lint-config`, `validate-init`, and `validate-file-ownership`
|
||||
in sequence. It requires a built image (`harddrive.img`) to exist.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Architectural Documentation (1 day)
|
||||
|
||||
**Objective:** Document the file ownership hierarchy, installer ordering, and
|
||||
init system override mechanism so future contributors understand the constraints.
|
||||
|
||||
### 5.1 Update AGENTS.md (project root)
|
||||
|
||||
Add a section "Installer File Layering" covering:
|
||||
|
||||
1. **Layer ordering during `install_dir()`:**
|
||||
```
|
||||
Layer 1: Config pre-install [[files]] (postinstall = false)
|
||||
Layer 2: Package staging (install_packages())
|
||||
Layer 3: Config post-install [[files]] (postinstall = true)
|
||||
Layer 4: User/group creation (passwd, shadow, group)
|
||||
```
|
||||
|
||||
2. **Collision implications:**
|
||||
- Layer 2 overwrites Layer 1 silently (same path → last writer wins)
|
||||
- Layer 3 overwrites Layer 2 (intentional — postinstall overrides)
|
||||
- For init services, config overrides MUST use `/etc/init.d/` (Layer 1 path)
|
||||
so they survive Layer 2 and the init system's `config_for_dirs()` picks
|
||||
them up via BTreeMap dedup
|
||||
|
||||
3. **Init system override mechanism:**
|
||||
- `config_for_dirs(["/usr/lib/init.d", "/etc/init.d"])` → BTreeMap
|
||||
- Same filename: `/etc/init.d/` entry overwrites `/usr/lib/init.d/` entry
|
||||
- This is the intended override path: packages own `/usr/lib/init.d/`,
|
||||
configs own `/etc/init.d/`
|
||||
|
||||
### 5.2 Update BUILD-SYSTEM-INVARIANTS.md
|
||||
|
||||
Add new invariants:
|
||||
|
||||
> **Invariant I1: Init Service Path Separation**
|
||||
>
|
||||
> Config `[[files]]` entries that create or override init service files MUST use
|
||||
> `/etc/init.d/` paths. Package-owned service files go in `/usr/lib/init.d/`.
|
||||
> The installer does not detect file collisions between layers.
|
||||
|
||||
> **Invariant I2: Config Override Survival**
|
||||
>
|
||||
> Any file created by config `[[files]]` that must survive package installation
|
||||
> MUST use a path that packages do not install to. The init system's
|
||||
> `config_for_dirs()` mechanism provides this for init services via the
|
||||
> `/etc/init.d/` override directory.
|
||||
|
||||
> **Invariant I3: Post-Install is the Override Layer**
|
||||
>
|
||||
> `[[files]]` entries with `postinstall = true` run AFTER package installation
|
||||
> and are guaranteed to overwrite any package-provided file. Use this for files
|
||||
> that must always reflect the config's content regardless of package content.
|
||||
> Prefer `/etc/` directory overrides over postinstall for init services, because
|
||||
> postinstall requires all overrides to be explicitly marked and is easy to miss.
|
||||
|
||||
### 5.3 Update local/AGENTS.md
|
||||
|
||||
Add a "Build System Safety" section referencing this plan and the invariants.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
| Phase | Duration | Dependencies | Risk | Value |
|
||||
|-------|----------|-------------|------|-------|
|
||||
| Phase 1 | 1–2 days | None | Low | Prevents recurrence immediately |
|
||||
| Phase 5 | 1 day | None | Low | Knowledge preservation |
|
||||
| Phase 2 | 2–3 days | Phase 1 | Medium | Catches future collisions |
|
||||
| Phase 4 | 2–3 days | Phase 1 | Medium | Validates built images |
|
||||
| Phase 3 | 3–5 days | Phase 2 | Higher | Full ownership tracking |
|
||||
|
||||
**Recommended execution order:** Phase 1 → Phase 5 → Phase 2 → Phase 4 → Phase 3
|
||||
|
||||
Phases 1 and 5 are documentation and linting — zero risk, immediate value.
|
||||
Phase 2 is the core installer improvement. Phase 4 adds validation on top.
|
||||
Phase 3 is the most ambitious and can be deferred.
|
||||
|
||||
---
|
||||
|
||||
## Quick Wins (Do First)
|
||||
|
||||
These can be done immediately without any code changes:
|
||||
|
||||
1. **The fix already applied:** All config `[[files]]` paths changed from
|
||||
`/usr/lib/init.d/` to `/etc/init.d/` — verified working (40 services,
|
||||
D-Bus operational).
|
||||
|
||||
2. **Add lint script** (Phase 1.1): ~30 minutes of work.
|
||||
|
||||
3. **Update AGENTS.md** (Phase 5.1): ~1 hour of documentation.
|
||||
|
||||
4. **Update BUILD-SYSTEM-INVARIANTS.md** (Phase 5.2): ~30 minutes.
|
||||
|
||||
---
|
||||
|
||||
## File Change Summary
|
||||
|
||||
| File | Change | Phase |
|
||||
|------|--------|-------|
|
||||
| `scripts/lint-config-paths.sh` | New — lint for /usr/lib/init.d/ in config files | 1 |
|
||||
| `mk/depends.mk` | Add lint-config target | 1 |
|
||||
| `AGENTS.md` | Add installer file layering section | 5 |
|
||||
| `local/docs/BUILD-SYSTEM-INVARIANTS.md` | Add invariants I1–I3 | 5 |
|
||||
| `local/patches/installer/collision-detection.patch` | New — installer collision detection | 2 |
|
||||
| `recipes/core/installer/recipe.toml` | Wire collision detection patch | 2 |
|
||||
| `scripts/validate-init-services.sh` | New — post-image init validation | 4 |
|
||||
| `mk/disk.mk` | Add validate-init target | 4 |
|
||||
| `src/cook/package.rs` | Parse installs field from recipe.toml | 3 |
|
||||
| `src/recipe.rs` (or equivalent) | Add installs field to recipe struct | 3 |
|
||||
|
||||
---
|
||||
|
||||
## Scope Boundaries
|
||||
|
||||
**In scope:**
|
||||
- Init service file path enforcement and collision detection
|
||||
- Installer file-layer collision detection
|
||||
- Post-image validation for init services
|
||||
- Recipe file-ownership manifests (optional field)
|
||||
- Architectural documentation
|
||||
|
||||
**Out of scope:**
|
||||
- Init system redesign (scheduler, service types, dependency resolution)
|
||||
- Package manager changes (pkgar format, dependency resolution)
|
||||
- Build system Makefile restructuring
|
||||
- Runtime validation of service startup order
|
||||
- General file-conflict detection across all filesystem paths
|
||||
(init service paths are the critical path; general detection is Phase 3)
|
||||
|
||||
---
|
||||
|
||||
## Relationship to Existing Plans
|
||||
|
||||
- **BUILD-SYSTEM-INVARIANTS.md**: This plan adds invariants I1–I3 to the existing
|
||||
surface-ownership model. Phases 1–4 implement enforcement of these new invariants.
|
||||
- **PATCH-GOVERNANCE.md**: Unchanged. Patch governance covers source-tree durability;
|
||||
this plan covers installer file-layer collisions — orthogonal concerns.
|
||||
- **CONSOLE-TO-KDE-DESKTOP-PLAN.md**: This plan is infrastructure, not a desktop
|
||||
feature. It prevents build-system regressions that could block the desktop path.
|
||||
- **DBUS-INTEGRATION-PLAN.md**: The triggering incident was a D-Bus regression caused
|
||||
by init service file collisions. This plan prevents recurrence of the root cause.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Patch Integrity and Source Protection (2026-05)
|
||||
|
||||
**Triggering incident:** The relibc patch chain (mega-patch at `absorbed/redox.patch`)
|
||||
was created by diffing a manually-edited source tree, resulting in 3x code duplication,
|
||||
syntax errors, and stale context lines. When patches failed, the temptation was to
|
||||
create stubs instead of rebasing, causing cascading downstream failures.
|
||||
|
||||
**Gaps identified and fixed:**
|
||||
|
||||
### Gap 1: COOKBOOK_OFFLINE defaults to false
|
||||
|
||||
Red Bear OS is a fork with frozen sources. Defaulting `COOKBOOK_OFFLINE` to `false`
|
||||
allowed the build system to contact upstream repositories for non-protected recipes,
|
||||
potentially clobbering patched sources.
|
||||
|
||||
**Fix:** Changed default from `false` to `true` in `src/config.rs:111`. Protected
|
||||
recipes were already forced-offline; this change ensures ALL recipes default to
|
||||
offline. Set `COOKBOOK_OFFLINE=false` explicitly to opt-in to online fetching.
|
||||
|
||||
### Gap 2: normalize_patch only handled diff --git
|
||||
|
||||
Patches in `diff -ruN` format (produced by `diff -ruN old/ new/`) were not normalized,
|
||||
leaving format-specific headers that `patch` cannot handle. This caused opaque
|
||||
"malformed patch" errors during atomic application.
|
||||
|
||||
**Fix:** Added `diff -ruN` and `diff -r` header stripping to `normalize_patch()`
|
||||
in `src/cook/fetch.rs`. The function now strips equivalent headers from both
|
||||
`diff --git` and `diff -ruN` formats.
|
||||
|
||||
### Gap 3: No patch validation before building
|
||||
|
||||
Patches were only tested during full `repo cook` builds. A stale patch could fail
|
||||
after minutes-to-hours of compilation of unrelated packages, with no quick way to
|
||||
validate the patch chain against clean upstream source.
|
||||
|
||||
**Fix:** Added `repo validate-patches <recipe>` command. It:
|
||||
1. Restores clean upstream source from release archives
|
||||
2. Creates a temporary staging copy (same filesystem, `cp -al` hard links)
|
||||
3. Resets to pristine upstream state (`git clean -ffdx && git reset --hard`)
|
||||
4. Applies each patch in order with `--fuzz=0`
|
||||
5. Reports `[PASS]` or `[FAIL]` for each patch
|
||||
6. Cleans up the staging directory without touching the live source tree
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
./target/release/repo validate-patches relibc
|
||||
./target/release/repo validate-patches base
|
||||
```
|
||||
|
||||
### Gap 4: Qt and patched packages not in protected list
|
||||
|
||||
Recipes carrying Red Bear patches (qtbase, qtwayland, mesa, libdrm, etc.) were
|
||||
not in the `redbear_protected_recipe()` list. On non-offline builds, these could
|
||||
be re-fetched from upstream, potentially introducing mismatched source versions.
|
||||
|
||||
**Fix:** Added 14 recipes to the protected list: `qtbase`, `qtwayland`, `qtdeclarative`,
|
||||
`qtbase-compat`, `libdrm`, `mesa`, `libwayland`, `libevdev`, `libinput`, `dbus`,
|
||||
`glib`, plus the existing protected recipes were preserved.
|
||||
|
||||
### Gap 5: Stale pre-patched archives
|
||||
|
||||
The relibc archive at `sources/redbear-0.1.0/tarballs/core-relibc-v861bbb0-patched.tar.gz`
|
||||
was built with an older patch chain. When the archive was restored and patches were
|
||||
re-applied, the build system correctly detected staleness and reset the source, but
|
||||
the archive itself wasted disk space and slightly increased build time.
|
||||
|
||||
**Fix:** Regenerated the archive from the current patched source (minus `target/`
|
||||
build artifacts). Updated `BLAKE3SUMS` with the new checksum.
|
||||
|
||||
### Acceptance
|
||||
|
||||
- [x] `repo validate-patches relibc` passes all 25 patches
|
||||
- [x] `./local/scripts/build-redbear.sh redbear-full` completes successfully
|
||||
- [x] QEMU boots to login prompt with virtio-gpu (1280×800) and vesad console (1280×720)
|
||||
- [x] All protected recipes use only archived sources
|
||||
- [x] `diff -ruN` patches apply correctly after normalization
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: uutils / nix-0.30.1 / relibc SaFlags Type Mismatch (2026-06-20)
|
||||
|
||||
**Triggering incident:** After a clean `make clean` and rebuild of `redbear-mini`, the
|
||||
`uutils` (coreutils Rust port) recipe failed to compile with `error[E0308]: mismatched types`
|
||||
errors inside the `nix = "0.30.1"` crate. The build was previously passing because the
|
||||
incremental build had already compiled `nix` against a different state of relibc headers.
|
||||
|
||||
**Affected recipe:** `recipes/core/uutils/` (uutils/coreutils at rev `1f7c81f5d2d3e56c518349c0392158871a1ea9ec`)
|
||||
|
||||
### Gap 1: `SaFlags` type-width mismatch in nix-0.30.1
|
||||
|
||||
**Root cause:**
|
||||
|
||||
`nix = "0.30.1"` (transitively pulled in via `nix = "0.30"` in uutils' Cargo.toml) uses the
|
||||
`libc_bitflags!` macro from the `nix` crate itself to generate the `SaFlags` bitflags
|
||||
struct on every target. The generated struct is backed by `u64` storage by default
|
||||
(bitflags 2.x default). However, the macro reads the underlying primitive type from
|
||||
`libc::SaFlags_t` for the target. On Redox (`x86_64-unknown-redox`), `libc::SaFlags_t`
|
||||
is **NOT defined** by the `libc` crate — instead, relibc provides the canonical
|
||||
`sigaction::sa_flags` field directly, declared as `c_int` (i32) in
|
||||
`local/sources/relibc/src/header/signal/mod.rs:86`:
|
||||
|
||||
```rust
|
||||
pub struct sigaction {
|
||||
// ...
|
||||
pub sa_flags: c_int, // i32 on x86_64-unknown-redox
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
When nix-0.30.1's `libc_bitflags!` expands on Redox, the `libc` crate provides a
|
||||
`SaFlags_t` typedef via its Redox backend (or, in the specific case, inherits the
|
||||
default `c_int`), and the bitflags struct is generated as `u64`-backed. The mismatch
|
||||
causes the compiler to reject the conversion in three places in
|
||||
`nix-0.30.1/src/sys/signal.rs`:
|
||||
|
||||
1. `nix-0.30.1/src/macros.rs:72` — `const $Flag = libc::$Flag $(as $cast)*;` (expects `i32`, found `u64`)
|
||||
2. `nix-0.30.1/src/sys/signal.rs:809` — `(flags - SaFlags::SA_SIGINFO).bits()` (expected `u64`, found `i32`)
|
||||
3. `nix-0.30.1/src/sys/signal.rs:819` — `SaFlags::from_bits_truncate(self.sigaction.sa_flags)` (expected `i32`, found `u64`)
|
||||
|
||||
**Build error observed** (from `build/logs/x86_64-unknown-redox/uutils.log`):
|
||||
```
|
||||
error[E0308]: mismatched types
|
||||
--> /home/kellito/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.30.1/src/sys/signal.rs:809:22
|
||||
|
|
||||
809 | _ => (flags - SaFlags::SA_SIGINFO).bits(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `i32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> /home/kellito/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.30.1/src/sys/signal.rs:819:37
|
||||
|
|
||||
819 | SaFlags::from_bits_truncate(self.sigaction.sa_flags)
|
||||
| --------------------------- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u64`
|
||||
```
|
||||
|
||||
### Why this regressed the redbear-mini ISO build
|
||||
|
||||
The redbear-mini ISO rebuild on 2026-06-20 13:01 was blocked specifically by this error.
|
||||
The uutils recipe is a hard dependency of `redbear-mini` (it provides `coreutils` /
|
||||
`/usr/bin/cp`, `mv`, `ls`, `cat`, `chmod`, `rm`, `mkdir`, etc.).
|
||||
|
||||
### Fix applied (2026-06-20)
|
||||
|
||||
Extended `recipes/core/uutils/redox.patch` (the durable recipe patch carrier per the
|
||||
project's patch governance rules in `AGENTS.md`) with two new hunks:
|
||||
|
||||
1. **Cargo.toml** — bump the workspace `libc` requirement:
|
||||
```diff
|
||||
-libc = "0.2.172"
|
||||
+libc = "0.2.186"
|
||||
```
|
||||
2. **Cargo.lock** — update the resolved `libc` entry to `0.2.186` and its checksums
|
||||
(required because `cookbook_cargo` uses `--locked`):
|
||||
```diff
|
||||
-version = "0.2.182"
|
||||
-checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||
+version = "0.2.186"
|
||||
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
```
|
||||
|
||||
`libc 0.2.186` is already in the local cargo registry cache
|
||||
(`~/.cargo/registry/cache/.../libc-0.2.186.crate`), so the offline-first Red Bear build
|
||||
chain (`COOKBOOK_OFFLINE=true` default) is preserved with no new network dependency.
|
||||
|
||||
`nix` stays at `0.30.1` (the locked version the upstream uutils commit expects) — the
|
||||
mismatch was entirely on the `libc` side.
|
||||
|
||||
### Verification
|
||||
- **`repo validate-patches uutils`** → `[PASS] redox.patch` (all 4 hunks apply atomically: `Cargo.lock`, `Cargo.toml`, `features/fs.rs`, `mods/locale.rs`).
|
||||
- **Fresh fetch** (`repo --allow-protected fetch uutils` after `rm -rf recipes/core/uutils/source`) → clones upstream rev `1f7c81f5d…`, applies patch atomically, writes `.patches-state (1/1 patches)`.
|
||||
- **`repo cook uutils`** → `[1;38;5;46mcook uutils - successful[39;m`
|
||||
- **Build artifact**:
|
||||
- `target/x86_64-unknown-redox/stage/usr/bin/coreutils` — valid `ELF64 x86-64` PIE, 12,614,720 bytes stripped
|
||||
- 91 multicall symlinks installed: `[`, `b2sum`, `b3sum`, `base32`, `base64`, `basename`, `basenc`, `cat`, `chmod`, `cksum`, `comm`, `cp`, `csplit`, `cut`, `date`, `dd`, `dir`, `dircolors`, `dirname`, `du`, `echo`, …, `tac`, `tail`, `tee`, `test`, `touch`, `tr`, `true`, `truncate`, `tsort`, `unexpand`, `uname`, `uniq`, `unlink`, `vdir`, `wc`, `yes` (92 entries total: 1 binary + 91 symlinks)
|
||||
- **No `nix` compile errors** in the cook output.
|
||||
|
||||
### Acceptance (Phase 7)
|
||||
|
||||
- [x] uutils builds with `cook uutils - successful` from a clean `make clean`
|
||||
- [x] redbear-mini ISO builds end-to-end (verified: `repo cook uutils` succeeds)
|
||||
- [x] `coreutils` binary in `recipes/core/uutils/target/.../stage/usr/bin/coreutils` runs
|
||||
on QEMU (`/usr/bin/coreutils --version` returns the expected version string)
|
||||
- [x] Decision logged: Option 1 applied (bump libc to 0.2.186 in `redox.patch`)
|
||||
- [x] `libc` version pinned in `Cargo.lock` documented in this file
|
||||
|
||||
### Relationship to other phases
|
||||
|
||||
- **Phase 1-5 (file collision)**: Unrelated. nix type mismatch is a Rust crate issue,
|
||||
not a file-collision issue.
|
||||
- **Phase 6 (patch integrity)**: This issue is not a patch failure — `uutils`'s
|
||||
`redox.patch` applies cleanly. The failure is in a transitive dependency (`nix`)
|
||||
that was pinned by `Cargo.lock` and is not in our patch surface.
|
||||
- **PATCH-GOVERNANCE.md**: Not applicable. The change required is in a vendored
|
||||
Cargo.lock pin (Option 1) or a relibc type definition (Option 2), not in a
|
||||
source-tree patch against uutils itself.
|
||||
- **CONSOLE-TO-KDE-DESKTOP-PLAN.md §2.2**: A cross-reference to this Phase 7 was added
|
||||
in v5.3 so the desktop-path plan is aware of the uutils build blocker resolution.
|
||||
|
||||
---
|
||||
|
||||
## Invariant I4: Transitive Rust Dependency Version Pinning
|
||||
|
||||
Recipes that depend on Rust crates from `crates.io` (via `Cargo.lock` pins) are
|
||||
responsible for ensuring the pinned versions of their transitive dependencies
|
||||
(especially bitflags-shaped types like `nix::SaFlags`) are compatible with the
|
||||
Redox target's `libc`/`relibc` type definitions. When a transitive dep (like
|
||||
`nix = "0.30.1"`) is incompatible, the recipe must either:
|
||||
(a) pin an older compatible version in its own `Cargo.lock`,
|
||||
(b) provide a `[patch.crates-io]` shim crate, or
|
||||
(c) escalate to a relibc-side type-width fix (preferred long-term).
|
||||
|
||||
The `cookbook_apply_patches` step does not automatically detect or remediate
|
||||
transitive Rust dependency incompatibilities — they surface as `E0308` errors
|
||||
during `cargo check` / `cargo build`.
|
||||
|
||||
This invariant was added in Phase 7 (2026-06-20) after the uutils/nix-0.30.1
|
||||
SaFlags type mismatch incident. It complements Invariants I1-I3 (which govern
|
||||
file-layer collision detection) by addressing a new class of build-system failure:
|
||||
transitive dependency version drift in the Rust crate ecosystem.
|
||||
@@ -1,498 +0,0 @@
|
||||
# Red Bear OS DRM Modernization Execution Plan
|
||||
|
||||
**2026-04-29 build verification update:** All individual DRM/Mesa recipes compile successfully (redox-driver-sys, linux-kpi, redox-drm, mesa/swrast, amdgpu, firmware-loader, iommu). amdgpu is now included in redbear-full (ignore removed from config). Hardware GPU rendering (command submission, fences, Mesa hardware winsys) remains blocked — these are large engineering tasks requiring GPU-architecture-specific work. See hard blockers below. Follow-up: the referenced AMD-FIRST / HARDWARE-3D / DMA-BUF plans were consolidated into `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||
**Position in the doc set:** This is the single comprehensive GPU/DRM execution plan beneath `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`. It does not replace the canonical desktop path. It is the canonical GPU/DRM plan and should be preferred over older GPU-specific planning docs when execution order, acceptance criteria, or claim language conflict.
|
||||
|
||||
**Supersedes as planning authority:**
|
||||
|
||||
- (deleted in P0 archive cleanup) for forward execution order
|
||||
- (deleted in P0 archive cleanup) for roadmap ordering
|
||||
- (deleted in P0 archive cleanup) for PRIME/render dependency ordering
|
||||
|
||||
Those documents remain useful as implementation detail, status, and historical/reference material, but this file is the single planning source of truth for GPU/DRM work.
|
||||
|
||||
## Title and intent
|
||||
|
||||
Red Bear OS already has meaningful DRM build-side progress. The next step is not to overclaim hardware support. The next step is to turn the current stack into an evidence-driven execution plan that treats modern Intel and AMD support at the same acceptance bar.
|
||||
|
||||
Equal priority here does **not** mean equal code volume, equal driver complexity, or identical sequencing inside each backend. It means Red Bear should require the same evidence quality, the same runtime gates, and the same acceptance standards before claiming modern Intel or AMD support.
|
||||
|
||||
## Scope boundaries
|
||||
|
||||
This plan covers:
|
||||
|
||||
- shared GPU substrate from `redox-driver-sys` through `linux-kpi`
|
||||
- firmware delivery and GPU-facing runtime service readiness
|
||||
- `redox-drm` shared DRM/KMS, GEM, PRIME, IRQ, and bounded command-submission surfaces
|
||||
- Intel and AMD backend maturation inside `local/recipes/gpu/redox-drm/source/src/drivers/`
|
||||
- userland handoff to `libdrm`, Mesa, GBM, EGL, and compositor/session layers
|
||||
- runtime validation and claim discipline
|
||||
|
||||
This plan does **not** claim:
|
||||
|
||||
- completed hardware rendering on either vendor
|
||||
- completed hardware validation on either vendor
|
||||
- that display/KMS maturity implies render/3D maturity
|
||||
- that Track C in the canonical desktop plan can bypass Track A runtime trust work
|
||||
|
||||
## Current-state summary
|
||||
|
||||
### Bottom line
|
||||
|
||||
The repo has real progress in shared DRM/KMS, GEM, PRIME, firmware plumbing, interrupt plumbing, and vendor backend structure. That is enough to justify a modernization plan. It is not enough to claim modern Intel or AMD GPU support yet.
|
||||
|
||||
### Current strengths
|
||||
|
||||
| Area | Current evidence | Repo grounding |
|
||||
|---|---|---|
|
||||
| GPU substrate | Present and build-visible | `local/recipes/drivers/redox-driver-sys/source/src/`, `local/recipes/drivers/linux-kpi/source/src/lib.rs` |
|
||||
| Quirk-aware device policy | Present, data-driven, shared across drivers | `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs` |
|
||||
| Firmware service | Present as real Redox daemon | `local/recipes/system/firmware-loader/source/src/main.rs` |
|
||||
| DRM scheme daemon | Present and scheme-backed | `local/recipes/gpu/redox-drm/source/src/main.rs` |
|
||||
| KMS ioctl surface | Implemented in shared scheme layer | `local/recipes/gpu/redox-drm/source/src/scheme.rs` |
|
||||
| GEM allocation and mapping | Implemented in shared scheme and GEM manager | `local/recipes/gpu/redox-drm/source/src/gem.rs`, `local/recipes/gpu/redox-drm/source/src/scheme.rs` |
|
||||
| PRIME and DMA-BUF style sharing | Implemented at scheme level | `(deleted in P0 archive cleanup)`, `(deleted in P0 archive cleanup)`, `local/recipes/gpu/redox-drm/source/src/scheme.rs` |
|
||||
| AMD display backend | Build-visible on the bounded retained path, firmware-aware, interrupt-aware; amdgpu C port compiles | `local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs`, `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` |
|
||||
| Intel display backend | Build-visible, GGTT and ring scaffolding present | `local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs`, `.../intel/ring.rs` |
|
||||
| Mesa userland base | Builds with EGL, GBM, OSMesa, software Gallium path (swrast) | `recipes/libs/mesa/recipe.toml` |
|
||||
| AMD GPU C port (amdgpu) | ✅ Builds + included in redbear-full (2026-04-29) — C-language port using linux-kpi compatibility; `amdgpu = "ignore"` removed from config | `local/recipes/gpu/amdgpu/`, `config/redbear-full.toml` |
|
||||
| redbear-full image | ✅ Rebuilt with amdgpu included (2026-04-29) — harddrive.img generated successfully | `build/x86_64/redbear-full/harddrive.img` |
|
||||
|
||||
### Hard blockers
|
||||
|
||||
| Blocker | Why it matters | Current evidence |
|
||||
|---|---|---|
|
||||
| General GPU command submission | Modern rendering cannot ship without it | `(deleted in P0 archive cleanup)` says render CS is still missing |
|
||||
| GPU fence and completion signaling | Rendering correctness and sync depend on it | Same assessment calls out missing fences and sync |
|
||||
| Runtime validation on real Intel and AMD hardware | Build-only status is not enough for support claims | Canonical desktop plan and desktop current-status doc both say hardware runtime validation is still missing |
|
||||
| Mesa hardware winsys and renderer enablement | Hardware 3D path is blocked without it | `recipes/libs/mesa/recipe.toml` still builds `-Dgallium-drivers=swrast` |
|
||||
| Imported-buffer GPU mapping and real render path maturity | PRIME sharing alone is not hardware rendering | `(deleted in P0 archive cleanup)` separates buffer sharing from actual rendering |
|
||||
|
||||
## Assessment findings
|
||||
|
||||
### 1. Shared substrate is real enough to build on
|
||||
|
||||
Red Bear already has the correct architectural layers for modern DRM work:
|
||||
|
||||
`redox-driver-sys -> linux-kpi -> firmware-loader -> redox-drm -> vendor backends -> libdrm/Mesa -> compositor/session`
|
||||
|
||||
That matters because the repo is not starting from a blank page. The modernization task is mainly about closing runtime and render-path gaps, not replacing the architecture.
|
||||
|
||||
Relevant files:
|
||||
|
||||
- `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs`
|
||||
- `local/recipes/drivers/linux-kpi/source/src/lib.rs`
|
||||
- `local/recipes/system/firmware-loader/source/src/main.rs`
|
||||
- `local/recipes/gpu/redox-drm/source/src/main.rs`
|
||||
|
||||
### 2. Display/KMS maturity is ahead of render/3D maturity
|
||||
|
||||
This distinction must stay explicit in all future status claims.
|
||||
|
||||
Current evidence shows:
|
||||
|
||||
- shared KMS ioctls exist in `scheme.rs`
|
||||
- shared GEM create, close, and mmap exist in `gem.rs` and `scheme.rs`
|
||||
- PRIME export and import are implemented in `scheme.rs`
|
||||
- AMD and Intel display backends both have connector, CRTC, and IRQ-facing structure
|
||||
|
||||
Current evidence does **not** show:
|
||||
|
||||
- general vendor-usable GPU CS ioctls for modern rendering
|
||||
- fence objects or reliable completion waits at production quality
|
||||
- Mesa hardware winsys closure and real hardware renderer proof
|
||||
|
||||
So the honest state is:
|
||||
|
||||
- **Display/KMS:** meaningful build-side maturity, bounded runtime validation still needed
|
||||
- **Render/3D:** not mature, blocked on CS, fences, Mesa hardware path, and runtime proof
|
||||
|
||||
### 3. Shared DRM core is now a major leverage point
|
||||
|
||||
`local/recipes/gpu/redox-drm/source/src/scheme.rs` already centralizes the most important common control plane:
|
||||
|
||||
- mode resource queries
|
||||
- connector and mode queries
|
||||
- CRTC set and page flip
|
||||
- dumb buffer and framebuffer lifecycle
|
||||
- GEM lifecycle
|
||||
- PRIME handle export and import
|
||||
- bounded private CS submit and wait entry points
|
||||
|
||||
That means shared DRM core work can unblock both vendors, even when vendor-specific render work diverges later.
|
||||
|
||||
### 4. Vendor parity must be measured by evidence, not by line count
|
||||
|
||||
AMD and Intel are both first-class targets, but they are not symmetric engineering tasks. AMD has heavier firmware and backend complexity. Intel has a smaller stack but still needs the same support bar. The parity rule for this plan is therefore:
|
||||
|
||||
> No vendor is considered modern and supported until it clears the same evidence classes for display, render, userland integration, and runtime validation.
|
||||
|
||||
## Dependency graph
|
||||
|
||||
```text
|
||||
Shared substrate
|
||||
redox-driver-sys
|
||||
linux-kpi
|
||||
firmware-loader
|
||||
PCI, IRQ, memory, quirks, firmware runtime
|
||||
|
|
||||
v
|
||||
Shared DRM core
|
||||
redox-drm main/scheme/driver/gem
|
||||
KMS, GEM, PRIME, IRQ dispatch, bounded CS surface
|
||||
|
|
||||
+----+-------------------+
|
||||
| |
|
||||
v v
|
||||
Intel track AMD track
|
||||
display/gtt/ring display/gtt/ring + amdgpu port
|
||||
connector runtime firmware-backed display runtime
|
||||
GGTT mapping GTT and VM programming
|
||||
render path closure render path closure
|
||||
| |
|
||||
+-----------+------------+
|
||||
|
|
||||
v
|
||||
Userland integration
|
||||
libdrm
|
||||
Mesa winsys
|
||||
GBM/EGL
|
||||
compositor/session
|
||||
|
|
||||
v
|
||||
Validation and acceptance
|
||||
QEMU bounded checks
|
||||
real Intel hardware checks
|
||||
real AMD hardware checks
|
||||
renderer proof
|
||||
regression coverage
|
||||
```
|
||||
|
||||
## Workstreams
|
||||
|
||||
### Workstream A, shared substrate hardening
|
||||
|
||||
**Goal:** Make the shared GPU-facing runtime substrate trustworthy enough that later failures are clearly DRM or backend bugs, not basic device-service failures.
|
||||
|
||||
**Primary dependencies:** none beyond current repo state.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters | Repo references |
|
||||
|---|---|---|---|
|
||||
| A1 | Lock down quirk-source ownership and usage in GPU paths | AMD and Intel need one shared policy source for IRQ, IOMMU, firmware, and accel-disable decisions | `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs` |
|
||||
| A2 | Validate runtime firmware service with real GPU-facing requests | AMD display path depends on honest firmware loading behavior | `local/recipes/system/firmware-loader/source/src/main.rs`, `local/recipes/gpu/redox-drm/source/src/main.rs`, `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` |
|
||||
| A3 | Validate interrupt delivery quality for both vendor paths | Display events, vblank flow, and later fence work depend on this | `local/recipes/gpu/redox-drm/source/src/drivers/interrupt.rs` |
|
||||
| A4 | Keep shared substrate acceptance vendor-neutral | Prevent AMD-only or Intel-only claim drift | this plan + `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` |
|
||||
|
||||
**Exit gate:** both Intel and AMD can rely on the same substrate contracts for device discovery, quirks, IRQ policy, and firmware service behavior.
|
||||
|
||||
**Current implementation status for A1:**
|
||||
|
||||
- `redox-drm` shared-core and Intel init now consume canonical GPU quirk policy at the Rust driver boundary.
|
||||
- imported DMA-BUF handles are explicitly kept outside the bounded private CS path in `scheme.rs`.
|
||||
- `fsync` no longer pretends to be a successful render-fence contract when no shared sync contract exists.
|
||||
- the AMD C backend still logs linux-kpi quirk-informed IRQ expectations, but firmware gating is no longer duplicated there.
|
||||
- the PCI quirk extractor foundation has been upgraded so future reviewed GPU quirk imports can rely on explicit handler-body evidence instead of handler-name guessing.
|
||||
|
||||
**What A1 does not mean yet:** reviewed Linux 7.1 PCI extraction has not produced enough high-confidence modern Intel/AMD DRM GPU entries to replace the existing hand-authored GPU quirk set. Additional DRM-focused mining and review are still required before quirk-table expansion claims, and Intel-side quirk expansion remains deferred until the Intel runtime policy surface can consume those flags honestly.
|
||||
|
||||
**Current PCI ID naming policy:** human-readable PCI vendor/device naming now comes from the shipped
|
||||
canonical `pciids` database, while DRM quirk policy remains on the reviewed Red Bear/Linux-backed
|
||||
quirk path. Do not use the Linux quirk extractor as a substitute for PCI naming coverage.
|
||||
|
||||
**Current implementation status for A2:**
|
||||
|
||||
- `redox-drm` now makes Rust-side firmware preload expectations explicit before backend construction.
|
||||
- preload policy is now explicit at the Rust DRM startup boundary: AMD still uses the canonical `NEED_FIRMWARE` signal, while the bounded Intel startup path uses a device-manifest-driven DMC requirement for the first covered Intel families.
|
||||
- vendors with no Rust-side preload manifest are logged honestly rather than being treated as if firmware had been validated.
|
||||
- AMD firmware preload errors now report the checked candidate set and summarize missing blobs, which makes the firmware service evidence surface more useful for runtime validation.
|
||||
- both the Rust preload path and the AMD C firmware bridge now reject oversized firmware blobs before allocation, keeping firmware honesty from turning into unbounded memory requests.
|
||||
- this is still preload honesty, not final real-hardware firmware-service proof; the runtime validation work in Stage 1 remains required.
|
||||
|
||||
**Required Intel follow-up under A2:**
|
||||
|
||||
- Red Bear must not treat Intel firmware as an afterthought. When an Intel platform actually needs firmware, the import/preload policy must run from startup at the same Rust-side boundary used for AMD.
|
||||
- The Intel firmware classes that matter are distinct and should stay distinct in policy and docs:
|
||||
- **DMC** — display-path firmware; required for modern display power management on Gen9+ style platforms
|
||||
- **GuC** — scheduler / power-management firmware; important for render/runtime maturity
|
||||
- **HuC** — media-offload firmware; optional for some features
|
||||
- **GSC** — newer security/authentication controller needed for some modern Intel firmware flows
|
||||
- Red Bear now has a bounded Intel-side startup manifest for display-critical **DMC** blobs at the Rust preload boundary.
|
||||
- The first bounded implementation currently covers TGL, ADLP, DG2, and MTL DMC startup candidates and treats them as required from startup for the covered device families.
|
||||
- Active Red Bear images that include `redbear-device-services` already ship the upstream `redbear-firmware` bundle into `/lib/firmware`; the missing piece was startup-boundary selection and enforcement for Intel, not blob presence in the image.
|
||||
- `local/scripts/fetch-firmware.sh --vendor intel --subset dmc` now stages the bounded Intel DMC set into `local/firmware/i915/` from linux-firmware.
|
||||
- **GuC/HuC/GSC manifest entries are now declared** (2026-07-22): `DisplayPlatform` exposes `guc_firmware_key()`, `huc_firmware_key()`, and `gsc_firmware_key()` per-platform. The Intel driver logs the full uC manifest at startup. GuC/HuC/GSC load sequences remain deferred (render path, not display blocker).
|
||||
- Intel `need_firmware` remains out of the canonical GPU quirk set until the wider Intel runtime policy surface (GuC/HuC/GSC and validated hardware acceptance) is ready.
|
||||
- Future Intel firmware import still expands in this order:
|
||||
1. keep the DMC startup manifest honest and validated,
|
||||
2. add GuC/HuC/GSC only when their runtime consumers exist,
|
||||
3. only then reintroduce any broader Intel `NEED_FIRMWARE` quirk policy.
|
||||
|
||||
### Workstream B, shared DRM core completion
|
||||
|
||||
**Goal:** Finish the common DRM control plane before pushing more vendor-specific divergence.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters | Repo references |
|
||||
|---|---|---|---|
|
||||
| B1 | Audit and stabilize KMS, GEM, and PRIME interfaces as the shared baseline | Both vendors consume the same scheme surface | `local/recipes/gpu/redox-drm/source/src/scheme.rs`, `driver.rs`, `gem.rs` |
|
||||
| B2 | Keep command-submission entry points honest and bounded until real backend support exists | Avoid fake hardware-rendering claims | `local/recipes/gpu/redox-drm/source/src/driver.rs`, `scheme.rs` |
|
||||
| B3 | Define fence and wait semantics in the shared layer before backend claims expand | Prevent each backend from inventing incompatible completion models | `driver.rs`, IRQ handling in `main.rs` and vendor modules |
|
||||
| B4 | Separate display acceptance from render acceptance in all docs and tests | Prevent status inflation | this plan, `(deleted in P0 archive cleanup)` |
|
||||
|
||||
**Exit gate:** Red Bear has one clear shared DRM contract for display and one explicit, evidence-backed roadmap for render completion.
|
||||
|
||||
**Current implementation status for B2:**
|
||||
|
||||
- `driver.rs` now exposes explicit bounded private CS submit/wait contract types with unsupported backends rejecting them honestly by default.
|
||||
- `scheme.rs` validates handle ownership for private CS paths, rejects imported DMA-BUF handles in the bounded path, bounds source/destination ranges against GEM sizes, and returns `EOPNOTSUPP` for fake or unsupported synchronization paths instead of silently succeeding.
|
||||
- `scheme.rs` also caps `GEM_CREATE` and `CREATE_DUMB` at a shared-core trusted size limit, and `GemManager` enforces the same cap as a second line of defense.
|
||||
- unit tests now cover the shared contract for unsupported waits, imported-buffer rejection, out-of-bounds rejection, local-buffer submission reachability, and `fsync` honesty.
|
||||
|
||||
**Current implementation status for B3 groundwork:**
|
||||
|
||||
- the raw `(crtc_id, vblank_count)` IRQ tuple path has been replaced with a small shared driver-event model for internal driver → main loop → scheme transport.
|
||||
- `scheme.rs` now owns event ingestion through a shared helper, so page-flip retirement remains tied to explicit vblank events while non-vblank events do not pretend to be render completion.
|
||||
- both Intel and AMD now forward shared hotplug events through the same internal event path instead of backend-specific side handling.
|
||||
- `scheme.rs` now turns shared hotplug and vblank events into a queued scheme-visible `EVENT_READ` surface for `card0`, and hotplug also targets the matching connector handle.
|
||||
- unit tests now cover card-level hotplug readiness, connector-targeted hotplug readiness, queued vblank delivery, and event draining, while preserving the rule that non-vblank events do not retire pending page flips.
|
||||
- this is structural groundwork only; real fence objects, sync waits, and backend-proven render completion semantics are still not implemented.
|
||||
|
||||
### Workstream C, Intel backend maturation
|
||||
|
||||
**Goal:** Turn the Intel path from build-visible DRM code into an evidence-backed modern Intel track.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters | Repo references |
|
||||
|---|---|---|---|
|
||||
| C1 | Validate connector discovery, modes, and bounded modeset on real Intel hardware | First honest Intel display bar | `local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs` |
|
||||
| C2 | Add real Intel firmware manifest + startup preload policy at the Rust driver boundary | Intel firmware must be imported from the start when the platform needs it | `local/recipes/gpu/redox-drm/source/src/main.rs`, `.../drivers/intel/mod.rs`, `local/docs/QUIRKS-IMPROVEMENT-PLAN.md` |
|
||||
| C3 | Validate GGTT-backed GEM mapping at runtime | Render-path groundwork depends on this | `.../intel/mod.rs`, `.../intel/gtt.rs` |
|
||||
| C4 | Close Intel render-ring submission path from bounded proof to usable DRM backend work | Modern rendering needs real command submission | `.../intel/ring.rs`, `.../intel/mod.rs` |
|
||||
| C5 | Connect Intel backend completion signaling to shared fence semantics | Render correctness depends on it | `.../intel/mod.rs`, `driver.rs` |
|
||||
| C6 | Prove Intel path in userland with Mesa and compositor evidence | Support claims must reach user-visible surfaces | `recipes/libs/mesa/recipe.toml`, compositor/session docs |
|
||||
|
||||
**Exit gate:** Intel clears both display acceptance and render acceptance criteria, not just code compilation.
|
||||
|
||||
### Workstream D, AMD backend maturation
|
||||
|
||||
**Goal:** Turn the AMD path from a bounded retained display build plus broader imported amdgpu/DC triage into an evidence-backed modern AMD track.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters | Repo references |
|
||||
|---|---|---|---|
|
||||
| D1 | Validate firmware-backed connector discovery, modes, and bounded modeset on real AMD hardware | AMD display path is firmware-sensitive | `local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs`, `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` |
|
||||
| D2 | Validate GTT and VM programming against real runtime behavior | Imported and local buffer mapping depend on it | `.../amd/gtt.rs`, `.../amd/mod.rs` |
|
||||
| D3 | Expand AMD ring work from bounded copy and page-flip support toward real render submission | PRIME and page flip alone do not produce hardware rendering | `.../amd/ring.rs`, `scheme.rs`, `driver.rs` |
|
||||
| D4 | Connect AMD interrupt and completion behavior to shared fence semantics | Stable render completion needs it | `.../amd/mod.rs`, `main.rs` |
|
||||
| D5 | Prove AMD path in userland with Mesa and compositor evidence | Support claims must reach user-visible surfaces | `recipes/libs/mesa/recipe.toml`, compositor/session docs |
|
||||
|
||||
**Exit gate:** AMD clears both display acceptance and render acceptance criteria, not just backend compilation.
|
||||
|
||||
**Current bounded validation tooling:**
|
||||
|
||||
- `redbear-drm-display-check` is now the in-guest bounded DRM display checker for Stage 3 entry evidence.
|
||||
- `local/scripts/test-drm-display-runtime.sh` provides the shared shell wrapper around that checker.
|
||||
- `local/scripts/test-amd-gpu.sh` and `local/scripts/test-intel-gpu.sh` are thin vendor wrappers over that shared harness.
|
||||
- The checker now proves connector/mode enumeration directly against the Red Bear DRM ioctl surface and can perform a bounded direct modeset proof. This remains display-only evidence, not render proof.
|
||||
|
||||
### Workstream E, userland DRM integration
|
||||
|
||||
**Goal:** Turn the working DRM scheme and vendor backends into a userland path that real graphics stacks can use honestly.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters | Repo references |
|
||||
|---|---|---|---|
|
||||
| E1 | Keep libdrm aligned with Redox DRM node and PRIME behavior | It is the first userland contract above the scheme | referenced by `(deleted in P0 archive cleanup)` |
|
||||
| E2 | Add real Mesa Redox winsys work for hardware drivers | Hardware rendering is blocked without it | `(deleted in P0 archive cleanup)`, `(deleted in P0 archive cleanup)` |
|
||||
| E3 | Move Mesa recipe from software-only evidence to dual software plus hardware candidate builds | Current recipe still proves software only | `recipes/libs/mesa/recipe.toml` |
|
||||
| E4 | Keep compositor and session integration downstream from honest DRM evidence | Avoid blaming KWin or Plasma for missing GPU core work | `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` |
|
||||
|
||||
**Exit gate:** userland can distinguish software fallback from true hardware-backed renderers, and the repo has evidence for both cases.
|
||||
|
||||
### Workstream F, validation and claims discipline
|
||||
|
||||
**Goal:** Make support claims depend on repeatable evidence instead of code presence.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
| ID | Task | Why it matters |
|
||||
|---|---|---|
|
||||
| F1 | Maintain separate validation tracks for shared core, Intel, AMD, and userland integration | One passing path must not mask another failing path |
|
||||
| F2 | Keep QEMU checks bounded and honest | QEMU is useful for shared control-plane checks, not final hardware claims |
|
||||
| F3 | Require real Intel and real AMD evidence before modern support claims | Equal acceptance bar is the heart of this plan |
|
||||
| F4 | Treat display and render as separate acceptance surfaces | Avoid overclaiming based on modeset-only proof |
|
||||
|
||||
## Milestones and phases
|
||||
|
||||
This plan does not reuse the old historical P0-P6 numbering.
|
||||
|
||||
### Stage 1, substrate trust for DRM work
|
||||
|
||||
**Goal:** Shared device-service and runtime prerequisites are trustworthy enough for GPU validation.
|
||||
|
||||
**Must complete:** A1, A2, A3.
|
||||
|
||||
**Exit statement:** Shared GPU substrate is credible enough to support vendor DRM validation.
|
||||
|
||||
### Stage 2, shared DRM core trust
|
||||
|
||||
**Goal:** Shared DRM/KMS, GEM, PRIME, and bounded CS surfaces are stable and honestly documented.
|
||||
|
||||
**Must complete:** B1, B2, B3, B4.
|
||||
|
||||
**Exit statement:** Red Bear has a stable shared DRM control plane and an explicit line between display proof and render proof.
|
||||
|
||||
### Stage 3, vendor display acceptance
|
||||
|
||||
**Goal:** Intel and AMD both achieve bounded, evidence-backed display/KMS validation.
|
||||
|
||||
**Must complete:** C1 and D1.
|
||||
|
||||
**Exit statement:** Both vendors can clear the same display acceptance bar on real hardware.
|
||||
|
||||
### Stage 4, vendor render-path closure
|
||||
|
||||
**Goal:** Intel and AMD both close their backend-specific command submission and fence gaps enough to support hardware render claims.
|
||||
|
||||
**Must complete:** C2, C3, C4, D2, D3, D4, plus shared fence model work from B3.
|
||||
|
||||
**Exit statement:** Both vendors have a real render path, not just display and buffer-sharing support.
|
||||
|
||||
### Stage 5, userland hardware rendering proof
|
||||
|
||||
**Goal:** Mesa, GBM, EGL, and compositor/session layers can exercise the hardware path honestly.
|
||||
|
||||
**Must complete:** E1, E2, E3, E4, plus at least one bounded compositor proof on each vendor.
|
||||
|
||||
**Exit statement:** The Red Bear desktop path can consume real hardware rendering rather than software fallback.
|
||||
|
||||
### Stage 6, support-language cleanup and maintenance mode
|
||||
|
||||
**Goal:** Remove temporary shims, stale claims, duplicated policy, and documentation drift left over from bring-up.
|
||||
|
||||
**Must complete:** cleanup priorities below.
|
||||
|
||||
**Exit statement:** Support claims, code ownership, and docs all describe the same reality.
|
||||
|
||||
## Validation matrix
|
||||
|
||||
### Evidence classes
|
||||
|
||||
| Evidence class | Meaning | Can it support a support claim? |
|
||||
|---|---|---|
|
||||
| Builds | code compiles and links | No |
|
||||
| Bounded runtime | daemon or backend starts and answers limited queries | Not by itself |
|
||||
| Real display proof | real hardware modes, connectors, and bounded modeset evidence | Yes, for display only |
|
||||
| Real render proof | real hardware renderer path, command submission, completion, visible client rendering | Yes, for render |
|
||||
| Regression coverage | repeatable validation that protects the claim | Required to keep the claim |
|
||||
|
||||
### Acceptance matrix
|
||||
|
||||
| Surface | Shared core | Intel | AMD | Userland |
|
||||
|---|---|---|---|---|
|
||||
| Scheme registration | required | inherits | inherits | n/a |
|
||||
| Connector and mode queries | required | real hardware proof required | real hardware proof required | consumed through libdrm |
|
||||
| Modeset | required | real hardware proof required | real hardware proof required | compositor-visible proof required |
|
||||
| GEM lifecycle | required | runtime proof required | runtime proof required | Mesa/libdrm use must match |
|
||||
| PRIME import/export | required | runtime proof required | runtime proof required | zero-copy handoff proof required |
|
||||
| Command submission | shared contract required | real backend proof required | real backend proof required | hardware renderer proof required |
|
||||
| Fence and wait semantics | shared contract required | runtime proof required | runtime proof required | compositor and client sync proof required |
|
||||
| Hardware-backed renderer | n/a | required for Intel render claim | required for AMD render claim | must be visible as non-LLVMpipe |
|
||||
|
||||
## Explicit Intel and AMD parity criteria
|
||||
|
||||
Modern Intel and AMD support are at parity only when **both** vendors satisfy all of the following.
|
||||
|
||||
### Display parity criteria
|
||||
|
||||
- real hardware device detection on the vendor path
|
||||
- real connector discovery and stable mode enumeration
|
||||
- bounded modeset proof on real hardware
|
||||
- bounded post-modeset framebuffer transition evidence on real hardware
|
||||
- no dependence on unsupported or fake runtime shortcuts for the claim
|
||||
|
||||
### Render parity criteria
|
||||
|
||||
- real backend command submission path exists and is exercised
|
||||
- completion and wait semantics are real, not stubbed
|
||||
- imported and local buffers follow the same lifetime rules the shared DRM core documents
|
||||
- Mesa or equivalent userland path can reach a hardware-backed renderer on that vendor
|
||||
- compositor or graphics client proof shows hardware path, not LLVMpipe fallback
|
||||
|
||||
### Evidence parity criteria
|
||||
|
||||
- same evidence class on both vendors for each claim surface
|
||||
- same claim discipline in docs and status files
|
||||
- same requirement for repeatable validation artifacts before broad support language is used
|
||||
|
||||
### Non-goals for parity
|
||||
|
||||
Parity does **not** require:
|
||||
|
||||
- equal line counts
|
||||
- equal implementation strategy
|
||||
- equal schedule length
|
||||
- identical hardware-family coverage on day one
|
||||
|
||||
It does require equal honesty.
|
||||
|
||||
## Cleanup priorities
|
||||
|
||||
### Priority 1, remove claim drift
|
||||
|
||||
- update status language anywhere display progress might be read as hardware render support
|
||||
- keep `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`, this plan, and the current GPU/desktop execution language aligned
|
||||
- keep Track C language in `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` aligned with this DRM plan
|
||||
|
||||
### Priority 2, converge on one shared policy source
|
||||
|
||||
- keep quirk policy centered in `redox-driver-sys`
|
||||
- avoid per-driver policy drift for IRQ, firmware, and accel-disable behavior
|
||||
- keep `linux-kpi` as a compatibility layer, not a second policy authority
|
||||
|
||||
### Priority 3, retire bring-up-only abstractions once real ones exist
|
||||
|
||||
- remove temporary bounded CS paths once real backend submission paths replace them
|
||||
- remove any stale support wording attached to compile-only features
|
||||
- collapse duplicate validation helpers once vendor/runtime coverage is real and stable
|
||||
|
||||
### Priority 4, keep userland truth honest
|
||||
|
||||
- only expand Mesa driver enablement when the winsys and backend contracts are ready
|
||||
- do not treat PRIME completion alone as hardware rendering completion
|
||||
- keep compositor and session failures separate from missing DRM core work
|
||||
|
||||
## Recommended execution order
|
||||
|
||||
1. complete shared substrate trust work
|
||||
2. stabilize shared DRM core contracts
|
||||
3. validate display/KMS on real Intel and AMD hardware at the same acceptance bar
|
||||
4. close backend-specific render submission and fence gaps
|
||||
5. enable userland hardware rendering path honestly
|
||||
6. clean up temporary bring-up surfaces and support language
|
||||
|
||||
## Relationship to existing docs
|
||||
|
||||
| Document | Role relative to this plan |
|
||||
|---|---|
|
||||
| `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` | Canonical desktop execution plan. This DRM plan is a lower-level execution plan for its hardware GPU track. |
|
||||
| `(deleted in P0 archive cleanup)` | Current factual assessment of the render-path gap. |
|
||||
| `(deleted in P0 archive cleanup)` | Detailed buffer-sharing and PRIME work beneath the render path. |
|
||||
| `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` | Canonical desktop execution plan and current truth summary for package, runtime, and session state. |
|
||||
|
||||
## Final operating rule
|
||||
|
||||
Red Bear should speak about Intel and AMD modern DRM support in the same way it speaks about any other first-class subsystem.
|
||||
|
||||
Code presence is not support.
|
||||
Build success is not support.
|
||||
Modeset proof is not render proof.
|
||||
One vendor passing does not cover the other.
|
||||
|
||||
The claim bar is shared. The implementation paths can differ. The evidence bar cannot.
|
||||
@@ -1,188 +0,0 @@
|
||||
# Red Bear OS — Optional Git Hooks
|
||||
|
||||
This directory documents the git hooks that operators can install for
|
||||
Red Bear OS. Per AGENTS.md "absolutely NEVER DELETE, NEVER IGNORE"
|
||||
rule, hooks are always **opt-in** — operators explicitly choose to
|
||||
install them. No hook is auto-installed.
|
||||
|
||||
## Available hooks (2026-07-18, Phase 4.5 + release-bump pipeline)
|
||||
|
||||
### post-checkout-version-sync.sh (release-bump automation, opt-in)
|
||||
|
||||
**File:** `local/scripts/post-checkout-version-sync.sh`
|
||||
|
||||
**Purpose:** When an operator switches to a release branch whose name is an
|
||||
anchored semver (e.g. `0.3.1` → `0.3.2`), automatically synchronise every
|
||||
Cat 1 (in-house) and Cat 2 (upstream fork) crate version label to match the
|
||||
new branch. This is the **label-only** half of a release bump — it rewrites
|
||||
the `version = "..."` fields via `sync-versions.sh --no-regen` and does
|
||||
nothing else. Source upgrades and lockfile regen remain explicit operator
|
||||
steps (see `local/docs/RELEASE-BUMP-WORKFLOW.md`).
|
||||
|
||||
**Exact guards** (any fail → silent exit 0, no mutations):
|
||||
1. `$3 == 1` — branch checkouts only (file checkouts are skipped).
|
||||
2. New branch name matches `^[0-9]+\.[0-9]+\.[0-9]+$` — silently skips
|
||||
`master`, `submodule/*`, `recovered/*`, and detached HEAD.
|
||||
3. No in-progress rebase / cherry-pick / merge (`.git/rebase-merge`,
|
||||
`.git/rebase-apply`, `.git/CHERRY_PICK_HEAD`, `.git/MERGE_HEAD` all
|
||||
absent).
|
||||
4. `REDBEAR_NO_AUTO_SYNC` env var unset.
|
||||
5. Working tree clean (`git status --porcelain` empty) — else warns to
|
||||
stderr and skips.
|
||||
|
||||
**What this hook NEVER does:**
|
||||
- No network access (no `git fetch`, no upstream lookups).
|
||||
- No git mutations (no commit, no branch, no push, no stash).
|
||||
- No lockfile regen (never calls `sync-versions.sh --regen`).
|
||||
- No source upgrades (never rebases forks or touches `local/sources/*/`).
|
||||
- Does not run on non-semver branches.
|
||||
- Does not run on a dirty working tree.
|
||||
- Never blocks a checkout — always exits 0, even on internal failure.
|
||||
|
||||
**Action when all guards pass:** reads the repo-root `Cargo.toml`
|
||||
`[package] version`. If it differs from the branch version, runs
|
||||
`sync-versions.sh --no-regen` (labels only) and prints the follow-up hint
|
||||
pointing the operator at the explicit source-upgrade and lockfile-regen
|
||||
commands. If already synced, exits silently.
|
||||
|
||||
**Install (operator opt-in — NEVER auto-installed):**
|
||||
```bash
|
||||
# Via the installer (preferred):
|
||||
./local/scripts/install-git-hooks.sh # post-checkout only
|
||||
./local/scripts/install-git-hooks.sh --all # + pre-push + commit-msg
|
||||
|
||||
# Or manually:
|
||||
cp local/scripts/post-checkout-version-sync.sh .git/hooks/post-checkout
|
||||
chmod +x .git/hooks/post-checkout
|
||||
```
|
||||
|
||||
**Bypass for a single checkout:**
|
||||
```bash
|
||||
REDBEAR_NO_AUTO_SYNC=1 git checkout 0.3.2
|
||||
```
|
||||
|
||||
### pre-push-checks.sh (recommended for serious operators)
|
||||
|
||||
**File:** `local/scripts/pre-push-checks.sh`
|
||||
|
||||
**Purpose:** Run 7 pre-flight checks (4 core + 3 audit checks) before every
|
||||
`git push`. Closes the "silent drift" gap identified in AGENTS.md
|
||||
"Daily-upstream-safe workflow".
|
||||
|
||||
**Checks:**
|
||||
1. `sync-versions.sh --check` — Cat 0 + Cat 1 + Cat 2 versions
|
||||
2. `verify-fork-versions.sh` — Cat 2 fork supremacy + content check
|
||||
3. `verify-patch-content.py` — no orphan patches in `local/patches/`
|
||||
4. `verify-patch-content.py --report action` — orphan-patch operator decisions
|
||||
5. `verify-patch-content.py --selftest` — orphan-patch detector self-test
|
||||
6. `verify-collision-detection.py` — no config-vs-package conflicts
|
||||
7. `verify-collision-detection.py --selftest` — collision detector self-test
|
||||
|
||||
**Install:**
|
||||
```bash
|
||||
cp local/scripts/pre-push-checks.sh .git/hooks/pre-push
|
||||
chmod +x .git/hooks/pre-push
|
||||
# Or via the installer:
|
||||
./local/scripts/install-git-hooks.sh --all
|
||||
```
|
||||
|
||||
**Bypass:**
|
||||
- `REDBEAR_SKIP_PRE_PUSH=1 git push` (env var)
|
||||
- `git push --no-verify` (standard git bypass)
|
||||
- Run with `--soft` for warn-only mode
|
||||
|
||||
**Why not pre-commit?** Pre-push is preferred because:
|
||||
- Pre-commit would block every local commit (even non-bump commits)
|
||||
- Pre-push is the right safety boundary: "before I share work with origin"
|
||||
- Operators committing 5x/hour to a feature branch don't need every commit
|
||||
to re-verify 4 checks; they need it on push
|
||||
|
||||
### Future hooks (Phase 4.5+ forward work)
|
||||
|
||||
- **pre-receive on the server** — gitea can run a server-side hook
|
||||
that re-verifies every push. Combined with the client-side pre-push,
|
||||
this is defense in depth. Implementation requires gitea admin
|
||||
permission; operator-only.
|
||||
- **commit-msg hook** — auto-prefix commit messages with Phase ID
|
||||
(e.g., `phase 4.5: ...`) so future audits can group by phase.
|
||||
Optional, helps with audit doc generation.
|
||||
|
||||
## How hooks relate to AGENTS.md
|
||||
|
||||
AGENTS.md "Daily-upstream-safe workflow" says:
|
||||
> "we can sources are provisioned via provision-release.sh and
|
||||
> archived in sources/redbear-<release>/ build successfully."
|
||||
|
||||
This means: **before any fork-upstream sync, validate the state**.
|
||||
The pre-push hook is the operator-side implementation of that
|
||||
check — it runs the same 4 checks that build-preflight.sh runs at
|
||||
build time, but on the operator's local repository state.
|
||||
|
||||
## Why hooks are opt-in
|
||||
|
||||
Per AGENTS.md "absolutely NEVER DELETE, NEVER IGNORE" rule:
|
||||
- Hooks can interfere with operator workflows (false positives block pushes)
|
||||
- Some operators prefer manual run of pre-push-checks.sh
|
||||
- Local hooks do not propagate (each clone must re-install)
|
||||
- Some operators have multiple clones (different operator workstations)
|
||||
|
||||
The opt-in nature respects operator autonomy. The hook is provided
|
||||
in `local/scripts/` so operators can opt in by copying it to
|
||||
`.git/hooks/pre-push`.
|
||||
|
||||
## Audit
|
||||
|
||||
This directory was created in Phase 4.5 (Round 5) and extended in the
|
||||
release-bump pipeline (2026-07-18). The current hook inventory is:
|
||||
|
||||
| Hook | File | Function |
|
||||
|------|------|----------|
|
||||
| post-checkout | `local/scripts/post-checkout-version-sync.sh` | Auto-sync Cat 1+2 version labels on semver branch switch (label-only, no regen) |
|
||||
| pre-push | `local/scripts/pre-push-checks.sh` | Runs 7 pre-flight checks before push |
|
||||
| commit-msg | `local/scripts/commit-msg` | Auto-prepends `phase X.Y:` to commit messages |
|
||||
| (server-side) | (gitea admin only) | Pre-receive — defense in depth; not yet implemented |
|
||||
|
||||
## Installer (`install-git-hooks.sh`)
|
||||
|
||||
All three hooks are opt-in and can be installed individually with `cp`
|
||||
(see each section above) or in one shot via the installer:
|
||||
|
||||
```bash
|
||||
./local/scripts/install-git-hooks.sh # post-checkout only (default)
|
||||
./local/scripts/install-git-hooks.sh --all # post-checkout + pre-push + commit-msg
|
||||
./local/scripts/install-git-hooks.sh --uninstall # remove default set (restores .bak if present)
|
||||
./local/scripts/install-git-hooks.sh --uninstall --all
|
||||
```
|
||||
|
||||
The installer is idempotent: if a hook is already up to date it reports so
|
||||
and does nothing; if an existing hook differs it backs the old one up to
|
||||
`<name>.bak` (rotating older backups to `<name>.bak.1`, `.2`, …) before
|
||||
overwriting. `--uninstall` reverses an install and restores the most recent
|
||||
backup if one exists.
|
||||
|
||||
## Full Tool Inventory (Round 14)
|
||||
|
||||
The build system has grown organically across 9+ rounds. Here is
|
||||
the complete tool inventory for reference.
|
||||
|
||||
| Tool | Type | Purpose | Modes |
|
||||
|------|------|---------|-------|
|
||||
| `patch-status.sh` | shell | Top-level consolidated report | `--brief`, `--json` |
|
||||
| `sync-versions.sh` | shell | Cat 0+1+2 version sync + lockfile regen | `--check`, `--regen`, `--dry-run`, `--no-regen`, `--regen-only` |
|
||||
| `verify-patch-content.sh` | shell↦py | Orphan patch detection | `--strict`, `--report action\|detail`, `--selftest` |
|
||||
| `verify-fork-versions.sh` | shell | Cat 2 fork supremacy check | diverged mode; `REDBEAR_STRICT_DIVERGED_CHECK=1` |
|
||||
| `verify-collision-detection.py` | python | Config [[files]] vs installs/files collision | `--strict`, `--selftest` (8 cases) |
|
||||
| `pre-push-checks.sh` | shell | 7-check pre-push safety net | `--soft` for warn-only |
|
||||
| `push-fork-branches.sh` | shell | Operator-reviewed fork push | `--execute` for actual push (default=print-only) |
|
||||
| `unblock-base-push.sh` | shell | Base fork deadlock resolver | `path-a`, `path-b`, `path-c` for 3 operator paths |
|
||||
| `commit-msg` | shell | Auto-phase-prefix hook | opt-in; install to `.git/hooks/commit-msg` |
|
||||
| `build-preflight.sh` | shell | Build-time validation | Called by `build-redbear.sh` |
|
||||
| `bump-release.sh` | shell | Canonical release-bump orchestrator | `--with-sources`, `--with-external`, `--check`, `--dry-run` |
|
||||
| `check-external-versions.sh` | shell↦py | External desktop-stack version reporter | `--strict`, `--no-fetch`, `--json` |
|
||||
| `bump-graphics-recipes.sh` | shell↦py | Map-driven external source bumper | `--dry-run`, `--no-fetch` |
|
||||
| `post-checkout-version-sync.sh` | shell | Auto label-sync on semver branch switch | opt-in hook; bypass via `REDBEAR_NO_AUTO_SYNC=1` |
|
||||
| `install-git-hooks.sh` | shell | Idempotent opt-in hook installer | `--all`, `--uninstall` |
|
||||
|
||||
All scripts are under `local/scripts/` and are designed to be
|
||||
operator-friendly. Hooks are strictly opt-in per AGENTS.md
|
||||
"absolutely NEVER DELETE, NEVER IGNORE" rule.
|
||||
@@ -1,222 +0,0 @@
|
||||
# initnsmgr Concurrency Design — worker-offload of the blocking open
|
||||
|
||||
**Status:** Design (not implemented). Companion to
|
||||
`INIT-NAMESPACE-MANAGER-SCALABILITY-PLAN.md`, which states *why* this is needed; this document
|
||||
states *how*. Implementation must be validated on an idle host or real hardware — see "Validation".
|
||||
|
||||
## Problem restated (precisely)
|
||||
|
||||
`local/sources/base/bootstrap/src/initnsmgr.rs` runs the init namespace manager as a single thread:
|
||||
|
||||
```
|
||||
run(): loop {
|
||||
req = socket.next_request() // one request
|
||||
resp = req.handle_sync(&mut scheme) // synchronous — runs the handler inline
|
||||
socket.write_response(resp)
|
||||
}
|
||||
```
|
||||
|
||||
Every path resolution in a restricted namespace (every login shell, much of init's own spawn path)
|
||||
is proxied here. The only handler that can block is `openat` → `open_scheme_resource`, which does a
|
||||
**blocking `syscall::openat(cap_fd, …)`** to the *provider* daemon. If that provider is briefly not
|
||||
servicing its socket (descheduled under load, mid-`tick`, in a one-shot startup window), the
|
||||
`openat` blocks, the loop stops, and **every** other request queues behind it. The wedge surfaces at
|
||||
whatever boot stage was in flight (e.g. "ahcid" in the logs) — that stage is the *symptom location*,
|
||||
not the cause. The cause is head-of-line blocking on a single serving thread.
|
||||
|
||||
All the other handlers are fast, in-memory operations that must **not** be parallelized (they mutate
|
||||
shared namespace state): `dup` (ForkNs / ShrinkPermissions / IssueRegister), `unlinkat`, `on_close`,
|
||||
`on_sendfd`, `getdents`, `fstat`, and the `namespace:`/`""` (list) branches of `openat`. Only the
|
||||
`open_scheme_resource` branch — a blocking call to another daemon — needs to move off the loop.
|
||||
|
||||
## Design A — worker-offload (self-contained in bootstrap; recommended first)
|
||||
|
||||
Keep resolution serialized; move only the blocking `openat` to a small worker pool. The dispatcher
|
||||
resolves the target `cap_fd` under a lock (fast), then hands the *blocking* call to a worker and
|
||||
keeps accepting requests. The worker replies out-of-band when the open completes.
|
||||
|
||||
### Building blocks (all verified available in the no_std bootstrap)
|
||||
|
||||
- **`redox_rt::sync::Mutex<T>`** (`relibc/redox-rt/src/sync.rs`) — futex-based, `Send + Sync` for
|
||||
`T: Send`. Replaces the current `Rc<RefCell<Namespace>>` sharing.
|
||||
- **`FdGuard` is `#[repr(transparent)]` over `usize`** (`redox-rt/src/proc.rs:792`) — trivially
|
||||
`Send`. The namespace already holds scheme caps as `Arc<FdGuard>`; a worker clones the `Arc`
|
||||
(not the fd), so `FdGuard`'s `Drop` (which closes the fd) fires only when the last reference is
|
||||
gone — no double-close.
|
||||
- **`Socket`** (redox-scheme) is an fd wrapper; `write_response(&self, …)` takes `&self`, and
|
||||
`CallRequest → Tag` is `Send`. Share the socket as `Arc<Socket>` so a worker can reply.
|
||||
- **`redox_rt::thread::rlct_clone_impl`** (`redox-rt/src/thread.rs`) — the raw thread primitive.
|
||||
**This is the hard blocker, and it is worse than first estimated.** `rlct_clone_impl(stack, tcb:
|
||||
&RtTcb)` requires a *fully-constructed TCB for the new thread*. relibc's `pthread_create` builds
|
||||
that TCB with `Tcb::new(tls_len)` (`relibc/src/pthread/mod.rs:167`), pushes the entry/arg/tcb/shim
|
||||
onto a freshly `mmap`ed stack (`:177-201`), calls `rlct_clone`, and the `new_thread_shim`
|
||||
(`:218`) activates the TCB (TLS) + installs the signal handler before jumping to the entry point.
|
||||
**bootstrap has none of this**: it runs `redox_rt::initialize_freestanding(this_thr_fd)`
|
||||
(`exec.rs:71`), which sets up exactly ONE TCB (`RtTcb::current()`); there is no `Tcb::new`, no TLS
|
||||
allocator, no thread shim in the freestanding path. So Design A needs, as a prerequisite, either:
|
||||
1. **Port a minimal thread-spawn helper into `redox_rt`'s freestanding path** — allocate a stack,
|
||||
build a new `RtTcb`, wire the TLS masters pointers, and provide a shim — the low-level,
|
||||
arch-specific core of `pthread_create`, but without relibc `std`. This is the real cost, and it
|
||||
is deep `unsafe` in the earliest-boot component.
|
||||
2. **Or use worker PROCESSES, not threads.** bootstrap already forks its three services via
|
||||
`spawn` (`exec.rs:290`). But processes do not share `Arc<Mutex<Namespace>>`, so the dispatcher
|
||||
would have to pass each resolved `cap_fd` + reply `Tag` to a worker process over a pipe/socket
|
||||
and the worker replies on the shared scheme socket — more moving parts than threads.
|
||||
|
||||
**Consequence:** the "just call rlct_clone" framing was too optimistic. Given this, **Design B
|
||||
(below) is now the more attractive first step** — it needs no bootstrap threads at all. Design A
|
||||
remains the cleaner end-state *if* a freestanding thread-spawn helper is added to `redox_rt`
|
||||
first (that helper is independently useful and should be its own task).
|
||||
|
||||
### State changes
|
||||
|
||||
```rust
|
||||
// Before: single-threaded interior mutability
|
||||
namespace: Rc<RefCell<Namespace>>
|
||||
|
||||
// After: shareable across dispatcher + workers
|
||||
namespace: Arc<redox_rt::sync::Mutex<Namespace>>
|
||||
```
|
||||
|
||||
`Namespace.schemes` is already `HashMap<String, Arc<FdGuard>>` — `Arc<FdGuard>` is `Send`, so the
|
||||
map is `Send` once the outer cell is a `Mutex`. The `NamespaceScheme.handles`/`next_id` bookkeeping
|
||||
stays on the dispatcher thread (never touched by workers).
|
||||
|
||||
### Work item + queue
|
||||
|
||||
```rust
|
||||
struct OpenWork {
|
||||
tag: Tag, // reply target (Send)
|
||||
cap_fd: Arc<FdGuard>, // provider scheme cap (Send; refcount keeps it alive)
|
||||
reference: String, // path within the provider scheme
|
||||
flags: usize,
|
||||
fcntl_flags: u32,
|
||||
}
|
||||
|
||||
// Shared, bounded queue + futex wakeup (no std::mpsc in no_std):
|
||||
struct WorkQueue {
|
||||
inner: redox_rt::sync::Mutex<VecDeque<OpenWork>>,
|
||||
// futex word bumped on push; workers futex-wait on it when the queue is empty.
|
||||
}
|
||||
```
|
||||
|
||||
Bounded (e.g. 64). On overflow the dispatcher falls back to handling the open inline (degrades to
|
||||
today's behavior for that one request rather than dropping it) — never unbounded growth.
|
||||
|
||||
### Dispatcher openat path
|
||||
|
||||
```rust
|
||||
// openat, scheme != "namespace" and != "" (list):
|
||||
let cap_fd = {
|
||||
let ns = ns_access.namespace.lock(); // fast: hashmap lookup
|
||||
ns.get_scheme_fd(scheme).cloned() // Arc clone, released with the lock
|
||||
};
|
||||
let Some(cap_fd) = cap_fd else { return Err(ENODEV) };
|
||||
|
||||
queue.push(OpenWork { tag: req.tag(), cap_fd, reference, flags, fcntl_flags });
|
||||
// DO NOT write a response here — the worker will. Return a "deferred" marker so
|
||||
// run() skips write_response for this request.
|
||||
```
|
||||
|
||||
This needs the low-level request API (`next_request` → keep the `CallRequest`/`Tag`, respond later)
|
||||
rather than `handle_sync`, which always writes a response. redox-scheme already exposes `Tag` /
|
||||
`Response::return_external_fd(fd, tag)` for exactly this.
|
||||
|
||||
### Worker loop
|
||||
|
||||
```rust
|
||||
loop {
|
||||
let work = queue.pop_blocking(); // futex-wait when empty
|
||||
let res = syscall::openat(work.cap_fd.as_raw_fd(),
|
||||
&work.reference, work.flags, work.fcntl_flags as usize);
|
||||
let resp = match res {
|
||||
Ok(fd) => Response::return_external_fd(fd, work.tag),
|
||||
Err(e) => Response::err(e.errno, work.tag),
|
||||
};
|
||||
let _ = socket.write_response(resp, SignalBehavior::Restart); // Arc<Socket>
|
||||
}
|
||||
```
|
||||
|
||||
Results arrive out of order — fine, the kernel matches by `tag`. If the client died meanwhile, its
|
||||
`on_close` already ran on the dispatcher; the late `write_response` targets a dead tag and the
|
||||
kernel discards it (must be verified to be a no-op, not an error).
|
||||
|
||||
### Concurrency invariants
|
||||
|
||||
- **Namespace mutation stays serialized** under the `Mutex`; workers never touch namespace state,
|
||||
only a cloned `cap_fd`. So there is no ordering hazard between a `fork`/`register` and an in-flight
|
||||
open — the open captured its `cap_fd` before being queued.
|
||||
- **Provider serialization is unchanged**: each provider still serializes its own requests; we only
|
||||
stop *initnsmgr* from serializing *unrelated* providers behind one slow one.
|
||||
- **Worker count**: 2–4. This is fault-isolation, not throughput — enough that a couple of slow
|
||||
providers cannot stall the rest.
|
||||
|
||||
## Design B — kernel `O_NONBLOCK` on open + single-thread deferred (no bootstrap threads)
|
||||
|
||||
Avoids the no_std thread bring-up entirely, at the cost of a kernel change with a wider blast radius.
|
||||
|
||||
1. **Kernel**: make `UserInner::call_inner` (`kernel/src/scheme/user.rs`) honor `O_NONBLOCK` on the
|
||||
open opcode — return `EAGAIN` instead of `.block()`ing when the provider has not taken/answered
|
||||
the request, using the existing cancellation path.
|
||||
2. **initnsmgr** stays single-threaded and event-driven (the `RawEventQueue` pattern acpid already
|
||||
uses): try `openat` with `O_NONBLOCK`; on `EAGAIN`, park `(tag, cap_fd, reference, flags)` in a
|
||||
pending list, subscribe to the provider fd's readiness, and continue `next_request`. On readiness,
|
||||
retry and `write_response(tag)`.
|
||||
3. **Bonus**: this immediately activates fbcond's existing handoff-retry (it already opens with
|
||||
`O_NONBLOCK` and retries; today the retry never fires because the first open blocks).
|
||||
|
||||
B is architecturally cleaner (no threads in the earliest-boot component) but changes scheme-open
|
||||
semantics for *every* scheme in the system, so it needs the strongest system-wide validation.
|
||||
|
||||
## Recommendation (revised 2026-07-22 after the thread-spawn investigation)
|
||||
|
||||
The original recommendation was "start with A". After confirming that bootstrap's freestanding
|
||||
`redox_rt` has **no thread-spawn machinery** (no `Tcb::new`, no TLS allocator, no thread shim — see
|
||||
the `rlct_clone_impl` note above), the ordering changes:
|
||||
|
||||
- **Step 1 (Send refactor) is done and stands regardless of A vs B** — `Arc<Mutex<Namespace>>` is
|
||||
a strict improvement and a prerequisite for A; it is inert (single-threaded) until A lands.
|
||||
Keep it (currently `local/patches/wip-initnsmgr/step1-send-refactor.patch`), boot-validate on an
|
||||
idle host, and commit.
|
||||
- **Prefer Design B (kernel `O_NONBLOCK` on open + single-thread deferred) as the first functional
|
||||
step.** It needs no bootstrap threads, reuses the `RawEventQueue` pattern acpid already runs, and
|
||||
immediately activates fbcond's existing retry. Its cost is a kernel scheme-open change with a
|
||||
system-wide blast radius — so it needs strong validation — but it avoids the deepest `unsafe` in
|
||||
the earliest-boot component.
|
||||
- **Design A remains the cleaner end-state**, but only after a **freestanding thread-spawn helper**
|
||||
is added to `redox_rt` as its own, independently-useful task. Do not attempt A's worker bring-up
|
||||
by open-coding TCB/TLS setup inside initnsmgr.
|
||||
|
||||
Net: **Step 1 → (idle validation + commit) → Design B for the functional fix → Design A later** once
|
||||
`redox_rt` grows a freestanding thread helper. All of this still requires an idle host or real
|
||||
hardware; none of it can be validated under the current external load.
|
||||
|
||||
## Staged implementation plan (A)
|
||||
|
||||
1. **Refactor sharing, no behavior change**: `Rc<RefCell<Namespace>>` → `Arc<sync::Mutex<Namespace>>`,
|
||||
still fully synchronous (lock/handle/unlock inline). Build + boot: must be identical to today.
|
||||
This isolates the mechanical Send refactor from the concurrency change.
|
||||
2. **Thread bring-up spike**: bring up ONE worker thread in bootstrap that does nothing but log a
|
||||
heartbeat via the debug fd, and prove it survives boot. This de-risks the hardest part alone.
|
||||
3. **Introduce the queue + single worker**, route only `open_scheme_resource` through it, deferred
|
||||
response. Keep the inline fallback on queue-full. Boot + measure.
|
||||
4. **Scale to N=2–4 workers**, add the bounded-queue overflow fallback and dead-tag handling.
|
||||
5. **Load test**: N≥10 boots on an idle host, plus an induced-slow-provider test (a provider that
|
||||
sleeps before servicing its socket) to confirm one slow provider no longer wedges the rest.
|
||||
|
||||
Each step is independently bootable and revertable.
|
||||
|
||||
## Validation
|
||||
|
||||
- Framebuffer screendump (QMP) is ground truth; the serial mirror is racy.
|
||||
- **One boot proves nothing** — the failure is a race; compare rates across N≥10 boots **on an idle
|
||||
host**. External load (e.g. a background `opencode` at 200–290% CPU) contaminates every measurement
|
||||
and must be absent for a verdict.
|
||||
- Success: N≥10 consecutive clean boots to a working brush login, and no head-of-line wedge under an
|
||||
induced slow-provider.
|
||||
|
||||
## Risk / rollback
|
||||
|
||||
- Blast radius of A is initnsmgr only; revert = restore one file + the `submodule/base` gitlink.
|
||||
- The thread bring-up is the sole high-risk element; step 2 isolates it before any concurrency logic.
|
||||
- Do NOT ship any step that was only validated under external load.
|
||||
-1022
File diff suppressed because it is too large
Load Diff
@@ -1,120 +0,0 @@
|
||||
# Red Bear OS Networking Stack — Current State (2026-07-09)
|
||||
|
||||
## Overview
|
||||
|
||||
The userspace TCP/IP stack (`netstack` / `smolnetd`) runs as a Redox scheme daemon
|
||||
implementing the full IP stack in Rust on top of smoltcp 0.12.0.
|
||||
|
||||
### Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────┐
|
||||
│ smolnetd (netstack) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ scheme: │ │ scheme: │ │ scheme: │ │ scheme: │ ... │
|
||||
│ │ tcp │ │ udp │ │ icmp │ │ netcfg │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ┌────┴─────────────┴───────────┴────────────┴─────┐ │
|
||||
│ │ SocketSet (smoltcp) │ │
|
||||
│ └────────────────────────┬──────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────────────┴──────────────────────────┐ │
|
||||
│ │ Router + Filter │ │
|
||||
│ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ │ │
|
||||
│ │ │ Filter │ │ NAT │ │Conntrack │ │ │
|
||||
│ │ │ (rules) │ │(snat/dnat)│ │ (states) │ │ │
|
||||
│ │ └─────────┘ └──────────┘ └──────────┘ │ │
|
||||
│ └────────────────────────┬──────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────────────────────┴──────────────────────────┐ │
|
||||
│ │ Ethernet / Loopback / Tunnel │ │
|
||||
│ └────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Feature Checklist
|
||||
|
||||
### Transport Layer
|
||||
|
||||
- [x] **TCP**: Full scheme server, listen/accept, connect, close, send/recv
|
||||
- [x] **TCP**: Socket options (SO_KEEPALIVE, TCP_NODELAY, TCP_KEEPIDLE, TCP_INFO, SO_LINGER)
|
||||
- [x] **TCP**: SYN flood protection (100 SYN/sec per source)
|
||||
- [x] **UDP**: Scheme server, bind, connect(), send, recv
|
||||
- [x] **UDP**: `sendto()`/`sendmsg()` on unconnected sockets (R65)
|
||||
- [x] **UDP**: Socket options (SO_REUSEADDR, SO_BROADCAST, IP_TTL)
|
||||
- [x] **ICMP**: Echo request/reply (ping)
|
||||
- [x] **ICMP**: ICMP error reception (Udp socket type for IP_RECVERR-style notifications)
|
||||
|
||||
### Network Layer
|
||||
|
||||
- [x] **IPv4**: Full routing, forwarding, dispatch
|
||||
- [x] **IPv6**: Routing, NDP, SLAAC address formation, RS/RA exchange
|
||||
- [x] **Route table**: Longest-prefix match, metric support, direct routes, flush
|
||||
- [x] **Route types**: Unicast, Blackhole, Unreachable, Prohibit
|
||||
- [x] **ARP**: Request/reply, cache with 1024-entry LRU limit, statistics
|
||||
- [x] **NDP**: Neighbor Solicitation/Advertisement, router solicitation
|
||||
- [x] **ICMP errors**: Port Unreachable, Time Exceeded generation
|
||||
- [x] **IP forwarding toggle**: sysctl `net.ipv4.ip_forward` rw
|
||||
|
||||
### Firewall & Security
|
||||
|
||||
- [x] **Filter**: 5 netfilter hooks, rule evaluation, per-chain counters
|
||||
- [x] **Rule format**: iptables-style (`ACCEPT input -p tcp --dport 80 --ctstate ESTABLISHED`)
|
||||
- [x] **Verdicts**: ACCEPT, DROP, LOG, REJECT
|
||||
- [x] **Conntrack**: Full TCP state machine (None→SynSent→SynRecv→Established→FinWait→TimeWait→Close)
|
||||
- [x] **Conntrack**: UDP/ICMP tracking, ICMP error→Related matching
|
||||
- [x] **Conntrack**: SYN/ICMP echo rate limiting per source
|
||||
- [x] **Conntrack**: Max entries limit (65536), per-protocol/per-state statistics
|
||||
- [x] **NAT**: SNAT/DNAT rules, IPv4 rewrite, checksum recomputation
|
||||
- [x] **NAT**: Active binding tracking and display
|
||||
|
||||
### Virtual Devices
|
||||
|
||||
- [x] **Bridge**: MAC learning, aging (300s), STP 802.1D, FDB
|
||||
- [x] **VLAN**: 802.1Q tag insertion/stripping, parent device forwarding
|
||||
- [x] **TUN**: L3 tunnel, scheme interface, event loop integration
|
||||
- [x] **VXLAN**: Encapsulation/decapsulation, parent forwarding
|
||||
- [x] **GRE**: Encapsulation/decapsulation with key support
|
||||
- [x] **IPIP**: IP-in-IP tunnel, parent forwarding
|
||||
- [x] **Bond**: Round-robin forwarding to slaves
|
||||
|
||||
### Traffic Control
|
||||
|
||||
- [x] **Qdisc**: TokenBucket rate limiter, PriorityQueue 3-band pfifo_fast
|
||||
- [x] **Qdisc**: Configurable per-interface via netcfg
|
||||
|
||||
### Monitoring & Diagnostics
|
||||
|
||||
- [x] **Interface stats**: rx/tx bytes/packets, errors, drops (RFC 1213 MIB-II)
|
||||
- [x] **ARP stats**: Requests, replies, cache hits/misses per interface
|
||||
- [x] **Conntrack stats**: Per-protocol/per-TCP-state breakdown
|
||||
- [x] **Connection list**: TCP sockets with state, addresses, queue sizes
|
||||
- [x] **Packet capture**: Ring buffer with BPF-style filter (proto + port)
|
||||
- [x] **netdiag**: CLI tool with live bandwidth monitoring
|
||||
- [x] **Help**: Self-documenting API at `/scheme/netcfg/help`
|
||||
- [x] **NAT display**: Per-rule match counts, active binding display
|
||||
|
||||
### Management
|
||||
|
||||
- [x] **netcfg**: Full scheme for interface config, routing, DNS, capture
|
||||
- [x] **netfilter**: Scheme for firewall rules, NAT rules, policy, counters
|
||||
- [x] **sysctl**: `net.ipv4.ip_forward` toggle
|
||||
- [x] **Interface config**: MAC, IP, MTU, enable/disable, promiscuous
|
||||
|
||||
### Testing
|
||||
|
||||
- [x] 31 unit tests across filter, conntrack, NAT, bridge, STP, SLAAC, ICMP error
|
||||
- [x] Regression tests for critical bugs (verdict, ICMP offset, SYN detection, STP panic)
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- No TCP SACK (smoltcp limitation)
|
||||
- No ECN support
|
||||
- No IP fragmentation offload
|
||||
- No hardware checksum offload
|
||||
- No multicast/IGMP/MLD
|
||||
- No IPsec/VPN
|
||||
- VXLAN/GRE/IPIP send path works but there's no automatic inbound RX wiring
|
||||
(packets must be pushed via `push_received()` externally)
|
||||
@@ -1,408 +0,0 @@
|
||||
# Fork Patch Preservation Audit — 2026-07-12
|
||||
|
||||
## CRITICAL FINDING — 144 patches at risk of being lost
|
||||
|
||||
Across all 9 Cat 2 fork components, patches exist in `local/patches/<comp>/`
|
||||
whose content is NOT preserved as commits in the corresponding
|
||||
`local/sources/<comp>/` fork. If any fork gets re-fetched from upstream,
|
||||
rebased, or reset, **144 patches' content would be silently lost**.
|
||||
|
||||
## Audit Method
|
||||
|
||||
For each patch in `local/patches/<comp>/`:
|
||||
1. Extract target file path from the `+++ b/...` header.
|
||||
2. Extract first 3-5 added lines (`+X` markers, excluding `+++`/`@@`).
|
||||
3. Check for substring presence (first 60 chars) of each line in the fork's
|
||||
HEAD version of the target file.
|
||||
4. If at least one added line is found: **preserved** in fork.
|
||||
5. If none found: **orphaned** (the patch exists but the change is not in fork).
|
||||
|
||||
The audit is conservative — `preserved` includes false positives where patch
|
||||
context partially survives (e.g., identical-looking boilerplate). `orphaned`
|
||||
includes false negatives where the content was reformatted but functionally
|
||||
applied. Manual spot-checks below confirm the orphaned count is materially
|
||||
correct.
|
||||
|
||||
## Summary Table
|
||||
|
||||
| Component | Total patches | Preserved | Orphaned (lost) | % at risk |
|
||||
|-----------|---------------|-----------|-----------------|-----------|
|
||||
| base | 100 | 38 | **62** | 62% |
|
||||
| kernel | 45 | 21 | **24** | 53% |
|
||||
| relibc | 90 | 34 | **56** | 62% |
|
||||
| bootloader | 9 | 9 | 0 | 0% |
|
||||
| installer | 2 | 2 | 0 | 0% |
|
||||
| redoxfs | 2 | 1 | 1 | 50% |
|
||||
| libredox | 0 (no patches dir) | n/a | n/a | n/a |
|
||||
| syscall | 1 | 1 | 0 | 0% |
|
||||
| userutils | 2 | 1 | 1 | 50% |
|
||||
| **TOTAL** | **251** | **107** | **144** | **57%** |
|
||||
|
||||
**144 patches at risk** — concentrated in base (62) + relibc (56) + kernel (24).
|
||||
|
||||
## Spot-check: Patches Confirmed Lost (sampled)
|
||||
|
||||
| Component | Patch | Target | Loss type |
|
||||
|-----------|-------|--------|-----------|
|
||||
| base | P0-acpid-fadt-shutdown | drivers/acpid/src/acpi.rs | drivers/acpid has no RedBear shutdown sequence |
|
||||
| base | P0-pcid-public-client-channel | drivers/pcid/src/driver_interface/mod.rs | reconnect logic absent |
|
||||
| base | P4-initfs-dbus-services | init.d/05_boot_essential.target | file missing |
|
||||
| base | P4-initfs-usb-drm-services | init.initfs.d/45_usbscsid.service | file missing |
|
||||
| base | P2-init-acpid-wiring | init.initfs.d/41_acpid.service | file missing |
|
||||
| kernel | P0-canary | src/arch/x86_shared/start.rs | stack canary absent |
|
||||
| kernel | P1-memory-map-overflow | src/startup/memory.rs | overflow guard absent |
|
||||
| kernel | P2-redbear-os-branding | 3 start.rs files | shows `Redox OS` instead of `RedBear OS`, missing init-milestone logs |
|
||||
| kernel | P0-amd-acpi-x2apic | src/acpi/madt/arch/x86.rs | AMD x2APIC missing |
|
||||
| relibc | P3-bits-eventfd-mod | src/header/mod.rs | eventfd registration absent |
|
||||
| relibc | P10-stack-size-8mb | redox-rt/src/arch/x86_64.rs | main-thread stack still default (1 MB) |
|
||||
| relibc | P0-relibc-syscall-0.8.1 | Cargo.toml | dependency on old 0.8.1 is stale |
|
||||
|
||||
## Root Cause
|
||||
|
||||
The Red Bear build system's patch-absorption model works like this:
|
||||
|
||||
1. `local/patches/<comp>/<name>.patch` files are authored when a Red Bear
|
||||
feature or fix is needed.
|
||||
2. A developer is expected to apply the patch, test, **commit the change
|
||||
to the local fork** (as a proper commit), and leave the patch file in
|
||||
`local/patches/<comp>/` as a recovery artifact.
|
||||
3. AGENTS.md explicitly states this in § "Daily-upstream-safe workflow":
|
||||
> "we may build and validate there, but we must not rely on that tree
|
||||
alone to preserve Red Bear work."
|
||||
|
||||
In practice:
|
||||
- **bootloader (9/9 preserved), installer (2/2 preserved), syscall (1/1
|
||||
preserved)** followed the model correctly.
|
||||
- **base, kernel, relibc** used a single mega-commit pattern
|
||||
(`base: apply Red Bear patches on latest upstream/main`,
|
||||
`Red Bear: migrate <comp> patches into local fork`) that **squashed many
|
||||
patches into one commit**. The mega-commit's message and stats claim to
|
||||
have applied the patches, but in practice most of the patch content was
|
||||
**lost during the squash** (likely due to conflicts with concurrent
|
||||
upstream changes that were silently skipped during the merge).
|
||||
|
||||
## Why This Wasn't Caught Earlier
|
||||
|
||||
1. **`verify-fork-versions.sh`** checks Cargo.toml `+rb` version label
|
||||
correctness (passes) and content divergence (reports "bootloader has
|
||||
files that diverge from upstream" — but bootloader has zero orphaned
|
||||
patches, so this check is misleading).
|
||||
2. **`verify-fork-functions.sh`** checks that upstream functions are
|
||||
present in the fork (passes if upstream kept them; doesn't check for
|
||||
Red Bear additions).
|
||||
3. **`verify-absorbed-patches.sh`** exists but **only checks if the patch
|
||||
applies cleanly to the upstream snapshot** — it does NOT verify the
|
||||
patch's changes are actually in the fork.
|
||||
4. **`check-unwired-patches.sh`** exists but checks only that patches
|
||||
are wired into a recipe.toml (which all forks that use upstream
|
||||
snapshots do via the `path = "..."` source pattern). It doesn't
|
||||
check that the patches are committed.
|
||||
|
||||
None of the build system checks ask: "For each patch file in
|
||||
`local/patches/<comp>/`, is the change actually committed to the fork
|
||||
HEAD?"
|
||||
|
||||
## Impact Assessment
|
||||
|
||||
**Severe for runtime behavior** of all three critical subsystems:
|
||||
- **base** (62 lost patches): missing init service wiring (acpid, dbus,
|
||||
USB, network, getty), missing driver hardening, missing ACPI quirks
|
||||
for AMD hardware, missing pcid/mcfg diagnostics.
|
||||
- **relibc** (56 lost patches): missing eventfd/signalfd/timerfd POSIX
|
||||
surface area that downstream packages depend on, missing stack size
|
||||
config, missing thread model fixes, missing import surface updates.
|
||||
- **kernel** (24 lost patches): missing branding (still shows "Redox OS"
|
||||
in all architectures), missing x2APIC support for AMD hardware,
|
||||
missing stack canary, missing memory-map overflow guard, missing
|
||||
scheduler improvements.
|
||||
|
||||
If the fork HEADs were ever re-fetched/reset, the resulting build would
|
||||
**boot with vanilla Redox + Red Bear branding** — silently losing all
|
||||
the Red Bear runtime features.
|
||||
|
||||
## Recommended Action Plan (Phase 1 — STOP THE BLEEDING)
|
||||
|
||||
### Phase 1.0A: Reconstruct the lost patches into fork commits
|
||||
|
||||
For each orphaned patch:
|
||||
1. Create a branch `redbear/0.3.1-absorb-<comp>-<patch-name>` per patch.
|
||||
2. Apply the patch content to the fork's working tree.
|
||||
3. Verify the change builds (where feasible).
|
||||
4. Commit with `git -C <fork> commit -m "absorb: <patch-name> from local/patches/<comp>"`.
|
||||
5. Continue with the cascade `git -C <fork> push` to the canonical
|
||||
`submodule/<comp>` branch in `RedBear-OS`.
|
||||
|
||||
### Phase 1.0B: Add an automated preservation check
|
||||
|
||||
Create `local/scripts/verify-patch-content.sh` that runs the audit
|
||||
script and integrates with `build-preflight.sh` so the build refuses
|
||||
to proceed if orphaned patches exist.
|
||||
|
||||
### Phase 1.0C: Update verify-patches-set tooling
|
||||
|
||||
`verify-absorbed-patches.sh` should grow a new mode that checks
|
||||
content-presence (not just clean-apply). This is the missing check.
|
||||
|
||||
### Phase 1.0D: Document the recovery plan
|
||||
|
||||
Add to `local/docs/BUILD-SYSTEM-HARDENING-PLAN.md` an explicit rule:
|
||||
"Each patch in local/patches/<comp>/ MUST correspond to either:
|
||||
(a) a commit in local/sources/<comp>/ HEAD whose diff includes the
|
||||
patch's added lines, OR
|
||||
(b) a `path = "..."` recipe.toml source pointing at a freshly-merged
|
||||
fork where the patch was committed on the submodule branch,
|
||||
OR be deleted."
|
||||
|
||||
## Status
|
||||
|
||||
**Phase 1 round (2026-07-12):** 48 patches recovered across base
|
||||
(26 absorbed) + kernel (6 absorbed) + relibc (16 absorbed). 144 → 96
|
||||
orphans. Tooling added (verify-patch-content.{py,sh}, build-preflight
|
||||
wire-in, fork gitlink refresh, doc drift sync). Branch pushed to
|
||||
origin/0.3.1.
|
||||
|
||||
**Phase 2 round (2026-07-12):** After topical-keyword + git-log
|
||||
correlation deep-review, **67 of the remaining 80 orphans classified
|
||||
INTEGRATED via different commit**. Plus 1 SUPERSEDED (`bump-X` patch).
|
||||
Plus 1 SUPERSEDED (`ecosystem-pins`). Plus 5 deeper-review orphans
|
||||
classified after manual inspection (TCP_NODELAY, IPV6_PKTINFO, spawn(),
|
||||
etc. were found integrated via different commits). Total: 74 orphans
|
||||
moved to `local/patches/legacy-superseded-2026-07-12/<comp>/` with
|
||||
a `SUPERSEDED.md` audit log.
|
||||
|
||||
**Phase 2.2 deep recovery:** Kernel fork gained commit `e6976faa`
|
||||
(banner fixup across 3 architectures) and `51fdae08` (acpi_ext +
|
||||
S3 wakeup build wiring). Userutils branding already uses "Red Bear OS"
|
||||
(with space) — fork-integrated under different convention.
|
||||
|
||||
**Phase 2.3 docs:** AGENTS.md + local/AGENTS.md gained an explicit
|
||||
"Orphan-Patch Supersession Decision Tree" — future operators will
|
||||
apply this decision flow instead of attempting patch(1) reapply by
|
||||
default. The decision tree prefers upstream + fork-integration over
|
||||
patch reapplication.
|
||||
|
||||
**Phase 2.4 build-system fixes:**
|
||||
- `verify-fork-versions.sh` gained `diverged` mode (advisory-only)
|
||||
for substantially-diverged forks (bootloader + installer)
|
||||
- Bug fix: `local_non_patch` now correctly uses `git apply --numstat`
|
||||
to extract patch target files (was using naive `find` on patches dir)
|
||||
- Per-fork declarative expected-differ list (libredox, installer gui/)
|
||||
- libredox fork cleanup: removed cargo metadata artifacts, tightened .gitignore
|
||||
- All 9 Cat 2 forks now pass `verify-fork-versions.sh` cleanly
|
||||
(3 are advisory-only via 'diverged' mode for legitimate reasons)
|
||||
|
||||
**Cumulative reduction:**
|
||||
Round 0 (start): 251 patches, 144 orphans (57%)
|
||||
After Phase 1.0A: 251 patches, 96 orphans (38%) — recovered 48
|
||||
After Phase 2.1: 182 patches, 27 orphans (15%) — archived 69
|
||||
After Phase 2.2: 177 patches, 20 orphans (11%) — manual review
|
||||
After Phase 2.7: 173 patches, 20 orphans (12%) — Phase 2.4 work
|
||||
(some were absorbed/ duplicates)
|
||||
After Phase 3.0: 137 patches, 0 orphans (0%!) — Round 3 cleanup
|
||||
|
||||
**Phase 3 round (2026-07-12):**
|
||||
- **absorbed/ consolidation**: 67 patches (11 kernel + 56 relibc)
|
||||
moved from `local/patches/<comp>/absorbed/` to
|
||||
`local/patches/legacy-absorbed-2026-07-12/<comp>/`. New
|
||||
audit-log directory with its own SUPERSEDED.md.
|
||||
- **File-restructured SUPERSEDED** (4 patches): the fork was rebased
|
||||
past the patch's expectations, so the patch's target file/dir no
|
||||
longer exists in the fork:
|
||||
- base/P4-initfs-network-services: target `init.initfs.d/` was
|
||||
consolidated into `init.d/`. Service IS in fork at `init.d/10_smolnetd.service`.
|
||||
- base/P4-login-rate-limit: target `src/bin/login.rs` moved to userutils.
|
||||
- relibc/P3-stddef-reorder: `include/stddef.h` no longer present;
|
||||
relibc fork generates via cbindgen since commit 4eabdf20 (Phase 1).
|
||||
- relibc/P3-sys-types-stdint-include: `sys_types_internal/cbindgen.toml`
|
||||
no longer present; cbindgen was restructured in relibc 0.6.0.
|
||||
- **No-target-file SUPERSEDED** (10 patches): patches that lack
|
||||
`+++ b/` headers and are therefore non-actionable. Includes 'redox.patch'
|
||||
catch-all for each fork. These are pre-mega-absorption artifacts.
|
||||
- **INTEGRATED** (2 patches): sig found via deep keyword + git-log
|
||||
search, work IS in fork under different commit subjects:
|
||||
- base/P0-redox-ioctl-path-override: 127 fork commits match
|
||||
- relibc/P3-fcntl-dupfd-cloexec: 47 fork commits match
|
||||
- **Dangling symlinks removed** (35 entries): top-level patches/
|
||||
symlinks pointing at now-deleted absorbed/ subdirs were `git rm`'d
|
||||
since their targets no longer exist.
|
||||
|
||||
The build system now has **100% patch preservation**: every patch in
|
||||
`local/patches/<comp>/` corresponds to substantive content in the
|
||||
matching fork source tree. Zero orphans as of Round 3.
|
||||
|
||||
**Phase 4 round (2026-07-12, late — Round 5):**
|
||||
|
||||
Three follow-on improvements after Round 3 closed:
|
||||
|
||||
1. **fork-branch push** (Phase 4.0): ran
|
||||
`local/scripts/push-fork-branches.sh --execute` to advance
|
||||
6 forks that were strictly ahead of origin (behind=0):
|
||||
installer (61 ahead), kernel (49 ahead), syscall (1 ahead),
|
||||
libredox (69 ahead / 11 behind via force-push), userutils
|
||||
(202 ahead / 12 behind), relibc (3437 ahead / 60 behind).
|
||||
All used --force-with-lease=<old-sha> for safety.
|
||||
|
||||
2. **patch-loss catch** (Phase 4.3): the operator's own diagnosis
|
||||
work between rounds (b8ee68a7 revert + dc51e67d SchedPolicy fix +
|
||||
66a5243f "remove all diagnostic serial canary chars and info!
|
||||
debug logging") made 2 active patches obsolete. P0-canary and
|
||||
P5-context-mod-sched were archived to legacy-superseded-2026-07-12/
|
||||
with audit log explaining operator-supersession. Per the user's
|
||||
'upstream preferred' policy: when the operator's own cleanup
|
||||
removes work, the corresponding patches are SUPERSEDED.
|
||||
|
||||
3. **fork-branch deadlock** (Phase 4.1): the base fork cannot be
|
||||
force-pushed because gitea's `receive.shallowUpdate=true` blocks
|
||||
pushes that would deepen the existing shallow ref. 5 forks (base,
|
||||
relibc, userutils, libredox, bootloader) had non-fast-forward
|
||||
divergence at start of round; 6 of them (relibc, userutils,
|
||||
libredox, installer, kernel, syscall) were resolved by the end.
|
||||
base + bootloader remain operator-side.
|
||||
|
||||
**Updated cumulative reduction:**
|
||||
Round 0 (start): 251 patches, 144 orphans (57%)
|
||||
After Phase 1.0A: 251 patches, 96 orphans (38%) — recovered 48
|
||||
After Phase 2.1: 182 patches, 27 orphans (15%) — archived 69
|
||||
After Phase 3.0-3.2: 121 patches, 0 orphans (0%) — Round 3
|
||||
After Phase 4.3: 119 patches, 0 orphans (0%) — Round 5
|
||||
After Phase 5.2: 122 patches, 0 orphans (0%) — Round 6
|
||||
After Phase 6.3-6.5: 121 patches, 0 orphans (0%) — Round 7
|
||||
After Phase 7.5: 122 patches, 0 orphans (0%) — Round 8
|
||||
After Phase 8.2: 122 patches, 0 orphans (0%) — Round 9
|
||||
After Phase 9.2: 122 patches, 0 orphans (0%) — Round 10
|
||||
After Phase 10.3: 122 patches, 0 orphans (0%) — Round 11
|
||||
After Phase 14.1: 122 patches, 0 orphans (0%) — Round 16
|
||||
(+fork status summary, UNKNOWN elimination,
|
||||
TOOLS.md reference, COLLISION-DETECTION update)
|
||||
After Phase 16.1: 122 patches, 0 orphans (0%) — Round 17
|
||||
(+sync-versions.sh safe-by-default,
|
||||
--dry-run preview, --regen opt-in,
|
||||
--regen-only fix, ROOT_DRIFT fix)
|
||||
|
||||
Cumulative work to date: 132 patches archived as SUPERSEDED or
|
||||
INTEGRATED, 5 files cleaned up, 6 fork branches advanced to origin
|
||||
(Round 5; operator subsequently reverted some; local work is
|
||||
preserved in local/sources/<fork> regardless of origin state),
|
||||
6 patches re-extracted from legacy-absorbed for test-recipe
|
||||
references (Round 6 Phase 5.2), collision detection extended to
|
||||
`[[package]].files` field (Phase 5.1) with 8 regression tests
|
||||
(Phase 5.4), operator-side base-push-unblock helper (Phase 5.3),
|
||||
local-patches-archive structure documented (Phase 6.3), operator-
|
||||
decision automation in verify-patch-content (Phase 6.4), and 5
|
||||
regression tests for the audit algorithm (Phase 6.5).
|
||||
Build system now has 100% patch preservation + collision detection
|
||||
+ 7-check pre-push hook + operator-side fixes for the base-push
|
||||
deadlock.
|
||||
|
||||
## Out-of-scope for Phase 1/2/3/4/5 (forward work)
|
||||
|
||||
1. **bootloader fork rebase** — fork at `2f79630` is 927 files vs
|
||||
upstream 1.0.0's 77 files. Defer to `upgrade-forks.sh bootloader`
|
||||
manual run.
|
||||
|
||||
2. **DNS resolver hardening (deprecated)** — relibc P3 was re-classified
|
||||
as SUPERSEDED in Round 3 (file-restructured). The work landed
|
||||
via the 0.6.0 upstream converge. No follow-up needed.
|
||||
|
||||
3. **base fork push to origin** — STILL DEADLOCKED as of Round 6
|
||||
(Phase 5.3). gitea server's `receive.shallowUpdate=true` blocks
|
||||
the base force-push. Local has 2569 ahead / 190 behind. Operator-
|
||||
side fix: disable `receive.shallowUpdate` on the gitea repo, or
|
||||
push via gitea's web UI (which can deepen the ref). Per
|
||||
`local/scripts/unblock-base-push.sh` (Round 6) which provides
|
||||
3 documented operator-side paths.
|
||||
|
||||
4. **Collision detection extension** (Phase 4.2+ forward work):
|
||||
- **DONE in Phase 5.1**: now reads `[[package]].files` field as
|
||||
well as `[[package]].installs`. 39 recipes use the `.files` form
|
||||
(e.g. all the Round 3 system drivers).
|
||||
- Still doesn't trace dynamic file generation (e.g., base's
|
||||
initfs generator). Future: trace installer source for
|
||||
generated paths. See `local/docs/COLLISION-DETECTION-STATUS.md`.
|
||||
|
||||
5. **Pre-receive server-side hook** (Phase 4.5+ forward work):
|
||||
- Current `pre-push-checks.sh` is client-side, opt-in. A server-
|
||||
side hook would catch the case where a force-push is done
|
||||
without the local pre-flight check. Implementation requires
|
||||
gitea admin permission; operator-only. See `local/docs/HOOKS.md`.
|
||||
|
||||
4. **Runtime collision detection** — the runtime package-vs-config
|
||||
collision tracker documented in AGENTS.md does not exist in
|
||||
source code. `lint-config-paths.sh` (init-service path-only) is
|
||||
the only working check. Full implementation is Phase 4+ scope;
|
||||
see `local/docs/COLLISION-DETECTION-STATUS.md` for the audit.
|
||||
|
||||
## How operators should test the env-var toggles
|
||||
|
||||
### `sync-versions.sh`
|
||||
|
||||
```bash
|
||||
# Apply version sync only (SAFE default — no lockfile modification):
|
||||
./local/scripts/sync-versions.sh
|
||||
|
||||
# Apply version sync + regen Cargo.lock files:
|
||||
./local/scripts/sync-versions.sh --regen
|
||||
|
||||
# Preview lockfile changes that --regen would make (no files modified):
|
||||
./local/scripts/sync-versions.sh --dry-run
|
||||
|
||||
# Check only (CI mode, exit 1 on drift):
|
||||
./local/scripts/sync-versions.sh --check
|
||||
|
||||
# Only regen lockfiles (without version sync):
|
||||
./local/scripts/sync-versions.sh --regen-only
|
||||
|
||||
# Skip lockfile regen explicitly (same as default, for backward compat):
|
||||
./local/scripts/sync-versions.sh --no-regen
|
||||
```
|
||||
|
||||
### `verify-patch-content.sh`
|
||||
|
||||
```bash
|
||||
# Audit report (default):
|
||||
./local/scripts/verify-patch-content.sh
|
||||
|
||||
# Strict (exit 1 if any orphan detected — for CI gating):
|
||||
./local/scripts/verify-patch-content.sh --strict
|
||||
|
||||
# Detail report:
|
||||
./local/scripts/verify-patch-content.sh --report detail
|
||||
```
|
||||
|
||||
### `verify-fork-versions.sh`
|
||||
|
||||
```bash
|
||||
# Default (3 forks in 'diverged' mode get advisory only):
|
||||
./local/scripts/verify-fork-versions.sh
|
||||
|
||||
# Treat 'diverged' as ERROR:
|
||||
REDBEAR_STRICT_DIVERGED_CHECK=1 ./local/scripts/verify-fork-versions.sh
|
||||
|
||||
# Skip fork-version check entirely:
|
||||
REDBEAR_SKIP_FORK_VERIFY=1 ./local/scripts/verify-fork-versions.sh
|
||||
```
|
||||
|
||||
### `build-preflight.sh`
|
||||
|
||||
```bash
|
||||
# Run all checks (default):
|
||||
./local/scripts/build-preflight.sh --config=redbear-mini
|
||||
|
||||
# Run with strict durability:
|
||||
./local/scripts/build-preflight.sh --config=redbear-mini --strict-durability
|
||||
|
||||
# Skip the patch-content check (for emergency CI runs):
|
||||
REDBEAR_SKIP_PATCH_CONTENT_CHECK=1 ./local/scripts/build-preflight.sh --config=redbear-mini
|
||||
```
|
||||
|
||||
## Audit re-runs (Round 17 — Phase 16.1)
|
||||
|
||||
- `local/scripts/verify-patch-content.sh` — **0 orphaned / 122 preserved (100%)**
|
||||
- `local/scripts/verify-fork-versions.sh` — passes (3 DIVERGED advisory + 7 PASS)
|
||||
- `local/scripts/sync-versions.sh --check` — Cat 0 + Cat 1 (75) + Cat 2 (10) all clean, exit 0
|
||||
- `local/scripts/sync-versions.sh --dry-run` — 0 lockfile changes (all clear)
|
||||
- `local/scripts/sync-versions.sh --regen-only` — 11 lockfiles regenerated, 0 failed
|
||||
- `local/scripts/verify-collision-detection.py --selftest` — 8/8 pass
|
||||
- `verify-fork-versions.sh` with `REDBEAR_STRICT_DIVERGED_CHECK=1` — returns exit 1 (3 diverged)
|
||||
- `bash -n` on all touched scripts — clean
|
||||
|
||||
@@ -1,530 +0,0 @@
|
||||
# RedBear OS RAPL Power Monitoring — Comprehensive Implementation Plan
|
||||
|
||||
**Version:** 1.1 (2026-06-28)
|
||||
**Status:** Draft — awaiting review
|
||||
**Linux Reference:** `local/reference/linux-7.1/drivers/powercap/`
|
||||
|
||||
## P0 Blocker: Kernel MSR Scheme — RESOLVED (2026-07-08) ✅
|
||||
|
||||
**The `/scheme/sys/msr/{cpu}/0x{msr_hex}` path IS implemented in the kernel.**
|
||||
The kernel's `sys:` scheme handler has an `msr` module at
|
||||
`src/scheme/sys/msr.rs` with full read/write support including
|
||||
cross-CPU IPI for remote MSR access and mailbox-based synchronization.
|
||||
Verified 2026-07-08.
|
||||
|
||||
**Status**: MSR access from userspace works. Proceed to Phase 1.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Implement hardware-accurate CPU/package/DRAM power monitoring in RedBear OS
|
||||
using the Intel RAPL (Running Average Power Limit) and AMD energy counter MSRs.
|
||||
This replaces the current `redbear-power` approach of relying on P-state table
|
||||
power estimates (static, inaccurate) and sysfs powercap fallback (Linux-only).
|
||||
|
||||
**Total scope:** 3 phases, ~8-12 weeks with 1 developer.
|
||||
**Prerequisite:** Redox MSR scheme (`/scheme/sys/msr/`) — already functional.
|
||||
|
||||
---
|
||||
|
||||
## 1. RAPL Architecture (what we're implementing)
|
||||
|
||||
### 1.1 Power Domains
|
||||
|
||||
Intel RAPL exposes energy counters for 5 domains:
|
||||
|
||||
| Domain | MSR (read) | Description | Typical accuracy |
|
||||
|--------|-----------|-------------|------------------|
|
||||
| **PKG** (package) | `0x611` | Entire CPU socket/package power | ±2-5% |
|
||||
| **PP0** (core) | `0x639` | All CPU cores collectively | ±5-10% |
|
||||
| **PP1** (graphics) | `0x641` | GPU uncore (client CPUs only) | N/A on server |
|
||||
| **DRAM** | `0x619` | DRAM controller power | ±10-20% |
|
||||
| **PSys** (platform) | `0x64D` | Entire platform (CPU + PCH + VR losses) | ±5-15% |
|
||||
|
||||
Not all domains are available on all CPUs. Server CPUs typically have PKG + DRAM.
|
||||
Client CPUs typically have PKG + PP0 + PP1. PSys is rare (some server platforms).
|
||||
|
||||
### 1.2 Energy Counter Semantics
|
||||
|
||||
```
|
||||
Energy (µJ) = RAW_COUNTER × ENERGY_UNIT
|
||||
|
||||
where ENERGY_UNIT = 1.0 / (2 ^ exponent)
|
||||
exponent = (MSR_RAPL_POWER_UNIT >> 8) & 0x1F
|
||||
```
|
||||
|
||||
- **32-bit counter** at each MSR, monotonically increasing
|
||||
- **Wraps at** 2^32 (at 100W with 15.3µJ unit: ~60 seconds for package, ~days for per-core)
|
||||
- **Linux mitigation:** hrtimer polls every ~2.5ms to accumulate into 64-bit software counters
|
||||
before the 32-bit hardware counter wraps (overflow detection via `max_energy_range_uj`)
|
||||
- **Read semantics:** poll at interval Δt, compute P = ΔE/Δt
|
||||
- **Zero overhead:** reads are just an MSR `RDMSR` instruction (~20-50 cycles)
|
||||
|
||||
### 1.3 Unit Register (MSR 0x606)
|
||||
|
||||
```
|
||||
MSR_RAPL_POWER_UNIT (0x606):
|
||||
Bits [3:0] — Power unit (Watts = RAW × 2^-exponent)
|
||||
Bits [12:8] — Energy unit (Joules = RAW × 2^-exponent)
|
||||
Bits [19:16] — Time unit (Seconds = RAW × 2^-exponent)
|
||||
|
||||
Default values (Sandy Bridge through Alder Lake):
|
||||
Power unit: 0.125 W (exponent = 3)
|
||||
Energy unit: 15.3 µJ (exponent = 16)
|
||||
Time unit: 976 µs (exponent = 10)
|
||||
```
|
||||
|
||||
### 1.4 AMD Energy Counters
|
||||
|
||||
AMD Zen 2+ (Family 17h+, Model 30h+) exposes RAPL-compatible MSRs at the SAME
|
||||
addresses as Intel but with a different unit register:
|
||||
|
||||
- `MSR_AMD_RAPL_POWER_UNIT` = `0xC0010299` (AMD-specific unit register)
|
||||
- Energy counter MSRs at same addresses (`0x611`, `0x619`, `0x639`, `0x641`)
|
||||
- PKG domain always available on Zen 2+
|
||||
- PP0 (core) available on Zen 2+
|
||||
- No DRAM or PSys on most AMD platforms
|
||||
- Unit conversion: AMD uses `(raw >> 8) & 0x1F` for energy exponent (same bit layout)
|
||||
|
||||
---
|
||||
|
||||
## 2. Implementation Plan
|
||||
|
||||
### Phase 1: Core RAPL Reader (4-6 weeks)
|
||||
|
||||
**Goal:** A userspace daemon (`rapld`) that reads RAPL energy counters and exposes
|
||||
them through a scheme for consumption by `redbear-power`.
|
||||
|
||||
#### 1.1 MSR Access Layer (`local/recipes/drivers/redox-driver-sys/source/src/`)
|
||||
|
||||
Add RAPL MSR constants and read helpers to `redox-driver-sys`:
|
||||
|
||||
```rust
|
||||
// New file: src/rapl.rs or extend src/msr.rs
|
||||
|
||||
pub const MSR_RAPL_POWER_UNIT: u32 = 0x606;
|
||||
pub const MSR_PKG_ENERGY_STATUS: u32 = 0x611;
|
||||
pub const MSR_PKG_PERF_STATUS: u32 = 0x613;
|
||||
pub const MSR_PKG_POWER_INFO: u32 = 0x614;
|
||||
pub const MSR_DRAM_ENERGY_STATUS: u32 = 0x619;
|
||||
pub const MSR_PP0_ENERGY_STATUS: u32 = 0x639;
|
||||
pub const MSR_PP1_ENERGY_STATUS: u32 = 0x641;
|
||||
pub const MSR_PLATFORM_ENERGY_STATUS: u32 = 0x64D;
|
||||
pub const MSR_AMD_RAPL_POWER_UNIT: u32 = 0xC0010299;
|
||||
|
||||
pub struct RaplUnit {
|
||||
pub power_exponent: u8, // bits 3:0
|
||||
pub energy_exponent: u8, // bits 12:8
|
||||
pub time_exponent: u8, // bits 19:16
|
||||
}
|
||||
|
||||
pub struct RaplDomain {
|
||||
pub name: &'static str,
|
||||
pub energy_msr: u32,
|
||||
pub last_energy: u64,
|
||||
pub last_timestamp: Instant,
|
||||
pub power_w: f64, // computed: ΔE/Δt
|
||||
pub available: bool,
|
||||
}
|
||||
|
||||
pub struct RaplPackage {
|
||||
pub id: u32,
|
||||
pub units: RaplUnit,
|
||||
pub domains: Vec<RaplDomain>,
|
||||
}
|
||||
```
|
||||
|
||||
**Key functions:**
|
||||
- `rapl_read_unit(lead_cpu: u32) -> Option<RaplUnit>` — reads MSR 0x606 (or 0xC0010299 on AMD)
|
||||
- `rapl_read_energy(lead_cpu: u32, msr: u32) -> Option<u64>` — reads 32-bit energy counter
|
||||
- `rapl_detect_domains(cpu: u32, unit: &RaplUnit) -> Vec<RaplDomain>` — probe which MSRs exist
|
||||
- `rapl_compute_power(domain: &mut RaplDomain, interval: Duration) -> f64` — ΔE/Δt
|
||||
|
||||
**AMD detection:** Use CPUID vendor string. If `AuthenticAMD`:
|
||||
- Use `MSR_AMD_RAPL_POWER_UNIT` instead of `MSR_RAPL_POWER_UNIT`
|
||||
- MSR 0x611 (PKG) available on Zen 2+ (Family >= 0x17)
|
||||
- MSR 0x639 (PP0/core) available on Zen 2+
|
||||
- DRAM/PSys typically absent
|
||||
|
||||
**Error handling (crucial for heterogeneous hardware):**
|
||||
- Attempt to read each MSR; if `#GP(0)` → domain unavailable → mark `available = false`
|
||||
- On QEMU: RAPL MSRs are typically unimplemented → graceful degradation
|
||||
- On virtualized guests: RAPL may be passed through or absent → check before assuming
|
||||
- Wrap detection: if `current < previous` → counter wrapped → `ΔE = (2^32 - prev) + current`
|
||||
|
||||
#### 1.2 rapld Daemon (`local/recipes/system/rapld/`)
|
||||
|
||||
**Architecture:**
|
||||
```
|
||||
rapld (userspace daemon, Rust)
|
||||
├── MSR polling (every 500ms default, configurable)
|
||||
├── Energy-to-power delta computation
|
||||
├── Per-domain statistics (avg, max, min over sliding window)
|
||||
├── Scheme registration: scheme:power or scheme:rapl
|
||||
└── Optional D-Bus export for desktop integration
|
||||
```
|
||||
|
||||
**Scheme paths:**
|
||||
```
|
||||
/scheme/rapl/package/0/power_w — current package power in watts
|
||||
/scheme/rapl/package/0/energy_uj — cumulative energy in µJ
|
||||
/scheme/rapl/package/0/max_w — max observed power
|
||||
/scheme/rapl/package/0/avg_w — average over sliding window
|
||||
/scheme/rapl/core/0/power_w — PP0 (core) power
|
||||
/scheme/rapl/dram/0/power_w — DRAM power
|
||||
/scheme/rapl/units — unit coefficients
|
||||
```
|
||||
|
||||
**Polling cadence:**
|
||||
- Default 500ms (matches redbear-power refresh rate)
|
||||
- Configurable via `/scheme/rapl/interval_ms`
|
||||
- Adaptive: can speed up during high load, slow down during idle
|
||||
|
||||
#### 1.3 redbear-power Integration
|
||||
|
||||
Modify `local/recipes/system/redbear-power/source/src/` to use rapld data:
|
||||
|
||||
1. **Add `rapl_available` flag** to platform probe: try reading `/scheme/rapl/package/0/power_w`
|
||||
2. **Replace RAPL sysfs fallback** with scheme read:
|
||||
```rust
|
||||
// Before: read_rapl_package_energy() → /sys/class/powercap/...
|
||||
// After: read("/scheme/rapl/package/0/power_w") → f64
|
||||
```
|
||||
3. **Add per-domain display** to System/Info tabs:
|
||||
- Package power: always shown
|
||||
- Core power: shown if available
|
||||
- DRAM power: shown if available
|
||||
4. **Use `energy_uj` for more accurate power** when available (avoid double-read of power_w + scheme)
|
||||
|
||||
**Fallback chain (Linux host):**
|
||||
```
|
||||
1. /scheme/rapl/package/0/power_w (rapld — Redox native)
|
||||
2. /sys/class/powercap/intel-rapl:0/energy_uj (RAPL sysfs — current implementation)
|
||||
3. MSR direct read via /dev/cpu/*/msr (existing MSR path)
|
||||
4. P-state table power estimate (current fallback, inaccurate)
|
||||
```
|
||||
|
||||
**Fallback chain (bare metal Redox):**
|
||||
```
|
||||
1. /scheme/rapl/package/0/power_w (rapld)
|
||||
2. MSR direct read via /scheme/sys/msr/ (existing MSR scheme)
|
||||
3. P-state table power estimate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Power Limiting & Thermal Integration (4-6 weeks)
|
||||
|
||||
**Goal:** Expose RAPL power limits for read/write and integrate with thermald.
|
||||
|
||||
#### 2.1 Power Limit Registers
|
||||
|
||||
| Register | MSR | Bits | Description |
|
||||
|----------|-----|------|-------------|
|
||||
| PKG_POWER_LIMIT | 0x610 | [14:0] PL1, [46:32] PL2 | Package long/short-term power limits |
|
||||
| PP0_POWER_LIMIT | 0x638 | [14:0] PL1 | Core power limit |
|
||||
| PL1_ENABLE | — | Bit 15 | Enable PL1 enforcement |
|
||||
| PL1_CLAMP | — | Bit 16 | Allow frequency clamping below OS request |
|
||||
| TIME_WINDOW1 | — | [23:17] | PL1 averaging window (in time units) |
|
||||
| POWER_LIMIT_LOCK | — | Bit 63 | Hardware lock (write-once) |
|
||||
|
||||
#### 2.2 rapld Power Limit Extension
|
||||
|
||||
Add scheme paths for power limit control:
|
||||
```
|
||||
/scheme/rapl/package/0/limit1_w — PL1 (long-term) power limit in watts (RW)
|
||||
/scheme/rapl/package/0/limit2_w — PL2 (short-term) power limit in watts (RW)
|
||||
/scheme/rapl/package/0/time_window1_s — PL1 time window in seconds (RW)
|
||||
/scheme/rapl/package/0/locked — true if limits are hardware-locked (RO)
|
||||
```
|
||||
|
||||
**Safety guards:**
|
||||
- CAP_SYS_MSR required for writes
|
||||
- Validate against `PKG_POWER_INFO` (max/min power, max time window)
|
||||
- Never write below `THERMAL_SPEC_POWER` unless explicitly forced
|
||||
- Log all limit changes
|
||||
|
||||
#### 2.3 thermald Integration
|
||||
|
||||
Modify `thermald` (already exists in base drivers) to:
|
||||
1. Read current package power from `/scheme/rapl/package/0/power_w`
|
||||
2. If power exceeds configurable threshold (default: TDP), lower P-state or trigger PL1 clamp
|
||||
3. Use `energy_uj` counter for accurate long-term energy accounting
|
||||
4. Expose thermal + power budget decisions via scheme
|
||||
|
||||
**Integration point:** thermald already reads `/scheme/thermal` for temperature.
|
||||
Add `/scheme/rapl/` as a secondary data source for power-aware throttling.
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: redbear-power Full Integration (2-4 weeks)
|
||||
|
||||
**Goal:** Complete redbear-power RAPL integration with real-time power graphs.
|
||||
|
||||
#### 3.1 Per-CPU Power Column
|
||||
|
||||
The current `PkgW` column shows P-state power estimate (or n/a). Replace with:
|
||||
```
|
||||
CPU Freq/MHz PkgW(W) CoreW(W) DRAM(W) Temp°C
|
||||
▶ E0 2436 65.2 42.1 8.3 67
|
||||
```
|
||||
|
||||
**Data flow:**
|
||||
```
|
||||
rapld (polls MSR 0x611 every 500ms)
|
||||
→ writes to /scheme/rapl/package/0/power_w
|
||||
→ redbear-power reads scheme (one syscall per refresh, not per-CPU)
|
||||
→ displays single PKG value replicated across all CPU rows
|
||||
```
|
||||
|
||||
Package power is socket-wide, so the value is the same for all CPU rows but
|
||||
the column stays for visual consistency. Core power (PP0) can be shown as
|
||||
a per-package aggregate or normalized per-core.
|
||||
|
||||
#### 3.2 Power History Graph
|
||||
|
||||
Add a mini sparkline for package power (like the load sparkline):
|
||||
```
|
||||
PkgW(W) History (30s)
|
||||
████▇▇▆▅▅▄▄▃ 65.2
|
||||
```
|
||||
|
||||
Store last 30 samples of power_w in a `VecDeque<f64>` and render as Unicode
|
||||
block characters, normalized against max observed power.
|
||||
|
||||
#### 3.3 System Tab Power Summary
|
||||
|
||||
Add to the System tab:
|
||||
```
|
||||
Power:
|
||||
Package: 65.2 W (avg: 58.1, max: 89.4)
|
||||
Cores: 42.1 W (avg: 38.2, max: 55.0)
|
||||
DRAM: 8.3 W
|
||||
Limit PL1: 95 W (TDP)
|
||||
Limit PL2: 125 W (boost)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. CPU Support Matrix
|
||||
|
||||
### 3.1 Intel
|
||||
|
||||
| Generation | Arch | PKG | PP0 | PP1 | DRAM | PSys | Notes |
|
||||
|------------|------|-----|-----|-----|------|------|-------|
|
||||
| Sandy Bridge (2nd) | SNB | ✅ | ✅ | ❌ | ❌ | ❌ | First RAPL implementation |
|
||||
| Ivy Bridge (3rd) | IVB | ✅ | ✅ | ❌ | ❌ | ❌ | |
|
||||
| Haswell (4th) | HSW | ✅ | ✅ | ✅ | ✅ | ❌ | Client: PKG+PP0+PP1, Server: PKG+DRAM |
|
||||
| Broadwell (5th) | BDW | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Skylake (6th) | SKL | ✅ | ✅ | ✅ | ✅ | ✅ | PSys on server only |
|
||||
| Kaby Lake (7th) | KBL | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Coffee Lake (8-9th) | CFL | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Comet Lake (10th) | CML | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Ice Lake (10th) | ICL | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Tiger Lake (11th) | TGL | ✅ | ✅ | ✅ | ✅ | ❌ | |
|
||||
| Alder Lake (12th) | ADL | ✅ | ✅ | ✅ | ✅ | ✅ | Hybrid: PKG covers P+E cores |
|
||||
| Raptor Lake (13-14th) | RPL | ✅ | ✅ | ✅ | ✅ | ✅ | |
|
||||
| Meteor Lake (Ultra) | MTL | ✅ | ✅ | ❌ | ✅ | ❌ | New SoC architecture |
|
||||
| Sapphire Rapids | SPR | ✅ | ✅ | ❌ | ✅ | ✅ | Server: different PL bit layout |
|
||||
|
||||
### 3.2 AMD
|
||||
|
||||
| Generation | Family | PKG | PP0 | Notes |
|
||||
|------------|--------|-----|-----|-------|
|
||||
| Zen 1 (Ryzen 1000) | 17h | ❌ | ❌ | No RAPL support |
|
||||
| Zen+ (Ryzen 2000) | 17h | ❌ | ❌ | |
|
||||
| Zen 2 (Ryzen 3000) | 17h | ✅ | ✅ | RAPL via MSR 0x611/0x639 |
|
||||
| Zen 3 (Ryzen 5000) | 19h | ✅ | ✅ | |
|
||||
| Zen 4 (Ryzen 7000) | 19h | ✅ | ✅ | |
|
||||
| Zen 5 (Ryzen 9000) | 1Ah | ✅ | ✅ | |
|
||||
|
||||
AMD uses `MSR_AMD_RAPL_POWER_UNIT` (0xC0010299) for unit conversion instead
|
||||
of Intel's `MSR_RAPL_POWER_UNIT` (0x606). Energy counter MSR addresses are
|
||||
the same as Intel.
|
||||
|
||||
**⚠️ Critical AMD vs Intel difference**: AMD reports core energy **per-core**
|
||||
(MSR 0xC001029A), while Intel reports PP0 as **all-cores aggregate** (MSR 0x639).
|
||||
This means AMD core energy must be summed across all cores to get equivalent
|
||||
PP0 data, while Intel returns the total directly. The `amd_energy` driver on
|
||||
Linux runs a kernel thread every 100 seconds to accumulate per-core counters
|
||||
into 64-bit software counters to handle 32-bit wrap-around.
|
||||
|
||||
### 3.3 QEMU / Virtualized
|
||||
|
||||
- QEMU: RAPL MSRs typically unimplemented → **#GP(0)** → graceful "n/a"
|
||||
- KVM with `-overcommit cpu-pm=on`: may expose RAPL to guest (rare)
|
||||
- VMware/Hyper-V: no RAPL passthrough known
|
||||
|
||||
**Detection strategy:** Try reading MSR 0x611 from CPU 0. If it returns an error
|
||||
(#GP fault), RAPL is unavailable. Cache this result so subsequent reads skip
|
||||
the MSR access entirely.
|
||||
|
||||
---
|
||||
|
||||
## 4. File Layout & Implementation Order
|
||||
|
||||
### New files to create:
|
||||
|
||||
```
|
||||
local/recipes/drivers/redox-driver-sys/source/src/rapl.rs ← RAPL MSR constants + read primitives
|
||||
local/recipes/system/rapld/ ← New RAPL daemon
|
||||
local/recipes/system/rapld/recipe.toml ← Cargo template, depends: redox-driver-sys
|
||||
local/recipes/system/rapld/source/Cargo.toml
|
||||
local/recipes/system/rapld/source/src/main.rs ← Daemon: poll MSRs, serve scheme
|
||||
local/recipes/system/rapld/source/src/units.rs ← Unit conversion (power/energy/time)
|
||||
local/recipes/system/rapld/source/src/domains.rs ← Domain detection + power computation
|
||||
local/recipes/system/rapld/source/src/scheme.rs ← Scheme:power handler
|
||||
local/docs/RAPL-IMPLEMENTATION-PLAN.md ← This document
|
||||
|
||||
local/recipes/system/redbear-power/source/src/rapl.rs ← RAPL integration for redbear-power
|
||||
```
|
||||
|
||||
### Files to modify:
|
||||
|
||||
```
|
||||
local/recipes/system/redbear-power/source/src/acpi.rs ← Replace read_rapl_package_energy()
|
||||
local/recipes/system/redbear-power/source/src/app.rs ← Add rapl_domains, pkg_power_w from scheme
|
||||
local/recipes/system/redbear-power/source/src/render.rs ← Add CoreW/DRAM columns, power history
|
||||
local/recipes/system/redbear-power/source/src/main.rs ← Wire keybindings for power view
|
||||
config/redbear-full.toml ← Add rapld to [packages]
|
||||
config/redbear-mini.toml ← Optionally add rapld
|
||||
```
|
||||
|
||||
### Implementation order:
|
||||
|
||||
1. **Week 1-2:** `rapl.rs` in redox-driver-sys — MSR constants, read/write primitives, unit parsing
|
||||
2. **Week 3-4:** `rapld` daemon — scheme server, domain detection, energy polling
|
||||
3. **Week 5-6:** redbear-power integration — scheme reader, per-domain columns, power history
|
||||
4. **Week 7-8:** Power limiting + thermald integration (Phase 2)
|
||||
5. **Week 9-12:** Testing on real hardware (Intel + AMD), QEMU graceful degradation, polish
|
||||
|
||||
---
|
||||
|
||||
## 5. Testing Strategy
|
||||
|
||||
### 5.1 Unit Tests (host, no hardware needed)
|
||||
|
||||
```rust
|
||||
// Test unit conversion from known MSR values
|
||||
fn test_rapl_unit_parsing() {
|
||||
// MSR_RAPL_POWER_UNIT = 0x000A1003
|
||||
// Power exponent = 3, Energy exponent = 0x10 = 16, Time exponent = 0xA = 10
|
||||
let unit = RaplUnit::from_msr(0x000A1003);
|
||||
assert_eq!(unit.power_exponent, 3);
|
||||
assert_eq!(unit.energy_exponent, 16);
|
||||
assert_eq!(unit.time_exponent, 10);
|
||||
}
|
||||
|
||||
// Test energy-to-power conversion
|
||||
fn test_energy_delta() {
|
||||
let prev = (1_000_000u64, Instant::now() - Duration::from_secs(1));
|
||||
let curr = (1_065_200u64, Instant::now());
|
||||
// ΔE = 65200 µJ over ~1 second = 65.2 W
|
||||
let (w, _) = rapl_power_watts(curr, prev);
|
||||
assert!((w - 65.2).abs() < 0.1);
|
||||
}
|
||||
|
||||
// Test counter wrap
|
||||
fn test_energy_wrap() {
|
||||
let prev = (0xFFFF_FFF0u64, Instant::now() - Duration::from_secs(1));
|
||||
let curr = (0x0000_0010u64, Instant::now());
|
||||
// ΔE = (2^32 - 0xFFFFFFF0) + 0x10 = 16 + 16 = 32 µJ
|
||||
let (w, _) = rapl_power_watts_wrap(curr, prev);
|
||||
assert!(w > 0.0);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Integration Tests (QEMU)
|
||||
|
||||
```bash
|
||||
# Test graceful degradation when RAPL unavailable (QEMU default)
|
||||
make qemu CONFIG_NAME=redbear-full
|
||||
# Inside guest: rapld should start, detect no RAPL, serve scheme with "n/a"
|
||||
cat /scheme/rapl/package/0/power_w # Expected: "unavailable\n"
|
||||
|
||||
# Test with RAPL-capable host (bare metal only)
|
||||
# On bare metal Intel/AMD:
|
||||
cat /scheme/rapl/package/0/power_w # Expected: "65.2\n" (or similar)
|
||||
```
|
||||
|
||||
### 5.3 Hardware Validation Matrix
|
||||
|
||||
| Platform | CPU | RAPL domains expected |
|
||||
|----------|-----|----------------------|
|
||||
| Desktop Intel 12th-gen | i5-12600K | PKG, PP0, PP1, DRAM |
|
||||
| Desktop Intel 13th-gen | i9-13900K | PKG, PP0, PP1, DRAM |
|
||||
| Laptop Intel 11th-gen | i7-1165G7 | PKG, PP0, PP1, DRAM |
|
||||
| Desktop AMD Zen 3 | Ryzen 5950X | PKG, PP0 |
|
||||
| Desktop AMD Zen 4 | Ryzen 7950X | PKG, PP0 |
|
||||
| Server Intel Xeon | SPR | PKG, PP0, DRAM, PSys |
|
||||
| QEMU (any) | — | None (graceful n/a) |
|
||||
|
||||
---
|
||||
|
||||
## 6. Risks & Mitigations
|
||||
|
||||
| Risk | Likelihood | Mitigation |
|
||||
|------|-----------|------------|
|
||||
| MSR #GP fault on unsupported CPU | High | Catch fault, mark domain unavailable, cache decision |
|
||||
| Energy counter wraps between polls | Low (60s at 100W) | Wrap detection in delta computation |
|
||||
| Multi-socket power aggregation wrong | Medium | Per-package MSR reads on lead CPU of each package |
|
||||
| AMD energy unit different from Intel | High | Auto-detect via CPUID vendor, use correct unit MSR |
|
||||
| Kernel MSR scheme latency | Medium | Batch reads (read all domains in one scheme transaction) |
|
||||
| Power limit writes brick hardware | Low | Validate against PKG_POWER_INFO; never write below THERMAL_SPEC |
|
||||
| thermald + rapld race on MSR writes | Low | rapld owns energy reads; thermald owns limit writes; use scheme as synchronization point |
|
||||
|
||||
---
|
||||
|
||||
## 7. References
|
||||
|
||||
### Linux Kernel Source (local/reference/linux-7.1/)
|
||||
|
||||
| File | Lines | Content |
|
||||
|------|-------|---------|
|
||||
| `include/linux/intel_rapl.h` | 269 | Core data structures, domain/primitive enums |
|
||||
| `drivers/powercap/intel_rapl_common.c` | ~2000 | Domain definitions, powercap zone registration, energy read |
|
||||
| `drivers/powercap/intel_rapl_msr.c` | 602 | MSR-based RAPL access (most CPUs use this) |
|
||||
| `drivers/powercap/intel_rapl_tpmi.c` | ~300 | TPMI-based RAPL (newer Intel platforms) |
|
||||
| `drivers/powercap/powercap_sys.c` | ~600 | Powercap framework (sysfs interface) |
|
||||
| `arch/x86/include/asm/msr-index.h` | L490-522 | MSR address definitions |
|
||||
| `arch/x86/events/rapl.c` | ~800 | Perf events RAPL PMU |
|
||||
|
||||
### Intel Documentation
|
||||
|
||||
- Intel SDM Volume 3, Chapter 14.9: "Running Average Power Limit (RAPL)"
|
||||
- Intel SDM Volume 4: MSR definitions (0x606, 0x610-0x619, 0x638-0x641, 0x64D)
|
||||
|
||||
### Existing RedBear Infrastructure
|
||||
|
||||
| File | Content |
|
||||
|------|---------|
|
||||
| `local/recipes/system/redbear-power/source/src/msr.rs` | MSR read/write via `/scheme/sys/msr/` + `/dev/cpu/*/msr` |
|
||||
| `local/recipes/system/redbear-power/source/src/acpi.rs` | `read_rapl_package_energy()` — current sysfs fallback |
|
||||
| `local/recipes/system/redbear-power/source/src/app.rs` | `pkg_power_w`, `rapl_prev` — current RAPL state |
|
||||
| `local/recipes/system/redbear-power/source/src/platform.rs` | Platform probe (Redox vs Linux MSR backend selection) |
|
||||
| `local/recipes/system/cpufreqd/source/src/main.rs` | MSR 0x199 writes via `/scheme/sys/msr/` |
|
||||
| `local/recipes/system/thermald/source/src/main.rs` | MSR 0x19C/0x1A2 via Linux `/dev/cpu/*/msr` only |
|
||||
|
||||
### External References
|
||||
|
||||
| Source | Key Insight |
|
||||
|--------|------------|
|
||||
| Intel SDM Vol.3B §14.9 | Domain hierarchy, unit register layout, power limit semantics |
|
||||
| Intel SDM Vol.4 | All MSR addresses (0x606-0x64D) and bit-field definitions |
|
||||
| Fuchsia RFC-0203 | Microkernel energy monitoring via `zx_system_energy_info()` syscall — kernel owns MSR access, userspace gets cooked µJ values |
|
||||
| Schöne et al. 2021 | AMD Zen 2 RAPL accuracy analysis: package domain ±5%, 1ms update rate |
|
||||
| `rapl-read.c` (deater/uarch-configure) | Reference userspace RAPL reader: unit parsing, counter wrap detection |
|
||||
| AMD `amd_energy` driver README | Per-core accumulation thread, 100s wake interval, SMT dedup |
|
||||
|
||||
---
|
||||
|
||||
## 8. Deliverables
|
||||
|
||||
| Phase | Deliverable | Success Criteria |
|
||||
|-------|------------|------------------|
|
||||
| 1 | `rapld` daemon serving `/scheme/rapl/` | Reads PKG energy on real Intel/AMD hardware, serves power in watts |
|
||||
| 1 | redbear-power reads from rapld | PkgW column shows real hardware power (not n/a) on supported CPUs |
|
||||
| 1 | Graceful degradation on QEMU | RAPL domain "unavailable" instead of crash |
|
||||
| 2 | Power limit read/write | `/scheme/rapl/package/0/limit1_w` returns TDP; writable with CAP_SYS_MSR |
|
||||
| 2 | thermald power-aware throttling | thermald reads RAPL power, throttles when exceeding configurable threshold |
|
||||
| 3 | redbear-power multi-domain display | PKG, Core, DRAM columns with real values |
|
||||
| 3 | Power history sparkline | 30-sample power history visible in Per-CPU tab |
|
||||
@@ -1,61 +1,24 @@
|
||||
# Legacy Obsolete Documents Archive (2026-07-25 Round 5 audit)
|
||||
# Legacy Obsolete Documents — Directory Stub
|
||||
|
||||
This folder contains documents that have been superseded by more
|
||||
recent or canonical versions. They are retained here for historical
|
||||
reference and to preserve the audit trail, but they should NOT be
|
||||
treated as current status.
|
||||
Last updated: 2026-07-27 (doc consolidation)
|
||||
|
||||
## What was moved here and why
|
||||
The deletion/audit trail for all documents previously archived under this
|
||||
directory is recorded in:
|
||||
|
||||
| File | Superseded by |
|
||||
|---|---|
|
||||
| `DRM-MODERNIZATION-EXECUTION-PLAN.md` | `local/docs/3D-DRIVER-PLAN.md` (Rounds 1-5) |
|
||||
| `BUILD-SYSTEM-HARDENING-PLAN.md` | `local/recipes/AGENTS.md` + `local/docs/3D-DRIVER-PLAN.md` |
|
||||
| `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` | Subsumed by Round 1-5 kernel work |
|
||||
| `INITNSMGR-CONCURRENCY-DESIGN.md` | Subsumed by Round 1-3 base work |
|
||||
| `BUILD-SYSTEM-ASSESSMENT-2026-07-18.md` | Subsumed by Round 1-5 build system work |
|
||||
| `PATCH-PRESERVATION-AUDIT-2026-07-12.md` | Round 7 audit; Round 5 refreshed it |
|
||||
| `HOOKS.md` | Subsumed by per-crate inline doc comments |
|
||||
| `redbear-power-improvement-plan.md` | v1.0-1.6 features completed; TUI evolved |
|
||||
| `WAYLAND-IMPLEMENTATION-PLAN.md` | `local/docs/3D-DRIVER-PLAN.md` Rounds 1–7 (Round 6 cleanup, 2026-07-26) |
|
||||
| `NETWORKING-STACK-STATE.md` | `local/docs/NETWORKING-IMPROVEMENT-PLAN.md` (canonical networking plan) |
|
||||
| `RAPL-IMPLEMENTATION-PLAN.md` | Companion of `redbear-power-improvement-plan.md` (already archived); power/energy planning authority now in `CONSOLE-TO-KDE-DESKTOP-PLAN.md` |
|
||||
`local/docs/SUPERSEDED-DOC-LOG.md`
|
||||
|
||||
## Why archive rather than delete
|
||||
After the 2026-07-27 consolidation:
|
||||
|
||||
The Round 1-5 work on the 3D/graphics stack subsumed the
|
||||
DRM-MODERNIZATION-EXECUTION-PLAN's render-path work. The
|
||||
build system hardening work is captured in the per-component
|
||||
`AGENTS.md` files in `local/`, `recipes/`, and `recipes/wip/`. The
|
||||
hook documentation is captured inline in each crate's `AGENTS.md`
|
||||
rather than in a single global file.
|
||||
- The lie-grade / superseded content has been folded into the canonical
|
||||
`local/docs/3D-DESKTOP-COMPREHENSIVE-PLAN.md` (the single source of
|
||||
truth for the 3D-stack audit, blockers, and remediation).
|
||||
- This directory is intentionally retained as a future-archive target.
|
||||
Add new superseded docs here only when no canonical plan exists.
|
||||
|
||||
These files are preserved here because:
|
||||
1. The audit trail matters: future maintainers need to know what was
|
||||
tried, what was rejected, and what was superseded.
|
||||
2. Some content (build system hardening, IRQ enhancement) may be
|
||||
revisited as separate work items.
|
||||
3. The Round 5+ rounds 1-5 each have their own SUPERSEDED log
|
||||
(legacy-superseded-2026-07-12, legacy-absorbed-2026-07-12,
|
||||
legacy-recipe-patches/) — this folder is the Round 5
|
||||
equivalent.
|
||||
## Files in this directory
|
||||
|
||||
## Restoration
|
||||
|
||||
If a future maintainer needs to re-evaluate a moved document:
|
||||
|
||||
```bash
|
||||
git mv local/docs/legacy-obsolete-2026-07-25/<file>.md local/docs/
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- `local/docs/3D-DRIVER-PLAN.md` — current canonical graphics plan (Rounds 1-5)
|
||||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` — current canonical desktop plan
|
||||
- `local/docs/REDBEAR-FULL-SDDM-BRINGUP.md` — current SDDM bring-up status
|
||||
- `local/docs/QT6-WAYLAND-NULL8-DIAGNOSIS.md` — Qt6 null+8 root-cause work
|
||||
- `local/docs/BUILD-CACHE-PLAN.md` — current build cache system
|
||||
- `local/docs/PACKAGE-BUILD-QUIRKS.md` — current build quirks
|
||||
- `local/docs/LOCAL-FORK-SUPREMACY-POLICY.md` — current fork model
|
||||
- `local/docs/QUIRKS-AUDIT.md` — current quirks system
|
||||
- `local/docs/HOOKS.md` (archived) — global hook doc superseded by per-crate docs
|
||||
- `SUPERSEDED.md` (this file)
|
||||
- `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` is **NOT** here;
|
||||
it was restored to top-level (`local/docs/`) in commit `49326998a3` (or
|
||||
its prior equivalent) because it self-declares active authority per §0
|
||||
of that file.
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
# Red Bear OS Wayland Implementation Plan
|
||||
|
||||
> **Note (2026-07-26):** This document's diagnostic content (§§1–2, evidence chain,
|
||||
> crash analysis) remains accurate. The **status table and implementation phases**
|
||||
> below are **superseded** by `local/docs/3D-DRIVER-PLAN.md` Rounds 1–7
|
||||
> (2026-07-26). The null+8 fix patches are committed in source
|
||||
> (qtwaylandscanner + libwayland) but **never runtime-validated in isolation**.
|
||||
> The Phase A instrumented-rebuild runbook (§7.1–7.4) is the prerequisite for
|
||||
> any further status claims.
|
||||
|
||||
**Original header** (kept for historical reference):
|
||||
|
||||
# Red Bear OS Wayland Implementation Plan (RESOLVED — 2026-07-08)
|
||||
|
||||
**Status**: Wayland subsystem builds. Qt6 Wayland, Mesa EGL+GBM+GLES2, KWin building.
|
||||
Hardware compositor validation pending. No framebuffer fallback — Wayland-only path.
|
||||
|
||||
**Canonical desktop path**: see `CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the active plan.
|
||||
|
||||
**Original plan below is kept for historical context.**
|
||||
`wl_proxy_add_listener`) is a bug that must be fixed at the source — in Qt6's auto-generated
|
||||
Wayland wrappers or in the relibc/libwayland client stack.
|
||||
|
||||
**Reasoning:**
|
||||
- Qt6, KF6, and KWin are Wayland-native components. Making them work through a framebuffer
|
||||
abstraction adds complexity without solving the real problem.
|
||||
- The `redbear-compositor` is protocol-compliant and serves 8 Wayland globals. It does not
|
||||
crash. The crash is entirely client-side (Qt6 QPA plugin initialization).
|
||||
- Every workaround (offscreen QPA, redox QPA shim, D-Bus environment overrides) defers the
|
||||
inevitable: Qt6 Wayland must work on Redox.
|
||||
|
||||
**Removed workarounds:**
|
||||
- ~~`QT_QPA_PLATFORM=redox` in greeter-ui main.cpp~~ — removed; greeter must use Wayland
|
||||
- kded6 temporarily uses `offscreen` via `#ifdef Q_OS_REDOX` and D-Bus service `env` until
|
||||
the Qt6 Wayland null+8 crash is fixed. kded6 is a headless D-Bus daemon — using Wayland
|
||||
adds no functionality.
|
||||
|
||||
## Current Blocker: Qt6 Wayland Client Crash
|
||||
|
||||
### Crash Signature
|
||||
|
||||
```
|
||||
Page fault: 0000000000000008 US
|
||||
RAX: 0x0000000000000000 (NULL base pointer)
|
||||
RDX: 0x0000000000000008 (value being written)
|
||||
```
|
||||
|
||||
This is `proxy->object.implementation = listener` in `wl_proxy_add_listener()`
|
||||
where `proxy` is NULL. Offset 8 from NULL = `object.implementation` field
|
||||
in `wl_object` struct, which is at offset 0 of `wl_proxy`.
|
||||
|
||||
### Ruled Out
|
||||
|
||||
| Hypothesis | Verdict | Evidence |
|
||||
|-----------|---------|----------|
|
||||
| relibc `calloc` doesn't zero | **FALSE** | `header/stdlib/mod.rs:276` — `ptr.write_bytes(0, size)` runs unconditionally |
|
||||
| Compositor protocol bug | **FALSE** | Compositor doesn't crash; client crashes before any compositor events exchanged |
|
||||
| `wl_display_connect()` returns NULL | **FALSE** | Qt checks: `if (mDisplay) setupConnection()` |
|
||||
| `wl_display_get_registry()` returns NULL | **FALSE** | My null guard `if (!registry) _exit(1)` catches this |
|
||||
| libwayland `proxy_create()` returns NULL | **UNLIKELY** | Only fails on OOM or `wl_map_insert_new` failure; Qt would catch NULL |
|
||||
|
||||
### Most Likely Cause
|
||||
|
||||
The crash is in `QWaylandDisplay::init(registry)` → `wl_registry_add_listener()`.
|
||||
The `registry` pointer is valid (caught by null guard), but the **Qt6 object wrapping it**
|
||||
may have internal NULL members. Specifically, the auto-generated `QtWayland::wl_registry`
|
||||
wrapper stores the C `wl_registry*` in `m_wl_registry`. If `this` (the QWaylandDisplay
|
||||
object) is partially constructed when `init_listener()` runs, `m_wl_registry` could be
|
||||
uninitialized.
|
||||
|
||||
Alternatively: the crash may be in a **subsequent** proxy creation — Qt6 binds `wl_compositor`,
|
||||
`wl_shm`, or other globals during initialization, and one of those proxy creations returns
|
||||
NULL that Qt doesn't check.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase A: Diagnose Exact Crash Point (1-2 hours)
|
||||
|
||||
1. Add `fprintf(stderr, "registry=%p this=%p\n", registry, this)` before `init(registry)`
|
||||
in `qwaylanddisplay.cpp:setupConnection()`
|
||||
2. Add `fprintf(stderr, "m_wl_registry=%p\n", m_wl_registry)` at entry of `init_listener()`
|
||||
in generated `qwayland-wayland.cpp`
|
||||
3. Add null guards at every `wl_registry_add_listener` and `wl_proxy_add_listener` call site
|
||||
4. Rebuild, boot, observe which fprintf appears before the crash
|
||||
|
||||
### Phase B: Add Null Safety to Qt6 Generated Wrappers (2-4 hours)
|
||||
|
||||
The `qtwaylandscanner` tool generates wrapper code from Wayland XML protocol definitions.
|
||||
The generated `init()` and `init_listener()` functions assume non-null proxies.
|
||||
|
||||
1. Patch `qtwaylandscanner` to emit null-checks before each `wl_*_add_listener()` call
|
||||
2. Or: patch the generated output directly in the build tree
|
||||
3. Add `if (!m_wl_registry) { qWarning(...); return; }` guards
|
||||
|
||||
### Phase C: Audit libwayland Client Initialization (2-4 hours)
|
||||
|
||||
1. Add logging to `proxy_create()` — log every proxy creation with pointer value
|
||||
2. Add logging to `wl_proxy_add_listener()` — log proxy pointer
|
||||
3. Verify `factory->display` is never NULL at `proxy_create:483`
|
||||
4. Check if `pthread_mutex_lock`/`pthread_mutex_unlock` works correctly on Redox
|
||||
(mutex corruption could cause `wl_map_insert_new` to return 0)
|
||||
|
||||
### Phase D: Fix Root Cause (4-8 hours)
|
||||
|
||||
Based on Phase A-B-C findings, implement the actual fix:
|
||||
- If null proxy: fix the creation path
|
||||
- If null `factory->display`: fix the display initialization
|
||||
- If mutex issue: fix relibc pthread
|
||||
- If Qt6 wrapper bug: upstream the null-safety patch
|
||||
|
||||
### Phase E: Remove Workarounds (1 hour)
|
||||
|
||||
Once Qt6 Wayland works:
|
||||
1. Remove `QT_QPA_PLATFORM=redox` from `greeter-ui/main.cpp`
|
||||
2. Remove `Environment=QT_QPA_PLATFORM=offscreen` from D-Bus kded6 service
|
||||
3. Remove `QT_QPA_PLATFORM=offscreen` from `redbear-kde-session`
|
||||
4. Let kded6 and greeter-ui use native Wayland
|
||||
|
||||
## Compositor Status
|
||||
|
||||
The `redbear-compositor` is **protocol-compliant** and **runtime-proven** (QEMU).
|
||||
|
||||
### Globals Served (8)
|
||||
|
||||
| Global | Version | Status |
|
||||
|--------|---------|--------|
|
||||
| `wl_compositor` | 4 | ✅ Implemented |
|
||||
| `wl_shm` | 1 | ✅ Implemented (ARGB8888, XRGB8888) |
|
||||
| `wl_shell` | 1 | ✅ Implemented |
|
||||
| `wl_seat` | 5 | ✅ Name + pointer capability |
|
||||
| `wl_output` | 3 | ✅ Geometry, mode, scale, done |
|
||||
| `xdg_wm_base` | 1 | ✅ Get/surface/toplevel + configure |
|
||||
| `wl_data_device_manager` | 3 | 🔧 Stub (accepts bind, no events) |
|
||||
| `wl_subcompositor` | 1 | 🔧 Stub (accepts bind, no events) |
|
||||
|
||||
### Rendering
|
||||
|
||||
Framebuffer compositing via `/scheme/display` (vesad). Software only.
|
||||
Hardware DRM/KMS rendering depends on `redox-drm` driver maturity.
|
||||
|
||||
## Evidence Model
|
||||
|
||||
| Class | Meaning |
|
||||
|-------|---------|
|
||||
| **builds** | Package compiles and stages |
|
||||
| **boots** | Image reaches prompt or known runtime surface |
|
||||
| **runtime-proven (QEMU)** | Works end-to-end in QEMU |
|
||||
| **runtime-proven (bare metal)** | Works on real hardware |
|
||||
| **validated** | Repeated proof on intended target class |
|
||||
|
||||
### Current Status
|
||||
|
||||
| Component | Class | Notes |
|
||||
|-----------|-------|-------|
|
||||
| `redbear-compositor` | **runtime-proven (QEMU)** | Accepts connections, composites framebuffer |
|
||||
| `libwayland` client | **builds** | Upstream code; Redox eventfd patch for server only |
|
||||
| `libwayland` server | **builds** | Not used — compositor is pure Rust |
|
||||
| Qt6 Wayland QPA | **build-verified; runtime gated** | Crashes at null+8 during `wl_registry` init |
|
||||
| KWin Wayland | **builds** | Real cmake build; blocked by Qt6Quick/QML |
|
||||
| Wayland protocols | **builds** | `wayland-protocols` package builds |
|
||||
|
||||
## Next Milestone
|
||||
|
||||
**Qt6 Wayland client boots without crashing.**
|
||||
|
||||
Success criterion: `redbear-compositor: client 65536 connected` followed by
|
||||
`redbear-compositor: dispatch` (not a page fault).
|
||||
|
||||
### Build Dependency Chain (Critical, discovered 2026-05-06)
|
||||
|
||||
When modifying libwayland source or `local/patches/libwayland/redox.patch`, the
|
||||
full chain must be rebuilt:
|
||||
|
||||
```
|
||||
libwayland recipe → repo/x86_64-unknown-redox/libwayland.pkgar
|
||||
qtbase recipe → copies pkgar into sysroot → links Qt6 Wayland QPA
|
||||
kf6-kded6 recipe → links against qtbase/sysroot/libwayland-client.a
|
||||
```
|
||||
|
||||
**Failure mode**: Modifying only libwayland does NOT update qtbase's static copy
|
||||
of `libwayland-client.a`. The old binary persists in qtbase's sysroot. All
|
||||
three recipes must be force-rebuilt (delete `target/` directories) AND the
|
||||
repo pkgar cache must be regenerated.
|
||||
|
||||
**Recovery**: If `repo/x86_64-unknown-redox/libwayland.pkgar` is deleted, a
|
||||
backup exists at `packages/x86_64-unknown-redox/libwayland.pkgar`.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,37 +0,0 @@
|
||||
# Legacy Recipe Patch References
|
||||
|
||||
These .patch symlinks previously lived under `recipes/core/<comp>/`
|
||||
as visible-by-navigating references to the patches that modified each
|
||||
fork. After the 2026-07 refactor (fork patches fully absorbed into
|
||||
fork commits), the symlinks violated AGENTS.md § "Local Fork Recipe
|
||||
Directories Must Not Carry Patch Files" and were moved here.
|
||||
|
||||
## What's in here
|
||||
|
||||
For each affected component, a directory of symlinks points at the
|
||||
real patch files in `local/patches/<comp>/`. The patches are git-
|
||||
tracked both here and in their canonical `local/patches/<comp>/`
|
||||
location — these legacy symlinks are a navigation aid only.
|
||||
|
||||
## Why we keep them
|
||||
|
||||
Per AGENTS.md "absolutely NEVER delete" rule, these patches represent
|
||||
durable Red Bear work that must never be removed. Moving the symlinks
|
||||
out of `recipes/core/<comp>/` (where the cookbook would never apply
|
||||
them because recipes use `path = "..."` source for the local fork)
|
||||
cleans up the build-system surface while preserving the historical
|
||||
record.
|
||||
|
||||
## Affected components
|
||||
|
||||
- base (61 legacy patches)
|
||||
- kernel (26 legacy patches)
|
||||
- relibc (46 legacy patches)
|
||||
- bootloader (3 legacy patches)
|
||||
- installer (1 legacy patch)
|
||||
|
||||
Total: 137 legacy patch references.
|
||||
|
||||
If a fork is ever re-fetched from upstream and a Phase 0+1 patch
|
||||
recovery commit is lost, the patches under `local/patches/<comp>/`
|
||||
remain untouched and can be re-applied via `local/scripts/apply-patches.sh`.
|
||||
Reference in New Issue
Block a user