Skip to content

grubconfig: create boot/grub2/grubenv if not existing #931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cci.jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ parallel build: {
}
stage("Unit tests") {
shwrap("""
dnf install -y grub2-tools-minimal
cargo test
""")
}
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
- name: Install grub2
run: |
set -xeu
dnf install -y grub2-tools-minimal
- name: Cache build artifacts
uses: Swatinem/rust-cache@v2
- name: cargo build
Expand All @@ -49,6 +53,10 @@ jobs:
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
- name: Install grub2
run: |
set -xeu
dnf install -y grub2-tools-minimal
- name: Cache build artifacts
uses: Swatinem/rust-cache@v2
- name: cargo build (release)
Expand All @@ -74,6 +82,10 @@ jobs:
toolchain: ${{ env.MSRV }}
- name: Cache build artifacts
uses: Swatinem/rust-cache@v2
- name: Install grub2
run: |
set -xeu
dnf install -y grub2-tools-minimal
- name: cargo build (release)
run: cargo build --all-targets --release
- name: cargo test (release)
Expand Down Expand Up @@ -111,6 +123,10 @@ jobs:
uses: dtolnay/rust-toolchain@v1
with:
toolchain: ${{ matrix.channel }}
- name: Install grub2
run: |
set -xeu
dnf install -y grub2-tools-minimal
- name: Cache build artifacts
uses: Swatinem/rust-cache@v2
- name: cargo build
Expand Down
34 changes: 34 additions & 0 deletions src/grubconfigs.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::fmt::Write;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Result};
use bootc_utils::CommandRunExt;
use fn_error_context::context;
use openat_ext::OpenatDirExt;

/// The subdirectory of /boot we use
const GRUB2DIR: &str = "grub2";
const CONFIGDIR: &str = "/usr/lib/bootupd/grub2-static";
const DROPINDIR: &str = "configs.d";
const GRUBENV: &str = "grubenv";

/// Install the static GRUB config files.
#[context("Installing static GRUB configs")]
Expand Down Expand Up @@ -62,6 +65,8 @@ pub(crate) fn install(
.context("Copying grub-static.cfg")?;
println!("Installed: grub.cfg");

write_grubenv(&bootdir).context("Create grubenv")?;

let uuid_path = if write_uuid {
let target_fs = if boot_is_mount { bootdir } else { target_root };
let bootfs_meta = crate::filesystem::inspect_filesystem(target_fs, ".")?;
Expand Down Expand Up @@ -104,6 +109,24 @@ pub(crate) fn install(
Ok(())
}

#[context("Create file boot/grub2/grubenv")]
fn write_grubenv(bootdir: &openat::Dir) -> Result<()> {
let grubdir = &bootdir.sub_dir(GRUB2DIR).context("Opening boot/grub2")?;

if grubdir.exists(GRUBENV)? {
return Ok(());
}
let editenv = Path::new("/usr/bin/grub2-editenv");
if !editenv.exists() {
anyhow::bail!("Failed to find {:?}", editenv);
}

std::process::Command::new(editenv)
.args([GRUBENV, "create"])
.current_dir(format!("/proc/self/fd/{}", grubdir.as_raw_fd()))
.run_with_cmd_context()
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -124,4 +147,15 @@ mod tests {
assert!(td.exists("boot/efi/EFI/fedora/grub.cfg")?);
Ok(())
}
#[test]
fn test_write_grubenv() -> Result<()> {
let td = tempfile::tempdir()?;
let tdp = td.path();
std::fs::create_dir_all(tdp.join("boot/grub2"))?;
let td = openat::Dir::open(&tdp.join("boot"))?;
write_grubenv(&td)?;

assert!(td.exists("grub2/grubenv")?);
Ok(())
}
}