Skip to content

BCF-6655: Default GRUB boot entry is changed after BMR#86

Open
Andrus Suvalau (svlv) wants to merge 1 commit intodevelopfrom
feature/BCF-6655-default-grub-boot-entry-is-changed-after-bmr
Open

BCF-6655: Default GRUB boot entry is changed after BMR#86
Andrus Suvalau (svlv) wants to merge 1 commit intodevelopfrom
feature/BCF-6655-default-grub-boot-entry-is-changed-after-bmr

Conversation

@svlv
Copy link

Save and recover grubenv

BCF-6655: Default GRUB boot entry is changed after BMR

Jira-Ref: BCF-6655: Default GRUB boot entry is changed after BMR
Copilot AI review requested due to automatic review settings March 23, 2026 15:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to preserve the GRUB2 environment block (grubenv) across bare-metal recovery (BMR) so that the default GRUB boot entry doesn’t change after recovery.

Changes:

  • Add helper functions to detect grub-editenv / grub2-editenv and to detect whether GRUB2 was used.
  • Save grubenv values during layout/save into $VAR_DIR/recovery/grubenv.
  • Restore those values during finalize by re-creating/updating the target system’s GRUB environment block.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
usr/share/rear/lib/bootloader-functions.sh Adds get_grub_editenv() and is_grub2_used() helpers used by save/restore scripts.
usr/share/rear/layout/save/default/700_save_grubenv.sh New save-stage script intended to persist grubenv into recovery metadata.
usr/share/rear/finalize/Linux-i386/665_set_grubenv.sh New finalize-stage script intended to restore saved grubenv into the recovered system.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1027 to +1029
grub_editenv=$(chroot "$TARGET_FS_ROOT" /bin/bash -c "$cmd")
else
grub_editenv=$($cmd)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chrooted type -P ... call relies on PATH inside the target system, but no PATH is set here. Elsewhere in the codebase chrooted type -P calls prepend PATH=/sbin:/usr/sbin:/usr/bin:/bin to avoid missing binaries. Consider doing the same here (or use run_in_chroot and set PATH in the command) so get_grub_editenv works reliably during recovery.

Suggested change
grub_editenv=$(chroot "$TARGET_FS_ROOT" /bin/bash -c "$cmd")
else
grub_editenv=$($cmd)
grub_editenv=$(chroot "$TARGET_FS_ROOT" /bin/bash -c "PATH=/sbin:/usr/sbin:/usr/bin:/bin:\$PATH; $cmd")
else
grub_editenv=$(PATH=/sbin:/usr/sbin:/usr/bin:/bin:$PATH $cmd)

Copilot uses AI. Check for mistakes.
Comment on lines +1041 to +1043
used_bootloader="$( cat "$VAR_DIR/recovery/bootloader" )"

case $used_bootloader in
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_grub2_used compares the whole contents of $VAR_DIR/recovery/bootloader against GRUB2|GRUB2-EFI. Other scripts read the first non-comment token (e.g., via an array or grep -v), which is more robust if the file contains trailing whitespace/newlines or comments. Consider normalizing to the first word / first non-comment line before the case match.

Suggested change
used_bootloader="$( cat "$VAR_DIR/recovery/bootloader" )"
case $used_bootloader in
if [[ -r "$VAR_DIR/recovery/bootloader" ]]; then
# Read the first non-comment, non-empty line and take its first token
used_bootloader=$(
grep -v '^[[:space:]]*#' "$VAR_DIR/recovery/bootloader" | \
awk 'NF { print $1; exit }'
)
fi
if [[ -z "$used_bootloader" ]]; then
return 1
fi
case "$used_bootloader" in

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +18
"$grub_editenv" - list > "$grubenv_file"
exit_code=$?

if exit_code -ne 0; then
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grub-editenv invocation looks incorrect: "$grub_editenv" - list passes - as a positional argument. grub-editenv expects list as the command (and optionally a FILE); - will be treated as a filename and can fail or read/write the wrong place. Call "$grub_editenv" list (or pass the explicit grubenv file path you intend to read).

Suggested change
"$grub_editenv" - list > "$grubenv_file"
exit_code=$?
if exit_code -ne 0; then
"$grub_editenv" list > "$grubenv_file"
exit_code=$?
if [ "$exit_code" -ne 0 ]; then

Copilot uses AI. Check for mistakes.
"$grub_editenv" - list > "$grubenv_file"
exit_code=$?

if exit_code -ne 0; then
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition is a syntax error (if exit_code -ne 0; then). It should reference the variable and use a test expression (e.g., [ $exit_code -ne 0 ] or (( exit_code != 0 ))). As written, the script will fail to parse when sourced.

Suggested change
if exit_code -ne 0; then
if [ "$exit_code" -ne 0 ]; then

Copilot uses AI. Check for mistakes.

local grubenv_file="$VAR_DIR/recovery/grubenv"
if [ ! -f "$grubenv_file" ]; then
LogPrintError "Failed to set grubenv: '$VAR_DIR/recovery/grubenv' does not exist."
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If $grubenv_file is missing you only log an error but continue; the subsequent input redirection done < "$grubenv_file" will fail and exit_code will remain 0, so the script can report success. Return non-zero (or set exit_code=1 and return) immediately when the file does not exist.

Suggested change
LogPrintError "Failed to set grubenv: '$VAR_DIR/recovery/grubenv' does not exist."
LogPrintError "Failed to set grubenv: '$VAR_DIR/recovery/grubenv' does not exist."
return 1

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +22
for restored_grubenv in /boot/grub2/grubenv /boot/grub/grubenv; do
if [ -f "$restored_grubenv" ]; then
rm "$restored_grubenv"
Log "'$restored_grubenv' was removed"
fi
done
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These paths (/boot/grub2/grubenv and /boot/grub/grubenv) are checked/removed in the recovery environment, not in the restored target system. To remove grubenv from the restored filesystem, prefix with $TARGET_FS_ROOT (or run the removal via run_in_chroot). As written, it may delete the wrong file and leave the target grubenv untouched.

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +37
# It is essential to set up the environment block in the reserved btrfs sector
# See https://en.opensuse.org/GRUB#GRUB2_on_btrfs_/boot for more details
chroot "$TARGET_FS_ROOT" /bin/bash -c "\"$grub_editenv\" - unset dummy"

local exit_code=0
local var_value
while IFS= read -r var_value; do
local var="${var_value%=*}"
# env_block is read only
if [ "$var" = "env_block" ] ; then
continue
fi
if ! chroot "$TARGET_FS_ROOT" /bin/bash -c "\"$grub_editenv\" - set \"$var_value\""; then
LogPrintError "Failed to set '$var_value' to grubenv"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chroot ... bash -c "\"$grub_editenv\" - unset dummy" / ... - set ... commands have fragile quoting and again pass - as an argument. Using run_in_chroot with a straightforward command string (and calling grub-editenv with the correct syntax and explicit grubenv file if needed) will be more reliable and easier to maintain.

Copilot uses AI. Check for mistakes.
if test "$RECOVERY_MODE"; then
grub_editenv=$(chroot "$TARGET_FS_ROOT" /bin/bash -c "$cmd")
else
grub_editenv=$($cmd)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In non-recovery mode this runs grub_editenv=$($cmd) where cmd contains shell operators (||). Bash won’t re-parse || from an expanded variable, so this ends up calling type with literal arguments like || type -P ..., which can yield incorrect output. Use bash -c "$cmd" (or eval for this fixed string) consistently in both branches.

Suggested change
grub_editenv=$($cmd)
grub_editenv=$(bash -c "$cmd")

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants