Fix GRUB reassessment findings: clean-build gap, validation, robustness
- Add grub package to redbear-full-grub.toml so make all works from a clean tree (the installer needs grub.efi before it runs) - Fix stat -f%z (macOS-only) to stat -c%s (Linux) in GRUB recipe - Normalize bootloader config value to lowercase in install_inner so bootloader = "GRUB" from config files is accepted - Add bad-cluster marker (0x0FFFFFF7) check in fat_tool.py _next_cluster to prevent potential infinite loops on degraded media - Fix file handle leak in fat_tool.py if _read_bpb raises - Clean up temp directory in fetch_bootloaders on error - Update AGENTS.md with GRUB recipe and installer documentation - Update GRUB plan with clean-build prerequisite note
This commit is contained in:
@@ -12,3 +12,8 @@ include = ["redbear-full.toml"]
|
|||||||
[general]
|
[general]
|
||||||
bootloader = "grub"
|
bootloader = "grub"
|
||||||
efi_partition_size = 16
|
efi_partition_size = 16
|
||||||
|
|
||||||
|
# GRUB recipe must be built before the installer runs.
|
||||||
|
# Including it here ensures `make all` builds it as part of the normal package set.
|
||||||
|
[packages]
|
||||||
|
grub = {}
|
||||||
|
|||||||
+68
-7
@@ -142,7 +142,7 @@ redox-master/ ← git pull updates mainline Redox
|
|||||||
│ ├── AGENTS.md ← This file
|
│ ├── AGENTS.md ← This file
|
||||||
│ ├── config/ ← Legacy configs (my-*, gitignored)
|
│ ├── config/ ← Legacy configs (my-*, gitignored)
|
||||||
│ ├── recipes/
|
│ ├── recipes/
|
||||||
│ │ ├── core/ ← ext4d (ext4 filesystem scheme daemon + mkfs tool)
|
│ │ ├── core/ ← ext4d (ext4 filesystem scheme daemon + mkfs tool), grub (GRUB 2.12 UEFI bootloader)
|
||||||
│ │ ├── branding/ ← redbear-release (os-release, hostname, motd)
|
│ │ ├── branding/ ← redbear-release (os-release, hostname, motd)
|
||||||
│ │ ├── drivers/ ← redox-driver-sys, linux-kpi (GPU/Wi-Fi compat only — NOT USB)
|
│ │ ├── drivers/ ← redox-driver-sys, linux-kpi (GPU/Wi-Fi compat only — NOT USB)
|
||||||
│ │ ├── gpu/ ← redox-drm (AMD + Intel display drivers), amdgpu (C port)
|
│ │ ├── gpu/ ← redox-drm (AMD + Intel display drivers), amdgpu (C port)
|
||||||
@@ -156,7 +156,7 @@ redox-master/ ← git pull updates mainline Redox
|
|||||||
│ │ ├── base/ ← Base patches (acpid fixes, power methods, pcid /config endpoint)
|
│ │ ├── base/ ← Base patches (acpid fixes, power methods, pcid /config endpoint)
|
||||||
│ │ ├── relibc/ ← relibc compatibility overlays still needed beyond upstream (eventfd, signalfd, timerfd, waitid, SysV IPC)
|
│ │ ├── relibc/ ← relibc compatibility overlays still needed beyond upstream (eventfd, signalfd, timerfd, waitid, SysV IPC)
|
||||||
│ │ ├── bootloader/ ← Bootloader patches
|
│ │ ├── bootloader/ ← Bootloader patches
|
||||||
│ │ └── installer/ ← Installer patches (ext4 filesystem support)
|
│ │ └── installer/ ← Installer patches (ext4 filesystem support + GRUB bootloader)
|
||||||
│ ├── Assets/ ← Branding assets (icon, loading background)
|
│ ├── Assets/ ← Branding assets (icon, loading background)
|
||||||
│ │ └── images/ ← Red Bear OS icon (1254x1254) + loading bg (1536x1024)
|
│ │ └── images/ ← Red Bear OS icon (1254x1254) + loading bg (1536x1024)
|
||||||
│ ├── firmware/ ← GPU firmware blobs (gitignored, fetched)
|
│ ├── firmware/ ← GPU firmware blobs (gitignored, fetched)
|
||||||
@@ -265,6 +265,13 @@ make all CONFIG_NAME=redbear-desktop
|
|||||||
./target/release/repo cook local/recipes/branding/redbear-release
|
./target/release/repo cook local/recipes/branding/redbear-release
|
||||||
./target/release/repo cook local/recipes/system/redbear-meta
|
./target/release/repo cook local/recipes/system/redbear-meta
|
||||||
./target/release/repo cook local/recipes/core/ext4d
|
./target/release/repo cook local/recipes/core/ext4d
|
||||||
|
./target/release/repo cook local/recipes/core/grub # GRUB bootloader (host build, produces EFI binary)
|
||||||
|
|
||||||
|
# GRUB boot manager (installer-native, Phase 2):
|
||||||
|
make r.grub # Build GRUB recipe
|
||||||
|
make all CONFIG_NAME=redbear-full-grub # Build with GRUB chainload
|
||||||
|
# Or post-build script (Phase 1):
|
||||||
|
./local/scripts/install-grub.sh build/x86_64/harddrive.img # Modify existing image
|
||||||
```
|
```
|
||||||
|
|
||||||
## TRACKING MAINLINE CHANGES
|
## TRACKING MAINLINE CHANGES
|
||||||
@@ -280,7 +287,7 @@ When mainline updates affect our work:
|
|||||||
| Mesa | OpenGL/Vulkan backend changes | `recipes/libs/mesa/` |
|
| Mesa | OpenGL/Vulkan backend changes | `recipes/libs/mesa/` |
|
||||||
| Build system | Makefile/config changes | `mk/`, `src/` |
|
| Build system | Makefile/config changes | `mk/`, `src/` |
|
||||||
| rsext4 | ext4 crate API changes | `local/recipes/core/ext4d/source/` Cargo.toml |
|
| rsext4 | ext4 crate API changes | `local/recipes/core/ext4d/source/` Cargo.toml |
|
||||||
| Installer | ext4 dispatch, filesystem selection | `local/patches/installer/redox.patch` |
|
| Installer | ext4 dispatch, filesystem selection, GRUB bootloader | `local/patches/installer/redox.patch` |
|
||||||
| Quirks | New Linux quirk entries to port | `local/recipes/drivers/redox-driver-sys/source/src/quirks/` |
|
| Quirks | New Linux quirk entries to port | `local/recipes/drivers/redox-driver-sys/source/src/quirks/` |
|
||||||
|
|
||||||
## PLANNING NOTES
|
## PLANNING NOTES
|
||||||
@@ -318,12 +325,13 @@ Do not present USB, Wi-Fi, Bluetooth, or low-level controller work as optional o
|
|||||||
|
|
||||||
## FILESYSTEMS
|
## FILESYSTEMS
|
||||||
|
|
||||||
Red Bear OS supports two filesystems:
|
Red Bear OS supports three filesystems:
|
||||||
|
|
||||||
| Filesystem | Implementation | Package | Status |
|
| Filesystem | Implementation | Package | Status |
|
||||||
|------------|---------------|---------|--------|
|
|------------|---------------|---------|--------|
|
||||||
| RedoxFS | Mainline Redox (default) | `recipes/core/redoxfs` | ✅ Stable |
|
| RedoxFS | Mainline Redox (default) | `recipes/core/redoxfs` | ✅ Stable |
|
||||||
| ext4 | rsext4 0.3 crate + ext4d scheme daemon | `local/recipes/core/ext4d` | ✅ Compiles + Installer wired |
|
| ext4 | rsext4 0.3 crate + ext4d scheme daemon | `local/recipes/core/ext4d` | ✅ Compiles + Installer wired |
|
||||||
|
| FAT (VFAT) | fatfs 0.3.6 crate + fatd scheme daemon | `local/recipes/core/fatd` | ✅ Compiles + Tools tested + label write verified |
|
||||||
|
|
||||||
### ext4 Workspace (`local/recipes/core/ext4d/source/`)
|
### ext4 Workspace (`local/recipes/core/ext4d/source/`)
|
||||||
|
|
||||||
@@ -369,23 +377,76 @@ recipes/core/ext4d → local/recipes/core/ext4d
|
|||||||
- `libredox = "0.1.13"` — High-level Redox syscalls (open, read, write, fstat)
|
- `libredox = "0.1.13"` — High-level Redox syscalls (open, read, write, fstat)
|
||||||
- `redox-path = "0.3.0"` — Redox path utilities
|
- `redox-path = "0.3.0"` — Redox path utilities
|
||||||
|
|
||||||
### Installer ext4 Integration (`local/patches/installer/redox.patch`)
|
### Installer ext4 + GRUB Integration (`local/patches/installer/redox.patch`)
|
||||||
|
|
||||||
The mainline installer is patched to support ext4 as an install target filesystem:
|
The mainline installer is patched to support ext4 as an install target filesystem and
|
||||||
|
GRUB as an alternative boot manager:
|
||||||
- `GeneralConfig.filesystem: Option<String>` — TOML field, accepts `"redoxfs"` (default) or `"ext4"`
|
- `GeneralConfig.filesystem: Option<String>` — TOML field, accepts `"redoxfs"` (default) or `"ext4"`
|
||||||
|
- `GeneralConfig.bootloader: Option<String>` — TOML field, accepts `"redox"` (default) or `"grub"`
|
||||||
- `FilesystemType` enum — dispatch tag used by `install_inner`
|
- `FilesystemType` enum — dispatch tag used by `install_inner`
|
||||||
- `with_whole_disk_ext4()` — GPT partition layout + ext4 mkfs + file sync (mirrors `with_whole_disk`)
|
- `with_whole_disk_ext4()` — GPT partition layout + ext4 mkfs + file sync (mirrors `with_whole_disk`)
|
||||||
- `Ext4SliceDisk<T>` — adapts `DiskWrapper` to rsext4's `BlockDevice` trait
|
- `Ext4SliceDisk<T>` — adapts `DiskWrapper` to rsext4's `BlockDevice` trait
|
||||||
- `sync_host_dir_to_ext4()` — copies staged sysroot files into ext4 filesystem
|
- `sync_host_dir_to_ext4()` — copies staged sysroot files into ext4 filesystem
|
||||||
- CLI flag: `--filesystem ext4` or `--filesystem redoxfs`
|
- GRUB chainload: when `bootloader = "grub"`, writes GRUB EFI + grub.cfg to ESP alongside Redox bootloader
|
||||||
|
- CLI flags: `--filesystem ext4` / `--bootloader grub`
|
||||||
|
|
||||||
Usage in config TOML:
|
Usage in config TOML:
|
||||||
```toml
|
```toml
|
||||||
[general]
|
[general]
|
||||||
filesystem = "ext4" # "redoxfs" is default
|
filesystem = "ext4" # "redoxfs" is default
|
||||||
|
bootloader = "grub" # "redox" is default
|
||||||
|
efi_partition_size = 16 # Required for GRUB (default 1 MiB is too small)
|
||||||
filesystem_size = 10240 # MB
|
filesystem_size = 10240 # MB
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See `local/docs/GRUB-INTEGRATION-PLAN.md` for the full GRUB architecture and usage guide.
|
||||||
|
|
||||||
|
### FAT (VFAT) Workspace (`local/recipes/core/fatd/source/`)
|
||||||
|
|
||||||
|
```
|
||||||
|
fatd/source/
|
||||||
|
├── Cargo.toml ← Workspace: fat-blockdev, fatd, fat-mkfs, fat-label, fat-check
|
||||||
|
├── fat-blockdev/ ← Block device adapter for fatfs crate
|
||||||
|
│ ├── src/lib.rs ← Re-exports: FileDisk (always), RedoxDisk (feature-gated)
|
||||||
|
│ ├── src/file_disk.rs ← FileDisk: std::fs::File → Read+Write+Seek
|
||||||
|
│ └── src/redox_disk.rs ← RedoxDisk: libredox → Read+Write+Seek (redox feature)
|
||||||
|
├── fatd/ ← FAT filesystem scheme daemon (Redox userspace)
|
||||||
|
│ ├── src/main.rs ← Daemon: fork, SIGTERM, dispatch to FileDisk/RedoxDisk
|
||||||
|
│ ├── src/mount.rs ← Scheme event loop (redox_scheme::SchemeSync)
|
||||||
|
│ ├── src/scheme.rs ← FatScheme: full FSScheme (open/read/write/mkdir/unlink/stat...)
|
||||||
|
│ └── src/handle.rs ← FileHandle, DirectoryHandle, Handle types
|
||||||
|
├── fat-mkfs/ ← mkfs.fat equivalent (create FAT12/16/32 filesystems)
|
||||||
|
│ └── src/main.rs
|
||||||
|
├── fat-label/ ← fatlabel equivalent (read + write volume labels via BPB)
|
||||||
|
│ └── src/main.rs ← `-s "LABEL"` writes label at BPB offset 43/71; verifies round-trip
|
||||||
|
└── fat-check/ ← fsck.fat equivalent (verify BPB, FAT chains, directory tree + safe repair)
|
||||||
|
└── src/main.rs ← `--repair` clears dirty flag, fixes FSInfo, reclaims lost clusters
|
||||||
|
```
|
||||||
|
|
||||||
|
**Architecture**: `fatd` is a Redox scheme daemon using `fatfs` v0.3.6 (MIT, no_std capable).
|
||||||
|
FAT is for data volumes and ESP only — NOT for root filesystem.
|
||||||
|
`fscommon::BufStream` wraps block device for mandatory caching.
|
||||||
|
|
||||||
|
**Recipe**: Symlinked into mainline search path:
|
||||||
|
```
|
||||||
|
recipes/core/fatd → ../../local/recipes/core/fatd
|
||||||
|
```
|
||||||
|
|
||||||
|
**Config**: Packages included via `config/redbear-device-services.toml` (inherited by
|
||||||
|
`redbear-desktop.toml` and `redbear-full.toml`). Init service at
|
||||||
|
`/usr/lib/init.d/15_fatd.service`.
|
||||||
|
|
||||||
|
**Dependencies**: fatfs 0.3.6, fscommon 0.1.1, redox_syscall, redox-scheme, libredox, libc
|
||||||
|
|
||||||
|
**Tool verification status** (2026-04-17):
|
||||||
|
- `fat-mkfs`: ✅ Creates FAT12/16/32, labels, auto-detection, tested up to 1GB
|
||||||
|
- `fat-label`: ✅ Reads labels; writes BPB + creates/updates root-directory volume-label entry; verifies round-trip on all FAT types (including previously unlabeled volumes)
|
||||||
|
- `fat-check`: ✅ BPB validation, boot signature check, directory tree walk, cluster stats; ✅ safe repair (dirty flag, FSInfo, lost clusters, orphaned LFN). Handles 0xFFFFFFFF FSInfo sentinel on fresh images.
|
||||||
|
- `fatd`: ✅ Compiles (links on Redox target only — expected). NOT runtime-tested (requires QEMU/bare metal).
|
||||||
|
- Phase 4 (runtime auto-mount): Deferred to runtime validation. Static init service exists.
|
||||||
|
- Known limitation: fatfs v0.3.6 strictly requires `total_sectors_16 == 0` for FAT32, rejecting some Linux `mkfs.fat` images
|
||||||
|
- `cargo test`: 0 unit tests (all testing done via integration tests with disk images)
|
||||||
|
|
||||||
## BRANDING ASSETS
|
## BRANDING ASSETS
|
||||||
|
|
||||||
Red Bear OS visual identity files live in `local/Assets/`.
|
Red Bear OS visual identity files live in `local/Assets/`.
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
# GRUB Integration Plan — Red Bear OS
|
# GRUB Integration Plan — Red Bear OS
|
||||||
|
|
||||||
**Date:** 2026-04-17
|
**Date:** 2026-04-17
|
||||||
**Status:** Phase 2 complete — installer-native GRUB support implemented and compiling
|
**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
|
**Approach:** Option A — GRUB as boot manager, chainloading Redox bootloader
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ index 417ff2d..4ad2202 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/src/installer.rs b/src/installer.rs
|
diff --git a/src/installer.rs b/src/installer.rs
|
||||||
index 4e077a9..a6f4e84 100644
|
index 4e077a9..b11d5b8 100644
|
||||||
--- a/src/installer.rs
|
--- a/src/installer.rs
|
||||||
+++ b/src/installer.rs
|
+++ b/src/installer.rs
|
||||||
@@ -3,6 +3,13 @@ use anyhow::{bail, Result};
|
@@ -3,6 +3,13 @@ use anyhow::{bail, Result};
|
||||||
@@ -467,10 +467,16 @@ index 4e077a9..a6f4e84 100644
|
|||||||
let bootloader_dir =
|
let bootloader_dir =
|
||||||
PathBuf::from(format!("/tmp/redox_installer_bootloader_{}", process::id()));
|
PathBuf::from(format!("/tmp/redox_installer_bootloader_{}", process::id()));
|
||||||
|
|
||||||
@@ -493,6 +741,20 @@ pub fn fetch_bootloaders(
|
@@ -491,36 +739,75 @@ pub fn fetch_bootloaders(
|
||||||
|
|
||||||
let mut bootloader_config = Config::bootloader_config();
|
fs::create_dir(&bootloader_dir)?;
|
||||||
bootloader_config.general = config.general.clone();
|
|
||||||
|
- let mut bootloader_config = Config::bootloader_config();
|
||||||
|
- bootloader_config.general = config.general.clone();
|
||||||
|
- install_packages(&bootloader_config, &bootloader_dir, cookbook)?;
|
||||||
|
+ let result = (|| -> Result<_> {
|
||||||
|
+ let mut bootloader_config = Config::bootloader_config();
|
||||||
|
+ bootloader_config.general = config.general.clone();
|
||||||
+
|
+
|
||||||
+ let use_grub = config
|
+ let use_grub = config
|
||||||
+ .general
|
+ .general
|
||||||
@@ -484,14 +490,55 @@ index 4e077a9..a6f4e84 100644
|
|||||||
+ .packages
|
+ .packages
|
||||||
+ .insert("grub".to_string(), Default::default());
|
+ .insert("grub".to_string(), Default::default());
|
||||||
+ }
|
+ }
|
||||||
+
|
|
||||||
install_packages(&bootloader_config, &bootloader_dir, cookbook)?;
|
|
||||||
|
|
||||||
let boot_dir = bootloader_dir.join("usr/lib/boot");
|
- let boot_dir = bootloader_dir.join("usr/lib/boot");
|
||||||
@@ -518,9 +780,31 @@ pub fn fetch_bootloaders(
|
- let bios_path = boot_dir.join(if live {
|
||||||
Vec::new()
|
- "bootloader-live.bios"
|
||||||
};
|
- } else {
|
||||||
|
- "bootloader.bios"
|
||||||
|
- });
|
||||||
|
- let efi_path = boot_dir.join(if live {
|
||||||
|
- "bootloader-live.efi"
|
||||||
|
- } else {
|
||||||
|
- "bootloader.efi"
|
||||||
|
- });
|
||||||
|
+ install_packages(&bootloader_config, &bootloader_dir, cookbook)?;
|
||||||
|
|
||||||
|
- let bios_data = if bios_path.exists() {
|
||||||
|
- fs::read(bios_path)?
|
||||||
|
- } else {
|
||||||
|
- Vec::new()
|
||||||
|
- };
|
||||||
|
- let efi_data = if efi_path.exists() {
|
||||||
|
- fs::read(efi_path)?
|
||||||
|
- } else {
|
||||||
|
- Vec::new()
|
||||||
|
- };
|
||||||
|
+ let boot_dir = bootloader_dir.join("usr/lib/boot");
|
||||||
|
+ let bios_path = boot_dir.join(if live {
|
||||||
|
+ "bootloader-live.bios"
|
||||||
|
+ } else {
|
||||||
|
+ "bootloader.bios"
|
||||||
|
+ });
|
||||||
|
+ let efi_path = boot_dir.join(if live {
|
||||||
|
+ "bootloader-live.efi"
|
||||||
|
+ } else {
|
||||||
|
+ "bootloader.efi"
|
||||||
|
+ });
|
||||||
|
|
||||||
|
- fs::remove_dir_all(&bootloader_dir)?;
|
||||||
|
+ let bios_data = if bios_path.exists() {
|
||||||
|
+ fs::read(bios_path)?
|
||||||
|
+ } else {
|
||||||
|
+ Vec::new()
|
||||||
|
+ };
|
||||||
|
+ let efi_data = if efi_path.exists() {
|
||||||
|
+ fs::read(efi_path)?
|
||||||
|
+ } else {
|
||||||
|
+ Vec::new()
|
||||||
|
+ };
|
||||||
|
|
||||||
|
- Ok((bios_data, efi_data))
|
||||||
+ let grub_efi_data = if use_grub {
|
+ let grub_efi_data = if use_grub {
|
||||||
+ let grub_path = boot_dir.join("grub.efi");
|
+ let grub_path = boot_dir.join("grub.efi");
|
||||||
+ if grub_path.exists() {
|
+ if grub_path.exists() {
|
||||||
@@ -514,14 +561,15 @@ index 4e077a9..a6f4e84 100644
|
|||||||
+ None
|
+ None
|
||||||
+ };
|
+ };
|
||||||
+
|
+
|
||||||
fs::remove_dir_all(&bootloader_dir)?;
|
|
||||||
|
|
||||||
- Ok((bios_data, efi_data))
|
|
||||||
+ Ok((bios_data, efi_data, grub_efi_data, grub_cfg_data))
|
+ Ok((bios_data, efi_data, grub_efi_data, grub_cfg_data))
|
||||||
|
+ })();
|
||||||
|
+
|
||||||
|
+ let _ = fs::remove_dir_all(&bootloader_dir);
|
||||||
|
+ result
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: make bootloaders use Option, dynamically create BIOS and EFI partitions
|
//TODO: make bootloaders use Option, dynamically create BIOS and EFI partitions
|
||||||
@@ -683,20 +967,58 @@ where
|
@@ -683,20 +970,58 @@ where
|
||||||
eprintln!("Creating EFI directory");
|
eprintln!("Creating EFI directory");
|
||||||
let root_dir = fs.root_dir();
|
let root_dir = fs.root_dir();
|
||||||
root_dir.create_dir("EFI")?;
|
root_dir.create_dir("EFI")?;
|
||||||
@@ -592,7 +640,7 @@ index 4e077a9..a6f4e84 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Format and install RedoxFS partition
|
// Format and install RedoxFS partition
|
||||||
@@ -712,6 +1034,222 @@ where
|
@@ -712,6 +1037,222 @@ where
|
||||||
with_redoxfs(disk_redoxfs, disk_option.password_opt, callback)
|
with_redoxfs(disk_redoxfs, disk_option.password_opt, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,20 +863,21 @@ index 4e077a9..a6f4e84 100644
|
|||||||
#[cfg(not(target_os = "redox"))]
|
#[cfg(not(target_os = "redox"))]
|
||||||
pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
||||||
_fs: &mut redoxfs::FileSystem<D>,
|
_fs: &mut redoxfs::FileSystem<D>,
|
||||||
@@ -801,6 +1339,23 @@ pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
@@ -801,6 +1342,24 @@ pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
||||||
|
|
||||||
fn install_inner(config: Config, output: &Path) -> Result<()> {
|
fn install_inner(config: Config, output: &Path) -> Result<()> {
|
||||||
println!("Installing to {}:\n{}", output.display(), config);
|
println!("Installing to {}:\n{}", output.display(), config);
|
||||||
+
|
+
|
||||||
+ if let Some(ref bl) = config.general.bootloader {
|
+ if let Some(ref bl) = config.general.bootloader {
|
||||||
+ match bl.as_str() {
|
+ let bl_lower = bl.to_lowercase();
|
||||||
|
+ match bl_lower.as_str() {
|
||||||
+ "redox" | "grub" => {}
|
+ "redox" | "grub" => {}
|
||||||
+ other => bail!(
|
+ other => bail!(
|
||||||
+ "Unknown bootloader '{}': expected \"redox\" or \"grub\"",
|
+ "Unknown bootloader '{}': expected \"redox\" or \"grub\"",
|
||||||
+ other
|
+ other
|
||||||
+ ),
|
+ ),
|
||||||
+ }
|
+ }
|
||||||
+ if bl.eq_ignore_ascii_case("grub") {
|
+ if bl_lower == "grub" {
|
||||||
+ let efi_size = config.general.efi_partition_size.unwrap_or(1);
|
+ let efi_size = config.general.efi_partition_size.unwrap_or(1);
|
||||||
+ if efi_size < 8 {
|
+ if efi_size < 8 {
|
||||||
+ bail!("GRUB bootloader requires efi_partition_size >= 8 MiB (got {} MiB). Add efi_partition_size = 16 to your config.", efi_size);
|
+ bail!("GRUB bootloader requires efi_partition_size >= 8 MiB (got {} MiB). Add efi_partition_size = 16 to your config.", efi_size);
|
||||||
@@ -839,7 +888,7 @@ index 4e077a9..a6f4e84 100644
|
|||||||
let cookbook = config.general.cookbook.clone();
|
let cookbook = config.general.cookbook.clone();
|
||||||
let cookbook = cookbook.as_ref().map(|p| p.as_str());
|
let cookbook = cookbook.as_ref().map(|p| p.as_str());
|
||||||
if output.is_dir() {
|
if output.is_dir() {
|
||||||
@@ -823,28 +1378,41 @@ fn install_inner(config: Config, output: &Path) -> Result<()> {
|
@@ -823,28 +1382,41 @@ fn install_inner(config: Config, output: &Path) -> Result<()> {
|
||||||
let live = config.general.live_disk.unwrap_or(false);
|
let live = config.general.live_disk.unwrap_or(false);
|
||||||
let password_opt = config.general.encrypt_disk.clone();
|
let password_opt = config.general.encrypt_disk.clone();
|
||||||
let password_opt = password_opt.as_ref().map(|p| p.as_bytes());
|
let password_opt = password_opt.as_ref().map(|p| p.as_bytes());
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ if [ ! -f "${COOKBOOK_STAGE}/usr/lib/boot/grub.efi" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GRUB_SIZE=$(stat -f%z "${COOKBOOK_STAGE}/usr/lib/boot/grub.efi" 2>/dev/null || stat -c%s "${COOKBOOK_STAGE}/usr/lib/boot/grub.efi" 2>/dev/null || echo "unknown")
|
GRUB_SIZE=$(stat -c%s "${COOKBOOK_STAGE}/usr/lib/boot/grub.efi" 2>/dev/null || echo "unknown")
|
||||||
echo "GRUB EFI image size: ${GRUB_SIZE} bytes"
|
echo "GRUB EFI image size: ${GRUB_SIZE} bytes"
|
||||||
|
|
||||||
# Copy default GRUB configuration from recipe directory.
|
# Copy default GRUB configuration from recipe directory.
|
||||||
|
|||||||
@@ -47,8 +47,12 @@ class Fat32:
|
|||||||
self.f = open(image_path, "r+b")
|
self.f = open(image_path, "r+b")
|
||||||
self.image_size = os.fstat(self.f.fileno()).st_size
|
self.image_size = os.fstat(self.f.fileno()).st_size
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
|
try:
|
||||||
self._read_bpb()
|
self._read_bpb()
|
||||||
self._load_fat()
|
self._load_fat()
|
||||||
|
except:
|
||||||
|
self.f.close()
|
||||||
|
raise
|
||||||
|
|
||||||
def _read_bpb(self):
|
def _read_bpb(self):
|
||||||
self.f.seek(self.offset)
|
self.f.seek(self.offset)
|
||||||
@@ -118,7 +122,10 @@ class Fat32:
|
|||||||
if not 2 <= cluster <= self.max_cluster:
|
if not 2 <= cluster <= self.max_cluster:
|
||||||
raise RuntimeError(f"FAT32: invalid cluster {cluster}")
|
raise RuntimeError(f"FAT32: invalid cluster {cluster}")
|
||||||
idx = cluster * 4
|
idx = cluster * 4
|
||||||
return read_le32(self.fat, idx) & 0x0FFFFFFF
|
val = read_le32(self.fat, idx) & 0x0FFFFFFF
|
||||||
|
if val == 0x0FFFFFF7:
|
||||||
|
raise RuntimeError(f"FAT32: bad cluster marker at {cluster}")
|
||||||
|
return val
|
||||||
|
|
||||||
def _set_fat(self, cluster, value):
|
def _set_fat(self, cluster, value):
|
||||||
write_le32(self.fat, cluster * 4, value & 0x0FFFFFFF)
|
write_le32(self.fat, cluster * 4, value & 0x0FFFFFFF)
|
||||||
|
|||||||
Reference in New Issue
Block a user