dc69317ddf
- redbear-sessiond: add Manager.Inhibit (pipe FD), CanPowerOff/CanReboot/ CanSuspend/CanHibernate/CanHybridSleep/CanSleep (return na), PowerOff/ Reboot/Suspend stubs, GetSessionByPID, ListUsers, ListSeats, ListInhibitors, ActivateSession/LockSession/UnlockSession/TerminateSession - redbear-sessiond: add Session SetIdleHint, SetLockedHint, SetType, Terminate methods; wire PauseDevice/ResumeDevice/Lock/Unlock signal emission via SignalEmitter injection; add dynamic device enumeration scanning /scheme/drm/card* and /dev/input/event* at startup - redbear-sessiond: replace infinite pending() with stoppable shutdown via tokio watch channel + control socket shutdown command - redbear-upower: add Changed signal emission with 30s periodic polling and power state snapshot comparison - redbear-notifications: add ActionInvoked signal, expand capabilities to body + body-markup + actions - redbear-polkit, redbear-udisks: replace pending() with stoppable shutdown via signal handling + watch channel - Add redbear-statusnotifierwatcher: new session bus service implementing org.freedesktop.StatusNotifierWatcher for KDE system tray - Add D-Bus activation file for StatusNotifierWatcher - KWin session.cpp: try LogindSession before NoopSession fallback - Consolidate config profiles: remove obsolete redbear-desktop, redbear-kde, redbear-live-*, redbear-minimal-*, redbear-wayland configs; simplify to three supported targets (redbear-full, redbear-mini, redbear-grub) - Update DBUS-INTEGRATION-PLAN.md and DESKTOP-STACK-CURRENT-STATUS.md with Phase 3/4 fragility assessment, KWin readiness matrix, and completeness gap analysis
392 lines
13 KiB
Markdown
392 lines
13 KiB
Markdown
# GRUB Integration Plan — Red Bear OS
|
||
|
||
**Date:** 2026-04-17
|
||
**Status:** Fully implemented (build-tested, not yet runtime boot-tested). ESP formatted as FAT32
|
||
per UEFI spec. Both Phase 1 (post-build script) and Phase 2 (installer-native) are wired.
|
||
**Remaining:** Runtime UEFI boot validation in QEMU (`make all CONFIG_NAME=redbear-grub && make qemu`).
|
||
**Prerequisite:** The `grub` package is included in `redbear-grub.toml` for clean-tree builds.
|
||
**Approach:** Option A — GRUB as boot manager, chainloading Redox bootloader
|
||
|
||
## Overview
|
||
|
||
Add GNU GRUB as an optional boot manager for Red Bear OS. GRUB presents a menu
|
||
at boot and chainloads the existing Redox bootloader, which then boots the
|
||
kernel normally. This gives users:
|
||
|
||
- Multi-boot capability alongside Linux, Windows, or other OSes
|
||
- Boot menu with timeout and manual selection
|
||
- Familiar GRUB rescue shell for debugging
|
||
- No changes to the Redox kernel, RedoxFS, or existing boot flow
|
||
|
||
## Architecture
|
||
|
||
```
|
||
UEFI firmware
|
||
→ EFI/BOOT/BOOTX64.EFI (GRUB standalone image)
|
||
→ grub.cfg: default entry chainloads Redox bootloader
|
||
→ EFI/REDBEAR/redbear.efi (Redox bootloader)
|
||
→ Reads RedoxFS partition
|
||
→ Loads kernel
|
||
→ Boots Red Bear OS
|
||
```
|
||
|
||
### ESP Layout (GRUB mode)
|
||
|
||
```
|
||
EFI/
|
||
├── BOOT/
|
||
│ ├── BOOTX64.EFI ← GRUB (primary, loaded by UEFI firmware)
|
||
│ └── grub.cfg ← GRUB configuration
|
||
└── REDBEAR/
|
||
└── redbear.efi ← Redox bootloader (chainload target)
|
||
```
|
||
|
||
### ESP Layout (default, no GRUB)
|
||
|
||
```
|
||
EFI/
|
||
└── BOOT/
|
||
└── BOOTX64.EFI ← Redox bootloader (unchanged)
|
||
```
|
||
|
||
## Why GRUB?
|
||
|
||
1. **GRUB does not support RedoxFS.** Writing a GRUB filesystem module for
|
||
RedoxFS is high-risk, GPL-licensing-sensitive work. Chainloading avoids it.
|
||
2. **The Redox bootloader works.** It reads RedoxFS directly and boots the
|
||
kernel. No need to replicate that logic in GRUB.
|
||
3. **GRUB is universally understood.** System administrators know GRUB. A
|
||
`grub.cfg` is easier to customize than a custom bootloader.
|
||
4. **Multi-boot.** GRUB can boot Linux, Windows, and other OSes alongside
|
||
Red Bear OS without any changes to those systems.
|
||
|
||
## GRUB Module Set
|
||
|
||
The standalone EFI image includes these modules:
|
||
|
||
| Module | Purpose |
|
||
|--------|---------|
|
||
| `part_gpt` | GPT partition table support |
|
||
| `part_msdos` | MBR partition table support |
|
||
| `fat` | FAT32 filesystem (ESP) |
|
||
| `ext2` | ext2/3/4 filesystem |
|
||
| `normal` | Normal mode (menu, scripting) |
|
||
| `configfile` | Load configuration files |
|
||
| `search` | Search for files/volumes |
|
||
| `search_fs_uuid` | Search by filesystem UUID |
|
||
| `search_label` | Search by volume label |
|
||
| `echo` | Print messages |
|
||
| `test` | Conditional expressions |
|
||
| `ls` | List files and devices |
|
||
| `cat` | Display file contents |
|
||
| `halt` | Shut down |
|
||
| `reboot` | Reboot |
|
||
|
||
Note: `chainloader` is a built-in command in GRUB 2.12 (no separate module needed).
|
||
|
||
Red Bear policy now requires a local `redoxfs.mod` artifact for GRUB builds.
|
||
The GRUB recipe resolves it in this order:
|
||
1. `local/recipes/core/grub/modules/redoxfs.mod`
|
||
2. `${COOKBOOK_SYSROOT}/usr/lib/grub/x86_64-efi/redoxfs.mod`
|
||
|
||
If neither exists, the GRUB recipe fails fast.
|
||
|
||
## GRUB Configuration
|
||
|
||
The default `grub.cfg`:
|
||
|
||
```cfg
|
||
# Red Bear OS GRUB Configuration
|
||
set default=0
|
||
set timeout=5
|
||
|
||
menuentry "Red Bear OS" {
|
||
chainloader /EFI/REDBEAR/redbear.efi
|
||
boot
|
||
}
|
||
|
||
menuentry "Reboot" {
|
||
reboot
|
||
}
|
||
|
||
menuentry "Shutdown" {
|
||
halt
|
||
}
|
||
```
|
||
|
||
Users can customize `grub.cfg` to add entries for other operating systems,
|
||
change the timeout, or add additional Red Bear OS entries (e.g., recovery
|
||
mode with different kernel parameters, once supported).
|
||
|
||
## ESP Size Requirements
|
||
|
||
| Component | Typical Size |
|
||
|-----------|--------------|
|
||
| GRUB EFI binary (with modules) | ~500 KiB (varies with module list) |
|
||
| Redox bootloader | 100–200 KiB |
|
||
| grub.cfg | < 1 KiB |
|
||
| **Total** | **~1 MiB** |
|
||
|
||
The default ESP is 1 MiB (too small for GRUB). Configs using GRUB must set:
|
||
|
||
```toml
|
||
[general]
|
||
efi_partition_size = 16 # 16 MiB, enough for GRUB + Redox bootloader + margin
|
||
```
|
||
|
||
## Linux-Compatible CLI
|
||
|
||
Red Bear OS provides `grub-install` and `grub-mkconfig` wrappers that match GNU GRUB
|
||
command-line conventions. Users migrating from Linux can use familiar switches.
|
||
|
||
| Linux Command | Red Bear OS Location |
|
||
|---------------|---------------------|
|
||
| `grub-install` | `local/scripts/grub-install` |
|
||
| `grub-mkconfig` | `local/scripts/grub-mkconfig` |
|
||
|
||
Add to PATH for convenience:
|
||
```bash
|
||
export PATH="$PWD/local/scripts:$PATH"
|
||
```
|
||
|
||
### grub-install
|
||
|
||
```bash
|
||
# Install GRUB into a disk image
|
||
grub-install --target=x86_64-efi --disk-image=build/x86_64/harddrive.img
|
||
|
||
# Verbose mode
|
||
grub-install --target=x86_64-efi --disk-image=build/x86_64/harddrive.img --verbose
|
||
|
||
# Show help
|
||
grub-install --help
|
||
```
|
||
|
||
Supported options: `--target=`, `--efi-directory=`, `--bootloader-id=`, `--removable`,
|
||
`--disk-image=`, `--modules=`, `--no-nvram`, `--verbose`, `--help`, `--version`.
|
||
|
||
Unsupported Linux options are accepted and ignored silently for script compatibility.
|
||
|
||
### grub-mkconfig
|
||
|
||
```bash
|
||
# Preview generated config
|
||
grub-mkconfig
|
||
|
||
# Write to file
|
||
grub-mkconfig -o local/recipes/core/grub/grub.cfg
|
||
|
||
# Custom timeout
|
||
grub-mkconfig --timeout=10 -o /boot/grub/grub.cfg
|
||
```
|
||
|
||
Supported options: `-o`/`--output=`, `--timeout=`, `--set-default=`, `--help`, `--version`.
|
||
|
||
## Implementation — Phase 1: Post-Build Script
|
||
|
||
Phase 1 uses a post-build script to modify the ESP in an existing disk image.
|
||
This approach requires **no changes to the installer** and works immediately.
|
||
|
||
### Files
|
||
|
||
| File | Purpose |
|
||
|------|---------|
|
||
| `local/recipes/core/grub/recipe.toml` | Build GRUB from source, produce `grub.efi` |
|
||
| `local/recipes/core/grub/grub.cfg` | Default GRUB configuration |
|
||
| `local/recipes/core/grub/modules/redoxfs.mod` | Mandatory local GRUB RedoxFS module artifact |
|
||
| `local/scripts/install-grub.sh` | Post-build ESP modification script |
|
||
| `local/scripts/fat_tool.py` | Python FAT32 tool (no mtools dependency) |
|
||
| `recipes/core/grub → local/recipes/core/grub` | Symlink for recipe discovery |
|
||
|
||
### Workflow
|
||
|
||
```bash
|
||
# 1. Build GRUB recipe
|
||
make r.grub
|
||
|
||
# 2. Build Red Bear OS (with larger ESP)
|
||
make all CONFIG_NAME=redbear-full # Must have efi_partition_size = 16
|
||
|
||
# 3. Install GRUB into disk image
|
||
./local/scripts/install-grub.sh build/x86_64/harddrive.img
|
||
|
||
# 4. Test
|
||
make qemu
|
||
```
|
||
|
||
### Requirements
|
||
|
||
- Python 3 (for `fat_tool.py` — no mtools dependency)
|
||
- GRUB build dependencies: `gcc`, `make`, `bison`, `flex`, `autoconf`, `automake`
|
||
- ESP must be ≥ 8 MiB (set `efi_partition_size = 16` in config)
|
||
|
||
## Implementation — Phase 2: Installer-Native Support
|
||
|
||
Phase 2 adds GRUB awareness directly to the Redox installer, eliminating the
|
||
post-build script step. The installer reads `bootloader = "grub"` from config,
|
||
fetches the GRUB package alongside the bootloader, and writes the chainload
|
||
ESP layout automatically.
|
||
|
||
### Changes Made
|
||
|
||
1. **`GeneralConfig`** (`config/general.rs`): Added `bootloader: Option<String>`
|
||
field (`"redox"` default, `"grub"` for GRUB), with merge support.
|
||
|
||
2. **`DiskOption`** (`installer.rs`): Added `grub_efi: Option<&[u8]>` and
|
||
`grub_config: Option<&[u8]>` fields for optional GRUB data.
|
||
|
||
3. **`fetch_bootloaders`**: When `bootloader = "grub"`, installs the `grub`
|
||
package alongside `bootloader` and returns `grub.efi` + `grub.cfg` data.
|
||
Return type extended to `(bios, efi, grub_efi, grub_cfg)`.
|
||
|
||
4. **`with_whole_disk` / `with_whole_disk_ext4`**: When `grub_efi` and
|
||
`grub_config` are both present, writes the GRUB chainload layout:
|
||
- `EFI/BOOT/BOOTX64.EFI` ← GRUB
|
||
- `EFI/BOOT/grub.cfg` ← GRUB configuration
|
||
- `EFI/REDBEAR/redbear.efi` ← Redox bootloader (chainload target)
|
||
|
||
5. **`install_inner`**: Passes GRUB data from `fetch_bootloaders` through
|
||
`DiskOption`.
|
||
|
||
6. **CLI** (`bin/installer.rs`): Added `--bootloader grub` flag that sets
|
||
`config.general.bootloader`.
|
||
|
||
7. **TUI** (`bin/installer_tui.rs`): Updated `DiskOption` construction with
|
||
`grub_efi: None, grub_config: None`.
|
||
|
||
### Config Usage
|
||
|
||
```toml
|
||
# config/redbear-grub.toml
|
||
include = ["redbear-full.toml"]
|
||
|
||
[general]
|
||
bootloader = "grub"
|
||
efi_partition_size = 16
|
||
```
|
||
|
||
Or via CLI (note: INSTALLER_OPTS replaces defaults, so --cookbook=. must be included):
|
||
```bash
|
||
./target/release/repo cook installer
|
||
make all CONFIG_NAME=redbear-full INSTALLER_OPTS="--cookbook=. --bootloader grub"
|
||
```
|
||
|
||
**Note:** The config file approach (`redbear-grub.toml`) is preferred over the CLI flag
|
||
because INSTALLER_OPTS completely replaces the default value (`--cookbook=.`) rather than
|
||
appending to it. Omitting `--cookbook=.` breaks local package resolution for GRUB.
|
||
|
||
## GRUB Recipe Design
|
||
|
||
The GRUB recipe uses `template = "custom"` because GRUB must be built for the
|
||
**host machine** (it's a build tool that produces EFI binaries), not for the
|
||
Redox target. The cookbook's `configure` template cross-compiles for Redox,
|
||
which is wrong for GRUB.
|
||
|
||
Key build steps:
|
||
1. Configure with `--target=x86_64 --with-platform=efi` (produces x86_64 EFI)
|
||
2. Disable unnecessary components (themes, mkfont, mount, device-mapper)
|
||
3. Run `grub-mkimage` to create standalone EFI binary with curated modules
|
||
4. Stage `grub.efi` and `grub.cfg` to `/usr/lib/boot/`
|
||
|
||
### Build Notes
|
||
|
||
The recipe uses `template = "custom"` because the cookbook's default `configure`
|
||
template sets `--host="${GNU_TARGET}"` for Redox cross-compilation, which is wrong
|
||
for GRUB (a host build tool producing EFI binaries).
|
||
|
||
Two issues required workarounds:
|
||
|
||
1. **Cross-compiler override.** The cookbook sets `CC`, `CXX`, `CFLAGS`, etc. to
|
||
the Redox cross-toolchain. GRUB must be built with the host compiler. Fix:
|
||
`unset CC CXX CPP LD AR NM RANLIB OBJCOPY STRIP PKG_CONFIG` and
|
||
`unset CFLAGS CXXFLAGS CPPFLAGS LDFLAGS` at the top of the script.
|
||
|
||
2. **Missing `extra_deps.lst`.** GRUB 2.12 release tarballs omit
|
||
`grub-core/extra_deps.lst` (normally generated by `autogen.sh` from git).
|
||
Fix: `touch "${COOKBOOK_SOURCE}/grub-core/extra_deps.lst"` before configure.
|
||
|
||
3. **grub.cfg location.** The config file lives in the recipe directory
|
||
(`${COOKBOOK_RECIPE}/grub.cfg`), not in the extracted source tarball
|
||
(`${COOKBOOK_SOURCE}/`). The copy step uses `COOKBOOK_RECIPE`.
|
||
|
||
## Security Considerations
|
||
|
||
- GRUB configuration is on the ESP (FAT32), which is readable/writable by any OS
|
||
- Secure Boot: GRUB standalone images are not signed. Users needing Secure Boot
|
||
must sign `BOOTX64.EFI` with their own key or use `shim`
|
||
- The chainload target (`EFI/REDBEAR/redbear.efi`) is also on the ESP
|
||
- No credentials or secrets are stored in the GRUB configuration
|
||
|
||
## Limitations
|
||
|
||
- GRUB cannot read RedoxFS (no module exists)
|
||
- Cannot pass kernel parameters directly (chainloading bypasses this)
|
||
- BIOS boot is not supported (only UEFI)
|
||
- ESP must be sized to ≥ 8 MiB in config (16 MiB recommended)
|
||
- GRUB bootloader is incompatible with `skip_partitions = true` (requires GPT layout with ESP)
|
||
- TUI installer does not support GRUB mode (intentional — TUI is for live disk reinstall)
|
||
- Runtime UEFI boot test has not been performed yet (requires full `make all` build, ~hours)
|
||
|
||
## Testing
|
||
|
||
### Phase 1: Post-build script (standalone)
|
||
|
||
```bash
|
||
# Build GRUB recipe
|
||
make r.grub
|
||
|
||
# Build image (any config with efi_partition_size >= 16)
|
||
make all CONFIG_NAME=redbear-full
|
||
|
||
# Install GRUB into disk image (uses fat_tool.py, no mtools needed)
|
||
./local/scripts/install-grub.sh build/x86_64/harddrive.img
|
||
|
||
# Verify ESP contents
|
||
python3 local/scripts/fat_tool.py ls build/x86_64/harddrive.img 1048576 /
|
||
|
||
# Boot in QEMU
|
||
make qemu
|
||
# Expected: GRUB menu appears, "Red Bear OS" entry boots successfully
|
||
```
|
||
|
||
### Phase 2: Installer-native (automatic)
|
||
|
||
```bash
|
||
# Build GRUB recipe (must be built before installer runs)
|
||
make r.grub
|
||
|
||
# Build image with GRUB config (installer fetches GRUB automatically)
|
||
make all CONFIG_NAME=redbear-grub
|
||
|
||
# Or via CLI flag
|
||
make all CONFIG_NAME=redbear-full INSTALLER_OPTS="--bootloader grub --cookbook=."
|
||
|
||
# Verify ESP contents
|
||
python3 local/scripts/fat_tool.py ls build/x86_64/harddrive.img 1048576 /
|
||
|
||
# Boot in QEMU
|
||
make qemu
|
||
# Expected: GRUB menu appears, "Red Bear OS" entry boots successfully
|
||
```
|
||
|
||
### Unit tests (no full build required)
|
||
|
||
```bash
|
||
# Verify GRUB recipe builds
|
||
CI=1 ./target/release/repo cook grub
|
||
|
||
# Verify host-side installer accepts --bootloader flag
|
||
build/fstools/bin/redox_installer --bootloader=grub --config=config/redbear-grub.toml --list-packages
|
||
|
||
# Verify fat_tool.py operations
|
||
python3 local/scripts/fat_tool.py --help
|
||
```
|
||
|
||
## References
|
||
|
||
- GNU GRUB Manual: https://www.gnu.org/software/grub/manual/grub/grub.html
|
||
- GRUB EFI standalone image: `grub-mkimage -O x86_64-efi ...`
|
||
- UEFI boot specification: `EFI/BOOT/BOOTX64.EFI` is the fallback boot path
|
||
- Redox bootloader source: `recipes/core/bootloader/source/`
|
||
- Installer GPT layout: `recipes/core/installer/source/src/installer.rs`
|