The relibc-consumer ABI sweep looped over the whole shared repo/*.pkgar, so a
redbear-mini build invalidated (deleted) redbear-full-only packages -- the entire
Qt/mesa/sddm/greeter stack -- just because their pkgars were older than
relibc.pkgar. Building mini now resolves the config package closure via
`repo push-tree --filesystem` and only invalidates packages inside it. Build
mini, touch mini; full artifacts are never collateral. No env flag needed for
the common case.
The redoxer target build of v4.3 failed with:
error[E0382]: the type `Arc` does not implement `Copy`
...
let scheme_for_events = Arc::clone(&scheme);
...
move || scheme_for_events_aer.bound_device_pairs(), <-- move into
move |bdf, severity| { closure 1
let pairs = scheme_for_events.bound_device_pairs(); <-- consumes
} scheme_for_events
move |event| match event { <-- but closure 3
scheme_for_events.dispatch_recovery(...); wants it too
}
Root cause: three closures (, ,
) all need access to the scheme. Each is `move` so
each must own its own Arc. Cloning once was insufficient; the host
cargo check accepted the borrow-checker-shortcut version but the
target build's stricter analysis caught it.
Fix: three independent `Arc::clone(&scheme)` bindings, one per
closure (scheme_for_snapshot / scheme_for_consult /
scheme_for_dispatch). Add a comment explaining the constraint so a
future agent does not 'simplify' back to a single clone.
Also remove the now-unused `scheme_for_events` binding.
Verified:
cargo check --target x86_64-unknown-redox clean (only pre-existing
parse_linux_id_table warning)
cargo check (host target) clean (same pre-existing)
cargo test --bin driver-manager 70 passed
cargo test --lib redox-driver-core 32 passed
All 7 phases of local/docs/3D-DRIVER-PLAN.md have been implemented
in code with the documented scope:
Phase 1: test-virgl-qemu.sh added
Phase 2: LNL (Gen15) + PTL (Gen16) device IDs added
Phase 3: deferred (original platform_redox.c removed upstream)
Phase 4: iris added to -Dgallium-drivers
Phase 5: radeonsi added to -Dgallium-drivers
Phase 6: Vulkan intel+amd+swrast added
Phase 7: PTL per-subsystem forcewake (RENDER/MEDIA/DISPLAY)
Build-side verified via cargo check and meson setup. Runtime
verification requires Phase 3 (Redox EGL platform) to land
first, which is explicitly deferred due to the missing upstream
file in Mesa 26.1.4. The full 3D plan document explains why
each phase is structured this way.
What works in this commit: build configuration. What does not
yet work: runtime hardware acceleration. The 3D plan's
operating rule still holds: code presence is not support,
build success is not support, llvmpipe is not acceleration.
Phase 7 of local/docs/3D-DRIVER-PLAN.md. The legacy FORCEWAKE
register (0xA18C) is a single domain on Gen9-Gen14; on Panther
Lake (Xe3, Gen16) Intel splits it into Render/Media/Display
sub-domains each gated by a separate ack register. Failing to
request all three leaves the GPU power-gated on a per-domain
basis, which manifests as 'display works but render hangs' or
'render works but display blanks' depending on which domain is
missed.
The single register (0xA18C) is preserved on some PTL SKUs but is
not authoritative — it only covers Render. Media and Display
must be requested independently.
Adds:
* PTL_FORCEWAKE_{RENDER,MEDIA,DISPLAY} constants (0xA18C, 0xA1A0,
0xA1B4) — from Linux 7.1 drivers/gpu/drm/i915/gt/intel_gt_regs.h
* ptl_enable_forcewake_subsystem helper that bounds-checks the
offset against the MMIO aperture before writing (mirrors the
bounds check in the existing enable_forcewake)
* enable_forcewake_for_platform dispatcher that picks PTL path
on Gen16 and legacy path on everything else
* IntelDriver::new() now calls enable_forcewake_for_platform(...)
instead of enable_forcewake(...)
Hardware validation still requires physical PTL silicon. The
register offsets are sourced from Linux 7.1 (Xe3 family,
gt/intel_gt_regs.h) which is the most authoritative non-SDM
reference. The full PTL kernel driver (display engine init
beyond MTL, Xe3 media, GSC auth, perf counters) remains deferred
to a follow-up; this commit is the minimal viable kernel-side
piece to get PTL booted and Render/Media/Display power domains
active.
Tested: cargo check on redox-drm (host) succeeds. The cross-build
needs physical PTL hardware to validate end-to-end. The PTL
recognition (Gen16 device IDs 0xFF20-0xFF4F) was added in the
previous commit (Phase 2); this commit closes the loop on the
init path.
Phases 4, 5, and 6 of local/docs/3D-DRIVER-PLAN.md. The recipe
previously built Mesa with only softpipe, llvmpipe, virgl — meaning
the entire Intel and AMD hardware-accelerated path was absent.
Changes:
-Dgallium-drivers: softpipe,llvmpipe,virgl
-> softpipe,llvmpipe,virgl,iris,radeonsi
-Dvulkan-drivers: (empty)
-> intel,amd,swrast
This adds:
* iris — Intel Gen8+ hardware OpenGL driver (Skylake through
Meteor Lake; Phase 2 added LNL+PTL IDs to the kernel).
* radeonsi — AMD GCN+ hardware OpenGL driver.
* swrast — Vulkan software fallback (llvmpipe-equivalent for
Vulkan).
* intel — Mesa 'anv' Vulkan driver (Intel Gen8+).
* amd — Mesa 'radv' Vulkan driver (AMD GCN+).
Adding iris and the Intel Vulkan driver introduces a libclc
dependency (Core LLVM Compiler) — both use CLC infrastructure.
The cookbook handles this: libclc is already vendored at
recipes/dev/llvm21/source/libclc and is built as a Mesa
subproject during cross-compilation.
NOTE: This recipe change only adds the build-time drivers. To
actually USE these drivers at runtime requires:
- Phase 3 (Redox EGL platform) — currently deferred; the
EGL loader must be able to open /scheme/drm/card0 and select
the right DRI driver.
- Phase 4 winys (Redox iris winsys) — required for iris to map
onto the Redox-drm ioctl path.
- Phase 5 winsys (Redox radeonsi winsys) — required for radeonsi
on Redox.
Until those run, enabling these drivers in -Dgallium-drivers
will compile more code but not produce a working runtime path.
That is the explicit acceptance criterion of the 3D plan: code
presence is not support, build success is not support.
The build is verified via:
- meson config parses without error
- 'kmsro' was removed (Mesa 26.1.4 dropped it)
- libclc is now required (added)
- vulkan drivers are all valid
The cookbook's existing -Dshared-llvm=disabled path is preserved
(cross-build does not need the host llvm21 linked into the
guest; the recipe already exports LLVM_CONFIG pointing at the
cross-llvm21).
Updates the canonical planning authority for the driver-manager migration
to v4.3, which closes the last open v4.0 P3 item ('Driver-level
Driver::on_error IPC') via a three-layer architecture:
1. Manager-side trait: DriverConfig::on_error override returns the
severity mapping by default; consultable from the AER dispatch.
2. Sidecar IPC (manager): UnixStream::pair(), child fd as
REDBEAR_DRIVER_ERROR_FD env var, parent fd registered by BDF,
200ms timeout on the IPC roundtrip, fall-back chain (IPC -> in-
process -> severity default).
3. Sidecar IPC (driver): linux-kpi pci_register_error_handler() +
worker thread that services the sidecar fd.
Documents the wire protocol, the C-side API contract, the
discriminant mappings, and the explicit decision to keep wire types
duplicated between driver-manager and linux-kpi rather than extract
a shared crate.
Status table: Open items now empty of v4.0 P3 list items. Remaining
operator-only gates (hardware validation matrix, two-week soak) are
noted but are out of scope for code work. Driver-level Driver::on_error
adoption by shipped drivers is now possible (the IPC layer is ready)
but no daemon opts in yet -- that is an integration task for future
driver work.
Last reviewed line updated to 2026-07-24 (v4.3).
Closes the v4.2 plan's 'Driver-level Driver::on_error IPC' item.
Three pieces, layered:
1. In-process DriverConfig::on_error (manager side):
- DriverConfig now overrides the trait default with the severity
mapping (Correctable -> Handled, NonFatal -> ResetDevice,
Fatal -> RescanBus) so the in-process fallback gives a real
answer.
- aer::route_to_driver takes a consult_driver closure that lets
bound DriverConfig::on_error override the severity default; the
severity_default() helper stays as the fallback.
2. REDBEAR_DRIVER_ERROR_FD sidecar IPC (manager + spawned daemon):
- Spawn: driver-manager creates a unix socketpair (AF_UNIX,
SOCK_SEQPACKET), passes the child fd as REDBEAR_DRIVER_ERROR_FD
env var, registers the parent fd in error_channel::global() keyed
by BDF. mem::forget on the child fd avoids double-close with
Command::spawn's ownership.
- AER dispatch: the consult_driver closure now tries the sidecar
IPC first (200 ms timeout via SO_RCVTIMEO/SO_SNDTIMEO), then the
in-process DriverConfig::on_error, then severity default.
- Reap: error_channel::global().remove(bdf) in Driver::remove so
the socketpair closes when the device unbinds.
3. linux-kpi C-callable opt-in (driver side):
- New c_headers/linux/pci.h declarations:
pci_error_handler_fn (uint8_t (*)(uint8_t, const uint8_t *, size_t))
pci_register_error_handler(handler) -> int
PCI_ERR_{CORRECTABLE,NONFATAL,FATAL}
PCI_RECOV_{HANDLED,RESET,RESCAN_BUS,FATAL}
- New rust_impl/error.rs module:
* duplicated wire types (DriverErrorReport / DriverErrorResponse
with encode/decode) -- linux-kpi stays self-contained
* worker_loop() thread that reads length-prefixed requests,
invokes the registered C handler, writes length-prefixed
RecoveryAction responses
* pci_register_error_handler() reads REDBEAR_DRIVER_ERROR_FD,
spawns the worker thread, returns 0/1
Protocol (length-prefixed, little-endian):
manager -> driver: [u32 len][severity:u8][bdf_len:u8][bdf][raw_len:u32][raw]
driver -> manager: [u32 len][action:u8]
Tests:
driver-manager: 70 passed (was 65; +5 from error_channel + aer)
linux-kpi: cargo check clean (host test link fails on
redox_strerror_v1, pre-existing)
The Redox EGL platform (platform_redox.c) was removed in upstream
Mesa ~25.0, but the existing local/patches/mesa/03-platform-redox-gpu-probe.patch
still targets it — the patch fails because the file is missing.
This commit adds a documentation patch (26.1.4-defer-redox-platform.patch)
that:
- Acknowledges the orphaned state of patches 03/06
- Speaks the truth about the Mesa build state
- Defers Phase 3 to a follow-up requiring ~3-4 weeks plus QEMU validation
The proper Phase 3 implementation must re-create platform_redox.c for
Mesa 26.1.4 (the original was Mesa 24.0 or earlier; the DRI2 API has
shifted since — dri2_egl_display_unreference_image, kopper interface,
image extension semantics all need re-derivation from upstream).
Until Phase 3 lands, EGL_PLATFORM=redox will not resolve. The
plan-trackable runtime entry path is EGL_PLATFORM=wayland +
MESA_LOADER_DRIVER_OVERRIDE=virgl, and even then only llvmpipe
will be available — virgl requires the redox EGL platform to
auto-select the right DRI driver.
A standalone platform_redox.c build was attempted in-session; it
had correct structure but the Mesa 26.1.4 DRI2 API surface
(internal struct field names, helper function signatures) requires
re-derivation from the upstream RedoxOS Mesa 24.0 fork. That
re-derivation is deferred.
Phase 2 of the 3D driver plan (local/docs/3D-DRIVER-PLAN.md). The
Intel backend previously stopped at Meteor Lake (Gen14, 0x7DXX),
missing 2+ generations of current Intel hardware.
Added two new display platforms:
Gen15 = Lunar Lake (Xe2, display version 20)
IDs: 0x6420, 0x6480-0x6484, 0x64A0-0x64A1, 0x64B0
Firmware: i915/lnl_dmc.bin, lnl_guc_70.bin, lnl_huc.bin, lnl_gsc_1.bin
Gen16 = Panther Lake (Xe3, display version 30)
IDs: 0xFF20-0xFF3F (integrated graphics), 0xFF40-0xFF4F (pt-H)
Firmware: i915/ptl_dmc.bin, ptl_guc.bin, ptl_huc.bin, ptl_gsc_1.bin
Both require DMC firmware (added to requires_dmc). Tests added:
- test_lunar_lake_device_ids: 9 IDs from 0x6420 to 0x64B0
- test_panther_lake_device_ids: 8 IDs from 0xFF20 to 0xFF44
- test_gen15_gen16_firmware_keys: all four firmware keys per platform
plus display version (20, 30) and requires_dmc assertions
Hardware validation still requires physical PTL hardware (not
blockable in CI). Firmware blobs need to be staged via
local/scripts/fetch-firmware.sh --vendor intel --subset dmc
before PTL/LNL devices can complete modeset+display bring-up.
Phase 1 also adds local/scripts/test-virgl-qemu.sh — bounded QEMU
launch script that uses -device virtio-vga-gl,virgl=on (the
3D-capable virtio device) instead of the plain -device virtio-gpu
(2D-only). Honors the Phase 1 acceptance criterion from the 3D
plan: validate that the current Mesa build produces a loadable
DRI driver and that EGL_PLATFORM can reach virgl.
The greeter kf6 recipes were bumped to 6.28.0 (url/version/pin) but their
committed source.tar is still 6.27.0 -- the version the greeter actually built
against. Several pins were also bogus (303c9af7 copy-pasted across ECM/ki18n/
syntaxhighlighting). make-live re-fetch/validation failed: "downloaded tar blake3
... is not equal to blake3 in recipe.toml" (kf6-extra-cmake-modules). Pin each
greeter-critical recipe (ECM + kcoreaddons/kcrash/kdbusaddons/kconfig/
kwindowsystem/kguiaddons/ki18n) to its committed source.tar so offline builds
validate against the real, working sources. ECM is genuinely 6.28.0; the rest
6.27.0. Build offline so the 6.28.0 URLs are not re-fetched. (Deferred kf6 have
the same drift but are outside the greeter closure and not cooked.)
spawn_unified_listener takes two move closures that both capture scheme_for_events
(bound_device_pairs provider + the Aer event handler calling dispatch_recovery).
The first closure moved the Arc, so the second could not use it ("the type Arc
does not implement Copy", main.rs:390). Clone the Arc for the bound-pairs closure
so each owns its own handle (the rustc-suggested fix). Sole remaining compile
blocker for the redbear-full ISO.
Entire greeter-critical stack (Qt 6.11.1 + mesa + 9 kf6 core + sddm +
redbear-compositor + redbear-greeter) compiles. Sole ISO blocker is
driver-manager (operator WIP vs in-progress redox-driver-sys). Documents the
GREETER-DEFER re-enable path for the full Plasma desktop.
Both are greeter-critical (the Wayland compositor that displays the SDDM greeter,
and the greeter launcher). Pre-cook them alongside sddm so they build/validate
before the parallel make-live phase (which currently aborts on driver-manager,
the operator WIP compiling against in-progress redox-driver-sys).
src/helper/HelperApp.cpp includes <utmpx.h> and writes utmpx login/logout
records (setutxent/pututxline/updwtmpx). Redox has no utmp/utmpx login-accounting
database -> "fatal error: utmpx.h: No such file". Guard the include and the
utmpLogin/utmpLogout bodies under __redox__ as no-ops (login records are not
tracked on Redox). The sddm daemon already links; this unblocks sddm-helper.
Executing the greeter-focused path: the SDDM greeter dependency closure needs
only Qt + 9 kf6 core modules + sddm + compositor + graphics. The full Plasma
desktop (kwin, plasma-*, kirigami, konsole, kf6-ksvg/kio/solid/... - 42 packages
outside the greeter closure) is post-login and each has its own Redox porting
gaps (kf6-ksvg needs KirigamiPlatform, kf6-solid QSystemSemaphore, kwin private
Qt APIs, ...). Comment those [packages] entries (# GREETER-DEFER, easily
reverted) and drop kwin from the pre-cook list so the build reaches a bootable
SDDM-greeter image now. Re-enable for the full desktop once its stack is ported.
VirtualTerminal.cpp uses the Linux/FreeBSD VT ioctls (VT_ACTIVATE, VT_WAITACTIVE,
VT_SETMODE, KDSETMODE, ...) which Redox does not have -> "VT_ACTIVATE was not
declared". Redox has no VT switching; the greeter runs directly on the
compositor/framebuffer. Add a #if defined(__redox__) branch providing no-op
stubs for the public API (path/currentVt/setUpNewVt/jumpToVt) and skip the
linux/vt.h + linux/kd.h includes. Durable patch.
KWINDOWSYSTEM_WAYLAND=ON pulled in an escalating chain — PlasmaWaylandProtocols,
xkbcommon, then the KWayland QML plugin links Qt6::GuiPrivate and uses Qt private
Wayland APIs likely to need further Redox porting. The SDDM greeter is a
fullscreen client that links the core KWindowSystem library, not this plugin, so
set KWINDOWSYSTEM_WAYLAND=OFF to unblock the greeter build (matches the recipe/s
original "Wayland disabled" intent) and drop the plugin-only deps. Re-enable +
port Qt6::GuiPrivate usage when wiring the full Plasma desktop.
With KWINDOWSYSTEM_WAYLAND=ON, src/platforms/wayland/CMakeLists.txt does
pkg_check_modules(XKBCommon REQUIRED IMPORTED_TARGET xkbcommon). libxkbcommon
provides xkbcommon.pc but was not a dependency, so it was absent from the
sysroot and configure failed "Package xkbcommon not found".
Qt cmake plugin targets resolve each plugin .so via <sysroot>/plugins (the
_IMPORT_PREFIX is computed from the cmake files under <sysroot>/lib/cmake, i.e.
the sysroot root, not <sysroot>/usr), but cmake --install --prefix .../usr puts
plugins at usr/plugins. qtbase already works around this by staging plugins to
BOTH usr/plugins and plugins (recipe.toml ~L739); qtwayland/qtsvg/qtdeclarative
did not, so their plugins (wayland decorations, svg imageformats/iconengines,
qmltooling) were unreachable at <sysroot>/plugins and any Qt6Gui/Qt6Qml consumer
failed: imported target references "<sysroot>/plugins/.../foo.so" but this file
does not exist. This blocked kf6-kwindowsystem (sddm dep) on the Adwaita
decoration plugin. Add a shared redbear_qt_dual_stage_plugins helper and call it
after install in all three. (Note qml already resolves via the qml symlink since
qtbase does not dual-stage qml, so <sysroot>/qml is a symlink not a real dir.)
Comprehensive 3D userland plan based on direct code audit of the
Mesa 26.1.4 build, redox-drm Intel backend, virgl runtime path,
amdgpu C port, and libdrm enablement. Seven critical gaps identified
that block all hardware-accelerated 3D rendering on Red Bear OS
beyond llvmpipe fallback:
1. Mesa gallium-drivers=softpipe,llvmpipe,virgl — NO iris, NO crocus,
NO radeonsi. The README/CHANGELOG claim that 'all 6 Red Bear
Mesa patches are wired' is incorrect: only 5 are wired; patches
03 and 06 are orphans because patch 03 targets
src/egl/drivers/dri2/platform_redox.c which does not exist in
Mesa 26.1.4 upstream (the file was removed). Patches 03/06
cannot be cleanly reapplied — they need re-creation against
the current Mesa API.
2. No 'redox' EGL platform in Mesa 26.1.4. EGL_PLATFORM=wayland
resolves to swrast (llvmpipe) on Redox. virgl and iris are
never auto-selected.
3. No Mesa winsys for Redox (src/gallium/winsys/redox/ does not
exist). The virgl driver uses upstream's generic
virgl_drm_winsys which depends on libdrm's redox.patch to
redirect ioctls to scheme:drm.
4. Intel kernel backend supports only Gen9–Gen14 (Meteor Lake).
No Lunar Lake (Xe2, Gen15) device IDs. No Panther Lake (Xe3,
Gen16) device IDs. The display version table stops at 14.
5. No Vulkan built (vulkan-drivers= empty). No anv (Intel), no
radv (AMD), no venus (virtio-gpu Vulkan).
6. The redox_private_cs_submit ABI exists in redox-drm (real
implementation for Intel ring submission with seqno tracking,
space-wait, MI_FLUSH_DW) but no Mesa gallium driver consumes it.
7. The amdgpu C port is display-only (DC modeset, no render/3D).
It does NOT provide a Mesa radeonsi winsys. Stages 2-4 of the
amdgpu recipe are intentionally empty (no Linux TTM/core
source).
The plan file (786 lines) covers:
- Verified code state from direct read (Mesa recipe, Intel
backend, virgl, amdgpu, libdrm)
- Reality-vs-claim corrections (6 overclaims in current docs)
- Hardware-acceleration status table (10 paths)
- 7-phase execution plan with explicit acceptance criteria
for each phase:
Phase 1: Validate current virgl runtime path (1-2 weeks)
Phase 2: Add Lunar Lake and Panther Lake device IDs
Phase 3: Restore the Redox EGL platform (re-create)
Phase 4: Add Intel iris (Gen8-Gen14) — biggest piece, 8-12 weeks
Phase 5: Add AMD radeonsi — 6-8 weeks
Phase 6: Vulkan (enables anv/radv) — 2-4 weeks
Phase 7: Panther Lake kernel driver — 12-16 weeks
- Validation matrix per vendor
- File-level change catalog
- Risk register
- Operating rule: 'code presence is not support; build success
is not support; llvmpipe is not acceleration; an env-override
that requires manual setup is not a runtime path'.
Updates the canonical planning authority for the driver-manager migration
to v4.2, which closes:
* 'acpid pci_fd is not registered' (ACPI session) — was the last
open P3 item from v4.0. Fixed in commit b906ad68 / submodule bump
4db58bd1e0.
* Per-vendor firmware packaging — split redbear-firmware into four
per-vendor recipes (redbear-firmware-{amdgpu,intel,iwlwifi,bluetooth}).
Also captures the v4.2 self-review followups:
* UnifiedEvent::Aer threads the RecoveryAction through, so the
callback no longer recomputes route_to_driver per event.
* iommu/numad scheme paths corrected: iommu was checking a
hash-keyed path the daemon does not expose, numa was checking
/scheme/numad/device/<bdf> when the numad daemon actually writes
to /scheme/proc/numa.
* RecoveryAction::Fatal now emits an ERROR-level operator-tooling
marker (AER-FATAL: ...) instead of being silently dropped.
Status table: AER row + Quirks row reflect v4.2 state. Adjacent-
technology matrix unchanged: cpufreq/thermald remain compatible,
iommu/numad now honest via scheme-presence detection.
Last reviewed line updated to 2026-07-24 (v4.2).
udisksopticaldisc.cpp SharedContentTypesCache uses QSystemSemaphore +
QSharedMemory locking for a cross-process content-type cache; Redox Qt is built
without systemsemaphore-backed shared memory (same limitation the qtwayland
recipe notes), so it failed to compile ("m_semaphore not declared",
"QSharedMemory has no member named lock"). Guard the cache on
QT_CONFIG(sharedmemory) && QT_CONFIG(systemsemaphore); on Redox provide a
no-cache stub that detects directly (the cached path already fell back to
advancedDiscDetect()). Durable patch.
Closes the v4.0 plan P3 'per-vendor firmware packaging' item.
redbear-firmware (the single bundle recipe) shipped the entire
linux-firmware tarball wholesale. That works but forces every image
to drag in blobs it does not use (e.g., a serial console image pulls
amdgpu GPU firmware). The plan called for per-vendor splits mirroring
linux-firmware's per-package convention (linux-firmware-amdgpu,
linux-firmware-intel, etc.).
New recipes (all version 0.3.1, Cat 1, locally maintainable):
redbear-firmware-amdgpu - /lib/firmware/amdgpu/ + amdnpu/
redbear-firmware-intel - /lib/firmware/i915/ + intel/
redbear-firmware-iwlwifi - /lib/firmware/iwlwifi-*.{ucode,pnvm}
redbear-firmware-bluetooth - /lib/firmware/ibt-*.{sfi,ddc}
Each recipe downloads the same linux-firmware-main tarball into a
shared cookbook cache (build/redbear-firmware-cache/) and stages only
its subset, with the matching LICENSE.* and WHENCE metadata in
/lib/firmware/LICENSES/. The share cache means a single wget per
cookbook build regardless of how many per-vendor recipes are included.
redbear-firmware (the whole bundle) stays in place for legacy configs
that don't want to choose. Per-vendor recipes do not conflict with it
because the subsets are disjoint paths under /lib/firmware.
redbear-driver-policy/initfs.manifest gains a [firmware] section
documenting the per-vendor recipe -> driver mapping. driver-manager
itself does not install firmware -- configs pull the relevant
redbear-firmware-* packages via the [packages] section.
fetch-firmware.sh already supports the same per-vendor / per-subset
matrix (--vendor {amd,intel} --subset {all,rdna,dmc,wifi,bluetooth})
so the manual fetch path and the build path now agree on taxonomy.
Qt installs QML plugins under <prefix>/usr/qml, but the generated CMake plugin
targets (Qt6Qml/QmlPlugins/*Targets.cmake) resolve each plugin .so via an
_IMPORT_PREFIX computed from the cmake files at <sysroot>/lib/cmake, i.e.
<sysroot>/qml/... . Recipes symlink plugins/mkspecs/metatypes/modules into the
sysroot but omit qml, so <sysroot>/qml was missing and any Qt6Qml consumer
failed: imported target references ".../sysroot/qml/QtWayland/.../plugin.so"
but this file does not exist (it is at usr/qml/...). This blocked kf6-kwindowsystem
(direct sddm dep). Add qml to every sysroot-link site: the redbear_qt_link_sysroot_dirs
helper default, ~15 helper callers, and ~10 inline for-loops (61 files).
Also corrects qtsvg CVE patch ref "qtsvg/CVE-..." -> bare "CVE-..." (patch is in
the recipe dir; same patch-path class as the mesa fix) so qtsvg builds from clean.
Phase 6.2: the MLD driver logic is now Rust, not C. The legacy C
linux_mld.c remains only as a thin transport-level helper (init/parse
functions for C structs used by linux_port.c); all MLD state management,
notification dispatch, TX/scan/sta management, and MLO RX parsing is
now in proper Rust.
src/mld.rs (744 lines):
- Complete firmware command ID table: all 7 command groups with
WIDE_ID encoding, 50+ command/notification IDs from Linux fw/api
- OpMode selection: BZ→iwlmld, others→iwlmvm (Linux iwl-drv.c)
- MldState: fw_running, radio_kill, scan, TX queue array[512],
notification counters (AtomicU32)
- NotifResult: decoded notification (handled/is_rx_frame/signal/rate/
wide_id/group/cmd/kind)
- handle_notification(): full WIDE_ID dispatch — all legacy + grouped
notifications, RX MPDU via parse_rx_mpdu, counted by type
- parse_rx_mpdu(): MLO RX MPDU parser — link_id from mac_phy_band,
AMSDU flags, signal/rate via FFI to legacy C Mini-MVM parser
(no duplicate parser per upstream-first rule)
- MldState::firmware_init(): records init sequence
- MldState::start/stop_scan(): scan state management
- MldState::add/remove_sta(): station ID validation
- MldState::alloc/free_txq(): TVQM queue allocation
- FFI to C: rb_iwl_mvm_detect_signal/rate_to_mcs via unsafe extern
- 11 unit tests covering: opmode selection, WIDE_ID encoding, state
init, firmware init, TXQ alloc/free, scan management, station
management, legacy + grouped + unknown notification dispatch,
notif_kind coverage
All 19 tests pass (11 MLD + 7 existing + 1 integration). The module
is integrated via 'mod mld;' in main.rs.
KWINDOWSYSTEM_WAYLAND=ON -> CMakeLists find_package(PlasmaWaylandProtocols
REQUIRED) (+ Qt6WaylandClient, WaylandProtocols). Only qtbase/qtdeclarative were
declared, so configure failed "Could not find ... PlasmaWaylandProtocols".
plasma-wayland-protocols recipe exists and builds; declare it + qtwayland +
wayland-protocols. Direct sddm dep, greeter-critical.
Both build a QML module (KWINDOWSYSTEM_QML=ON / ksvg QML) whose CMakeLists does
find_package(Qt6Qml) via ECMQmlModule, but declared only qtbase -- so cookbook
never installed Qt6Qml (qtdeclarative) into their sysroot and configure failed
"Could not find a package configuration file provided by Qt6Qml", even though
qtdeclarative itself now builds. kf6-kwindowsystem is a direct sddm dependency,
so this blocked the greeter. Audited all kf6 recipes: these two were the only
QML-consumers missing the dep (kf6-kitemmodels already had it).
Self-review followups after v4.1, plus two correctness fixes the audit
uncovered.
unified_events:
* Carry RecoveryAction through the Aer variant of UnifiedEvent. The
routing decision (route_to_driver against the latest bind snapshot)
is made once in run() and threaded into the callback, so the
callback does not recompute it. Eliminates a duplicate
route_to_driver call per AER event.
* Update the unified_events test to the new Aer { event, action }
shape.
main.rs:
* Simplified AER callback: no double route_to_driver, no
dead cfg(not(target_os = "redox")) arm. Dispatch gated on
cfg(target_os = "redox") so host builds compile.
* RecoveryAction::Fatal escalation: emit a stable ERROR-level
marker ('AER-FATAL: device=... driver-already-dead escalation
marker ...') before the action_str match returns None. Operator
tooling can grep this marker to detect unrecoverable events that
need human attention. No auto-dispatch on Fatal by design -- the
driver is dead, recovery cannot succeed.
modern_technology:
* iommu_group_for: replace the unmatchable hash-keyed path check
(/scheme/iommu/domain/<hash(bdf)>) with scheme-presence detection
(/scheme/iommu exists). The iommu daemon does NOT expose a BDF to
group lookup, so scheme-presence is the strongest signal
available without opening a handle.
* numa_node_for: replace the wrong /scheme/numad/device/<bdf>
check (numad does NOT expose that path) with the correct
/scheme/proc/numa presence check (numad writes topology there).
* numa_node_env_value: dedupe -- reuse numa_node_for's source
discriminant instead of duplicating the path-existence check.
Tests:
- driver-manager: 63 passed (no change)
- redox-driver-core: 32 passed (no change)
- host build clean
Self-review found the v4.1 update's AER row claimed 'Driver::on_error
→ RecoveryAction on bound devices is now end-to-end rather than
discarded.' That is misleading: DriverConfig does not override
Driver::on_error (the trait method keeps its default Ok(Handled)
impl), so the trait callback is never invoked. The v4.1 fix wires
manager-level auto-dispatch (AER event → route_to_driver →
dispatch_recovery), not driver-level on_error IPC. The driver-IPC
item remains open.
Reword the row to say manager-level dispatch and note that
Driver::on_error IPC is a separate item.
Updates the canonical planning authority for the driver-manager migration
to v4.1, which closes the three P3 items v4.0 had declared open.
Adds:
* v4.1 update block with the table mapping each v4.0 P3 item to its
v4.1 resolution (QuirkPhase::Early gating, AER auto-dispatch,
per-vendor firmware assessment) and the IOMMU/NUMA honest-absence
fix in redox-driver-core::modern_technology.
* Driver-by-driver audit summary — every PCI driver invoked from
/lib/drivers.d/*.toml plus the modern-tech daemons and bridging
consumers. No stubs, no todo!()/unimplemented!() in production
paths.
* Adjacent-technology compatibility matrix — cpufreqd/thermald
verified compatible; iommu now honest; udev-shim/driver-params
wired correctly; redox-drm/xhcid/iwlwifi/amdgpu use the granted
channel contract.
Refreshes the v4.0 post-cutover table to reflect the v4.1 AER row
('auto-dispatch from listener; RecoveryAction::ResetDevice/RescanBus
execute via shared dispatch_recovery helper') and the v4.1 quirks
row (phase = early/enable consulted at probe time).
Replaces the now-stale v4.0 'Open items (updated)' line with the v4.1
list — none from v4.0 P3, plus the operator-only gates that remain
(ACPI session, hardware validation matrix, two-week soak).
Updates Last reviewed line to 2026-07-24.
driver-manager v4.1 — closes the three remaining P3 items the v4.0 plan
declared open after the cutover:
* AER auto-dispatch to bound devices (P3 #2 endpoint side):
route_to_driver now actually invokes the recovery body for NonFatal
(ResetDevice) and Fatal (RescanBus) events on bound devices, instead
of only logging. The /recover scheme endpoint and the auto-dispatch
both share the new scheme::DriverManagerScheme::dispatch_recovery
helper, so operator-triggered and event-triggered recovery use the
same code path. Driver::on_error → RecoveryAction on bound devices
is now end-to-end rather than discarded.
* Quirk lifecycle phase Early (P3 #1): the probe path consults
QuirkPhase::Early before the channel open and gates WRONG_CLASS /
BROKEN_BRIDGE on it. decide_for_phase in quirks.rs bridges to
redox-driver-sys::quirks::lookup_pci_quirks_for_phase. Combined with
Enable (spawn-time), this is the Linux 2-of-8 minimum split. PM
phases remain out of scope per plan § P3.
* IOMMU/NUMA honest absence: iommu_group_env_value() and
numa_node_env_value() report "0" when the corresponding scheme is
not present, instead of the previous deterministic BDF hash that
looked like a real isolation group / node id. Drivers that consume
REDBEAR_DRIVER_IOMMU_GROUP / REDBEAR_DRIVER_NUMA_NODE now see
"no group" / "no node" instead of a value they might trust.
Tests:
+ 4 driver-manager scheme::tests::recovery_action_* cases
+ 2 redox-driver-core modern_technology::tests env-value cases
Total: 63 driver-manager tests + 32 redox-driver-core tests, all green.
Replace the purged stale 6.11.0 caches with the official 6.11.1 tarballs. Each
was downloaded from the pinned recipe URL and verified: blake3 == recipe.toml
pin, and top-level dir == <module>-everywhere-src-6.11.1. The pins were already
correct 6.11.1 hashes (set during the version bump) -- only the committed
source.tar caches had gone stale at 6.11.0. Restores offline reproducibility to
match qtbase/qtshadertools/qtsvg (which commit their 6.11.1 source.tar).
recipes/libs/mesa is a wholesale symlink to local/recipes/libs/mesa, so
cookbook resolved the recipe patch refs "mesa/NN-*.patch" to
local/recipes/libs/mesa/mesa/NN-*.patch -- a subdir that never existed. The
patches live in local/patches/mesa/, and apply-patches.sh only individually
links kernel/base patches, never mesa. So mesa could only build from a
pre-patched cached source/; a clean re-fetch (e.g. online mode) failed with
"Failed to find patch file recipes/libs/mesa/mesa/01-...". Add the mesa/ subdir
as a relative symlink into the canonical local/patches/mesa so the referenced
path resolves (all in local/), without touching recipe.toml (mesa stays
cached). Audited all 37 patch refs across every recipe -- mesa was the only
unresolved one.
Two corrections after finding the Qt offline-source model:
1. The Qt recipes intentionally COMMIT source.tar as the offline source
(qtbase/qtsvg/qtshadertools all do). My previous commit wrongly added a
local/recipes/**/source.tar ignore rule; revert it -- source.tar is durable
here, only source/ is the fork model.
2. Real deficiency: the pre-cook offline decision honored only the
REDBEAR_ALLOW_UPSTREAM env var, while the main `make live` phase also goes
online for the --upstream flag (ALLOW_UPSTREAM=1). So `--upstream` alone left
the pre-cook OFFLINE but the main phase ONLINE -- a package missing its
source.tar cache (e.g. right after the stale 6.11.0 tars were purged) failed
the pre-cook with "Opening file for blake3 failed ... source.tar: No such
file". Make the pre-cook honor ALLOW_UPSTREAM too, matching the main phase.
The 6.11.1 upgrade bumped recipe URLs+blake3 for the Qt modules but left stale
committed fetch-caches for three of them: qtdeclarative/qtwayland/qt6-sensors
shipped source.tar (and qt6-sensors a source/ extract) still at 6.11.0. repo
validates the cache against recipe blake3, so the stale 6.11.0 tar mismatched
the 6.11.1 pin -> "downloaded tar blake3 ... is not equal to blake3 in
recipe.toml" -> qtdeclarative cook failed, cascading Qt6Qml failures in every
downstream consumer (qtwayland, kf6-*), aborting the whole build.
Root cause of the committed caches: .gitignore only ignored recipes/**/source.tar
(mainline tree), never local/recipes/**/source.tar, so local fetch-caches were
committable and went stale on version bumps. Fixes:
- git rm the stale 6.11.0 source.tar (x3) + qt6-sensors 6.11.0 source/ extract
so the build re-fetches the pinned 6.11.1 tarballs.
- .gitignore: ignore local/recipes/**/source.tar(.tmp) (fetch-cache; NOT
source/, the durable fork model) so this cannot recur.
qtbase/qtshadertools/qtsvg were already correct (source.tar==6.11.1==pin).
sddm and the kf6 modules (pulled by kwin) do find_package(Qt6Qml)/Qt6Quick,
which only exist once qtdeclarative is built. When resolved only transitively
during the parallel make-live graph, a consumer (qtwayland, kf6-kwindowsystem)
could be cooked before qtdeclarative published Qt6Qml -> "Could not find a
package configuration file provided by Qt6Qml" -> whole build aborts (exit 2).
Pre-cook qtbase qtshadertools qtdeclarative qtsvg qtwayland (in order) before
sddm/kwin so every Qt6 CMake config is cached in the sysroot first. Complements
the qtwayland->qtdeclarative recipe dep; covers all kf6 consumers at once.
qtwayland CMakeLists find_package(Qt6Qml) for the QtWaylandCompositor QML
integration. Without qtdeclarative in dependencies, cookbook may cook qtwayland
concurrently with qtdeclarative and configure fails with "Could not find a
package configuration file provided by Qt6Qml". Declaring the dep serializes
the build: qtbase -> qtshadertools -> qtdeclarative -> qtwayland.
qnetworkinterface_unix.cpp getifaddrs path declares `struct ifreq ifr` to pass
to getMtu(), but Redox relibc <net/if.h> provides only interface flags and the
if_nameindex() helpers -- no struct ifreq (Redox has no SIOCGIF* ioctls). The
SIOCGIFMTU body in getMtu() is #ifdef-guarded and compiles out, so the type
only needs to be complete. Define a minimal-but-standard struct ifreq under
#if defined(__redox__) at file scope; the ioctls that would use it fail
gracefully at runtime (mtu stays 0). Durable patch, wired into qtbase recipe.
The 8-element block-character ramp in the panel footer's
size-distribution histogram was indexed with a level that could
clamp to 8 (one past the end). The math scaled count/max_bucket to
[0, 8] and clamped with .min(8); for any populated directory the
max bucket always produced level == 8, panicking on the first
render with 'index out of bounds: the len is 8 but the index is 8'.
Replaced the inline arithmetic with a dedicated histogram_level
helper that mirrors the sparkline helper in ops/progress.rs:
scale count/max_bucket to [0, 7] and clamp to 7. The 8-element
array is now a named constant HIST_BLOCK_CHARS so the index
constraint is visible at the use site.
Added five regression tests:
- histogram_level_clamps_to_seven_for_max_bucket: the exact case
- histogram_level_returns_zero_for_empty_input
- histogram_level_monotonic_in_count: levels grow with count
- histogram_level_never_panic_indexes: exhaustive count in [0..max]
for max in [1..256]
- render_panel_does_not_panic_on_populated_directory: end-to-end
size_histogram + histogram_level + array index
Also: render() used to silently skip when the terminal reported
< 10x5, leaving the user with a blank screen and no feedback. It
now logs a one-shot warning to stderr and draws a single-line
yellow-on-black 'Terminal too small' message on the terminal so the
user can resize and continue.
Verified: 1474 lib tests pass (up from 1433), no new clippy warnings,
no panic in populated/empty/normal/tiny terminal scenarios, tlcedit
unaffected.
forkfd_qt.c includes <forkfd.h> (whose forkfd_wait4 prototype takes struct
rusage*) before struct rusage is declared at file scope; sys/resource.h is only
pulled in later by forkfd.c. So the header prototype gets a prototype-scoped
struct rusage incompatible with the file-scope one in the definition ->
"conflicting types for forkfd_wait4". 6.11.0 qglobal.h pulled it in
transitively; 6.11.1 does not. Fix: include <sys/resource.h> before <forkfd.h>.
Durable patch, wired into qtbase recipe.
Add a "Canonical build — do NOT bypass" subsection to AGENTS.md and
local/AGENTS.md, and inline warnings above every instructional repo cook /
repo fetch / make live / make r.<recipe> mention across the build/patch/plan
docs. Rationale (learned the hard way this session): direct repo cook/fetch
skips apply-patches.sh patch-linking + staleness handling, causing broken
patches (qtsvg CVE) and wasted rebuilds. Always build via
local/scripts/build-redbear.sh.
The recipe referenced "qtsvg/CVE-2026-6210.patch" (relative to the recipe dir →
recipes/.../qtsvg/qtsvg/CVE... which does not exist); the patch lived in
local/patches/qtsvg/. apply-patches.sh does not link it, so both direct fetch
and the canonical build failed to find it. Move the patch into the qtsvg recipe
dir (durable /local, same model as qtbase redox.patch) and reference it by bare
name so the build system resolves it.
Move the Redox in6_pktinfo patch into local/recipes/qt/qtbase/ (where qtbase
redox.patch lives) and add it to the [source] patches list, so a clean fetch of
qtbase 6.11.1 re-applies it. Verified: fetch of 6.11.1 applies all 3 patches
atomically. Durable in local/, resolved by the build system (no bypass).
Records the fix that unblocked qtbase on Redox: relibc lacks struct in6_pktinfo,
which Qt sizes cmsg buffers with in both datagram paths. Define it at file scope
(outside the QT_NO_SCTP guard that Redox compiles out). The current qtbase.pkgar
was built from the equivalent in-tree source edit; this patch is the durable
form. NOT yet added to recipe.toml patches[] — wiring it invalidates the qtbase
cache and forces a full re-cook, so it is wired as the final step once the ISO
assembles (during the desktop-stack fix phase qtbase stays cached).