diff --git a/local/docs/ACPI-I2C-HID-IMPLEMENTATION-PLAN.md b/local/docs/ACPI-I2C-HID-IMPLEMENTATION-PLAN.md index 7bdd049a..1da7d522 100644 --- a/local/docs/ACPI-I2C-HID-IMPLEMENTATION-PLAN.md +++ b/local/docs/ACPI-I2C-HID-IMPLEMENTATION-PLAN.md @@ -141,6 +141,48 @@ Acceptance: - 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 + +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` diff --git a/local/docs/USB-BOOT-INPUT-PLAN.md b/local/docs/USB-BOOT-INPUT-PLAN.md new file mode 100644 index 00000000..04e7a477 --- /dev/null +++ b/local/docs/USB-BOOT-INPUT-PLAN.md @@ -0,0 +1,169 @@ +# 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. diff --git a/local/docs/USB-IMPLEMENTATION-PLAN.md b/local/docs/USB-IMPLEMENTATION-PLAN.md index 3c1fb9e3..89efe24d 100644 --- a/local/docs/USB-IMPLEMENTATION-PLAN.md +++ b/local/docs/USB-IMPLEMENTATION-PLAN.md @@ -53,6 +53,26 @@ The Red Bear USB stack consists of: full stack, and storage autospawn - an in-guest scheme-tree checker (`redbear-usb-check`) +### Boot-input reality + +For bare-metal boot resilience, the current USB stack is still incomplete. + +External USB keyboard input is reliably available only when the keyboard is reached through the +`xHCI -> usbhubd/usbhidd -> inputd` path. This is an important distinction because modern bare +metal does not guarantee that an attached keyboard will land on the xHCI runtime path. + +If a keyboard instead lands on: + +- an EHCI-owned path +- a UHCI/OHCI companion path +- a firmware routing topology where low/full-speed devices do not reach the xHCI runtime path + +then Red Bear may still detect controller ownership and connected ports, but it does not yet have a +complete runtime host path that reaches the existing HID class daemons. + +This means Red Bear cannot yet honestly claim that an external USB keyboard is a reliable universal +boot fallback on bare metal. + ### Red Bear xHCI Patch Layer The Red Bear patch at `local/patches/base/redox.patch` carries these changes over the upstream @@ -105,12 +125,17 @@ source: Even with the Red Bear patch applied: - HID is still wired through the legacy mixed-stream `inputd` path +- external USB keyboard fallback is not guaranteed on bare metal unless the keyboard reaches the + xHCI runtime path +- EHCI/UHCI/OHCI are not yet full runtime host-controller implementations - Any remaining USB composite/device-model issues now sit above the bounded helper fixes already landed for active alternates, endpoint direction, real interface/alternate hub configuration, and SSP-aware endpoint-context calculations. - ~57 TODO/FIXME comments remain across xHCI driver files - usbhubd: interrupt-driven change detection implemented; 1-second polling retained as fallback - usbscsid: `ReadCapacity16` now implemented with automatic fallback from `ReadCapacity10` +- `usbhidd` keyboard LED sync is only a bounded per-device best-effort path, not a system-global + lock-state authority - No real hardware USB validation — all testing is QEMU-only - No hot-plug stress testing - No USB storage data I/O validation (autospawn checked, but no read/write tested) @@ -124,8 +149,9 @@ Even with the Red Bear patch applied: |---|---|---| | Host mode | **builds / QEMU-validated** | Real host-side stack, interrupt-driven, QEMU-validated only | | xHCI controller | **builds / QEMU-validated** | Red Bear patch: 88 error handling fixes, ERDP split, endp_direction fix, cfg_idx fix, real grow_event_ring, mutex poison recovery on all hot-path locks; no real hardware validation yet | +| EHCI/UHCI/OHCI | **builds / enumerates** | Ownership, port handling, and logging exist, but they are not yet full runtime enumeration paths | | Hub handling | **builds / good quality** | `usbhubd`: all `expect()` eliminated, interrupt-driven change detection with polling fallback, graceful per-port error handling | -| HID | **builds / QEMU-validated in narrow path** | `usbhidd` handles keyboard/mouse/button/scroll via legacy input path, no panics in report loop | +| HID | **builds / QEMU-validated in narrow path** | `usbhidd` handles keyboard/mouse/button/scroll via legacy input path, no panics in report loop; keyboard LED sync exists as a bounded per-device best-effort path | | Mass storage | **builds / good quality** | `usbscsid`: typed `ScsiError`, fallible parsing, `ReadCapacity16` for >2TB, stall recovery, resilient event loop | | Native tooling | **builds / enumerates** | `lsusb`, `usbctl`, `redbear-info`, `redbear-usb-check` provide observability | | Low-level userspace API | **builds** | `xhcid_interface` with `UsbSpeed` enum, `attach_with_speed()` | diff --git a/local/patches/relibc/P3-fcntl-dupfd-cloexec.patch b/local/patches/relibc/P3-fcntl-dupfd-cloexec.patch index 2cd0a837..1a72d29f 100644 --- a/local/patches/relibc/P3-fcntl-dupfd-cloexec.patch +++ b/local/patches/relibc/P3-fcntl-dupfd-cloexec.patch @@ -1,18 +1,10 @@ diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs -@@ -8,6 +8,7 @@ use crate::{ - c_str::CStr, - error::{Errno, ResultExt}, - header::errno::ENAMETOOLONG, +@@ -9,0 +10 @@ + header::unistd::close, - platform::{ - Pal, Sys, - types::{ -@@ -78,6 +79,23 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) -> - _ => 0, - }; - +@@ -75,0 +77,17 @@ ++ + if cmd == F_DUPFD_CLOEXEC { + let new_fd = Sys::fcntl(fildes, F_DUPFD_CLOEXEC, arg).or_minus_one_errno(); + if new_fd >= 0 { @@ -29,6 +21,3 @@ diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs + } + return new_fd; + } -+ - Sys::fcntl(fildes, cmd, arg).or_minus_one_errno() - } diff --git a/local/patches/relibc/redox.patch b/local/patches/relibc/redox.patch index 2c08f6f5..1a72d29f 100644 --- a/local/patches/relibc/redox.patch +++ b/local/patches/relibc/redox.patch @@ -1,37 +1,10 @@ -diff --git a/src/c/stdlib.c b/src/c/stdlib.c -index 62e98108..a9c72392 100644 ---- a/src/c/stdlib.c -+++ b/src/c/stdlib.c -@@ -4,6 +4,13 @@ long double strtold(const char *nptr, char **endptr) { - return (long double)strtod(nptr, endptr); - } - -+long double relibc_compat_cpp_strtold(const char *nptr, char **endptr) -+ __asm__("_Z7strtoldPKcPPc"); -+ -+long double relibc_compat_cpp_strtold(const char *nptr, char **endptr) { -+ return strtold(nptr, endptr); -+} -+ - double relibc_ldtod(const long double* val) { - return (double)(*val); - } diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs -index ec37906c..95604e06 100644 --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs -@@ -8,6 +8,7 @@ use crate::{ - c_str::CStr, - error::{Errno, ResultExt}, - header::errno::ENAMETOOLONG, +@@ -9,0 +10 @@ + header::unistd::close, - platform::{ - Pal, Sys, - types::{ -@@ -78,6 +79,23 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) -> - _ => 0, - }; - +@@ -75,0 +77,17 @@ ++ + if cmd == F_DUPFD_CLOEXEC { + let new_fd = Sys::fcntl(fildes, F_DUPFD_CLOEXEC, arg).or_minus_one_errno(); + if new_fd >= 0 { @@ -48,6 +21,3 @@ index ec37906c..95604e06 100644 + } + return new_fd; + } -+ - Sys::fcntl(fildes, cmd, arg).or_minus_one_errno() - }