7c031f95e4
Add blake3 checksum for grub-2.12.tar.xz for recipe integrity verification. Remove the chain module from grub-mkimage — the chainloader command is built-in in GRUB 2.12, no separate module needed. Image shrinks from 540 KiB to 512 KiB. Update module table and size estimate in GRUB integration plan.
335 lines
11 KiB
Markdown
335 lines
11 KiB
Markdown
# GRUB Integration Plan — Red Bear OS
|
||
|
||
**Date:** 2026-04-17
|
||
**Status:** Phase 2 complete — installer-native GRUB support implemented and compiling.
|
||
**Prerequisite:** The `grub` package must be in the build plan (included in `redbear-full-grub.toml`)
|
||
for `make all` to work from a clean tree. Phase 2 is automatic only after `grub` is available in
|
||
the local repo or build output.
|
||
**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).
|
||
|
||
No RedoxFS module is needed — GRUB chainloads the Redox bootloader instead.
|
||
|
||
## 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
|
||
```
|
||
|
||
## 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/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-full-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-full-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)
|
||
|
||
## 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-full-grub
|
||
|
||
# Or via CLI flag
|
||
make all CONFIG_NAME=redbear-full INSTALLER_OPTS="--bootloader grub"
|
||
|
||
# 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-full-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`
|