Submodule bump (base f315a9be):
- Vendored acpi-rs fork with real Opcode::Notify (upstream panicked).
- acpid Phase 5: GPE/PM1 dispatch, EC query loop, lid/button/fan
scheme surfaces, AML notification queue, SCI IRQ subscription.
- i2c-hidd Phase 4.4: HID 1.11 descriptor parser + decoder, multi-
touch digitizer forwarding (absolute pointer + two-finger scroll).
Parent changes:
- redbear-upower: 250 ms notification drain arm polls
/scheme/acpi/notifications and emits Changed D-Bus signal on power
state transitions. The existing 30 s poll stays as a safety net.
- LG-GRAM-16Z90TP-COMPATIBILITY-PLAN.md: Phase 4.4 + Phase 5
(P5.0-P5.5) marked code-complete with status preambles, stub sweep
notes, file mappings, and runtime-gate-still-open disclaimers.
Runtime validation (Gate 5: AC event latency, lid, power button, fan)
remains pending Phase 1 bare-metal boot.
38 KiB
LG Gram 16Z90TP-G.AL89C — Host Compatibility Plan
Created: 2026-07-20 Status: Planning — no implementation started Source evidence: Host dmesg (Linux 7.1.3-1-MANJARO), six-point codebase recon (drivers/PCI-ID inventory, redox-drm Intel state, redbear-iwlwifi state, IOMMU/kernel state, ACPI/power state, USB/input/audio state) Host class: Modern Intel laptop (Arrow Lake-H), first-class bare-metal target
1. Host Profile
| Property | Value |
|---|---|
| Model | LG Electronics 16Z90TP-G.AL89C (2025) |
| BIOS | Phoenix A1ZJ3000 X64, 2024-12-26, UEFI 2.7, Secure Boot off |
| CPU | Intel Core Ultra 7 255H (Arrow Lake-H), family 0x6 model 0xC5, 16 cores (hybrid P/E/LP-E), x2APIC, TSC 3.69 GHz, HWP, TM1, CET/IBT |
| RAM | 32 GB |
| GPU | Intel Meteor Lake graphics [8086:7d51], display version 14.00, VT-d active |
| Storage | SK Hynix NVMe [1c5c:1959] (nvme0, 16 queues) |
| Wi-Fi | Intel Wi-Fi 7 BE201 320MHz [8086:7740] CNVi (crf 0x2001910, cnv 0x80930), fw bz-b0-fm-c0-c102.ucode, op_mode iwlmld |
| Bluetooth | Intel [8087:0037] (USB-attached CNVi BT), fw ibt-0093-0291.sfi + .ddc |
| Audio | HDA [8086:7728] via SOF/cAVS (sof-arl.ri, IPC4, ALC298 codec, 2× DMIC, HDMI) |
| USB | xHCI ×2: [8086:7ec0] (USB4-adjacent), [8086:777d]; Linux quirks 0x200009810 |
| Input | PS/2 i8042 keyboard (AUX disabled); I2C-HID multitouch touchpad 04CA:00CC on LPSS DesignWare I2C [8086:7778/7779] |
| Camera | UVC 1.50 [30c9:00f2] |
| IOMMU | Intel VT-d, 2× DRHD (0xfc800000/0xfc801000), IRQ remapping, force-enabled by platform |
| Power | EC at 0x66/0x62 (GPE 0x6e), BAT0, ADP1, lid, sleep/power buttons, thermal zone, fan PNP0C0B, S0ix only (LPIT; no S3), LG WMI, TPM2 |
| Misc PCI | LPC 8086:7702, SMBus 8086:7722, SPI 8086:7723, UART 8086:7745, MEI 8086:7770, GNA 8086:774c, VPU/NPU 8086:7d1d, proc-thermal 8086:7d03, PMC telemetry 8086:777f, ISH 8087:0AC2 |
| Notable quirks | HPET dysfunctional in PC10 (Linux force-disables); no wired Ethernet — Wi-Fi is the only network device |
2. Device-by-Device Support Matrix (dmesg vs. codebase recon)
Legend: ✅ = expected to work today (code match + mature path) · 🟡 = code exists, gap or unproven · ❌ = no support
| Device | ID | Red Bear component | Verdict | Evidence |
|---|---|---|---|---|
| UEFI boot | — | bootloader fork | ✅ | Standard Phoenix UEFI 2.7; boot proven on AMD/Intel bare metal |
| CPU/SMP | 0x6/0xC5 | kernel x2APIC dual-path | ✅ | local_apic.rs x2 via CPUID; 16-core boot expected |
| HPET | — | kernel | ✅ (n/a) | Redox uses LAPIC/TSC timers; HPET-dysfunctional quirk harmless |
| NVMe | 1c5c:1959 | nvmed (class 1/8) |
✅ | Class-based match; initfs-capable |
| xHCI ×2 | 8086:7ec0, 8086:777d | xhcid |
✅→🟡 | Class match 0x0C/0x03/0x30 + Intel baseline quirks; 7ec0 (USB4-adjacent) has no specific quirk entry; unvalidated on HW |
| PS/2 keyboard | i8042 | kernel serio + ps2d |
✅ | AUX-disabled handled (test_aux_port → SECOND_DISABLED); QEMU + BM proven |
| VESA console | — | vesad+fbcond |
✅ | Boot framebuffer path, always present |
| iGPU | 8086:7d51 | redox-drm Intel |
🟡 | 0x7D51 is in INTEL_GEN12_MTL_IDS; but display init assumes Gen8-era register layout; DMC preload gated but never loaded to HW; no GuC/HuC |
| Legacy iGPU fb | 8086:7d51 | ihdgd |
🟡 | Also claims 0x7D51 — priority vs redox-drm must be enforced |
| Wi-Fi BE201 | 8086:7740 | redbear-iwlwifi |
🟡→❌ | ID in table, fw family correct (bz-b0-fm-c0), but Mini-MVM is iwlmvm-era and BE201 needs iwlmld; fw API 102 vs expected 92–100; zero HW validation |
| BT | 8087:0037 | redbear-btusb |
🟡 | Recipe exists (bounded BLE slice); Intel bootload/fw-load (sfi+ddc) untested |
| Audio HDA | 8086:7728 | ihdad |
❌ (arch) | Class-matched and will probe, but cAVS/SOF platform — legacy HDA cannot reach ALC298 behind the DSP; needs SOF port |
| USB audio (dongle) | — | redbear-usbaudiod |
✅ (interim) | UAC1 full impl; viable interim audio |
| Touchpad | 04CA:00CC | intel-lpss-i2cd/dw-acpi-i2cd + i2c-hidd |
🟡 | Chain compiles; controller ACPI HID likely not in any SUPPORTED_IDS; no BM validation; single-touch parsing only |
| I2C controllers | 8086:7778/7779 | same | 🟡 | ACPI-HID matching may miss Arrow Lake HIDs; PCI-ID fallback matching absent |
| Camera | 30c9:00f2 | — | ❌ | No UVC driver anywhere |
| Battery/AC | BAT0/ADP1 | acpid AML _BST/_PSR |
🟡 | Polling works; no event notifications (no GPE) |
| Lid/buttons | PNP0C0D/C/E | — | ❌ | Zero lid code; button GPE re-enable documented as caller's job |
| GPE/EC events | GPE 0x6e | acpid/ec.rs |
❌ | EC byte protocol exists; no GPE dispatch, no QR_EC loop |
| Thermal zones | TZ00 | acpid+thermald |
🟡 | _TMP/_PSV/_CRT + passive cooling via cpufreq works; fan is soft-model only |
| CPU freq | ARL-H | cpufreqd HWP/EPP |
✅ | Code explicitly notes Arrow Lake-H HWP; MSR path generic |
| CPU temp/RAPL | — | coretempd, redbear-power |
✅ | MSR 0x19C/0x1A2/0x606+; no model gating needed |
| Suspend | S0ix/LPIT | acpid s2idle |
🟡→❌ | Prep sequence exists; no LPIT parser, MWAIT loop unwired, no _PRW wake mgmt; S3 absent on this host |
| Shutdown/reboot | S5/reset | acpid/kernel |
✅ | Implemented; robustness tracked in ACPI-IMPROVEMENT-PLAN |
| IOMMU (VT-d) | DMAR | iommu daemon |
✅ (safe no-op) | AMD-Vi only; detects DMAR, logs, registers empty scheme; do not set REDBEAR_DMAR_INIT=1 (gl_sts hang risk) |
| LPC/SMBus/SPI/UART/MEI/GNA/VPU/PMC/ISH/TPM | various | — | ❌ | No drivers; none are boot-critical |
| LG WMI hotkeys | — | — | ❌ | No WMI subsystem |
| USB-C eth dongle (interim net) | — | redbear-ecmd |
✅ (interim) | CDC-ECM driver exists — only viable interim network path (no wired NIC on host) |
2.1 Critical config-level defect found during recon
e1000d wildcard collision. local/config/drivers.d/10-network.toml matches
vendor=0x8086 class=2 with no subclass filter → on this host it would claim the
BE201 Wi-Fi (class 0x02 subclass 0x80) and collide with redbear-iwlwifi.
The pcid-side e1000d/config.toml whitelist is correct; the driver-manager entry
is too broad. Must fix (Phase 0) — add subclass = 0x00.
2.2 Known non-issues (verified, do not re-investigate)
- VT-d force-enabled: harmless —
iommudaemon is a clean no-op on DMAR-only machines. - HPET dysfunctional: kernel timers don't need HPET.
- AUX port disabled:
ps2dhandles it. - PCI root ports/LPC/host bridge: bus-layer devices, no userspace driver needed by design.
- x2APIC: fully supported; IRQ remapping absence does not block MSI/MSI-X delivery.
3. Boot Path Analysis (redbear-mini on this host)
UEFI 2.7 (Phoenix) → Red Bear bootloader (✅ expected)
→ kernel: x2APIC detect (✅), 16-core SMP (✅), MADT (✅), MCFG ECAM 0xC0000000 (✅)
→ initfs: pcid → nvmed (✅ SK Hynix) → rootfs mount (✅)
→ vesad + fbcond console (✅)
→ pcid-spawner + driver-manager:
xhcid ×2 (✅ class match, Intel baseline quirks — watch 7ec0)
ps2d (✅)
ihdad (🟡 probes, finds no usable codec — must fail gracefully, not hang)
redbear-iwlwifi (🟡 probes, fw API mismatch likely — must fail gracefully)
e1000d (❌ COLLISION — Phase 0 fix)
→ acpid: RSDP/FADT/DSDT/SSDT/EC (✅), battery/AC poll (🟡), shutdown (✅)
→ cpufreqd HWP (✅), coretempd (✅), thermald (🟡)
→ login prompt (✅ expected) — redbear-mini usable with keyboard + USB-Ethernet dongle
Expected first-boot result: boots to login on VESA console with working keyboard, NVMe, USB, CPU power management, battery readout, and shutdown — but no touchpad, no network (without USB dongle), no DRM/KMS, no audio, no suspend.
4. Multiphase Plan
Phase ordering respects the canonical subsystem order (IRQ/low-level → USB → Wi-Fi → BT → desktop) but prioritizes host boot-blockers and the no-wired-NIC reality. Every phase ends with a validation gate on the real host (this machine is available — that changes everything vs. prior plans blocked on hardware access). Evidence language per project rules: compile-visible ≠ QEMU-bounded ≠ hardware-validated.
Effort scale: S (<1 week) · M (1–3 weeks) · L (3–8 weeks) · XL (8+ weeks)
PHASE 0 — Host bring-up prerequisites (S, config-level, zero risk)
STATUS: COMPLETE (2026-07-20). All items landed; affected components cross-compile for
x86_64-unknown-redox; all host-side test suites pass (redox-driver-sys 72, firmware-loader 11, redbear-iwlwifi 8, redbear-wifictl 21).
| # | Work item | Files | Notes |
|---|---|---|---|
| 0.1 | Fix e1000d wildcard collision — add subclass = 0x00 to e1000d match |
local/config/drivers.d/10-network.toml + embedded copy in config/redbear-device-services.toml |
✅ DONE — same defect class also fixed for rtl8168d (Realtek ships subclass-0x80 Wi-Fi too) |
| 0.2 | Add DMI quirk-table entry for LG Electronics 16Z90TP |
redbear-quirks/source/quirks.d/50-system.toml |
✅ DONE — and repaired the system-quirk parsing pipeline: the sibling LG entries' flags (force_s2idle etc.) silently parsed to empty sets (unknown names dropped). Added SystemQuirkFlags + DmiSystemQuirkRule + dual-namespace parsing in toml_loader.rs + quirks::system_quirks() consumer API in redox-driver-sys. Consumer wiring (acpid force_s2idle, ps2d kbd_deactivate_fixup) remains Phase 5 work — the flags parse and are queryable but nothing branches on them yet. 16Z90TP entry matches on board_name = "16Z90TP" (exact-match semantics; product_name carries the SKU suffix) |
| 0.3 | Verify/port xHCI quirks for 8086:7ec0 & 8086:777d — decode Linux 0x200009810 |
redox-driver-sys/source/src/quirks/xhci_table.rs |
✅ DONE — decoded as SPURIOUS_SUCCESS | LPM_SUPPORT | INTEL_HOST | AVOID_BEI | DEFAULT_PM_RUNTIME_ALLOW. Missing piece was the universal hci_version > 0x96 → SPURIOUS_SUCCESS rule (Linux xhci.c:5477); added it + a flag-parity test pinning the LG Gram controllers to the exact Linux flag set. The >= 0x120 → DEFAULT_PM_RUNTIME_ALLOW rule already existed |
| 0.4 | Confirm graphics spawn priority: redox-drm wins over ihdgd for 0x7D51 | drivers.d/30-graphics.toml, pcid.d/intel_gpu.toml, redbear-{mini,full}.toml |
✅ VERIFIED CORRECT — redox-drm Intel entry priority 61 > vesad 60; redbear-mini empties /etc/pcid.d/ihdgd.toml; redbear-full overrides it to spawn redox-drm; /etc/pcid.d overrides /usr/lib/pcid.d via config_for_dirs() BTreeMap; base package stages into /usr/lib/pcid.d so no layer collision. No change needed |
| 0.5 | Stage firmware blobs | local/firmware/, redbear-iwlwifi/main.rs, redbear-wifictl/backend.rs, firmware-loader/blob.rs, redbear-device-services.toml |
✅ DONE — staged host-verified blobs (iwlwifi bz-b0-fm-c0 c101/c102/c103/c106 + pnvm, gf-a0 set, i915/mtl_dmc.bin + guc/huc/gsc, ibt-0093-0291.sfi/.ddc). Key discovery: the c-prefixed series is the iwlmld firmware — candidate tables rewritten to prefer c106→c101 over the legacy 92–101 series. Fixed firmware path gap: new linux-firmware ships iwlwifi under intel/iwlwifi/; added wildcard path-map to firmware-loader builtins + /etc/firmware-fallbacks.d/10-iwlwifi.toml. Image path confirmed: redbear-firmware recipe ships the full set (cache has c106) |
Phase 0 discoveries beyond the original scope (all fixed, none deferred):
rtl8168dhad the same wildcard collision as e1000d → fixed with the samesubclass = 0filter.- The
[[dmi_system_quirk]]TOML entries in50-system.tomlwere dead data — every system flag silently dropped by the parser, and no consumer API existed. Now a real pipeline:SystemQuirkFlags→DmiSystemQuirkRule→quirks::system_quirks()→ consumers (acpid/ps2d wiring lands in Phases 4–5). integrate-redbear.shAMD-only firmware staging intofirmware-loader/source/firmware/amdgpu/never reaches the image (package ships only the binary) — the real image path is theredbear-firmwarerecipe (full linux-firmware install, local 2.8 GB cache already present). Documented here; the dead staging path is legacy cleanup, not Phase 0 scope.- Firmware fallback chains in
redbear-device-services.tomlare embedded 16× (fragment composition); updates must use replace-all edits.
Gate 0: ✅ changed components cook successfully for the target;
redbear-iwlwifi, redbear-wifictl, firmware-loader, redox-driver-sys all build + publish.
PHASE 1 — Bare-metal boot validation (S, evidence-first)
This host is available — run the existing validation harnesses against it and record everything. No code changes in this phase except genuine boot-blocker fixes.
| # | Work item | How |
|---|---|---|
| 1.1 | Boot redbear-mini live ISO on host; capture full boot log to local/docs/boot-logs/lg-16z90tp-*.log |
USB stick; serial capture if console fails |
| 1.2 | Validate: 16-core SMP, NVMe root, xHCI enumeration (both controllers), PS/2 keyboard, VESA console at native panel resolution, battery/AC readout, HWP P-states, coretemp, ACPI shutdown + reboot | Manual + redbear-info, redbear-ecmd |
| 1.3 | Validate USB-Ethernet interim networking: CDC-ECM dongle → redbear-ecmd → DHCP |
redbear-netctl |
| 1.4 | Run bounded low-level controller proofs (MSI-X, xHCI IRQ, PS/2, timer) | local/scripts/test-lowlevel-controllers-qemu.sh analogues on BM; record results |
| 1.5 | Add host entry to local/docs/HARDWARE-VALIDATION-MATRIX.md with honest evidence levels |
Per row: compile / QEMU / BM-validated |
| 1.6 | Fix only true boot-blockers discovered (root-cause fixes per ABSOLUTE RULE) | Triage as found |
Gate 1: redbear-mini boots to login on the host with keyboard + NVMe + USB + shutdown/reboot verified. This is the " minimally usable " milestone.
PHASE 2 — CPU & platform power validation (S–M)
| # | Work item | Files | Effort |
|---|---|---|---|
| 2.1 | Validate cpufreqd HWP on ARL-H: governor switching, EPP hints, per-core HWP_REQUEST |
local/recipes/system/cpufreqd/ |
S |
| 2.2 | Validate RAPL domains (pkg/pp0/pp1/dram/platform) in redbear-power; check 0x64D platform energy on ARL |
redbear-power/source/src/msr.rs |
S |
| 2.3 | Validate coretempd + thermald passive cooling loop under load (stress via cub builds) |
thermald + cpufreqd integration | S |
| 2.4 | Hybrid topology: feed CPUID leaf 0x1A P/E/LP-E classification (exists in redbear-power) into cpufreqd per-cluster governor policy | cpufreqd, redbear-power/cpuid.rs |
M |
| 2.5 | Serial console bring-up via DBG2 16550 (0x3f8) for headless debugging of later phases | kernel/boot config | S |
Gate 2: redbear-power shows correct per-cluster frequencies, temps, RAPL power;
thermal throttling engages and recovers under sustained load.
PHASE 3 — Display: VESA → DRM/KMS on Meteor Lake (L, critical path for desktop)
Follows local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md Workstream C.
| # | Work item | Files | Effort |
|---|---|---|---|
| 3.1 | Validate vesad at native panel mode (eDP; likely 2560×1600); confirm fbcond + any framebuffer consumers | vesad/bootloader EDID handoff | S |
| 3.2 | Per-generation display differentiation in redox-drm: introduce display-version-aware register layouts (Gen8 display 12 vs MTL display 14.00). Reference: local/reference/linux-7.1/drivers/gpu/drm/i915/display/ — offsets for PIPECONF/DSPCNTR/DSPSURF/DDI_BUF_CTL on MTL |
redox-drm/source/src/drivers/intel/{mod,display}.rs |
L |
| 3.3 | Real connector/EDID bring-up on eDP: GMBUS read at panel; bounded modeset proof via redbear-drm-display-check on the host |
display.rs + test-drm-display-runtime.sh | M |
| 3.4 | DMC firmware load sequence: CSS header parse, DMA-to-DMC-store, DC state enable — port from Linux i915 intel_dmc.c. Consume the already-preloaded mtl_dmc.bin |
intel/mod.rs, new intel/dmc.rs; firmware-loader |
M–L |
| 3.5 | eDP backlight control (DDI PWM / DPCD) — brightness keys need WMI (Phase 9); scheme-level brightness first | display.rs / new backlight module | M |
| 3.6 | GuC/HuC/GSC: manifest entries now, load sequences deferred (render path, not display blocker). Document as convergence work in DRM plan | main.rs firmware keys |
S (manifest only) |
Gate 3: redox-drm drives the internal panel at native resolution with correct
EDID modeset + page flips on the host; vesad remains as fallback. This unblocks the
whole desktop path (Qt6/KWin) on this machine.
PHASE 4 — Touchpad: I2C-HID chain bring-up (M)
STATUS: 4.1–4.4 COMPLETE (2026-07-21). The entire I2C transfer chain was stubbed end-to-end and has been replaced with real implementations (see "stub sweep" below). 4.4 (multitouch report parsing) landed on 2026-07-21. Only 4.5 (host runtime validation) remains open and requires the running system.
Stub sweep (all found during this phase, all replaced with real code):
- i2cd transfer path was a stub —
queue_transfer_stubreturned "not implemented yet" for every transfer, and its wire format didn't even match the only in-tree consumer (i2c-hidd sends a bareI2cTransferRequest, i2cd expectedI2cControlRequest::Transfer). → Real provider routing: adapter resolution by name/alias (exact-first, ambiguity-rejecting) + forwarding to the provider daemon's/scheme/<provider>/transferendpoint. - intel-lpss-i2cd / dw-acpi-i2cd were register-and-park stubs — they
mapped the MMIO, logged register offsets in a debug line, registered an
adapter name, and parked forever without initializing the controller or
executing a single transfer.
→ New shared crate
drivers/i2c/designware(dw-i2c): real DesignWare master engine ported from Linux 7.1i2c-designware-master.c/common.c- shared
/scheme/<name>transfer endpoint. (amd-mp2-i2cd is a different IP — the AMD mailbox controller — and remains a registration-only daemon until its own engine lands; every transfer to it fails honestly with "no transfer provider". It is NOT covered by this sweep.)
- shared
Review-fix round (2026-07-20, post-implementation review):
A 5-lane review (goal/QA/code-quality/security/context) returned FAIL with two verified-CRITICAL and ~14 MAJOR findings. All legitimate findings were fixed in the same session (fix commits on submodule/base + 0.3.1):
| Finding | Fix |
|---|---|
CRITICAL: IC_CON/IC_TAR written while enabled |
Engine restructured to Linux i2c_dw_xfer_init ordering: wait-idle → disable → program → enable with IC_ENABLE_STATUS polling on every transfer |
| CRITICAL: Intel LPSS PCI bring-up skipped parent init | Proper pcid_interface claim + enable_device, BAR size validation, intel_lpss_init_dev port (reset-deassert + 64-bit remap at BAR0+0x200) |
| MAJOR: NACK-reported-as-success | wait_for now checks TX_ABRT before success predicates on every poll |
| MAJOR: SCL timing wrong (fall-time source + rounding) | HCNT uses sda_fall_ns, round-to-nearest division; corrected to Linux vectors FS 100/200, SS 552/652 with pinned tests |
MAJOR: stop=false hangs |
Rejected honestly (Invalid) |
| MAJOR: abort/timeout left controller wedged | recover() — ABORT-bit cycle + disable + state flush after any failed transfer |
MAJOR: unbounded requests (Read(usize::MAX) → OOM) |
validate_request: segment/byte/address/10-bit limits before any MMIO |
MAJOR: provider_scheme unchecked capability |
Grammar validation at registration (single safe component) |
| MAJOR: routing ambiguity (short alias shadows exact) | Exact-first resolution in both i2cd and the endpoint; last-component accepted only when unambiguous |
| MAJOR: ACPI-alias startup race | Bounded retry in alias discovery; acpid runs from initfs (41_acpid) so ordering is satisfied |
MAJOR: setrens fail-open |
endpoint::serve takes a Result-returning callback; namespace failure is fatal |
MAJOR: MLD (c-series) firmware fed to Mini-MVM |
c-series removed from current candidate lists (returns with the MLD op-mode in Phase 6); fallback chains no longer mix MLD/MVM series |
| MAJOR: subdirectory blobs invisible to candidate detection | Detection probes both flat and intel/iwlwifi/ layouts |
| MAJOR: untyped error flattening | I2cTransferResponse.status (typed I2cTransferStatus, serde-defaulted, wire-compatible) |
Open findings deferred with records: AMD MP2 mailbox engine (separate port), system-quirk consumers in acpid/ps2d (Phase 5), redbear-firmware supply-chain pinning (pre-existing, separate task), CallerCtx authZ on i2c schemes (design question), fake-MMIO state-machine tests (test-infrastructure work).
- intel-lpss-i2cd could never bind on modern hardware — it matched only
legacy ACPI HIDs, but MTL/ARL platforms bind LPSS I2C by PCI ID
(Linux
intel-lpss-pci.cmodel). → PCI discovery for ARL-H (0x7750/0x7751, 0x7778–0x777b) and MTL-P (0x7e50/0x7e51, 0x7e78–0x7e7b) with BAR0 from PCI config space (32/64-bit BAR decode), ACPI alias resolution by matchingFixedMemory32 == BAR0across/scheme/acpi/resources/. - Six broken spawn paths —
drivers.dcommand paths pointed at/usr/lib/drivers/for binaries staged at/usr/bin/(i2cd, gpiod, dw-acpi-i2cd, intel-gpiod, i2c-gpio-expanderd, i2c-hidd) → fixed. - No init service for intel-lpss-i2cd → added
00_intel-lpss-i2cd.service(type = { scheme = "i2c-lpss" }, absolute cmd path — init PATH covers only /usr/bin);dw-acpi-i2cdservice type upgraded fromoneshot_asynctotype = { scheme = "dw-acpi-i2c" }; i2c-hiddrequires_weakupdated. - Boot-order race — controller daemons could lose registration if i2cd
wasn't ready yet → bounded retry (100 × 50 ms) in
register_adapter.
| # | Work item | Files | Effort |
|---|---|---|---|
| 4.1 | Identify actual ACPI _HID of the two LPSS I2C controllers on the host |
— | ✅ DONE — no _HID exists on this platform (host-verified via sysfs: PCI function 00:15.0/00:15.1 ↔ \_SB_.PC00.I2C0/I2C1, DesignWare adapter spawned by intel-lpss MFD with bxt_i2c_info, 133 MHz). PCI-ID discovery implemented instead, per Linux's model |
| 4.2 | Controller bring-up: BAR/IRQ, DesignWare init sequence, bus speed | drivers/i2c/designware/, intel-lpss-i2cd |
✅ DONE (polling engine; IRQ-driven completion is a documented IRQ-plan follow-up, not a stub) |
| 4.3 | i2c-hidd: probe 04CA:00CC (PNP0C50), _DSM HID descriptor, report descriptor fetch |
i2c-hidd, i2cd, endpoint chain |
✅ CODE-READY — protocol chain verified end-to-end in code (i2c-hidd's bare I2cTransferRequest → i2cd routing → provider endpoint). Runtime proof pending host boot (Phase 1) |
| 4.4 | Multitouch digitizer report parsing (ABS_MT_* slots, tracking IDs) + forwarding through inputd → evdevd gesture module | i2c-hidd/{hid,input,report_desc}.rs |
✅ CODE-COMPLETE (2026-07-21) — HID 1.11 §6.2.2 descriptor parser + decoder in new report_desc.rs (digitizer contacts, generic-desktop X/Y/wheel, buttons, keyboard page fallback, sign-extended fields, usage-min/max expansion, global-state stack). Integrated via forward_layout_report: first touching contact → absolute MouseEvent; two simultaneous contacts → vertical ScrollEvent (two-finger scroll); buttons → ButtonEvent. 3 unit tests pass on host. Runtime palm rejection / gesture tuning stays open with 4.5 (needs boot) |
| 4.5 | Host validation: pointer, click, two-finger scroll; palm-rejection tuning | — | S — OPEN (needs boot) |
Adapter naming chain (documented for future consumers):
touchpad _CRS I2cSerialBus resource source (e.g. \_SB_.PC00.I2C0) →
i2c-hidd sends it as I2cTransferRequest.adapter → i2cd resolves against
registered names + aliases (exact → normalized → last-component) →
provider daemon (intel-lpss-i2cd registered alias PC00.I2C0 discovered by
matching FixedMemory32 == BAR0) → engine executes on the controller's BAR0.
Gate 4 (partial): base fork cooks for x86_64-unknown-redox with the new
chain; all unit tests pass (dw-i2c 3, intel-lpss-i2cd 3, i2c-hidd 3, others
green); binaries staged at verified paths. Full gate (touchpad usable on host)
is now blocked only on Phase 1 boot — 4.4 (multitouch parsing) landed
2026-07-21.
PHASE 5 — Laptop ACPI events: GPE/EC/lid/buttons (M–L)
This phase removes the biggest "not a real laptop" gap: event-driven power state.
STATUS: CODE-COMPLETE (2026-07-21). All five sub-items (P5.1–P5.5) landed plus a prerequisite P5.0; affected crates compile for
x86_64-unknown-redox;cook baseandcook redbear-upowersucceed; i2c-hidd (3) + dw-i2c (5) + intel-lpss-i2cd (1) tests pass on host. acpid host-side tests can't link (pre-existing libredox limitation — tests must run viaredoxer). Runtime Gate 5 remains open pending Phase 1 bare-metal boot.
Prerequisite work (P5.0):
The upstream acpi-rs crate (rev 90cbe88) panicked on every AML
Notify (target, value) opcode — the interpreter path was literally
unimplemented!(). Since Notify is the backbone of ACPI event flow
(EC queries fan it out, battery/AC/lid/thermal devices use it, _Qxx
methods end with Notify(\_SB.BAT0, 0x80)), this is unworkable on real
laptop firmware. Fixed by vendoring the acpi-rs crate into the base
fork (drivers/acpi-rs/) with a real Opcode::Notify executor:
src/aml/mod.rs: resolves the target ACPI path, then invokesHandler::handle_notify(target_path, value).src/lib.rs: newHandler::handle_notifydefault (no-op) so existing users of the crate (amlserde, others) keep compiling.drivers/acpid/Cargo.toml+drivers/amlserde/Cargo.toml: switched toacpi = { path = "../acpi-rs", features = ["alloc", "aml"] }so every consumer sees the same fork (avoids the dual-version trap).Cargo.toml(workspace): added"drivers/acpi-rs"to members.
This is a vendored fork, not a local/sources/acpi-rs/ submodule.
It lives inside the base fork and travels with it. Upstream acpi-rs
has Notify unimplemented at the time of vendoring; if upstream lands a
real Notify implementation we will re-evaluate convergence per the
upstream-first rule (CONSOLE-TO-KDE § "upstream-first for fast-moving
components").
Stub sweep in this phase:
- acpi-rs
Notifyopcode wasunimplemented!()→ vendored fork with a real executor that resolves the target path and calls back into the handler. - acpid had no SCI/GPE/PM1 path at all → new
gpe.rs(FADT-driven GPE block map, write-1-to-clear status, read-modify-write enable preserving firmware state on every other GPE) +power_events.rs(init + SCI dispatch following Linuxevgpe.c/ec.c/button.c). - EC query protocol had no event-loop caller →
pub fn sci_evt_set()andpub fn query()exposed onEc, called by the SCI handler with a 32-iteration bounded drain guard. - No lid/button/fan scheme surface → scheme.rs grew
Lid,LidState,ButtonDir,Button,Notifications,Fan,FanState,FanSpeedhandle kinds with proper directory-vs-file separation. evaluate_acpi_methodtook&mut self→ changed to&selfeverywhere; AML mutation goes through the existingRwLock-guardedAmlSymbolsinner state, which is how the EC query loop and the notification drain can run from a read-only context.
Review-fix round (2026-07-20): this phase inherited all Phase 4 review fixes (LPSS PCI bring-up, I2C engine ordering, firmware op-mode honesty) because it shares the base fork. No additional review has been run on the Phase 5 surface yet; the implementation follows the same Linux 7.1 reference patterns and bounded-validation discipline.
| # | Work item | Files | Status |
|---|---|---|---|
| 5.0 | (prerequisite) Real AML Notify opcode (was unimplemented!() in upstream acpi-rs) |
drivers/acpi-rs/ (vendored fork), drivers/acpid/Cargo.toml, drivers/amlserde/Cargo.toml, workspace Cargo.toml |
✅ DONE — vendored fork at base drivers/acpi-rs/; Handler::handle_notify hook added; all acpi consumers in the base workspace pointed at the path dep |
| 5.1 | GPE dispatch infrastructure in acpid: SCI via /scheme/irq (ACPI sci_int from FADT), GPE status/enable block access, per-GPE handler registry |
drivers/acpid/src/gpe.rs (new), drivers/acpid/src/main.rs |
✅ DONE — GpeBlocks::from_fadt builds the register map; PM1 fixed-event bits (PWRBTN/SLPBTN/RTC) per ACPI 6.4 §4.8.3.1; enable preserve + status write-1-to-clear; main loop subscribes /scheme/irq/{sci_irq} (default 9) and dispatches via handle_sci. 2 unit tests cover block mapping + GPE1 base offset |
| 5.2 | EC event loop: SCI_EVT poll/IRQ → QR_EC query → dispatch _Qxx AML methods; wire battery/AC change notifications (\_SB.BAT0 notify 0x80) |
drivers/acpid/src/power_events.rs (new), drivers/acpid/src/ec.rs, drivers/acpid/src/notifications.rs (new), drivers/acpid/src/aml_physmem.rs |
✅ DONE — ECDT parse for EC device path + GPE (ACPI 6.4 §5.2.16) with _HID = PNP0C09 probe fallback over conventional paths (mirrors Linux acpi_ec_ecdt_start); handle_sci drains the EC query queue (bounded at 32 iterations); Ec::sci_evt_set() / Ec::query() exposed; _Qxx AML methods evaluated; AmlNotifications shared queue receives Notify events pushed by the vendored acpi-rs handle_notify hook |
| 5.3 | Lid switch (PNP0C0D _LID) + power/sleep fixed events (PM1_STS PWRBTN/SLPBTN) → scheme surfaces + kstop events |
drivers/acpid/src/scheme.rs, drivers/acpid/src/power_events.rs, drivers/acpid/src/acpi.rs |
✅ DONE — lid device discovered via _LID evaluation over candidate paths (EC child + \_SB); PM1 fixed events cleared-before-dispatch; surfaces at /scheme/acpi/{lid/state, button/{power,sleep}, notifications}; PowerButton increments edge counter and triggers the main-loop shutdown path; SleepButton increments counter and calls enter_s2idle; AML Notify(\_SB.LID_,…) refreshes _LID and emits LidChanged(open) on edge transitions |
| 5.4 | Event-driven redbear-upower (replace polling with notify-driven refresh) |
local/recipes/system/redbear-upower/source/src/main.rs |
✅ DONE — added 250 ms notify_interval tokio arm draining /scheme/acpi/notifications; on non-empty drain, snapshots power state and emits Changed D-Bus signal if it changed. The existing 30 s poll arm stays as a safety net for missed events |
| 5.5 | Fan: real PNP0C0B/EC fan control replacing thermald soft model | drivers/acpid/src/scheme.rs, drivers/acpid/src/power_events.rs, drivers/acpid/src/acpi.rs |
✅ DONE — implementation differs from the original plan wording: instead of replacing thermald's soft fan model, acpid now owns the ACPI 4.0 fan method surface directly. Probes _FST-exposing devices over conventional placements (EC child + LPCB + \_SB), exposes read+write at /scheme/acpi/fan/<idx>/{state,speed} (_FST on read, _FSL on write, percent clamped 0–100). thermald keeps its soft model for now; convergence between the two is a Phase 9.x hardening task |
Gate 5 (code-complete, runtime open): Unplug/replug AC → instant battery/AC event; close/open lid → event logged; power button → clean shutdown flow; fan responds to thermal load. All code paths exist and compile; none have been exercised on the host yet (Phase 1 boot is the prerequisite). The 250 ms notification drain in redbear-upower should turn the existing 30 s worst-case state lag into a near-instant event, but this is a runtime claim and remains to be measured.
PHASE 6 — Wi-Fi BE201: the iwlmld gap (XL, hardest network work)
Pre-agreed reality: this is not a device-ID add. The Mini-MVM layer is
iwlmvm-era; BE201 firmware is iwlmld-era with different command IDs, RX
descriptors, and notification dispatch. Respect WIFI-IMPLEMENTATION-PLAN.md
phases W0–W7.
| # | Work item | Files | Effort |
|---|---|---|---|
| 6.0 | De-risk transport on older silicon first: if any AX210-class card is available (USB/M.2 test card), validate existing Mini-MVM path end-to-end on the host's sibling hardware before touching iwlmld | redbear-iwlwifi | S (if HW available) |
| 6.1 | Firmware plumbing: add API-102 candidates iwlwifi-bz-b0-fm-c0-102.ucode to tables in main.rs + redbear-wifictl/backend.rs; extend fetch-firmware.sh; TLV parser audit vs API 102 |
redbear-iwlwifi/source/src/{main.rs,linux_mvm.c} |
S |
| 6.2 | Mini-MLD layer: port Linux 7.1 drivers/net/wireless/intel/iwlwifi/mld/ structures — new RX/multi-link descriptor format, notification IDs, op-mode registration; gate MLD vs MVM on device family (BZ→MLD) |
new linux_mld.{c,h} beside linux_mvm.{c,h}; linux_port.c op-mode dispatch |
XL |
| 6.3 | Bounded runtime ladder on host: probe → fw boot alive → scan (see real SSID) → association → DHCP → reconnect persistence. Use existing redbear-phase5-wifi-* in-guest harness |
redbear-wifictl + test scripts | M (iterative) |
| 6.4 | Integration: netctl profile, boot-time autoconnect, honest redbear-info states |
wifictl, config fragments | S |
Gate 6: BE201 associates with the host's AP and passes traffic on the host — real wireless connectivity, not bounded simulation.
PHASE 7 — Bluetooth: Intel CNVi BT (M)
| # | Work item | Files | Effort |
|---|---|---|---|
| 7.1 | Intel BT firmware load in redbear-btusb: bootloader-mode detection, ibt-0093-0291.sfi download, DDC apply — port from Linux btintel.c |
local/recipes/drivers/redbear-btusb/ |
M |
| 7.2 | HCI bring-up on the host: reset → read version → operational mode; bounded BLE battery-level slice validation via existing harness | btusb + test-bluetooth-qemu.sh host analogue |
M |
| 7.3 | redbear-btctl scan/pair/connect on host |
redbear-btctl | S |
Gate 7: redbear-btctl sees and connects to a BLE peripheral on the host.
PHASE 8 — Audio: SOF/cAVS (XL, largest single effort)
| # | Work item | Files | Effort |
|---|---|---|---|
| 8.0 | Interim (do first): USB-audio dongle path via redbear-usbaudiod validated on host — documented as the interim answer |
redbear-usbaudiod | S |
| 8.1 | Probe ihdad on 8086:7728 to record exact failure mode (expected: no codecs behind DSP); ensure graceful failure, never a boot hang | ihdad/src/hda/device.rs |
S |
| 8.2 | SOF/AVS port: cAVS 2.5 (ARL) DSP bring-up — power gating, ROM boot, sof-arl.ri firmware download via firmware-loader, IPC4 channel, HDA link DMA. Reference: local/reference/linux-7.1/sound/soc/sof/intel/ + sound/soc/intel/avs/; revive local/docs/archived/INTEL-HDA-IMPLEMENTATION-PLAN.md HDA-011 track |
new local/recipes/drivers/redbear-sof/ (per LINUX REFERENCE SOURCE POLICY: implemented in-tree, Linux as reference only) |
XL |
| 8.3 | ALC298 codec verbs over the HDA link; speaker + headphone jack routing; DMIC later | sof codec layer | L |
Gate 8: Speaker playback on the host. (DMIC + HDMI audio are post-gate follow-ups.)
PHASE 9 — Platform extras (post-core, S–M each)
| # | Item | Notes | Effort |
|---|---|---|---|
| 9.1 | Suspend (s2idle) completion: LPIT parser (ACPI 6.5 §5.2.9.9), MWAIT idle-loop wiring, _PRW wake-device enumeration, GPE wake re-arm. The host has no S3 — this is the only suspend path |
acpid, kernel idle |
L |
| 9.2 | LG WMI hotkeys: WMI subsystem (PNP0C14 GUID dispatch) → brightness/rfkill/volume events → evdev | new redbear-wmi |
M |
| 9.3 | UVC camera: new redbear-uvcd (UVC 1.1/1.5) — well-specified; reference Linux drivers/media/usb/uvc/ |
new recipe | L |
| 9.4 | ISH sensor hub (8087:0AC2): only if a consumer exists (auto-rotate/ALS). Lowest priority | — | M |
| 9.5 | Intel VT-d runtime (intel_vtd.rs in iommu daemon): converges acpid's orphaned DMAR parser into the daemon (per ACPI-IMPROVEMENT-PLAN ownership note). Value: DMA isolation for later Wi-Fi/GPU hardening |
local/recipes/system/iommu/ |
L |
| 9.6 | Non-critical devices documented as permanent no-driver: MEI, GNA, VPU/NPU, PMC telemetry, SMBus, SPI, UART, TPM — with one-line justification each (no consumer) | this doc | S |
No stubs anywhere in this phase — per local/AGENTS.md zero-tolerance policy, each item is a real implementation or it does not ship.
PHASE 10 — Validation, quirks, and hardening (continuous)
| # | Item |
|---|---|
| 10.1 | Keep HARDWARE-VALIDATION-MATRIX.md row for 16Z90TP current after every phase gate |
| 10.2 | Every discovered hardware workaround → data-driven quirk entry (compiled table or redbear-quirks TOML + DMI match), never an #ifdef-style special case |
| 10.3 | Boot logs per milestone archived to local/docs/boot-logs/ |
| 10.4 | Durability: all source changes land as fork commits (local/sources/*) or patches (local/patches/*) in the same session — per DURABILITY POLICY |
| 10.5 | Upstream-sync safety: any new generic infrastructure (GPE dispatch, Mini-MLD, SOF) is implemented in the canonical component (acpid / redbear-iwlwifi / new recipe), not as host-specific hacks |
5. Dependency Graph
Phase 0 (collision fix, quirks, firmware) ──► Phase 1 (BM boot validation)
Phase 1 ──► Phase 2 (power validation)
Phase 1 ──► Phase 3 (display) ──► desktop path (Qt6/KWin on host)
Phase 1 ──► Phase 4 (touchpad) ──► usable laptop input
Phase 1 ──► Phase 5 (ACPI events) ──► Phase 9.1 (suspend)
Phase 1 ──► Phase 6 (Wi-Fi, XL) ──► network without dongle
Phase 1 ──► Phase 7 (Bluetooth)
Phase 1 ──► Phase 8 (audio SOF, XL)
Phase 3+4+5+6 complete = "daily-drivable laptop" milestone
6. Suggested Execution Order (effort-sequenced)
- Phase 0 + 1 — boot the host, fix the e1000d collision, capture the matrix (week 1)
- Phase 4 (touchpad) + Phase 2 (power) — makes it a usable laptop (weeks 1–3)
- Phase 5 (ACPI events) — makes it a real laptop (weeks 3–6)
- Phase 3 (display DRM) — desktop path on the host (weeks 3–10, parallel)
- Phase 6 (Wi-Fi iwlmld) — the XL rock to push (start early, longest lead time)
- Phase 7 (BT), Phase 8 (audio) — after their USB/PCI substrates are proven
- Phase 9 extras — as capacity allows
7. Explicitly Out of Scope (per policies)
- No removal/ignore/comment-out of any package or device entry that fails to probe (ABSOLUTE RULE) — failures get root-cause fixes or honest "unsupported" reporting.
- No new branches, repos, or submodules without the documented necessity case.
- Linux kernel source is reference-only; all ports are in-tree implementations.
- TPM2/secure-boot/ME features — no consumer, no plan.