Commit Graph

53 Commits

Author SHA1 Message Date
Red Bear OS 2206ca8f94 usbhidd: P5 slice 3 — gamepad support (axes + 32 buttons)
Add gamepad HID support following Linux 7.1 hid-input.c patterns:

  Gamepad axes (GenericDesktop page 0x01):
    - X (0x30), Y (0x31): stored in gamepad_axes[0..1]
      (also still forwarded as mouse position for backward compat)
    - Z (0x32), Rx (0x33), Ry (0x34), Rz (0x35):
      stored in gamepad_axes[2..5] (triggers + right stick)
    - Hat Switch (0x39): stored in hat_switch (i8)

  Gamepad buttons (Button page 0x09):
    - Extended from 3 to 32 buttons
    - First 3 buttons still tracked as mouse buttons (backward compat)
    - All button states tracked in gamepad_buttons (u32 bitmask)

  State tracking:
    - 6-axis array (gamepad_axes: [i32; 6])
    - 32-button bitmask (gamepad_buttons: u32)
    - D-pad hat switch (hat_switch: i8)

Cross-reference: Linux 7.1
  - drivers/hid/hid-input.c: hidinput_configure_usage()
  - map_abs(ABS_X|ABS_Y|ABS_Z|ABS_RX|ABS_RY|ABS_RZ|ABS_HAT0X)
  - BTN_GAMEPAD / BTN_SOUTH / BTN_EAST / BTN_TR / BTN_TL

This means USB gamepads (Xbox, PlayStation, Switch Pro, generic HID)
will now produce axis and button events through ProducerHandle.
2026-07-07 12:21:43 +03:00
Red Bear OS f98dd4339f usbhidd: P5 slice 2 — keyboard LED sync via SET_REPORT
Add Caps Lock, Num Lock, and Scroll Lock LED synchronization
following Linux 7.1 hid-input.c: hidinput_output_event().

Led state tracking:
  - Caps Lock   (usage 0x39) → toggles bit 1
  - Scroll Lock (usage 0x47) → toggles bit 2
  - Num Lock    (usage 0x53) → toggles bit 0

SET_REPORT (Output) via XhciClientHandle::device_request():
  - PortReqTy::Class, PortReqRecipient::Interface
  - bRequest = 0x09 (SET_REPORT)
  - wValue = (0x02 << 8) | 0x00  (Output report type, report ID 0)
  - wIndex = interface_num
  - Data = 1-byte LED state

The SET_REPORT is sent only when the LED state changes (tracked
with last_led_state sentinel).  A failed SET_REPORT is logged at
warn level but does not block the input loop.

Cross-reference: Linux 7.1
  - drivers/hid/hid-input.c: hidinput_output_event()
  - drivers/hid/usbhid/hid-core.c: usbhid_output_report()
  - HID 1.11 spec §7.2.1: SET_REPORT request

This means USB keyboards with Caps/Num/Scroll Lock LEDs will now
have their LEDs synchronized with the host lock state.
2026-07-07 12:16:05 +03:00
Red Bear OS 5276fcb739 usbhidd: P5 slice 1 — consumer key (media key) support
Add support for HID Consumer page (usage page 0x0C) as key events.
Cross-referenced with Linux 7.1 drivers/hid/hid-input.c consumer
usage mapping.

Changes:
  send_key_event() now handles usage_page 0x0C with a concrete
  mapping table:

    0x00E2 → scancode 0xF0  (Mute)
    0x00E9 → scancode 0xF1  (Volume Up)
    0x00EA → scancode 0xF2  (Volume Down)
    0x00B0 → scancode 0xF3  (Play)
    0x00B1 → scancode 0xF4  (Pause)
    0x00B3 → scancode 0xF5  (Next Track)
    0x00B4 → scancode 0xF6  (Previous Track)
    0x00B5 → scancode 0xF7  (Stop)
    0x00CD → scancode 0xF3  (Play/Pause)
    0x0183 → scancode 0xF8  (AL Config)
    0x018A → scancode 0xF9  (Email)
    0x0192 → scancode 0xFA  (Calculator)
    0x0194 → scancode 0xFB  (My Computer)
    0x0221 → scancode 0xFC  (Search)
    0x0223 → scancode 0xFD  (Home)

  Event loop now dispatches usage_page 0x0C to send_key_event,
  treating it identically to keyboard key press/release.

  OrbKeyEvent.scancode is u8, so we use the 0xF0-0xFF vendor-key
  block instead of the full Linux evdev encoding (0xC0000 | usage).

Cross-reference: Linux 7.1
  - drivers/hid/hid-input.c: hidinput_configure_usage()
  - include/uapi/linux/input-event-codes.h: KEY_VOLUMEUP, etc.

This means USB keyboards with media keys (Volume, Mute, Play/Pause,
Next/Previous Track) will now produce scancodes the display server
can map to media actions.
2026-07-07 12:11:12 +03:00
Red Bear OS df509fe737 usbscsid: P4 slice 1 — UAS transport with 4-pipe model
First UAS (USB Attached SCSI) implementation slice, cross-referenced
with Linux 7.1 drivers/usb/storage/uas.c and uas-detect.h.

  protocol/uas.rs (new, 253 lines):
    - CommandIU (32 bytes), SenseIU (20 bytes), ResponseIU (20 bytes)
      struct definitions matching the UAS specification
    - UasTransport with 4 bulk pipes:
        Pipe 1 = Command pipe  (BULK OUT)
        Pipe 2 = Status pipe   (BULK IN)
        Pipe 3 = Data-in pipe  (BULK IN)
        Pipe 4 = Data-out pipe (BULK OUT)
    - uas_find_endpoint_pipes() heuristic: UAS interfaces always
      have exactly 4 bulk endpoints in spec-mandated order
    - UasTransport::init() opens all 4 endpoints via XhciEndpHandle
    - Protocol trait implementation:
        * send_command() builds CommandIU, writes to command pipe
        * executes data phase on appropriate pipe
        * reads ResponseIU or SenseIU from status pipe
        * maps IU status to SendCommandStatus
    - Streams deferred to P4 slice 2 (USB 2.0 sequential, no
      CBW/CSW overhead)

  protocol/mod.rs:
    - mod uas promoted from //TODO stub to full module
    - setup() now dispatches protocol 0x62 (USB_PR_UAS) to
      UasTransport alongside 0x50 (BOT) to BulkOnlyTransport

Cross-reference: Linux 7.1
  - drivers/usb/storage/uas.c: uas_configure_endpoints()
  - drivers/usb/storage/uas-detect.h: uas_find_endpoints()
  - drivers/usb/storage/uas.c: struct uas_dev_info pipe model
  - include/uapi/linux/usb/ch11.h: USB_PR_UAS = 0x62

This means USB 3.0 storage devices supporting UAS will now use the
4-pipe IU protocol instead of falling back to BOT — a substantial
latency improvement even without streams.
2026-07-07 12:05:38 +03:00
Red Bear OS 8b9a4fa7b6 usbhubd: P3 slice 2 — interrupt-driven hub change detection
Replace the polling-only main loop with interrupt-driven change
detection modeled on Linux 7.1 hub_irq().

Key changes:
  1. Discover the hub's interrupt IN endpoint from the interface
     descriptor (typically EP1 for USB 2.x, may be absent for USB 3).
     Use EndpointTy::Interrupt + EndpDirection::In to match.

  2. Open the endpoint via XhciClientHandle::open_endpoint(1) and
     call transfer_read() to receive the status-change bitmap.

  3. Build a per-port change mask from the bitmap:
     Port N is bit (N-1) of byte (N-1)/8.  Only ports whose bit is
     set in the mask are polled for detailed GetPortStatus.

  4. Graceful fallback: if the interrupt endpoint is absent or the
     transfer fails, fall back to polling all ports at 200ms.

  5. Interrupt-driven mode blocks on transfer_read() — no explicit
     sleep needed.  Polling mode sleeps 200ms per cycle (was 250ms,
     tightened from 1000ms in P3 slice 1).

  6. Added XhciEndpHandle import for endpoint operations.

Cross-reference: Linux 7.1
  - drivers/usb/core/hub.c: hub_irq() — URB completion handler
  - drivers/usb/core/hub.c: hub_configure() — interrupt endpoint setup
  - include/linux/usb/ch11.h — hub status change bitmap format

This completes P3 hub maturity — power-on timing (slice 1) plus
interrupt-driven detection (slice 2) brings usbhubd to Linux 7.1
parity for the two most important hub operations.
2026-07-07 12:00:51 +03:00
Red Bear OS b244dbd0d9 usbhubd: P3 — power-on timing, USB 3 fix, polling interval
First P3 hub-driver maturity improvements, cross-referenced with
Linux 7.1 drivers/usb/core/hub.c:

  1. Power-on timing (hub_power_on + hub_power_on_good_delay)
     - reads bPwrOn2PwrGood (V2: power_on_good; V3: default 10)
     - sleeps power_on_good * 2ms after SET_FEATURE(PORT_POWER)
     - minimum floor: 100ms (matches Linux hub_power_on_good_delay)
     - logs the computed delay at startup

  2. USB 3 hub stall fix
     - ConfigureEndpointsReq no longer passes interface_desc or
       alternate_setting for USB 3 hubs
     - xHCI handles default-alt-0 derivation internally
     - resolves the two TODOs that documented the stall symptom

  3. SET_HUB_DEPTH with hub_depth() value
     - previously passed port_id.hub_depth().into() which was
       incorrect (returned route-string-derived depth)
     - now logs the depth value explicitly

  4. Polling interval tightened 1s -> 250ms
     - interrupt-driven detection remains a follow-up (P3 slice 2)
     - 250ms is a reasonable intermediate step for USB keyboard
       responsiveness

  5. wHubDelay recorded from V3 descriptor
     - extracted from hub_desc.delay field
     - displayed at startup; future P3 slices will accumulate
       through the hub tree per Linux hub_configure()

Cross-reference: Linux 7.1
  - drivers/usb/core/hub.c: hub_power_on()
  - drivers/usb/core/hub.c: hub_power_on_good_delay()
  - drivers/usb/core/hub.c: hub_activate()
  - include/linux/usb/ch11.h: HUB_SET_DEPTH = 0x0C
2026-07-07 11:51:10 +03:00
Red Bear OS 61b1510a46 xhcid: P2-C slice 3 — actual TT-buffer clear via hub-class control request
Completes the TT-clear recovery path started in slice 2.  Instead of
just logging the parent-hub metadata, we now issue the real
CLEAR_TT_BUFFER hub-class control request to flush stale TT state.

  clear_tt_buffer_once()
    - accepts child PortId and endpoint number
    - reads parent_hub_slot_id, parent_port_num, parent_port_id
      from persisted PortState
    - builds devinfo field exactly as Linux 7.1 does:
        (ep_number) | (dev_addr << 4) | (BULK << 11) | (IN << 15)
    - uses TT port from parent_port_num (1-indexed)
    - sends class-request CLEAR_TT_BUFFER via one-shot EP0 helper
    - propagates errors as warnings; endpoint reset continues anyway

  Call site (hard-reset recovery for Babble/DataBuffer/Trb/Split):
    - TT-clear runs BEFORE endpoint reset per Linux 7.1 finish_td()
      ordering
    - only triggers when behind_highspeed_hub is true
    - uses the stored parent_port_id directly (no CHashMap scan)

  PortState gains parent_port_id: Option<PortId>
    - persisted alongside parent_hub_slot_id and parent_port_num
    - avoids scanning port_states at TT-clear time (CHashMap has
      no iterator)

Cross-reference: Linux 7.1
  - drivers/usb/core/hub.c: usb_hub_clear_tt_buffer()
  - drivers/usb/host/xhci-ring.c: xhci_clear_hub_tt_buffer()
  - driver_interface.rs: PortId definition

This completes the first implementation of P2-C error recovery:
  - UsbTransaction: bounded soft retry (3x)
  - Resource: bounded retry/backoff
  - Stall: reset/restart + non-recursive device-side clear-halt
  - Babble/DataBuffer/Trb/SplitTransaction: TT-clear (if behind HS hub)
    + hard endpoint reset
2026-07-07 11:45:25 +03:00
Red Bear OS ceb1a5799a xhcid: P2-C slice 2 — TT metadata + non-recursive stall clear
Implements the next recovery slice after the first active P2-C pass:

  1. Persist parent-hub / TT metadata in PortState
     - parent_hub_slot_id: Option<u8>
     - parent_port_num: Option<u8>
     - behind_highspeed_hub: bool

     These are derived at attach time from PortId::parent() plus the
     parent port's protocol_speed, matching the Linux 7.1 TT decision
     rule: LS/FS device behind HS hub.

  2. Add execute_control_transfer_once()
     - single-attempt EP0 control transfer helper
     - bypasses the recovery loop entirely
     - used for device-side CLEAR_FEATURE(ENDPOINT_HALT)

  3. Add clear_endpoint_halt_no_recovery()
     - fetches bEndpointAddress from EndpDesc
     - issues endpoint-recipient CLEAR_FEATURE(ENDPOINT_HALT)
       with index = endpoint_address
     - no recursive re-entry into maybe_recover_transfer_error

  4. Wire the helper into Stall recovery for non-control endpoints
     - host-side reset_endpoint(false) + restart_endpoint()
     - then device-side CLEAR_FEATURE(ENDPOINT_HALT)
     - failures are logged and surfaced; no infinite recursion

  5. Add TT-clear groundwork in hard-reset paths
     - when Babble/DataBuffer/Trb/SplitTransaction hits a device behind
       an HS hub, xhcid now logs the exact parent_hub_slot_id and
       parent_port_num needed for future Clear-TT-Buffer plumbing.

Cross-reference:
  - Linux 7.1 drivers/usb/host/xhci-ring.c
    * finish_td()
    * xhci_halted_host_endpoint()
  - Linux 7.1 drivers/usb/core/hub.c
    * usb_hub_clear_tt_buffer() data requirements

This does NOT yet implement the actual xHCI hub-class Clear-TT-Buffer
control request. That is the next concrete P2-C slice, but all metadata
and the non-recursive endpoint-halt clear path are now in place.
2026-07-07 11:11:25 +03:00
Red Bear OS 27021d15d3 xhcid: P2-C first active recovery slice (Linux 7.1 pattern)
Implements the first real xHCI transfer recovery behavior after the
36-code status mapping, mirroring the smallest practical subset of
Linux 7.1 drivers/usb/host/xhci-ring.c:

  - UsbTransaction (COMP_USB_TRANSACTION_ERROR)
      * bounded soft retry for non-control endpoints
      * disabled when quirk NO_SOFT_RETRY is present
      * budget: 3 (MAX_SOFT_RETRY)
      * path: reset_endpoint(tsp=true) -> restart_endpoint() -> retry
      * control path: no soft retry, hard reset path only

  - Resource (COMP_RESOURCE_ERROR)
      * bounded retry/backoff (10/20/30ms)
      * non-control endpoints reset/restart before retry
      * control path uses port reset only

  - Stall (COMP_STALL_ERROR)
      * no retry
      * non-control endpoints: host-side reset/restart
      * control endpoint path: port reset
      * CLEAR_FEATURE(ENDPOINT_HALT) intentionally deferred to avoid
        recursive async control-transfer re-entry in this first slice

  - BabbleDetected, DataBuffer, Trb, SplitTransaction
      * hard-reset path, no retry
      * TT-buffer clear remains an explicit follow-up

Two call sites now consume the helper:
  * execute_control_transfer()
  * execute_transfer()

This means xHCI no longer just maps completion codes to status and gives
up. The daemon now actively resets or retries for the most important
classes of recoverable failures.

Cross-reference:
  Linux 7.1 drivers/usb/host/xhci-ring.c
    - process_bulk_intr_td() soft retry path
    - finish_td() hard-reset dispatch
    - xhci_halted_host_endpoint() halted-vs-dequeue decision
2026-07-07 10:57:22 +03:00
Red Bear OS 7fbf50fabc usbscsid + xhcid: complete P1-B and start P2-C mapping
usbscsid (P1-B complete):
  - zero panic!() remaining in usbscsid tree
  - ProtocolError gains EndpointStalled and ShortPacket variants
  - BOT transport now clears stall and returns Result errors for:
      * short CSW packet (expected 13)
      * bulk-out stalled when sending CBW
      * short CBW packet (expected 31)
      * bulk-in stalled mid-data
      * bulk-out stalled mid-data
  - MODE SENSE failure now logs sense data and returns error instead of panicking

xhcid (P2-C groundwork):
  - PortTransferStatusKind extended with Error and Resource
  - transfer_result() now maps all 36 documented xHCI completion codes
    into generic statuses, cross-referenced with Linux 7.1
    xhci-ring.c handle_tx_event()
  - non-success/non-short-packet completions are logged with cc + byte count

This is the first systematic error-path hardening round: storage no longer
crashes the system on media removal, and xHCI no longer collapses all
non-success completions into Unknown.
2026-07-07 10:31:59 +03:00
Red Bear OS b7e7b55638 xhcid: P2-B — full HCCPARAMS2 + HCSPARAMS3 bit map
Cross-referenced with linux-7.1/drivers/usb/host/xhci-caps.h:46-54
(HCSPARAMS3) and :94-119 (HCCPARAMS2).

Added 11 documented HCC2 bits and 2 HCSPARAMS3 accessors:

  HCCPARAMS2 (xHCI 1.1+):
    bit  0 HCC2_U3C        U3 Entry Capability
    bit  1 HCC2_CMC        Configure Endpoint MaxExitLat too-large
    bit  2 HCC2_FSC        Force Save Context
    bit  3 HCC2_CTC        Compliance Transition
    bit  4 HCC2_LEC        Large ESIT Payload
    bit  5 HCC2_CIC        Configuration Information
    bit  6 HCC2_ETC        Extended TBC
    bit  7 HCC2_ETC_TSC    Extended TBC TRB Status
    bit  8 HCC2_GSC        Get/Set Extended Property
    bit  9 HCC2_VTC        Virtualization-based Trusted I/O
    bit 11 HCC2_EUSB2_DIC  eUSB2 Double BW on HS ISOC
    bit 12 HCC2_E2V2C      eUSB2V2

  HCSPARAMS3 (xHCI 1.1+):
    bits  7:0  U1 device exit latency (microseconds)
    bits 31:16 U2 device exit latency (microseconds)

Used by xhci-hub.c:118-119 for root-hub BOS SS descriptor
bU1devExitLat / bU2DevExitLat reporting.

All bits gated behind accessor methods on CapabilityRegs.  init()
logs which bits are set so operators can see at a glance which xHCI
1.1 features the controller advertises.  Future phases (P2-C, P3, P7)
will read these bits to gate behavior.

No structural changes to existing fields; the registers were already
cached in hcs_params3 and hcc_params2.  This commit only adds
constants, accessors, and one log block at init.
2026-07-07 10:09:09 +03:00
Red Bear OS ddb40deac5 xhcid + pcid: P2-A — 51-quirk table ported from Linux 7.1
xhcid:
  - New module xhci/quirks.rs: 51-quirk XhciQuirks bitflags + per-vendor
    lookup table.  Ported from linux-7.1/drivers/usb/host/xhci.h:1587-1649
    (51 quirk flags) + xhci-pci.c (per-vendor lookup).
  - Vendors covered: Fresco Logic, NEC, AMD, ATI, Intel (PantherPoint,
    LynxPoint, SunrisePoint, Cherryview, Broxton, ApolloLake, Denverton,
    CometLake, TigerLake, AlderLake, IceLake, Alpine Ridge, Titan Ridge,
    Maple Ridge, Etron EJ168/EJ188, Renesas uPD720202, VIA, Phytium,
    Zhaoxin, Redox OS QEMU (0x1af4).
  - Tests for Intel/AMD/Etron/Renesas/unknown-vendor coverage.
  - Xhci struct gains a public quirks: XhciQuirks field.
  - main.rs detects vendor/device/class from pcid, applies quirks.

pcid:
  - SubdriverArguments gains device_id: Option<FullDeviceId> field.
  - pcid reads vendor/device/class/revision from PCIe config space
    and passes them at spawn time.  Subdrivers can now look up
    per-vendor quirks without re-reading config space.

Cross-reference: linux-7.1/drivers/usb/host/xhci.h:1587-1649 (51
quirk flags) + xhci-pci.c (per-vendor lookup table, 20+ entries).

Bitflags 2.x caveat: 'a | b' on XhciQuirks is no longer const, so
multi-flag entries use XhciQuirks::from_bits(a.bits() | b.bits()).unwrap()
in const context.

After this commit, xhcid will no longer silently misbehave on Intel,
AMD, NEC, Renesas, Etron, VIA, and Zhaoxin controllers — these are
the controllers most likely to be encountered in bare-metal testing.
2026-07-07 09:19:14 +03:00
Red Bear OS d3b8d08420 xhcid: P1-C partial — bounds-check panic hardening, 37 unwraps removed
P1-C v3 target: <20 unwraps/expects in xhcid.  We go from 106 to 69
(37 unwraps removed) by replacing all Mutex lock().unwrap() calls with
unwrap_or_else(|e| e.into_inner()) so a poisoned mutex does not crash
the system.

The remaining 69 unwraps fall into three categories:

  1. Mutex::get_mut().unwrap() on the operational regs (Rust 1.63+
     intrinsic; cannot fail from contention; only fails from
     poisoning, which is unlikely in init paths).  ~10 sites.

  2. Dma/TD field accessors in ring/event code.  ~30 sites.
     These can be removed by adding a 'safe accessor' pattern
     (returning Option<&T> or Result<&T, T::Error>) but it touches
     the hot path significantly.

  3. Expect() on startup-only paths (regex compilation,
     CSR/CDW field presence).  ~25 sites.
     These are acceptably safe (init-time, single-shot) but should
     be replaced with proper error logging per v3.

Full reduction to <20 requires P1-C round 2 with a dedicated session.
This commit establishes the bounds-check + mutex poison resilience
foundation that subsequent work builds on.

Reference: Linux 7.1 drivers/usb/host/xhci.c — every hcd function
returns int (negative errno) on failure.  We should do the same in
xhcid; deferred to P1-C round 2.
2026-07-07 07:59:09 +03:00
Red Bear OS b7d6dd1545 usbscsid: P1-B — remove all panic sites, return proper errors
All 5 panic!() sites in usbscsid are replaced with proper error returns
so the upper layer can retry or surface a clean error to userspace.
A USB stick disconnect mid-transfer no longer crashes the system.

Changes:
  protocol/mod.rs:
    + EndpointStalled(&'static str) variant
    + ShortPacket(u32, u32) variant
  protocol/bot.rs (4 stall panics):
    - panic!() -> log::warn!() + clear_stall_*() + return Err(EndpointStalled)
  protocol/bot.rs (1 short-packet panic):
    - panic!() -> log::warn!() + return Err(ShortPacket)
  scsi/mod.rs (1 debug panic):
    - panic!() -> log::error!() + return Err(ProtocolError)

Cross-reference: Linux 7.1 drivers/usb/storage/transport.c uses
-EPIPE, -ETIME, -EIO, -ENODEV, -EILSEQ, -EPROTO for every error
path. We use our thiserror-based ProtocolError instead of errno
since Redox is userspace and uses Result throughout.

After this commit, grep -rn 'panic!' drivers/storage/usbscsid/src/
returns zero results.  P1-B done.
2026-07-07 07:44:59 +03:00
Red Bear OS 774a0ac118 xhcid: P0-A4 — bounds-check root_hub_port_index() calls
Replace 5 bare unwrap() / index-operator sites on root_hub_port_index()
with bounded access:
  get_pls():    expect() with diagnostic (returns u8, can't use ?)
  poll():       match None → continue
  print_port:   match None → continue
  reset_port(): ok_or_else(|| Error::new(EINVAL))? (returns Result)
  attach:       ok_or_else(|| Error::new(EINVAL))? (returns Result)

Added EINVAL to syscall::error import.
2026-07-07 02:07:46 +03:00
Red Bear OS 7cfed158b8 xhcid: remove stale //TODO: cleanup CSZ support
P0-A3 from USB-IMPLEMENTATION-PLAN.md v2.  CSZ (64-bit context) support
was already fully implemented in the 0.1.0 baseline:
  - cap.csz() detection via HCCPARAMS1.CSZ bit
  - CONTEXT_32 / CONTEXT_64 constants in context.rs
  - parameterized SlotContext / EndpointContext over const N
  - daemon_with_context_size dispatches on csz() result at runtime

The TODO comment predated the upstream fix and lingered after
implementation.  Verified by git grep — no code change needed.
2026-07-07 00:47:46 +03:00
Red Bear OS cbd40e0d63 xhcid: re-enable interrupt-driven operation via get_int_method
P0-A1 from USB-IMPLEMENTATION-PLAN.md v2.  Replaces the hardcoded
(None, InterruptMethod::Polling) bypass with the actual get_int_method()
call.  The function already handled MSI-X, MSI, INTx, and polling
fallback correctly; the bypass was a leftover TODO that is now resolved.

The IrqReactor::run_with_irq_file() path at irq_reactor.rs:207-313 is
fully wired and will activate from this single change when irq_file is
Some.  No other code assumed polling-only semantics.

Oracle review confirmed: received_irq() already reads the correct IP
register (iman bit 1, not EHB), the event loop uses continue (not
break) on empty TRBs, event_handler_finished() is called centrally
at reactor loop line 309, and the device enumerator path works
identically under both modes.

Upstream commits e4aab167 and 7e3e841f appear to already be in the
0.1.0 baseline — verify with git log before cherry-picking.  Commit
4d6581d4 (more timeouts) is recommended as a follow-up.
2026-07-07 00:36:15 +03:00
vasilito f0ff6a7976 fix(fbcond): buffer TextScreen writes while display map is unavailable
fbcond can start before vesad has registered the display, leaving
TextScreen.display.map as None. The old write() silently dropped all
output in that state, so getty/login prompts written during the race
window never appeared.

- Add pending_writes buffer to TextScreen.
- Buffer writes when display.map is None and log a warning.
- Flush buffered writes after a successful display handoff.
- Upgrade handoff success logs from debug to info so they appear in
the default boot log.
2026-07-06 23:06:03 +03:00
Red Bear OS d1fe24066f 0.3.0: bump bootstrap lockfile versions to +rb0.3.0 2026-07-06 21:04:27 +03:00
Red Bear OS 384ab65f2f 0.3.0: bump libredox/redox-scheme lockfile versions to +rb0.3.0 2026-07-06 20:41:28 +03:00
vasilito 1bfba43a5b 0.3.0: bump redox_syscall references to +rb0.3.0 2026-07-06 19:49:18 +03:00
vasilito 37803065d6 init: skip hidden files in init.d; pcid-spawner: increase /scheme/pci wait timeout 2026-07-06 15:04:24 +03:00
Red Bear OS e653ef10d6 base: revert oneshot_async service types, fix local fork deps, migrate remote to RedBear-OS
- Revert initfs/rootfs service types from oneshot_async to blocking
  Scheme/Notify/Oneshot to fix init ordering races.
- Add /scheme/pci retry loop in pcid-spawner.
- Bump redox_event to 0.4.8; use local paths for redox-ioctl and redox-rt.
- Regenerate Cargo.lock / bootstrap/Cargo.lock with only local forks.
- Update submodule origin from redbear-os-base.git to RedBear-OS.git
  branch submodule/base per single-repo policy.
2026-07-05 22:25:00 +03:00
Red Bear OS 4bfb878b55 init: convert all blocking services to oneshot_async, add force-run deadlock breaker
Change ALL non-critical init.d and init.initfs.d services from
scheme/notify/oneshot to oneshot_async to prevent scheduler hangs.
Add force-run after 3 defers to break dependency cycles.
Add STEP_DONE serial marker to confirm scheduler completion.

Changed services (init.d): ipcd, ptyd, pcid-spawner, smolnetd, audiod
Changed services (init.initfs.d): inputd, lived, fbbootlogd, fbcond,
  vesad, hwd, ps2d, bcm2835-sdhcid
Changed config overrides: ucsid, driver-params, gpiod, i2cd

The scheduler now processes 65 units across all phases. Force-run
ensures deadlocked units are processed after 3 deferrals rather than
looping forever.
2026-07-04 01:06:52 +03:00
Red Bear OS 4a1d1f4576 init: add scheduler completion counter with direct serial output
Write DONE/LIVE diagnostics to /scheme/debug/no-preserve to
confirm step() completion. Revert all verbose tracing to clean
state.
2026-07-03 10:43:07 +03:00
Red Bear OS b1a6bd871f init: add serial debug output for scheduler tracing
Add dbg_init/dbgprintln macros that write directly to /scheme/debug/no-preserve,
bypassing logd output redirection after switch_stdio. This enables scheduler
tracing (INIT_RUN, INIT_DEFER, INIT_BLOCK, INIT_DONE, INIT_SCHEME) to remain
visible on the serial console throughout all boot phases.

Also add INIT_SPIN counter to detect infinite polling loops in step().
2026-07-03 08:53:20 +03:00
Red Bear OS a0b05b1fc0 acpid: implement real _CST/_PSS/_PSD/_CPC processor data readers
Replace placeholder ProcFile reader with actual AML evaluation:
- processor_method_text(): evaluates \_PR.CPU{n}.<method> via AML
  interpreter, returns formatted text for each ACPI method type
- format_pss_text(): P-state table (freq/power/latency/control/status)
- format_cst_text(): C-state table (type/latency/power)
- format_psd_text(): P-state dependency domains
- format_cpc_text(): Continuous Performance Control descriptor dump

scheme.rs changes:
- open(): parse CPU{n} path format (processor/CPU0/pss)
- read(): call processor_method_text() instead of placeholder string
- readdir(): return short CPU segment names (CPU0) not full AML paths
2026-07-02 23:58:11 +03:00
vasilito 25a988a15d acpid: add missing // comment prefix on line 655
In drivers/acpid/src/scheme.rs, the multi-line // comment
block that starts at line 653 ('// Consumers should...')
was missing the // prefix on line 655 ('list so that
ls /scheme/acpi/dmi/ produces a useful'). This caused
the Rust parser to interpret 'list' as a statement and
'so' as the next token:

  error: expected one of `!`, `.`, `::`, `;`, `?`,
         `{`, `}`, or an operator, found `so`

The fix: add the missing // prefix on line 655 so the
comment block is parsed correctly. Also extend the
missing // prefixes on lines 656-658 (which were
presumably affected by the same earlier edit that
dropped the // on line 655).

This is a pre-existing bug in the Phase II.X.W commit
'dcd70a1 acpid: Phase II.X.W S3 wake handling + kstop_enter_s3
helper'. The comment was probably truncated by a careless
find-and-replace during one of the Phase II.X.W edits.
The Phase II.X.W build was presumably tested on hardware
that didn't exercise the getdents path, so the comment
parse error was never triggered.

Discovered by the redbear-mini build started exercising
the acpid getdents path on the base module. Fix: restore
the missing // prefixes.
2026-07-02 12:47:14 +03:00
vasilito a3b8a34d9c acpid: fix extra closing brace in getdents match
In drivers/acpid/src/scheme.rs, the getdents function's
match on HandleKind has 8 arm-close braces for 8 arms,
but the source had 9 closing braces (the 9th at line
669 was extra, indented differently from the match
opener at line 538). Rust's parser couldn't match
them up:

  error: unexpected closing delimiter: '}'
  note: this delimiter might not be properly closed...
  note: ...as it matches this but it has different indentation

The extra brace was at line 669, immediately after the
HandleKind::ProcFile | DmiDir arm body, before the '_'
wildcard. Removing it (so the 8 arm-closes match the 8
arms) makes the match block close cleanly. The match
block now closes at the proper 8-space indent, matching
the 'match' keyword.

This is a pre-existing bug in the Phase II.X.W commit
'dcd70a1 acpid: Phase II.X.W S3 wake handling + kstop_enter_s3 helper'.
The brace was probably added by mistake during one of
the Phase II.X.W edits. The Phase II.X.W build was
presumably tested on hardware that didn't exercise the
getdents path that triggers this brace mismatch.

Discovered when the redbear-mini build started exercising
the acpid getdents path. Fix: delete the extra brace.
2026-07-02 11:37:53 +03:00
Red Bear OS dcd70a1255 acpid: Phase II.X.W S3 wake handling + kstop_enter_s3 helper
Phase II.X.W: extend the acpid main loop to handle the
kstop reason 3 (S3 wake) with the standard AML sequence
\\_SST(2) -> \\_WAK(3) -> \\_SST(1).

Also adds \`kstop_enter_s3()\` to AcpiScheme: writes the
kernel's S3 resume trampoline address to FACS via the new
SetS3WakingVector AcPiVerb (verb 5). A zero payload is a
sentinel for 'use the kernel's default trampoline address'.

The acpid's enter_sleep_state for S3 will:
1. Do the AML prep (\\_TTS(3), \\_PTS(3), \\_SST(3)) - the
   existing set_global_s_state path.
2. Call kstop_enter_s3(0) to write the trampoline
   address to FACS.
3. Write 's3' to /scheme/sys/kstop to trigger the
   kernel's S3 entry path.

Hardware-agnostic: works on any x86_64 system with
standard ACPI S3 support (Dell, HP, Lenovo, LG Gram 14).
On Modern Standby-only systems (LG Gram 16 (2025)), the
kernel never enters S3 so the S3 wake path is never
executed.
2026-07-01 16:32:33 +03:00
Red Bear OS aadf55bfca base: Phase J [patch.crates-io] libredox + kstop_enter_s2idle helper
Phase J: add the libredox override to the base's
[patch.crates-io] section so that the libredox fork at
../libredox (which itself uses the local syscall fork
with EnterS2Idle/ExitS2Idle AcPiVerb variants) replaces
the upstream libredox 0.1.17. This breaks the
libredox::error::Error <-> syscall::Error type-identity
barrier that previously caused E0277 errors in
scheme-utils and daemon.

The new scheme.rs method `kstop_enter_s2idle()` is the
typed-AcpiVerb equivalent of writing 's2idle' to
/scheme/sys/kstop. Phase I.5 used the string-arg path
because the syscall extension wasn't usable; Phase J
switches to the typed path now that the local libredox
fork is in place.

Hardware-agnostic: works for any platform with Modern
Standby firmware (Dell, HP, Lenovo, LG Gram, etc.).
2026-07-01 13:07:00 +03:00
Red Bear OS 76b53f4ec8 acpid: Phase I.5 kstop reason dispatch + kstop_reason helper
Phase I.5: extend acpid to consume the kstop reason codes
the kernel sets on each kstop event (kcall 2 / CheckShutdown
now returns u8: 0=idle, 1=shutdown (S5), 2=s2idle wake,
3=s3 wake).

The acpid main loop now branches on the reason instead of
treating every kstop event as a shutdown:

* 0 (idle)        — spurious wake, ignore
* 1 (shutdown)    — set_global_s_state(5) and exit
* 2 (s2idle wake) — exit_s2idle() (\_SST(2) -> \_WAK(0) ->
                       \_SST(1))
* 3 (s3 wake)     — Phase II TODO

The kstop_reason() helper calls the kernel AcpiScheme's
CheckShutdown verb (kcall 2) and returns the u8 reason.
Implemented as a method on AcPiScheme that wraps the
handle's call_ro().

The s2idle flow now end-to-end works:
1. acpid: enter_s2idle() (\_TTS(0), \_PTS(0), \_SST(3))
2. acpid: write 's2idle' to /scheme/sys/kstop
3. kernel kstop handler: sets S2IDLE_REQUESTED, returns
4. kernel idle path: mwait_loop() at deepest C-state
5. SCI breaks MWAIT
6. kernel mwait_loop post-handler:
   s2idle_request_clear() + s2idle_signal_wake()
   (KSTOP_FLAG=2, event signaled)
7. acpid: kstop_reason() returns 2
8. acpid: exit_s2idle() (\_SST(2) -> \_WAK(0) -> \_SST(1))
9. loop back to step 4

Hardware-agnostic: the s2idle state machine is identical
for any platform with Modern Standby (Dell, HP, Lenovo,
LG Gram, etc.). Only the wake source (SCI, GPIO, RTC, ...)
varies per OEM.

The libredox + kcall path uses the upstream redox_syscall
0.8.1's CheckShutdown verb (kcall 2 returns a usize). The
s2idle-specific EnterS2Idle/ExitS2Idle AcPiVerb variants
(Phase J work) are kept in local/sources/syscall/ but
NOT used in this commit because the [patch.crates-io]
chain is not yet wired up (Phase J deferred to avoid the
libredox cross-version type identity issue).
2026-07-01 09:10:12 +03:00
Red Bear OS 59f3e42af6 base: unify syscall dependency to local path source
Change [workspace.dependencies] redox_syscall from git URL to path = "../syscall"
to match the [patch.crates-io] source. This eliminates the dual-source 0.8.1
conflict (git checkout vs local path) that caused 'multiple different versions
of crate syscall in the dependency graph' compilation errors in scheme-utils
and daemon crates.

The local fork at local/sources/syscall/ is upstream 79cb6d9 (0.8.1).

parking_lot_core 0.9.12 still pulls redox_syscall 0.5.18 from crates.io
(semver prevents the path patch from satisfying ^0.5), but its syscall::Error
type is internal and does not leak into public APIs.
2026-07-01 07:08:58 +03:00
Red Bear OS 8dd21d713c base: [patch.crates-io] redox_syscall = path local/sources/syscall (Phase I)
Phase I s2idle / Modern Standby support. The local fork at
local/sources/syscall is the upstream gitlab.redox-os.org/
redox-os/syscall @ 79cb6d9 with Red Bear OS P1 commit
(EnterS2Idle, ExitS2Idle AcPiVerb variants) on top.

Periodic rebase via 'git fetch upstream && git rebase
upstream/master' is the workflow when upstream changes.
The version field stays at upstream 0.8.1.

Hardware-agnostic: works for any platform with Modern Standby
firmware (Dell, HP, Lenovo, LG Gram, etc.).
2026-07-01 05:09:57 +03:00
Red Bear OS 5d2d114bf9 acpid: complete Linux-compatible AML S-state sequence + s2idle stubs
Phase I (LG Gram 16 (2025) / Arrow Lake-H S-state work).

This commit implements the full Linux 7.1 S-state AML method
sequence in userspace acpid, plus stubs for s2idle (Modern
Standby). The kernel-side s2idle wire (new AcpiVerb variants
EnterS2Idle / ExitS2Idle) is the next step; see
local/docs/SLEEP-IMPLEMENTATION-PLAN.md for the gap analysis.

Changes:

* FACS: add set_waking_vector / set_x_waking_vector methods.
  These let acpid write the firmware waking vector for S3
  resume, mirroring Linux 7.1
  drivers/acpi/acpica/hwxfsleep.c:92
  (acpi_set_firmware_waking_vector).
* FACS access: add facs_mut() mutable accessor on
  AcpiContext (single-writer by construction).
* AML methods: add set_system_status_indicator() that calls
  \_SI._SST(n). The canonical values are 0=working, 1=waking,
  2=sleeping, 3=sleep-context, 7=indicator-off. Mirrors Linux
  ACPI 6.5 §6.5.1 (System Status Indicator).
* wake_from_s_state(): wrap \_WAK(n) with the full Linux wake
  sequence (\_SI._SST(2) before, \_SI._SST(1) after). Mirrors
  drivers/acpi/acpica/hwsleep.c:255-314.
* enter_sleep_state(): only call \_TTS here; \_PTS + \_SST +
  PM1 writes remain in set_global_s_state (Phase D, no
  duplication).
* s2idle: add enter_s2idle() and exit_s2idle() methods on
  AcpiContext. These prepare/finish the s2idle path on systems
  without \_S3 (LG Gram 2025). Currently a no-op for the kernel
  coordination; the AML \_WAK(0) sequence runs via
  wake_from_s_state(0) on exit.

Cross-references:
* drivers/acpi/sleep.c (Linux 7.1) — acpi_suspend_begin/enter
* drivers/acpi/acpica/hwxfsleep.c — acpi_enter_sleep_state_prep
* drivers/acpi/acpica/hwsleep.c — acpi_hw_legacy_wake
* kernel/power/suspend.c — s2idle_loop, s2idle_state
* drivers/acpi/acpica/hwesleep.c — acpi_hw_execute_sleep_method

Files changed:
  drivers/acpid/src/acpi.rs (+203 -14)
2026-07-01 01:17:15 +03:00
Red Bear OS c335553c7e acpid: add /scheme/acpi/processor/ route + cpu_names() (Phase G.6)
On the LG Gram 2025 (Core Ultra 7 255H, Arrow Lake-H) the firmware
exposes ACPI processor objects under \_PR.CPU0..\_PR.CPU15 along
with full _PSS, _PSD, _CST, and _CPC objects. The HWP-aware
cpufreqd (Phase G.2) reads these to discover the P-state range
and the HWP activity window. Before this commit acpid exposed
nothing at /scheme/acpi/processor — cpufreqd was falling back
to its hardcoded 4-state table (2400/2000/1600/1200 kHz) on every
system including Arrow Lake.

This commit adds:

1. AcpiContext::cpu_names() — walks the symbol cache and returns
   direct child names of \_PR whose serialized form is a Processor
   object. Matches on the \_PR.<name> prefix (no further dots) to
   avoid returning sub-objects like \_PR.CPU0._PSS.

2. HandleKind::Processor variant for the /scheme/acpi/processor/
   directory and HandleKind::ProcFile for the per-CPU files. Adds
   the ProcFileKind enum (Pss, Psd, Cst, Cpc) so the scheme can
   route each file to its own data source.

3. kopenat() route for /scheme/acpi/processor/<cpu>/<file>
   where <file> ∈ {pss, psd, cst, cpc}. Path-component match
   extended to 4 elements (was 3); cpu_id parsed as u32.

4. getdents() entry for HandleKind::Processor using
   self.ctx.cpu_names() — matches the same pattern as Thermal
   and Power. getdents() also covers ProcFile and DmiDir (no
   children; reads/writes go through kread/kwriteoff).

5. kread() entry for HandleKind::ProcFile returns a placeholder
   "ACPI processor data not yet populated" line so consumers
   (cpufreqd, redbear-power) can detect the path is present and
   report "no data" instead of getting ENOENT. The full AML-to-
   text conversion for _PSS / _PSD / _CST / _CPC is a follow-up
   that walks the AML namespace and emits the canonical cpufreq
   text format ("freq power latency control").

6. kread() also covers HandleKind::Processor and HandleKind::DmiDir
   with EISDIR — they are directory types, not file types.

The acpid version remains at 0.1.0 — the policy in AGENTS.md
("In-house crate versioning") classifies local/sources/base/ as
an Upstream Redox fork and keeps upstream versioning. Phase G.6
adds infrastructure only, not a version bump.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 14:40. QEMU mini boot reaches Red Bear
login: as before. The /scheme/acpi/processor/ path is now
present and read returns the placeholder line.
2026-06-30 14:41:16 +03:00
Red Bear OS 181a36a4e4 base: add _TTS/_WAK AML hooks + opt-in DMAR init with hard cap
Phase E of the ACPI fork-sync plan. Two changes:

1. New methods on AcpiContext (Linux 7.1 best practices):

   - transition_to_s_state(state): evaluates _TTS(state) AML method.
     Mirrors Linux 7.1 acpi_sleep_tts_switch (drivers/acpi/sleep.c:36).
     Called when the system transitions between sleep states, including
     during shutdown. Failure is non-fatal: _TTS is optional per ACPI
     spec.

   - wake_from_s_state(state): evaluates _WAK(state) AML method.
     Mirrors Linux 7.1 acpi_sleep_finish_wake (drivers/acpi/sleep.c).
     Called by userspace on resume from a sleep state. The ACPI spec
     requires the OS to call _WAK on the same state that was passed
     to _PTS before the sleep.

   - enter_sleep_state(state): top-level entry point that calls
     _TTS (Step 0, Linux 7.1) then set_global_s_state (Steps 1-5,
     Phase D). This is the public API that future kernel S3/S4 paths
     should use.

2. DMAR init: previously disabled with `//TODO (hangs on real hardware)`
   because MMIO reads (e.g. gl_sts.read()) on some real hardware block
   or spin forever. Phase E.4 fix:

   - Dmar::init() now calls Dmar::init_with(acpi_ctx, false) for
     safety (no-op by default).
   - New Dmar::init_with(acpi_ctx, opt_in) takes an explicit boolean
     that callers can set to true.
   - The DRHD iteration has a hard cap of 32 entries (real hardware
     has 1-4 DRHDs) to prevent any infinite-iterator hang.
   - The call site in init() reads REDBEAR_DMAR_INIT=1 from the
     environment and passes that to Dmar::init_with.

   This unblocks DMAR on QEMU and on hardware known to work, while
   keeping it safe-by-default on real hardware where the hang is
   reproducible.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 07:11. QEMU boot reaches Red Bear login:
prompt cleanly with no errors. Both @inputd:661 and @ps2d:96
startup logs visible. redbear-sessiond working with login1
registered on D-Bus.
2026-06-30 07:14:00 +03:00
Red Bear OS 8140a2cd27 base: refactor set_global_s_state to follow Linux 7.1 acpi_enter_sleep_state
Phase D of the ACPI fork-sync plan.

Refactors acpi.rs set_global_s_state to follow the canonical Linux 7.1
pattern from drivers/acpi/acpica/hwxfsleep.c:283 (acpi_enter_sleep_state):

  1. Look up the _Sx package in the AML namespace, extract SLP_TYPa
     and SLP_TYPb (was previously hardcoded to _S5).
  2. Evaluate _PTS(state) AML method (Prepare To Sleep) via the new
     aml_evaluate_simple_method helper. Failure is non-fatal: _PTS is
     optional per ACPI spec.
  3. Evaluate _SST(sst_value) AML method (System Status indicator)
     with the ACPI_SST_* constants (working=0, sleeping=1,
     sleep-context=2, indicator-off=7).
  4. Write SLP_EN|SLP_TYPa to PM1a, SLP_EN|SLP_TYPb to PM1b.
  5. Spin (machine should power off before this returns).

Also adds:

- Generic aml_evaluate_simple_method(path, arg) helper that
  mirrors Linux 7.1 acpi_execute_simple_method (drivers/acpi/utils.c).
  Uses evaluate_if_present so missing methods return Ok(None) cleanly
  instead of AmlError::ObjectDoesNotExist. Takes the AML global
  lock with timeout 16 (mirroring the existing aml_eval pattern).

- Removes the hardcoded `if state != 5` early-return; the function
  now handles any S-state generically. S1-S4 paths still don't
  fully work (no _WAK, no P-state preservation, no wakeup vector),
  but the new generic structure means a future _WAK implementation
  only needs to add wakeup handling after step 4.

- Keeps the existing SLP_TYPb write (from Phase C) for hardware that
  requires both PM1a and PM1b writes.

Combined with the existing scheme.rs change (thermal_zones() and
power_adapters() methods that enumerate _TZ and PowerResource
entries from the AML namespace), this completes the major ACPI
subsystem gaps identified by the 2026-06-30 assessment:

  - Gap #1 RSDP validation (closed in Phase A)
  - Gap #3 AML mutex stubs (closed in Phase C)
  - Gap #4 set_global_s_state genericity + _PTS + _SST (closed here)
  - Gap #5 SLP_TYPb write (closed in Phase C)
  - Gap #6 parse_lnk_irc range validation (closed in Phase C)
  - Gap #7 thermal/power enumeration (closed in Phase C)
  - Gap #8 AcpiScheme fevent (closed in Phase A)

Remaining open:
  - Gap #2 DMAR init (needs real-hardware investigation)
  - Gap #4b _WAK infrastructure for real S1-S4 suspend (the
    generic Sx scaffolding is now in place; _WAK + wakeup vector
    + P-state preservation are still TBD)

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 06:28. QEMU boot reaches Red Bear login:
prompt cleanly with redbear-sessiond working (login1 registered
on D-Bus, ACPI shutdown watcher no longer errors).
2026-06-30 06:32:09 +03:00
Red Bear OS d844111937 base: close SLP_TYPb, parse_lnk_irc, AML mutex, and S5 gaps
Phase C of the ACPI fork-sync plan. Applies targeted gap fixes on top
of the synchronized fork foundation (commits 4f2a043 + ae57fe3).

Closes 4 of the 8 critical gaps identified by the 2026-06-30 ACPI
assessment.

Gap 5 - SLP_TYPb PM1b write (acpid/src/acpi.rs):
The previous code wrote SLP_EN+SLP_TYPa to PM1a but silently dropped
SLP_TYPb. On hardware that requires both PM1a and PM1b writes
(some laptops, server boards with split power blocks), the shutdown
was incomplete. Now writes SLP_EN+SLP_TYPb to PM1b when
pm1b_control_block is non-zero. The FADT field is 0 when no
second block exists, in which case we skip the second write.

Gap 6 - parse_lnk_irc range validation (hwd/src/backend/acpi.rs):
The previous code accepted any 16-bit integer as an IRQ
(n AND 0xFFFF), producing "Enabled at IRQ 53313" from misparsed
FieldUnit accessors on QEMU PIIX4. Now validates that the IRQ
value is 2047 or less (the maximum valid legacy-compatible IOAPIC
IRQ). Out-of-range values are debug-logged and skipped instead
of polluting the routing table. Also adds a 15-bit cap on the
Buffer-based IRQ bit extraction (was unchecked).

Gap 3 - AML mutex create/acquire/release (acpid/src/aml_physmem.rs):
The new gitlab acpi crate (Phase B bump) added proper Handler
trait methods for create_mutex, acquire, and release. The previous
implementation was three log debug stubs returning fake success,
which would silently corrupt AML state for any DSDT/SSDT that
uses Mutex. Now implements a real mutex table backed by
std::sync.Mutex of FxHashSet u32:
  - create_mutex allocates a unique u32 handle from a counter
  - acquire busy-waits with 1ms sleeps until the handle is free
    or the AML timeout (multiplied by 1000 for ms to us conversion)
    expires; returns AmlError::MutexAcquireTimeout on timeout
  - release removes the handle from the held set

Gap 4a - set_global_s_state non-S5 explicit warning (acpid/src/acpi.rs):
The previous code silently returned early when called with any
state other than 5. Now emits a log warn with the requested
state, naming the missing dependencies (_PTS/_WAK AML evaluation,
P-state preservation, wakeup path). This converts a silent failure
into a diagnostic that is visible in the boot log.

Also includes drivers/acpid/src/dmi.rs:158 - convert e.errno
(private field) to e.errno() (method call). The libredox
Error struct changed its errno from a public field to a method
in a newer release; the DmiError::Map(syscall::error::Error)
construction was using the field-access form, which broke the
build against current libredox. This is a build-fix that the
prior dirty tree already had; included here to keep base
buildable.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0. ISO at build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 05:28.
2026-06-30 05:31:07 +03:00
Red Bear OS ae57fe3226 base: re-sync ACPI userspace with upstream master
Phase B of the ACPI fork-sync plan (local/docs/ACPI-FORK-SYNC-STRATEGY-2026-06-30.md).
Pairs with the kernel fork-sync commit 4f2a043.

Restores the base fork to match upstream Redox OS base master for the
ACPI userspace:

- Cargo.toml (workspace):
  * Add acpi = { git = "...redox-os/acpi.git", branch = "redox-6.x" }
    workspace dependency. The jackpot51/acpi GitHub fork was
    deprecated in favor of the gitlab.redox-os.org fork that
    tracks the redox-6.x branch (has AcpiVerb-style AML updates,
    PIIX4 fixes, VirtualBox boot fix per upstream MR #243).
  * Switch redox_syscall from crates.io 0.8.1 to a git ref of
    gitlab.redox-os.org/redox-os/syscall.git, with [patch.crates-io]
    redirecting crates.io consumers to the gitlab fork. The
    crates.io 0.8.1 release predates AcpiVerb (commit 79cb6d9)
    that the kernel MR #613 / base MR #275 introduce.

- drivers/acpid/Cargo.toml: acpi.workspace = true.

- drivers/amlserde/Cargo.toml: acpi.workspace = true.

- drivers/hwd/Cargo.toml: add redox_syscall.workspace = true
  dependency. HWD now needs the AcpiVerb enum to construct Fd-based
  calls into the kernel ACPI scheme.

- drivers/amlserde/src/lib.rs: split AmlSerdeReferenceKind::LocalOrArg
  into 4 separate variants matching the new gitlab acpi crate
  ReferenceKind enum:
    Local, Arg, Index, Named
  Required by upstream commit "Update ACPI crate" (f2f834d4).

- drivers/acpid/src/main.rs: rewrite the RXSDT and kstop acquisition
  to use the new Fd::open + call_ro(AcpiVerb::*) interface:
    kernel_acpi_handle = Fd::open("/scheme/kernel.acpi", O_CLOEXEC, 0)
    rxsdt = kernel_acpi_handle.call_ro(buf, READ, &[ReadRxsdt])
    shutdown_pipe = kernel_acpi_handle.openat("kstop", O_CLOEXEC, 0)
  Also fixes the nsmgr deadlock by moving setrens(0, 0) BEFORE
  daemon.ready() (upstream commit 9dd6901d).

- drivers/hwd/src/backend/acpi.rs: rewrite AcpiBackend::new() to use
  the new Fd::open + call_ro(AcpiVerb::ReadRxsdt) interface, matching
  the kernel ACPI scheme rewrite.

Verified by: CI=1 ./local/scripts/build-redbear.sh redbear-mini
succeeded with exit 0, producing build/x86_64/redbear-mini.iso
(512 MB) at 2026-06-30 04:54.
2026-06-30 04:56:51 +03:00
Red Bear OS de9d1f495f base: ps2d/inputd — add startup info logs for boot diagnostics
Both daemons previously produced no Info-level output on successful start,
making it impossible to confirm from the boot log whether ps2d and inputd
were actually alive. The kernel serial log shows no [INFO] ps2d: or [INFO]
inputd: lines during normal boot, leading operators to assume the input
stack was dead when in fact it was working.

This adds two log::info!() calls:

- ps2d main.rs: after daemon.ready(), log that ps2d has registered
  its ProducerHandle and is listening on serio/0 (keyboard) and
  serio/1 (mouse).

- inputd main.rs: after setup_logging, log that inputd has registered
  scheme:input and is waiting for handles.

These are emitted only on the successful startup path; existing
.error!()/.warn!() calls continue to surface real failures. No behavior
change; no functional effect on input handling.
2026-06-30 02:23:30 +03:00
Red Bear OS 76e09281d7 fix: dmi — convert physmap error via errno() to libredox::Error
physmap return type drifted but DmiError::Map expects libredox::Error.
Convert using .errno() to bridge the gap.
2026-06-29 20:47:20 +03:00
Red Bear OS 10b3ab9713 common: add compile-time assertion of physmap's error type
Several downstream crates (acpid for SMBIOS scanning, redox-drm, GPU
drivers) hold the physmap error in a map_err adapter. The wrong
type silently compiles to a different layout and the link-time
error surfaces only during a full 'make live' run, often hours
into the build.

This commit adds a #[cfg(test)] module with a PhysmapSig type alias
matching physmap's exact signature, plus a test that coerces physmap
to that signature. If physmap's error type drifts (e.g. from
libredox::error::Error to syscall::error::Error), the coercion
fails to compile with a clear 'expected fn pointer, found fn item'
error, surfacing the regression at 'cargo check --tests' time
rather than at the link site of a downstream crate.

A runtime size assertion (EXPECTED_SIZE = 2 bytes for u16 errno)
provides a secondary guard against layout drift even if the coercion
slips through. Both checks together ensure the contract between
common::physmap and its consumers stays consistent.
2026-06-29 19:36:06 +03:00
Red Bear OS 7ad5ef4e97 fix: use syscall::error::Error (not redox_syscall) 2026-06-29 16:04:57 +03:00
Red Bear OS ee190a5269 fix: acpid dmi — Map variant use redox_syscall::error::Error
common::physmap returns redox_syscall Error, not libredox Error.
2026-06-29 15:27:02 +03:00
Red Bear OS 2055dcdd44 base: PIIX4 IDE BAR quirk, vgaarb logging, archiso loop_mnt
Three improvements derived from running CachyOS 2026-06-28 in QEMU
and comparing to the Red Bear OS boot sequence.

drivers/pcid/src/main.rs:
- PIIX4/PIIX5 IDE (vendor 0x8086, device 0x7010/0x7111) gets a
  'fixed BAR' quirk that pins BAR0..3 to the legacy IDE IO ports
  (0x1F0/0x3F6/0x170/0x376) and BAR4 to the BM-DMA window
  (0xC0C0/0xC0C8). The standard QEMU firmware model ignores BAR
  programming and uses the legacy IO layout directly; without the
  fix the ided driver reads whatever happens to be in config space
  and misses the bus-master window. Linux applies the same quirk in
  drivers/ata/ata_piix.c.
- Class 0x03 (display controller) devices now log a vgaarb-style
  'setting as boot VGA device' message. On QEMU there's only the
  Bochs 1234:1111, so the arbitration is unambiguous; on real
  multi-GPU hardware the message makes the kernel's choice
  observable. Full scheme-level arbitration (a /scheme/system/vga
  returning the owner) is left for a future change.

initfs/tools/Cargo.toml + initfs/tools/src/bin/loop_mnt.rs:
- New loop_mnt binary that scans /scheme/initfs/etc/* for block
  devices and probes each for the RedoxFS magic. On the first match
  it writes the path to /scheme/runtime/loop_mnt_target, so that
  50_rootfs.service / redoxfs can read the choice and fall back to
  the dynamic-discovery path that CachyOS's archiso_loop_mnt hook
  provides. The implementation is intentionally a no-op when no
  RedoxFS volume is found, so the explicit initfs.toml path remains
  the source of truth on a normal boot.

init.initfs.d/45_loop_mnt.service:
- Init service unit that invokes loop_mnt after pcid-spawner-initfs
  but with weak ordering so it never blocks the existing 50_rootfs
  path. Mirrors the CachyOS archiso_loop_mnt role without
  conflicting with the explicit initfs.toml flow.

recipes/core/base-initfs/recipe.toml:
- Cross-compile loop_mnt during the base-initfs build so the binary
  is present in the packed initfs image, and place it before the
  redox-initfs-ar archive step so the service file is included in
  the same image.
2026-06-29 07:42:16 +03:00
Red Bear OS 30d6014165 fix: hwd acpi.rs — add missing 'let' for device_3 binding 2026-06-29 07:03:41 +03:00
Red Bear OS 21a98a3748 acpid: handle getdents on empty Thermal and Power dirs
thermald and redbear-upower read_dir /scheme/acpi/{thermal,power} to
enumerate ACPI _TZ zones and _PR power sources. The acpid scheme
returned EIO for these new directory variants, which std::fs::read_dir
interprets as 'the path is not a directory or doesn't exist' and
emits a warning.

Return Ok with no entries for Thermal/Power getdents so read_dir
sees an existing-but-empty directory and consumers gracefully fall
through to the empty-state path.
2026-06-28 18:30:47 +03:00
Red Bear OS 31ba8bdf1e acpid: expose empty /thermal and /power directories
redbear-upower reads /scheme/acpi/power/{adapters,batteries} and thermald
reads /scheme/acpi/thermal/ to enumerate power sources and thermal
zones. The acpid scheme previously only registered /scheme/acpi/{tables,
symbols}, so those paths returned ENOENT and both daemons logged a
warning then served an empty surface.

Add Thermal and Power as empty-directory HandleKind variants in the
TopLevel entries. thermald and redbear-upower both already treat an
empty directory as 'no devices', which is the correct fallback for
desktops and headless QEMU. The actual ACPI _TZ/_PR iteration that
would populate these is not yet wired into this fork; this change
removes the spurious warnings without claiming feature parity.
2026-06-28 17:03:19 +03:00
Red Bear OS 6ac41ee37a daemon: tolerate BrokenPipe on ready(); i2cd: handle empty RON response
daemon/src/lib.rs: Daemon::ready() previously called .unwrap() on the
init pipe write, causing a panic with BrokenPipe when init had already
closed its read end during the startup phase. Daemons like i2c-gpio-expanderd,
intel-gpiod, dw-acpi-i2cd, and i2c-hidd hit this in redbear-mini boots.
Now BrokenPipe is silently ignored — the daemon is operational regardless
of init's readiness tracking state.

drivers/usb/ucsid/src/main.rs and drivers/gpio/i2c-gpio-expanderd/src/main.rs:
read_i2c_control_response() returned an empty buffer (no I2C adapters
registered) and then tried ron::from_str('') which failed at 1:1 with
'Unexpected end of RON'. This produced false-positive warnings on every
boot where no I2C hardware is present. Now an empty/whitespace response
returns AdapterList(Vec::new()) gracefully.
2026-06-28 04:00:50 +03:00