GRUB doesn't remember the last chosen OS/kernel

Hi, I’m currently struggling with making GRUB boot to previous OS/kernel (menu entry).

Since I use btrfs as root partition, I am aware that GRUB_SAVEDEFAULT doesn’t work on btrfs partition because of some sparse file stuff, so I created separate ext4 partition on which i mounted /boot (/boot/efi is still mounted on EFI partition) so the overall partitions mounting looks like this:

/dev/nvme0n1p4 on / type btrfs (rw,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=256,subvol=/@)
/dev/nvme0n1p4 on /home type btrfs (rw,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=257,subvol=/@home)
/dev/nvme0n1p4 on /var/cache type btrfs (rw,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=258,subvol=/@cache)
/dev/nvme0n1p4 on /var/log type btrfs (rw,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=259,subvol=/@log)
/dev/nvme0n1p6 on /data type fuseblk (rw,nosuid,nodev,noatime,user_id=0,group_id=0,allow_other,blksize=4096)
/dev/nvme0n1p2 on /win type fuseblk (rw,nosuid,nodev,noatime,user_id=0,group_id=0,allow_other,blksize=4096)
/dev/nvme0n1p7 on /boot type ext4 (rw,relatime)
/dev/nvme0n1p1 on /boot/efi type vfat (rw,noatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)

here’s /etc/default/grub file:

GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true

#GRUB_SAVEDEFAULT=false
GRUB_DISTRIBUTOR='EndeavourOS'
GRUB_CMDLINE_LINUX_DEFAULT='nowatchdog nvme_load=YES loglevel=3'
GRUB_CMDLINE_LINUX=""

# Preload both GPT and MBR modules so that they are not missed
GRUB_PRELOAD_MODULES="part_gpt part_msdos btrfs"

# Uncomment to enable booting from LUKS encrypted devices
#GRUB_ENABLE_CRYPTODISK=y

# Set to 'countdown' or 'hidden' to change timeout behavior,
# press ESC key to display menu.
GRUB_TIMEOUT_STYLE=menu

# Uncomment to use basic console
GRUB_TERMINAL_INPUT=console

# Uncomment to disable graphical terminal
#GRUB_TERMINAL_OUTPUT=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `videoinfo'
GRUB_GFXMODE=2560x1440,1920x1080,1280x720,3840x2160,auto

# Uncomment to allow the kernel use the same resolution used by grub
GRUB_GFXPAYLOAD_LINUX=keep

# Uncomment if you want GRUB to pass to the Linux kernel the old parameter
# format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx"
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
GRUB_DISABLE_RECOVERY='true'

# Uncomment and set to the desired menu colors.  Used by normal and wallpaper
# modes only.  Entries specified as foreground/background.
#GRUB_COLOR_NORMAL="light-blue/black"
#GRUB_COLOR_HIGHLIGHT="light-cyan/blue"

# Uncomment one of them for the gfx desired, a image background or a gfxtheme
#GRUB_BACKGROUND='/usr/share/endeavouros/splash.png'
GRUB_THEME="/boot/grub/themes/sleek/theme.txt"

# Uncomment to get a beep at GRUB start
#GRUB_INIT_TUNE="480 440 1"

# Uncomment to make GRUB remember the last selection. This requires
# setting 'GRUB_DEFAULT=saved' above.
#GRUB_SAVEDEFAULT=true

# Uncomment to disable submenus in boot menu
GRUB_DISABLE_SUBMENU='false'

# Probing for other operating systems is disabled for security reasons. Read
# documentation on GRUB_DISABLE_OS_PROBER, if still want to enable this
# functionality install os-prober and uncomment to detect and include other
# operating systems.
#GRUB_DISABLE_OS_PROBER=false

and /boot/grub/grub.cfg:

#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
insmod part_gpt
insmod part_msdos
insmod btrfs
if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
insmod part_gpt
insmod btrfs
search --no-floppy --fs-uuid --set=root 2cf532f7-4ef5-4ee1-9a4f-c975325dae45
    font="/@/usr/share/grub/unicode.pf2"
fi

if loadfont $font ; then
  set gfxmode=2560x1440,1920x1080,1280x720,3840x2160,auto
  load_video
  insmod gfxterm
  set locale_dir=$prefix/locale
  set lang=ru_RU
  insmod gettext
fi
terminal_input console
terminal_output gfxterm
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
insmod gfxmenu
loadfont ($root)/grub/themes/sleek/Poppins-14.pf2
loadfont ($root)/grub/themes/sleek/Poppins-16.pf2
loadfont ($root)/grub/themes/sleek/Poppins-18.pf2
loadfont ($root)/grub/themes/sleek/Poppins-20.pf2
loadfont ($root)/grub/themes/sleek/Poppins-48.pf2
loadfont ($root)/grub/themes/sleek/terminus-12.pf2
loadfont ($root)/grub/themes/sleek/terminus-14.pf2
loadfont ($root)/grub/themes/sleek/terminus-16.pf2
insmod png
set theme=($root)/grub/themes/sleek/theme.txt
export theme
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/10_linux ###
menuentry 'EndeavourOS Linux' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
	load_video
	set gfxpayload=keep
	insmod gzio
	insmod part_gpt
	insmod ext2
	search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
	echo	'Загружается Linux linux-zen …'
	linux	/vmlinuz-linux-zen root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
	echo	'Загружается начальный виртуальный диск …'
	initrd	/amd-ucode.img /initramfs-linux-zen.img
}
submenu 'Дополнительные параметры для EndeavourOS Linux' $menuentry_id_option 'gnulinux-advanced-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	menuentry 'EndeavourOS Linux, с Linux linux-zen' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-zen-advanced-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux-zen …'
		linux	/vmlinuz-linux-zen root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux-zen.img
	}
	menuentry 'EndeavourOS Linux, with Linux linux-zen (fallback initramfs)' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-zen-fallback-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux-zen …'
		linux	/vmlinuz-linux-zen root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux-zen-fallback.img
	}
	menuentry 'EndeavourOS Linux, с Linux linux-lts' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-advanced-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux-lts …'
		linux	/vmlinuz-linux-lts root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux-lts.img
	}
	menuentry 'EndeavourOS Linux, with Linux linux-lts (fallback initramfs)' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-fallback-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux-lts …'
		linux	/vmlinuz-linux-lts root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux-lts-fallback.img
	}
	menuentry 'EndeavourOS Linux, с Linux linux' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux …'
		linux	/vmlinuz-linux root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux.img
	}
	menuentry 'EndeavourOS Linux, with Linux linux (fallback initramfs)' --class endeavouros --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-fallback-2cf532f7-4ef5-4ee1-9a4f-c975325dae45' {
	savedefault
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod part_gpt
		insmod ext2
		search --no-floppy --fs-uuid --set=root d86d5b03-603c-492e-8d61-c4fb8f66bda9
		echo	'Загружается Linux linux …'
		linux	/vmlinuz-linux root=UUID=2cf532f7-4ef5-4ee1-9a4f-c975325dae45 rw rootflags=subvol=@  nowatchdog nvme_load=YES loglevel=3
		echo	'Загружается начальный виртуальный диск …'
		initrd	/amd-ucode.img /initramfs-linux-fallback.img
	}
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/30_uefi-firmware ###
if [ "$grub_platform" = "efi" ]; then
	fwsetup --is-supported
	if [ "$?" = 0 ]; then
		menuentry 'UEFI Firmware Settings' $menuentry_id_option 'uefi-firmware' {
			fwsetup
		}
	fi
fi
### END /etc/grub.d/30_uefi-firmware ###

### BEGIN /etc/grub.d/35_fwupd ###
### END /etc/grub.d/35_fwupd ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg
fi
### END /etc/grub.d/41_custom ###

### BEGIN /etc/grub.d/41_snapshots-btrfs ###
### END /etc/grub.d/41_snapshots-btrfs ###

### BEGIN /etc/grub.d/45_eos_windows ###

menuentry 'Windows Boot Manager (on /dev/nvme0n1p1)' --class windows --class os $menuentry_id_option 'osprober-efi-F6EA-7ECE' {
	savedefault
	insmod part_gpt
	insmod fat
	search --no-floppy --fs-uuid --set=root F6EA-7ECE
	chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
### END /etc/grub.d/45_eos_windows ###

As far as I know GRUB’s default menu entry should be stored in /boot/grub/grubenv but it doesn’t content any variables:

# GRUB Environment Block
# WARNING: Do not edit this file by tools other than grub-editenv!!!
##################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################

can someone explain what am I doing wrong?

If I am not mistaken, on Btrfs the grubenv file cannot be written to so it is not possible to save the last booted entry.

Try: GRUB_TOP_LEVEL instead for the entry you want as default.

For example:

GRUB_TOP_LEVEL="/boot/vmlinuz-linux"

Also, regenerate grub.cfg after making the change:

sudo grub-mkconfig -o /boot/grub/grub.cfg

Hopefully this will work.

1 Like

it’s true that you can’t write grubenv in btrfs, but /boot is mounted on ext4, so this shouldn’t be the case I think.When i had /boot on root partition i had “error: sparse file not allowed”, but now i dont get any errors on boot

1 Like

Right, perhaps that shouldn’t be a problem then.
I’m afraid then I wouldn’t know what might cause Grub not to “remember” the last booted entry.
Please wait for some more input from other members.

Should that line be uncommented?

There’s GRUB_SAVEDEFAULT and GRUB_DEFAULT in the beginning of /etc/default/grub file

You should uninstall grub-btrfs.

Thanks, I’ll try it out when I got home. Out of curiosity, how could this potentially help?

There are two points:

  • grub-btrfs does not allow a snapshot entry to be automatically selected in GRUB menu after booting into the snapshot.

  • Kernel initramfs are stored in Ext4 under /boot

This is why you don’t need grub-btrfs

I found this in archwiki:

If using GRUB, you can automatically populate your boot menu with btrfs snapshots when regenerating the configuration file with the help of grub-btrfs or grub-btrfs-gitAUR.

Wouldn’t uninstallation of grub-btrfs make it impossible to boot into snapshots from grub?

Also, currently grub doesnt remember windows as last boot option as well, not only btrfs snapshots or any Linux os

grub-btrfs is useless, if initramfs is outside of your Btrfs system and is in /boot using Ext4, this initramfs does not match other kernel module after booting into a snapshot with the other kernel module.

You need to arch-chroot your system and reinstall kernel.

Because grub-btrfs disables the option. Try to uninstall grub-btrfs then run $ sudo grub-mkconfig

Can you please tell what’s the point of reinstalling the kernel? Can I do it without arch-chroot from the Linux that’s currently installed? Like this:

sudo pacman -S linux linux headers

I don’t have any snapshots yet. Just uninstalled grub-btrfs and ran

sudo grub-mkconfig -o /boot/grub/grub.cfg

still nothing has changed

No, you do not.
If you boot into any old snapshot with old kernel via GRUB menu, boot will fail. Then you need to arch-chroot to your system and reinstall kernel after boot failure.
Sorry for the confusion.

Maybe the current grub can’t write the config file grubenv in /boot with ext4 filesystem after choosing a boot option. The problem is new to me. :man_shrugging:

If you need a solution, switch to other bootloader.

I guess I faced that boot failure you’ve mentioned :frowning: i had failed mount for /boot, /boot/efi, everything failed except root partition and emergency menu just froze, can’t even input anything so I gave up on this idea, chroot’ed from live usb and made /boot on btrfs partition as it was. I guess I’ll try doing what i want to achive with rEFInd instead :smiling_face_with_tear: