restore driver-manager + pcid service + lost configs from 0.2.3→0.2.4 sync

Root cause: the 0.2.4 upstream sync silently removed driver-manager (our
in-house PCI driver orchestrator) and never added a pcid init service,
leaving /scheme/pci uncreated and breaking all PCI device enumeration.

Changes:
- base-initfs/recipe.toml: restore driver-manager dep, binary copy,
  drivers.d/ config dir, set -eo pipefail
- redbear-device-services.toml: add driver-manager = {} to packages
- redbear-boot-stages.toml: restore from 0.2.3 (109 lines)
- protected-recipes.toml: restore from 0.2.3 (99 lines)
- redbear-mini.toml: add boot-stages to include chain
- driver-manager Cargo.toml: fix pcid path from symlink to physical
- base fork pointer: acdcb183 (adds 35_pcid.service to initfs)
- UPSTREAM-SYNC-PROCEDURE.md: document sync flaw, never-delete rule,
  driver-manager rationale
- PACKAGE-BUILD-QUIRKS.md: document pcid/pcid-spawner architecture,
  Redox flag values, kernel kcall on AcpiScheme

Verified: redbear-mini boots to login prompt in QEMU UEFI with working
PCI enumeration (6 devices), e1000d network driver, DHCP, driver-manager.
This commit is contained in:
2026-06-19 11:39:24 +03:00
parent 49f383b386
commit 06b316076f
11 changed files with 391 additions and 5 deletions
+99
View File
@@ -0,0 +1,99 @@
# Protected recipes — these recipes are NEVER re-fetched from upstream.
# They use offline/archived sources from sources/redbear-<release>/.
#
# Protection reasons:
# - patched: carries Red Bear patches (upstream changes could break patches)
# - custom: Red Bear-specific recipe (no upstream equivalent)
# - core: core system component (kernel, libc, bootloader, etc.)
#
# The Rust code in src/cook/fetch.rs reads this file at startup.
# Recipes NOT listed here but carrying patches (patches = [...] in recipe.toml)
# are automatically protected by the recipe_has_patches() check.
# Core patched recipes (upstream + Red Bear patches)
[patched]
recipes = [
"relibc", "bootloader", "kernel", "base", "base-initfs",
"installer", "redoxfs", "grub",
]
# Red Bear custom core recipes
[custom]
recipes = [
"ext4d", "fatd",
]
# Red Bear driver infrastructure
[drivers]
recipes = [
"redox-driver-sys", "linux-kpi", "firmware-loader",
"redbear-btusb", "redbear-iwlwifi",
"redox-drm", "amdgpu",
]
# Red Bear system tools
[system]
recipes = [
"cub", "evdevd", "udev-shim", "iommu",
"redbear-firmware", "redbear-hwutils", "redbear-info", "rbos-info",
"redbear-meta", "redbear-netctl", "redbear-netctl-console",
"redbear-netstat", "redbear-btctl", "redbear-wifictl",
"redbear-traceroute", "redbear-mtr", "redbear-nmap",
"redbear-sessiond", "redbear-authd", "redbear-session-launch",
"redbear-greeter", "redbear-dbus-services", "redbear-notifications",
"redbear-upower", "redbear-udisks", "redbear-polkit", "redbear-quirks",
"redbear-release", "redbear-keymapd", "redbear-ime", "redbear-accessibility",
]
# Qt stack with Red Bear patches
[qt]
recipes = [
"qtbase", "qtwayland", "qtdeclarative", "qtbase-compat",
]
# Graphics / display stack with Red Bear patches
[graphics]
recipes = [
"libdrm", "mesa",
"libwayland", "libevdev", "libinput",
"libepoxy", "libxcvt", "libdisplay-info", "lcms2",
"dbus", "glib",
]
# Red Bear custom libs (no stubs)
[libs]
recipes = [
"zbus", "libqrencode",
"pipewire", "wireplumber",
]
# Red Bear Wayland
[wayland]
recipes = [
"qt6-wayland-smoke", "smallvil", "seatd-redox",
]
# Red Bear KDE (47 recipes)
[kde]
recipes = [
"kf6-extra-cmake-modules", "kf6-kcoreaddons", "kf6-kwidgetsaddons",
"kf6-kconfig", "kf6-ki18n", "kf6-kcodecs", "kf6-kguiaddons",
"kf6-kcolorscheme", "kf6-kauth", "kf6-kitemmodels", "kf6-kitemviews",
"kf6-karchive", "kf6-kwindowsystem", "kf6-knotifications",
"kf6-kjobwidgets", "kf6-kconfigwidgets", "kf6-kcrash", "kf6-kdbusaddons",
"kf6-kglobalaccel", "kf6-kservice", "kf6-kpackage", "kf6-kiconthemes",
"kf6-kxmlgui", "kf6-ktextwidgets", "kf6-solid", "kf6-sonnet",
"kf6-kio", "kf6-kbookmarks", "kf6-kcompletion", "kf6-kdeclarative",
"kf6-kcmutils", "kf6-kidletime", "kf6-kwayland", "kf6-knewstuff",
"kf6-kwallet", "kf6-prison", "kf6-kirigami",
"kf6-ksvg", "kf6-pty", "kf6-notifyconfig", "kf6-parts",
"kdecoration", "kwin", "plasma-desktop", "plasma-workspace",
"plasma-framework", "plasma-wayland-protocols", "kirigami",
"kglobalacceld",
]
# Orbutils (has local patch)
[other]
recipes = [
"orbutils",
]
+109
View File
@@ -0,0 +1,109 @@
# Red Bear OS boot stage targets
#
# Semantic boot stages that create ordering through the init system's
# BFS dependency traversal. Each target depends on the previous one.
#
# Stage mapping:
# 00_base.target — kernel schemes ready (defined in base package initfs)
# 02_early_hw.target — ACPI + PCI bus access ready
# 04_drivers.target — driver spawning complete
# 06_services.target — system services (D-Bus, session broker)
# 08_userland.target — user-facing (console, greeter, desktop)
#
# Services use requires_weak against their stage target.
# Targets use requires_weak to chain to the previous stage.
#
# Serial boot markers (02-08_serial_*.service) echo a stage completion
# message to stderr, which appears on the serial console for diagnostics.
[[files]]
path = "/etc/init.d/02_early_hw.target"
data = """
[unit]
description = "Early hardware: ACPI + PCI bus access"
requires_weak = [
"00_base.target",
]
"""
[[files]]
path = "/etc/init.d/02_serial_early_hw.service"
data = """
[unit]
description = "Serial boot marker: early hardware stage"
requires_weak = ["02_early_hw.target"]
[service]
cmd = "echo"
args = ["RB_STAGE_02_EARLY_HW"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/04_drivers.target"
data = """
[unit]
description = "Driver spawning stage"
requires_weak = [
"02_early_hw.target",
]
"""
[[files]]
path = "/etc/init.d/04_serial_drivers.service"
data = """
[unit]
description = "Serial boot marker: drivers stage"
requires_weak = ["04_drivers.target"]
[service]
cmd = "echo"
args = ["RB_STAGE_04_DRIVERS"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/06_services.target"
data = """
[unit]
description = "System services: D-Bus, session broker, seat management"
requires_weak = [
"04_drivers.target",
]
"""
[[files]]
path = "/etc/init.d/06_serial_services.service"
data = """
[unit]
description = "Serial boot marker: services stage"
requires_weak = ["06_services.target"]
[service]
cmd = "echo"
args = ["RB_STAGE_06_SERVICES"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/08_userland.target"
data = """
[unit]
description = "User-facing: console, greeter, desktop"
requires_weak = [
"06_services.target",
]
"""
[[files]]
path = "/etc/init.d/08_serial_userland.service"
data = """
[unit]
description = "Serial boot marker: userland stage"
requires_weak = ["08_userland.target"]
[service]
cmd = "echo"
args = ["RB_STAGE_08_USERLAND"]
type = "oneshot"
"""
+1
View File
@@ -6,6 +6,7 @@
redbear-quirks = {}
pciids = {}
fatd = {}
driver-manager = {}
# Firmware fallback chain configs
[[files]]
+1 -1
View File
@@ -9,7 +9,7 @@
# - all non-graphics, non-firmware packages from the full profile
# - no linux-firmware payload, no firmware-loader, no GPU/display drivers
include = ["minimal.toml", "redbear-legacy-base.toml", "redbear-netctl.toml", "redbear-device-services.toml"]
include = ["minimal.toml", "redbear-legacy-base.toml", "redbear-netctl.toml", "redbear-device-services.toml", "redbear-boot-stages.toml"]
[general]
filesystem_size = 1536
+93
View File
@@ -378,6 +378,99 @@ When you encounter a new build quirk:
---
## Package: base-initfs (initfs image builder)
### pcid Must Start Before pcid-spawner
**Problem:** `pcid-spawner` calls `fs::read_dir("/scheme/pci")` as its first
action. `/scheme/pci` is created by `pcid` via `register_sync_scheme()`. If
`pcid` is not started, `pcid-spawner` fails with `ENODEV`.
**Root cause:** No init service started `pcid` in initfs. The upstream model
assumed `pcid` would be started, but no `.service` file existed for it. This
was masked in 0.2.3 because `driver-manager` (Red Bear's replacement) does
its own PCI enumeration via `redox_driver_pci` and doesn't depend on
`/scheme/pci`.
**Fix:** Added `35_pcid.service` to `init.initfs.d/`:
```ini
[unit]
description = "PCI bus enumeration daemon (creates /scheme/pci)"
requires_weak = ["30_acpid.service"]
[service]
cmd = "pcid"
type = { scheme = "pci" }
```
The `type = { scheme = "pci" }` tells init to wait for `/scheme/pci` to be
registered before marking the service as started. This ensures `pcid-spawner`
(which depends on `35_pcid.service` via `requires_weak`) only runs after
`/scheme/pci` exists.
### driver-manager Removed During Sync
**Problem:** The 0.2.3 → 0.2.4 upstream sync silently removed `driver-manager`
from `base-initfs` dependencies and `redbear-device-services.toml` packages.
**Root cause:** Upstream doesn't have `driver-manager` — it's a Red Bear
in-house project. The sync blindly overwrote tracked files with upstream
versions.
**Fix:** Restored:
- `"driver-manager"` in `base-initfs/recipe.toml` dependencies
- `cp driver-manager` binary copy to initfs/bin/
- `driver-manager = {}` in `redbear-device-services.toml` `[packages]`
- `drivers.d/` config directory creation in build script
- `set -eo pipefail` in build script
**See also:** `UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Upstream Not Ready"
---
## Redox Flag Values (Critical for Ported Code)
Redox flag values differ from Linux. Code ported from Linux that assumes
Linux conventions will be WRONG on Redox:
| Flag | Linux | Redox |
|------|-------|-------|
| `O_RDONLY` | `0` | `0x0001_0000` |
| `O_WRONLY` | `1` | `0x0002_0000` |
| `O_RDWR` | `2` | `0x0003_0000` |
| `O_ACCMODE` | `3` | `0x0003_0000` |
| `O_CLOEXEC` | `0x80000` | `0x0100_0000` |
**Common bug:** `flags & O_ACCMODE == O_RDONLY` evaluates to `0 == 0` on Linux
(read-only check passes), but on Redox `O_CLOEXEC & O_ACCMODE = 0 ≠ O_RDONLY`,
so a file opened with `O_CLOEXEC` without explicit `O_RDONLY` fails with `EROFS`.
**Fix:** Always pass `O_RDONLY` explicitly when opening for read:
```rust
let fd = Fd::open(path, O_RDONLY | O_CLOEXEC, 0)?;
```
### Kernel kcall on ACPI Scheme
**Problem:** Upstream-synced `acpid` uses `AcpiVerb` call API (`ReadRxsdt=1`,
`CheckShutdown=2`) but the kernel's `AcpiScheme` didn't implement `kcall`,
returning `EOPNOTSUPP`.
**Fix:** Added `kcall` method to `impl KernelScheme for AcpiScheme` in
`src/scheme/acpi.rs`. The kernel fork commit is `c7af6c43`.
**Signature:**
```rust
fn kcall(&self, fds: &[usize], payload: UserSliceRw, flags: CallFlags,
metadata: &[u64], token: &mut CleanLockToken) -> Result<usize>
```
- `fds[0]` = handle id
- `metadata[0]` = verb (u64): `1` = ReadRxsdt, `2` = CheckShutdown
- `payload` = UserSliceRw (read/write buffer)
---
## Cross-Reference
| Document | Relevance |
+75
View File
@@ -684,3 +684,78 @@ relibc, and installer from `build-redbear.sh`. Only bootloader (which uses
`git + patches`, not `path=`) still gets `apply_patch_dir`.
**Verification:** Kernel source hashes now identical before and after build.
---
## CRITICAL: Red Bear Package Preservation Rules
### Never Delete — Comment Out
When syncing with upstream removes or restructures packages, configs, or
services that are Red Bear in-house projects:
1. **NEVER delete** the package, config, or service entry.
2. **Comment it out** with a clear explanation of why.
3. **ASK THE USER** if uncertain whether to keep or remove.
This applies to:
- Packages in `[packages]` sections of config TOMLs
- Dependencies in `recipe.toml` files
- Init service files (`.service`, `.target`)
- Build system patches and scripts
- Any file under `local/` or `config/redbear-*`
### driver-manager: Upstream Not Ready
**Status:** Red Bear internal project. Upstream Redox does NOT have an equivalent.
`driver-manager` (`local/recipes/system/driver-manager/`) is a combined PCI
enumeration + driver matching + hotplug daemon that replaces the upstream
`pcid + pcid-spawner` pair. It was developed because upstream's PCI driver
launching was not ready for Red Bear's needs (advanced driver matching via
`/lib/drivers.d/*.toml`, ACPI device enumeration, hotplug event handling).
**Upstream may provide its own solution in the future.** If and when upstream
Redox offers a concrete, working replacement that matches or exceeds
driver-manager's capabilities, notify the user for a route decision.
Until then, `driver-manager` is the canonical PCI driver orchestration path.
### Systemic Sync Flaw (2026-06 Incident)
**Root cause:** The 0.2.3 → 0.2.4 upstream sync blindly overwrote tracked
config and recipe files. Red Bear in-house packages, services, and configs
were silently dropped because upstream doesn't have them.
**What was lost (partial list):**
- `driver-manager` removed from base-initfs dependencies and packages
- `config/protected-recipes.toml` deleted (99 lines of protection rules)
- `config/redbear-boot-stages.toml` deleted (109 lines of boot stage targets)
- `set -eo pipefail` removed from base-initfs build script
- `drivers.d/` initfs config directory creation removed
- Multiple patches lost (libdrm, mesa, pipewire, sddm, wireplumber)
- `local/recipes/AGENTS.md` deleted
**Prevention:** Before ANY upstream sync:
1. Run `git diff` between the pre-sync and post-sync tree.
2. Flag ALL removed files, especially under `config/`, `local/`, and `recipes/`.
3. Flag ALL removed entries from `[packages]` sections and dependency arrays.
4. Cross-reference with `config/protected-recipes.toml` — protected recipes
must NEVER be removed.
5. Any removal must be explicitly approved by the user.
### pcid + pcid-spawner Architecture
**Upstream model:**
1. `pcid` creates `/scheme/pci` (PCI bus enumeration)
2. `pcid-spawner` reads `/scheme/pci` and launches drivers per `pcid.d/*.toml`
**Red Bear model (0.2.3 and forward):**
1. `pcid` creates `/scheme/pci` (initfs service `35_pcid.service`)
2. `pcid-spawner --initfs` launches critical boot drivers (initfs)
3. `driver-manager --hotplug` handles full driver matching + hotplug (rootfs)
**Key learning:** Without `35_pcid.service` in initfs, `/scheme/pci` is never
created, and BOTH `pcid-spawner` (initfs and rootfs) fail with ENODEV. This
was masked in 0.2.3 because driver-manager does its own PCI enumeration via
`redox_driver_pci` and doesn't depend on `/scheme/pci`.
@@ -11,7 +11,7 @@ path = "src/main.rs"
[dependencies]
redox-driver-core = { path = "../../drivers/redox-driver-core" }
redox-driver-pci = { path = "../../drivers/redox-driver-pci" }
pcid_interface = { path = "../../../../recipes/core/base/source/drivers/pcid", package = "pcid" }
pcid_interface = { path = "../../../../local/sources/base/drivers/pcid", package = "pcid" }
redox_syscall = "0.7"
log = "0.4"
toml = "0.8"
@@ -11,7 +11,7 @@ path = "src/main.rs"
[dependencies]
redox-driver-core = { path = "../../../drivers/redox-driver-core/source" }
redox-driver-pci = { path = "../../../drivers/redox-driver-pci/source" }
pcid_interface = { path = "../../../../../recipes/core/base/source/drivers/pcid", package = "pcid" }
pcid_interface = { path = "../../../../../local/sources/base/drivers/pcid", package = "pcid" }
redox-scheme = "0.11"
syscall = { package = "redox_syscall", version = "0.8" }
log = "0.4"
Submodule local/sources/base updated: 7766fb91f3...acdcb183cd
+7 -1
View File
@@ -6,8 +6,11 @@ template = "custom"
dependencies = [
"redoxfs",
"ion",
"driver-manager",
]
script = """
set -eo pipefail
BINS=(
init
logd
@@ -71,8 +74,10 @@ mkdir -p "${COOKBOOK_BUILD}/initfs/lib/init.d"
cp "${COOKBOOK_SOURCE}/init.initfs.d"/* "${COOKBOOK_BUILD}/initfs/lib/init.d/"
mkdir -pv "${COOKBOOK_BUILD}/initfs/lib/drivers.d"
cp -v "${COOKBOOK_SOURCE}/drivers/initfs-storage.toml" "${COOKBOOK_BUILD}/initfs/lib/drivers.d/00-storage.toml"
mkdir -pv "${COOKBOOK_BUILD}/initfs/lib/pcid.d"
cp -v "${COOKBOOK_SOURCE}/drivers/initfs.toml" "${COOKBOOK_BUILD}/initfs/lib/pcid.d/initfs.toml"
cp -v "${COOKBOOK_SOURCE}/drivers/initfs-pcid-storage.toml" "${COOKBOOK_BUILD}/initfs/lib/pcid.d/00-storage.toml"
export CARGO_PROFILE_RELEASE_OPT_LEVEL=s
export CARGO_PROFILE_RELEASE_PANIC=abort
@@ -96,6 +101,7 @@ done
cp "${COOKBOOK_SYSROOT}/usr/bin/redoxfs" "${COOKBOOK_BUILD}/initfs/bin"
cp "${COOKBOOK_SYSROOT}/usr/bin/ion" "${COOKBOOK_BUILD}/initfs/bin"
cp "${COOKBOOK_SYSROOT}/usr/bin/driver-manager" "${COOKBOOK_BUILD}/initfs/bin"
ARCH="$(echo "${GNU_TARGET}" | cut -d - -f1)"
RUSTFLAGS="$RUSTFLAGS -Ctarget-feature=+crt-static -Clink-arg=-nostartfiles -Clink-arg=-nostdlib" cargo \
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
qemu-system-x86_64 -m 8G -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd -drive file=/home/kellito/Builds/rbos/build/x86_64/redbear-mini.iso,format=raw -device virtio-gpu-pci -serial mon:stdio