# Red Bear OS: Boot Process & Hardware Detection Improvement Plan **Version:** 1.5 (2026-05-15) **Reference:** Linux 7.1-rc3 (`local/reference/linux-7.1/`) **Status:** Canonical plan for boot efficiency, hardware detection completeness, and init ordering ## Implementation Status (2026-05-15) **Approach changed:** Instead of creating a separate `redbear-hwdetect` daemon, we are **enhancing the existing `driver-manager`** with ACPI bus support and boot stage targets. This builds on the existing `redox-driver-core` device model (DeviceId, DeviceInfo, Bus, Driver, DeviceManager) rather than duplicating it. ### Completed | Wave | Status | What was done | |------|--------|---------------| | Wave 0 | ✅ Done | Created `config/redbear-boot-stages.toml` with 4 stage targets (02_early_hw, 04_drivers, 06_services, 08_userland) + serial boot markers | | Wave 1 | ✅ Done | Created `local/recipes/drivers/redox-driver-acpi/` with `AcpiBus` that enumerates ACPI devices from `/scheme/acpi/symbols/`. Registered in `driver-manager` alongside `PciBus`. Added `_HID`-based device classification (maps ~40 ACPI hardware IDs to PCI-equivalent class/subclass/vendor). 15 unit tests pass. | | Wave 2 | ✅ Done | Created `resource.rs` — ACPI resource descriptor parser (raw byte buffers → typed structs for IRQ, MMIO, I/O port, DMA, address spaces). Covers all 25 ACPI resource types (types 0-25). Created `prt.rs` — _PRT PCI IRQ routing table resolver (parses RON-serialized Package-of-Packages, resolves static GSI and dynamic link device routing). Fixed `bus.rs` to use child symbol lookup for `_HID`/`_CID` (the RON `Device` variant is unit — properties are separate namespace children). Added `query_device_resources()` API to AcpiBus. 20+ new unit tests across all modules. | | Wave 2b | ✅ Done | Extended `driver-manager/config.rs` `probe()` to handle ACPI device binding alongside PCI. ACPI devices get `ACPI_DEVICE_PATH`, `ACPI_DEVICE_NAME`, `ACPI_MMIO_N`, `ACPI_IRQ_N`, `ACPI_IO_N` env vars passed to spawned drivers. PCI devices continue using `PCID_CLIENT_CHANNEL`/`PCID_DEVICE_PATH`. Updated `scheme.rs` to accept ACPI device names in the scheme namespace (relaxed PCI-only validation). `main.rs` now notifies bound devices for both buses. | | Wave 2c | ✅ Done | Created ACPI driver config with match criteria in `60-gpio-i2c.toml` — Intel I2C (class=0x0C/sub=0x05/vendor=0x8086 → dw-acpi-i2cd), AMD I2C (class=0x0C/sub=0x05/vendor=0x1022 → amd-mp2-i2cd), Intel GPIO (class=0x0C/sub=0x80/vendor=0x8086 → intel-gpiod). Wired into `redbear-device-services.toml` as `/lib/drivers.d/60-gpio-i2c.toml`. Infrastructure daemons (i2cd, gpiod) remain as init services (scheme providers); controller drivers are dual-pathed (init fallback + driver-manager matching). | | Wave 3 | ✅ Done | Rewired all services in `redbear-device-services.toml`, `redbear-mini.toml`, `redbear-full.toml` to use stage targets instead of flat `00_base.target` | | Wave 4 | ✅ Done | Removed dead `/etc/pcid.d/` entries from `redbear-mini.toml` and `redbear-full.toml`. Confirmed no runtime binary reads `/etc/pcid.d/`. All driver matching now uses `/lib/drivers.d/`. | | Wave 5 | ✅ Already had | `driver-manager/config.rs` already has scheme-aware deferred probing via `check_scheme_available()` + `depends_on` field | ### Not Yet Started | Wave | Status | What remains | |------|--------|---------------| | Wave 2c | Not started | Runtime _CRS evaluation via ACPI scheme `call()` interface for Method-type _CRS (currently only Buffer-type _CRS is parsed). Link device _CRS resolution for dynamic _PRT entries. Full image build verification. | ### Config consistency verified (2026-05-15) All `requires_weak` references in config files resolve to valid targets or services: - `00_base.target` — staged by `base` package at `/usr/lib/init.d/00_base.target` - Stage targets (`02_early_hw` through `08_userland`) — defined in `redbear-boot-stages.toml` - `12_boot-late.target` — compat alias defined in `redbear-device-services.toml` - `05_boot-essential.target` — defined in `redbear-full.toml` and `redbear-greeter-services.toml` - All service dependencies have corresponding `[[files]]` entries or package-staged definitions --- ## Purpose This document is the execution plan for making the Red Bear OS boot process **stellar**: efficient, complete, and — above all — featuring **perfect hardware detection and initialization**. It is grounded in a comprehensive study of Linux 7.1-rc3's boot flow (`init/main.c`, `drivers/base/`, `drivers/pci/`, `drivers/acpi/`) and maps Linux's proven patterns to Red Bear OS's microkernel architecture. ## Honest Current State ### What works today - UEFI boot on x86_64 (bootloader → kernel → initfs → init → login) - ACPI boot-baseline: RSDP/SDT/MADT/FADT/HPET parsing in kernel - PCI enumeration via `pcid` + driver matching via `driver-manager` - Wired networking (e1000d, rtl8168d, virtio-netd) in QEMU - PS/2 keyboard/mouse via kernel `serio` scheme - Framebuffer text console via `vesad` - Multi-core x2APIC/SMP works - Greeter/login QEMU proof passes on `redbear-full` ### What is broken or missing (THESE ARE THE GAPS) | Gap | Linux equivalent | RedBear status | |-----|-----------------|----------------| | **No unified hardware detection** | `start_kernel()` → `driver_init()` → initcalls | Fragmented across `pcid`, `acpid`, `hwd`, `driver-manager` | | **No device model** | `struct device`, `struct driver`, `struct bus_type` | No common device/driver/bus abstraction | | **No ACPI device enumeration** | `acpi_bus_scan()` walks namespace, creates platform devices | `acpid` parses tables but doesn't enumerate devices | | **No deferred probe with real semantics** | `-EPROBE_DEFER` + retry queue in `driver_deferred_probe_trigger()` | `driver-manager` has a 30-retry loop but no dependency graph | | **No device resource tracking** | `request_region()`, `request_irq()`, `ioremap()` with resource tree | BARs mapped ad-hoc per driver, no global resource registry | | **No boot-stage ordering** | initcall levels (core → postcore → arch → subsys → device → late) | Flat `requires_weak` everywhere; no semantic stages | | **PCI enumeration too late** | PCI scanned at `subsys_initcall` level (level 4) | `driver-manager` is a userspace service with no hard dependency | | **No platform/I2C/SPI device discovery** | ACPI `_HID`/`_CID` creates platform/i2c/spi devices | I2C/SPI daemons exist but no device enumeration from ACPI | | **No USB device enumeration** | `usb_new_device()` → device descriptor → class matching | xHCI controller starts but no USB topology enumeration | | **No sysfs/udev equivalent** | `/sys/devices/` tree + udev rules | `udev-shim` exists but is minimal | | **Silent service failures** | Kernel oops if critical subsystem fails | `requires_weak` + `oneshot_async` → failures are invisible | ## Architecture: What Linux Does That We Must Reimplement ### Linux Boot Flow (from `init/main.c`) ``` start_kernel() ├── setup_arch() → arch-specific: page tables, early param parsing ├── trap_init() → IDT/exception vectors ├── mm_init() → memory management, slab allocator ├── sched_init() → scheduler ├── early_irq_init() → early IRQ descriptors ├── init_IRQ() → architecture IRQ controllers (IOAPIC, LAPIC) ├── time_init() → HPET/PIT/timers ├── console_init() → early console ├── driver_init() → device model core (kobject, sysfs, bus, class) └── rest_init() └── kernel_init() └── do_basic_setup() └── do_initcalls() ├── level 0 (core): kobject, debugfs, kernel core ├── level 1 (postcore): driver core, workqueue ├── level 2 (arch): arch-specific devices ├── level 3 (subsys): PCI, ACPI, network stack ├── level 4 (fs): filesystems ├── level 5 (device): device drivers └── level 6 (late): late drivers, networking ``` ### Linux Device Model (from `drivers/base/`) Three core abstractions: 1. **`struct bus_type`** — PCI, ACPI, platform, USB, I2C, SPI 2. **`struct device`** — represents hardware, has parent, bus, driver, resources 3. **`struct device_driver`** — probe/remove/shutdown callbacks, ID table Binding flow: ``` bus->probe(dev) → driver->probe(dev, id) → device bound to driver ``` Deferred probing (`drivers/base/dd.c`): ``` driver_probe_device() returns -EPROBE_DEFER → device added to deferred_probe_pending_list → driver_deferred_probe_trigger() retries on schedule → wake_up_all() after each successful bind ``` ### Linux ACPI Device Discovery (from `drivers/acpi/scan.c`) ``` acpi_init() └── acpi_bus_scan() └── acpi_walk_namespace() ├── Read _HID (hardware ID) ├── Read _CID (compatible IDs) ├── Read _STA (status: present, enabled, functional) ├── Read _CRS (current resource settings: IRQ, MMIO, I/O ports) └── Create device: ├── PCI root bridge → pci_scan_child_bus() ├── I2C controller → i2c_register_adapter() ├── SPI controller → spi_register_controller() ├── GPIO controller → gpiochip_add() ├── Platform device → platform_device_register() └── Thermal zone → thermal_zone_device_register() ``` ### Linux PCI Enumeration (from `drivers/pci/probe.c`) ``` pci_scan_child_bus(bus) for devfn in 0..0xFF: pci_scan_slot(bus, devfn) ├── Read PCI_VENDOR_ID → skip if 0xFFFFFFFF ├── Read PCI_HEADER_TYPE → multifunction? ├── Read PCI_CLASS, PCI_REVISION ├── Read BARs (6 base address registers) ├── Parse capability chain (MSI, MSI-X, PCIe, power management) ├── Assign IRQ (from ACPI _PRT or BIOS) ├── If PCI bridge: recursively scan subordinate bus └── Register device → driver core → bus_probe_device() ``` ## Design: RedBear OS Hardware Detection Architecture ### Core Principle **RedBear OS is a microkernel.** Unlike Linux where everything runs in kernel space, RedBear OS runs all drivers as **userspace daemons** accessing hardware through schemes. This means our "device model" lives in **userspace**, not in the kernel. The kernel provides: - `scheme:irq` — interrupt delivery - `scheme:memory` — physical memory mapping - `scheme:pci` — PCI config space access - `scheme:acpi` — ACPI table access - `scheme:serio` — PS/2 controller Everything else — device discovery, driver matching, resource allocation — is userspace. ### Proposed Architecture ``` ┌─────────────────────────────────────────────────────────┐ │ Kernel (microkernel) │ │ schemes: irq, memory, pci, acpi, serio, event, time │ │ ACPI early: RSDP, MADT (LAPIC/IOAPIC), HPET │ │ x2APIC/SMP: AP startup, interrupt routing │ └───────────────────────┬─────────────────────────────────┘ │ scheme IPC ┌───────────────────────▼─────────────────────────────────┐ │ redbear-hwdetect (NEW DAEMON) │ │ unified hardware detection & device registry │ │ │ │ 1. PCI bus walk (via scheme:pci) │ │ → enumerate all devices, parse BARs/caps/IRQ │ │ → build device tree with parent-child relationships │ │ │ │ 2. ACPI device scan (via scheme:acpi + acpid) │ │ → walk ACPI namespace for _HID/_CID/_STA/_CRS │ │ → create platform/I2C/SPI devices from ACPI │ │ → resolve PCI IRQ routing via _PRT │ │ │ │ 3. USB topology (via xhcid scheme) │ │ → enumerate USB devices on each controller │ │ → match by class/vendor/product │ │ │ │ 4. Driver matching │ │ → match devices to /lib/drivers.d/*.toml │ │ → spawn driver daemons with correct resources │ │ → deferred retry with real dependency tracking │ │ │ │ 5. Device registry (scheme:hwdetect) │ │ → /scheme/hwdetect/devices → list all detected HW │ │ → /scheme/hwdetect/pci/{bdf} → per-device info │ │ → /scheme/hwdetect/acpi/{path} → per-ACPI device │ │ → /scheme/hwdetect/drivers → driver status │ │ → JSON output for diagnostics │ │ │ │ Registers scheme: hwdetect │ └─────────────────────────────────────────────────────────┘ ``` ### Why Enhance driver-manager Instead of Creating a New Daemon > **Decision (2026-05-15):** We chose to enhance the existing `driver-manager` instead of > creating `redbear-hwdetect`. The `redox-driver-core` crate already provides a solid device > model (DeviceId, DeviceInfo, Bus trait, Driver trait, DeviceManager with deferred probing), > and `driver-manager` already uses it for PCI enumeration. Adding ACPI bus support as a > second `Bus` implementation follows the established pattern and avoids duplicating the > device model, driver matching, and deferred probe logic. The current `driver-manager` does PCI matching but: - No ACPI device enumeration - No USB topology - No device tree - No resource tracking - No parent-child relationships - Deferred retry is naive (fixed interval, no dependency graph) Rather than bolting more onto `driver-manager`, the original plan was to create `redbear-hwdetect` as the **single source of truth** for hardware state, and `driver-manager` becomes a thin consumer of its device registry. **However, since `redox-driver-core` already provides the device model abstractions, we enhance `driver-manager` by registering additional `Bus` implementations (ACPI, and eventually USB).** ## Implementation Plan ### Wave 0: Boot Stage Definitions (config-only, zero code) **Goal:** Replace the flat `requires_weak` service model with explicit boot stages. **Current problem:** Every service uses `requires_weak = ["00_base.target"]` which means no real ordering guarantee. Services can start in any order and silently fail. **Linux equivalent:** initcall levels (core → postcore → arch → subsys → device → late) **Proposed boot stages:** ``` Stage 0: PLATFORM — kernel schemes ready (irq, memory, pci, acpi, serio) Stage 1: CORE — tmpdir, logging, random, null/zero Stage 2: EARLY_HW — acpid (ACPI tables), pcid (PCI bus access) Stage 3: BUS_ENUM — redbear-hwdetect (PCI walk, ACPI scan, USB topology) Stage 4: DRIVERS — driver spawning (storage, network, GPU, audio, USB class) Stage 5: LATE_HW — IOMMU, firmware loading, NUMA topology Stage 6: SERVICES — D-Bus, session broker, seat management Stage 7: USERLAND — console, greeter, desktop ``` **Implementation:** Add target files: ```toml # /etc/init.d/00_platform.target [unit] description = "Platform stage: kernel schemes ready" # /etc/init.d/01_core.target [unit] description = "Core stage: basic services" requires = ["00_platform.target"] # /etc/init.d/02_early_hw.target [unit] description = "Early hardware: ACPI + PCI bus access" requires = ["01_core.target"] # /etc/init.d/03_bus_enum.target [unit] description = "Bus enumeration: PCI walk + ACPI scan" requires = ["02_early_hw.target"] # /etc/init.d/04_drivers.target [unit] description = "Driver spawning stage" requires = ["03_bus_enum.target"] # /etc/init.d/05_late_hw.target [unit] description = "Late hardware: firmware, IOMMU, NUMA" requires = ["04_drivers.target"] # /etc/init.d/06_services.target [unit] description = "System services: D-Bus, session broker" requires = ["05_late_hw.target"] # /etc/init.d/07_userland.target [unit] description = "User-facing: console, greeter, desktop" requires = ["06_services.target"] ``` **Key change:** Use `requires` (hard dependency, blocks if not met) instead of `requires_weak` for stages. Services within a stage use `requires_weak` against their stage target. ### Wave 1: redbear-hwdetect — The Unified Hardware Detection Daemon **Goal:** Create a single daemon that discovers ALL hardware, builds a device tree, and manages driver lifecycle. **Source location:** `local/recipes/system/redbear-hwdetect/source/` **Cargo.toml:** ```toml [package] name = "redbear-hwdetect" version = "0.1.0" edition = "2024" [dependencies] redox-daemon = "0.1" redox-scheme = "0.11" libredox = "0.1" redox_syscall = "0.7" serde = { version = "1", features = ["derive"] } serde_json = "1" toml = "0.8" log = "0.4" [features] default = [] ``` **Module structure:** ``` redbear-hwdetect/source/src/ ├── main.rs — daemon entry, scheme registration, event loop ├── device.rs — Device trait, DeviceInfo, DeviceType, DeviceStatus ├── registry.rs — DeviceRegistry: HashMap ├── pci/ │ ├── mod.rs — PciEnumerator: bus walk via scheme:pci │ ├── config.rs — PCI config space reader │ ├── capability.rs — PCI capability chain parser (MSI, MSI-X, PCIe, PM) │ └── resource.rs — BAR parsing, IRQ assignment, resource allocation ├── acpi/ │ ├── mod.rs — AcpiScanner: device enumeration from ACPI tables │ ├── namespace.rs — ACPI namespace walker (via acpid) │ ├── resource.rs — _CRS parser (IRQ, MMIO, I/O port resources) │ └── pci_routing.rs — _PRT (PCI IRQ routing table) resolver ├── usb/ │ ├── mod.rs — UsbScanner: USB topology via xHCI schemes │ └── descriptor.rs — USB device/class descriptor parsing ├── driver/ │ ├── mod.rs — DriverMatcher: load /lib/drivers.d/*.toml │ ├── match.rs — Device-driver matching (class, vendor, subclass) │ └── spawn.rs — Driver process spawning with resource handoff ├── deferred.rs — Deferred probe queue with dependency graph └── scheme.rs — scheme:hwdetect handler ``` **Key data structures:** ```rust /// Unique device identifier #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] pub enum DeviceId { Pci { domain: u16, bus: u8, device: u8, function: u8 }, Acpi { path: String }, // ACPI namespace path (e.g., "\_SB.PCI0.I2C0") Usb { controller: u8, port: u8, address: u8 }, Platform { name: String, id: u32 }, } /// Device information #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeviceInfo { pub id: DeviceId, pub device_type: DeviceType, pub status: DeviceStatus, pub vendor_id: Option, pub device_id: Option, pub class_code: Option, pub subclass_code: Option, pub prog_if: Option, pub revision: Option, pub parent: Option, pub resources: Vec, pub driver: Option, pub quirks: Vec, pub description: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum DeviceType { PciDevice, PciBridge, AcpiDevice, UsbController, UsbDevice, PlatformDevice, I2cController, I2cDevice, SpiController, SpiDevice, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum DeviceStatus { Detected, // Found during scan, not yet probed Probing, // Driver probe in progress Bound, // Driver successfully bound Deferred, // Probe deferred (dependency not ready) Failed(String), // Probe failed permanently NoDriver, // No matching driver found } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Resource { pub resource_type: ResourceType, pub base: u64, pub size: u64, pub flags: ResourceFlags, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum ResourceType { Mmio, // Memory-mapped I/O IoPort, // I/O port range Irq, // Interrupt (GSI number) Dma, // DMA channel/range Firmware, // Required firmware blob } bitflags! { #[derive(Serialize, Deserialize)] pub struct ResourceFlags: u32 { const PREFETCHABLE = 0x01; const CACHEABLE = 0x02; const SHARED = 0x04; const MSI = 0x08; const MSI_X = 0x10; } } /// Driver match rule (from /lib/drivers.d/*.toml) #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DriverMatch { pub vendor: Option, pub device: Option, pub class: Option, pub subclass: Option, pub prog_if: Option, } /// Driver configuration #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DriverConfig { pub name: String, pub description: String, pub priority: u32, pub command: Vec, pub depends_on: Vec, // scheme names that must exist before spawn pub matches: Vec, } ``` **PCI enumeration flow (from Linux `drivers/pci/probe.c`):** ```rust impl PciEnumerator { /// Walk all PCI buses (mirrors Linux pci_scan_child_bus) pub fn scan_all_buses(&mut self) -> Result> { let mut devices = Vec::new(); // Read from scheme:pci — get all PCI devices for entry in self.read_pci_scheme()? { let domain = entry.domain; let bus = entry.bus; let dev = entry.device; let func = entry.function; // Read config space (mirrors Linux pci_scan_slot) let config = self.read_config(domain, bus, dev, func)?; // Skip invalid devices (vendor 0xFFFF) if config.vendor_id == 0xFFFF { continue; } // Parse device info (mirrors Linux pci_setup_device) let mut device = DeviceInfo { id: DeviceId::Pci { domain, bus, device: dev, function: func }, device_type: if config.is_bridge() { DeviceType::PciBridge } else { DeviceType::PciDevice }, status: DeviceStatus::Detected, vendor_id: Some(config.vendor_id), device_id: Some(config.device_id), class_code: Some(config.class_code), subclass_code: Some(config.subclass_code), prog_if: Some(config.prog_if), revision: Some(config.revision), parent: self.find_parent_bridge(domain, bus), resources: Vec::new(), driver: None, quirks: Vec::new(), description: format!("PCI {:04x}:{:02x}:{:02x}.{} [{:04x}:{:04x}]", domain, bus, dev, func, config.vendor_id, config.device_id), }; // Parse BARs (mirrors Linux pci_read_bases) for bar_idx in 0..6 { if let Some(resource) = self.parse_bar(domain, bus, dev, func, bar_idx)? { device.resources.push(resource); } } // Parse capability chain (mirrors Linux pci_init_capabilities) self.parse_capabilities(&mut device, domain, bus, dev, func)?; // Assign IRQ (from ACPI _PRT or IOAPIC routing) if let Some(irq) = self.assign_irq(&device)? { device.resources.push(Resource { resource_type: ResourceType::Irq, base: irq as u64, size: 1, flags: ResourceFlags::empty(), }); } // Apply quirks self.apply_quirks(&mut device)?; devices.push(device); } Ok(devices) } } ``` **Deferred probe with real dependency graph (from Linux `drivers/base/dd.c`):** ```rust pub struct DeferredQueue { /// Devices waiting for dependencies pending: HashMap>, // device → missing dependencies /// Maximum retries per device max_retries: u32, /// Retry interval in ms retry_interval: u64, } impl DeferredQueue { /// Add a deferred device (mirrors Linux driver_deferred_probe_add) pub fn add(&mut self, device_id: DeviceId, missing_deps: Vec) { self.pending.insert(device_id, missing_deps); } /// Retry all deferred devices (mirrors Linux driver_deferred_probe_trigger) pub fn retry_cycle(&mut self, registry: &mut DeviceRegistry) -> Vec { let mut resolved = Vec::new(); // Check each deferred device let pending_ids: Vec = self.pending.keys().cloned().collect(); for id in &pending_ids { if let Some(missing) = self.pending.get(id) { // Check if all dependencies are now available let all_ready = missing.iter().all(|dep| { // Check if the scheme/file exists std::path::Path::new(&format!("/scheme/{}", dep)).exists() || std::path::Path::new(&format!("/bin/{}", dep)).exists() }); if all_ready { let deps = self.pending.remove(id).unwrap(); log::info!("Deferred device {:?} resolved (deps: {:?})", id, deps); if let Some(device) = registry.get_mut(id) { device.status = DeviceStatus::Detected; // Reset to retry resolved.push(device.clone()); } } } } resolved } } ``` ### Wave 2: ACPI Device Enumeration **Goal:** Walk the ACPI namespace to discover non-PCI devices (I2C, SPI, GPIO, thermal, battery, AC adapter, platform devices). **Linux reference:** `drivers/acpi/scan.c::acpi_bus_scan()` **Implementation in redbear-hwdetect:** ```rust impl AcpiScanner { /// Enumerate ACPI devices (mirrors Linux acpi_bus_scan) pub fn scan(&mut self) -> Result> { let mut devices = Vec::new(); // Connect to acpid via scheme:acpi let acpi = File::open("/scheme/acpi")?; // Walk ACPI namespace (read device entries) // Linux does: acpi_walk_namespace(ACPI_TYPE_DEVICE, ...) // RedBear: read entries from acpid's device enumeration for entry in self.enumerate_acpi_devices(&acpi)? { let hid = self.read_hid(&entry)?; let cid = self.read_cid(&entry)?; let sta = self.read_sta(&entry)?; // Skip if not present (mirrors Linux acpi_bus_check_add) if !sta.present { continue; } // Parse _CRS resources (mirrors Linux acpi_walk_resources) let resources = self.parse_crs(&entry)?; // Determine device type from _HID/_CID let device_type = match hid.as_str() { "PNP0A03" | "PNP0A08" => DeviceType::PciBridge, // PCI root bridge "INT33C3" | "INT3433" | "AMDI0010" => DeviceType::I2cController, "INT33C0" | "INT3430" | "AMDI0061" => DeviceType::SpiController, _ => DeviceType::PlatformDevice, }; let device = DeviceInfo { id: DeviceId::Acpi { path: entry.path.clone() }, device_type, status: DeviceStatus::Detected, vendor_id: None, device_id: None, class_code: None, subclass_code: None, prog_if: None, revision: None, parent: Some(DeviceId::Acpi { path: entry.parent.clone() }), resources, driver: None, quirks: Vec::new(), description: format!("ACPI device {} ({})", entry.path, hid), }; devices.push(device); } Ok(devients) } } ``` ### Wave 3: Service Ordering Fix **Goal:** Replace the current flat `requires_weak` model with stage-based ordering. **Changes to config files:** 1. **Add stage targets** to `config/redbear-device-services.toml` (shared fragment) 2. **Rewire services** to depend on their stage target instead of `00_base.target` **New service wiring example:** ```toml # acpid: early hardware stage [[files]] path = "/etc/init.d/02_acpid.service" data = """ [unit] description = "ACPI daemon" requires = ["02_early_hw.target"] [service] cmd = "acpid" type = { scheme = "acpi" } """ # redbear-hwdetect: bus enumeration stage [[files]] path = "/etc/init.d/03_redbear-hwdetect.service" data = """ [unit] description = "Hardware detection and device registry" requires = ["03_bus_enum.target", "02_acpid.service"] [service] cmd = "redbear-hwdetect" type = { scheme = "hwdetect" } """ # driver-manager: driver spawning stage (now consumes hwdetect registry) [[files]] path = "/etc/init.d/04_driver-manager.service" data = """ [unit] description = "Driver manager (consumes hwdetect registry)" requires = ["04_drivers.target", "03_redbear-hwdetect.service"] [service] cmd = "driver-manager" type = "oneshot_async" """ ``` ### Wave 4: Driver Config Unification **Goal:** Consolidate `/etc/pcid.d/` and `/lib/drivers.d/` into a single config format. **Current problem:** Two config systems exist: - `/etc/pcid.d/*.toml` — legacy pcid format - `/lib/drivers.d/*.toml` — driver-manager format **Solution:** Use only `/lib/drivers.d/*.toml` (driver-manager format). Remove all `/etc/pcid.d/` config file generation from TOML configs. **Updated driver config format (enhanced from current):** ```toml [[driver]] name = "e1000d" description = "Intel Gigabit Ethernet" priority = 50 command = ["/usr/lib/drivers/e1000d"] depends_on = ["pci"] # scheme dependencies (NEW) capabilities = ["net"] # declares what it provides (NEW) [[driver.match]] vendor = 0x8086 class = 0x02 subclass = 0x00 # Optional: specific device IDs for better matching [[driver.match]] vendor = 0x8086 device = 0x100e # 82540EM class = 0x02 ``` ### Wave 5: Boot Diagnostics **Goal:** Make boot failures visible and diagnosable. **Implementation:** 1. **`redbear-hwdetect --status`** — print detected hardware and driver status 2. **Boot marker on serial** — `echo "STAGE_03_BUS_ENUM_COMPLETE"` at each stage 3. **Device failure logging** — every deferred/failed probe logged with reason 4. **JSON diagnostic output** — `redbear-hwdetect --json` for automated testing ### Wave 6: USB Topology Enumeration **Goal:** Discover USB devices beyond just the xHCI controller. **Linux reference:** `drivers/usb/core/hub.c::hub_events()` This is a later wave because it depends on xHCI IRQ stability (per the blocker chain). **Implementation approach:** - Query each xHCI controller for its device list - Parse USB device descriptors - Match USB class drivers (HID, mass storage, audio, CDC ACM) - Register in device registry ## Execution Order | Wave | Duration | Deliverable | Depends on | |------|----------|-------------|------------| | Wave 0 | 1 day | Boot stage targets in config | Nothing | | Wave 1 | 2-3 weeks | `redbear-hwdetect` daemon with PCI enumeration | Wave 0 | | Wave 2 | 1-2 weeks | ACPI device enumeration in hwdetect | Wave 1 | | Wave 3 | 1 week | Service rewiring to stage targets | Wave 0 | | Wave 4 | 3-5 days | Driver config unification | Wave 1 | | Wave 5 | 3-5 days | Boot diagnostics | Wave 1 | | Wave 6 | 2-3 weeks | USB topology enumeration | Wave 1, xHCI IRQ stability | **Total estimate:** 6-10 weeks for waves 0-5 (core boot and hardware detection). Wave 6 (USB) follows the blocker chain after low-level controller quality. ## Acceptance Criteria ### Boot process is "stellar" when: 1. ✅ Boot completes from power-on to login in < 10 seconds on QEMU 2. ✅ Every PCI device is enumerated and logged with full info (vendor, device, class, BARs, IRQ) 3. ✅ Every ACPI device with a present status is discovered 4. ✅ Every device that has a matching driver is bound within 3 seconds of enumeration 5. ✅ Deferred probes resolve within 5 seconds of dependency availability 6. ✅ Boot failures are visible on serial console with stage markers 7. ✅ `redbear-hwdetect --status` shows complete hardware state 8. ✅ No `requires_weak` remains for critical boot-path services 9. ✅ Service ordering is deterministic: same order on every boot 10. ✅ Missing hardware does not cause panics or hangs ### Hardware detection is "perfect" when: 1. ✅ PCI: all devices on all buses enumerated, including behind bridges 2. ✅ PCI: BARs parsed correctly (type, size, prefetchable) 3. ✅ PCI: capabilities parsed (MSI, MSI-X, PCIe, power management, vendor-specific) 4. ✅ PCI: IRQ assigned from ACPI _PRT or IOAPIC routing 5. ✅ ACPI: all devices with _STA present enumerated 6. ✅ ACPI: _CRS resources parsed (IRQ, MMIO, I/O ports, DMA) 7. ✅ USB: all devices on all controllers discovered (Wave 6) 8. ✅ Platform: I2C/SPI/GPIO controllers discovered from ACPI (Wave 2) 9. ✅ Quirks: hardware-specific quirks applied automatically 10. ✅ Hotplug: new devices detected and drivers spawned in < 2 seconds ## Relationship to Other Plans | Plan | Relationship | |------|-------------| | `ACPI-IMPROVEMENT-PLAN.md` | ACPI robustness is prerequisite for Wave 2 | | `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` | IRQ quality is prerequisite for hardware detection reliability | | `USB-IMPLEMENTATION-PLAN.md` | USB topology (Wave 6) depends on USB maturity | | `CONSOLE-TO-KDE-DESKTOP-PLAN.md` | Desktop path benefits from better boot/hardware detection | | `QUIRKS-SYSTEM.md` | Quirks integrated into hwdetect's device discovery | ## Linux 7.1 Reference Files Key files to consult when implementing: | RedBear component | Linux 7.1 reference | |---|---| | PCI enumeration | `drivers/pci/probe.c`, `drivers/pci/setup-bus.c` | | PCI driver matching | `drivers/pci/pci-driver.c` | | ACPI device scan | `drivers/acpi/scan.c`, `drivers/acpi/bus.c` | | ACPI resource parsing | `drivers/acpi/resource.c` | | PCI IRQ routing | `drivers/acpi/pci_irq.c`, `drivers/acpi/pci_link.c` | | Device model core | `drivers/base/core.c`, `drivers/base/bus.c`, `drivers/base/dd.c` | | Deferred probing | `drivers/base/dd.c` | | Boot initcalls | `init/main.c`, `include/linux/init.h` | | IRQ management | `kernel/irq/manage.c`, `kernel/irq/chip.c` | | Resource management | `kernel/resource.c` | | DMA mapping | `kernel/dma/mapping.c` |