0

I'm running openSUSE Tumbleweed (20120913 when I type this, good chance it's different by the time you read it), kernel 5.14.1-1-default, grub2 version 2.06-6.1. If my hardware specs are pertinent to this (other than that I'm using a GF1080ti, using the nvidia drivers, version 470.63.01 on an Asus Strix Z270F mobo, then lemme know and I'll post them) .

Anyways, I'm dual booting Windows/Linux, probably about 60/40%. I'm booting (UEFI but secure boot off) off the drive Linux is installed on (except when Microsoft thinks it owns my computer and changes the boot order without asking me), and used YaST to set the Windows bootloader as default, and have a timeout (8 seconds, probably not important).

The problem is that I have a multi-monitor setup and for whatever reason the graphics card uses the side monitor as the default monitor (where the BIOS appears, and anything else before graphics drivers are loaded) even though a lot of the time that screen isn't even plugged into the power (don't need it being an energy vampire when I'm not using it). This means that grub only loads on that screen, so while I can boot into Windows fine (by doing nothing) or get to pick an option (by pressing a key), so I either have to plug in and turn on the other monitor or blindly try and pick the right thing in the boot menu (given some of available options, probably not a good idea). Turning on the other monitor isn't ideal because that makes KDE automatically switch it being the primary monitor, so I have to go into the display settings (takes a bit of time to load when you have five things connected to your graphics card) to reset it, but that's a complaint for another post (unless you can help now, I won't mind).

So what I'm looking for... is there any way I can setup grub so that if I cancel the initial countdown, it starts another one for Linux to be the default? Or set a key so I just have to mash that while booting until the primary display turns on and I know it's booting into Linux? Or something along those lines... basically a blind way to choose a (preferably specific) non-default entry in grub?

Thanks in advance for the answers!

2 Answers 2

0

Grub 2 supports hotkeys so you can achieve that.

If you edit grub.cfg and add the parameter --hotkey=l to the menuentry you will be able to achive what you are looking for. But /boot/grub.cfg file gets overriten when grub-update is executed.

I don't have a dual boot so I can't test it properly but editing /etc/grub.d/10_linux did the trick in my system.

find in that file this section:

linux_entry ()
{
  os="$1"
  version="$2"
  type="$3"
  args="$4"

  if [ -z "$boot_device_id" ]; then
      boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
  fi
  if [ x$type != xsimple ] ; then
      case $type in
          recovery)
              title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "$(gettext "${GRUB_RECOVERY_TITLE}")")" ;;
          init-*)
              title="$(gettext_printf "%s, with Linux %s (%s)" "${os}" "${version}" "${type#init-}")" ;;
          *)
              title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
      esac
      if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
          replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
          quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
          title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title>
          grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`>
      fi
      echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | >
  else
      echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} --hotkey=l \$menuentry_id_option  'gnulinux-simple-$boot_device_id' {" |>
  fi      
  if [ "$quick_boot" = 1 ]; then
      echo "    recordfail" | sed "s/^/$submenu_indentation/"
  fi
  if [ x$type != xrecovery ] ; then
      save_default_entry | grub_add_tab
  fi

And add the --hotkey=l parameter where it's place there. Execute grub-update and test if pressing the l boots straigth to linux

3
  • Thanks for the suggestion. I tried adding it as you suggested, but I just get grub-update: command not found when I try and run it in a shell using sudo. Commented Sep 18, 2021 at 10:43
  • Update: Thanks for pointing me in the right direction, looking at update output, I think I need to be using grub2-mkconfig). But while I was in /etc/grub.d/10_linux I noticed the lines ``` hotkey=1 incr_hotkey() { [ -z "$hotkey" ] && return expr $hotkey + 1 } print_hotkey() { keys="123456789abdfgijklmnoprtuvwyz" if [ -z "$hotkey" ]||[ $hotkey -eq 0 ]||[ $hotkey -gt 30 ]; then return fi echo "--hotkey=$(expr substr $keys $hotkey 1)" }``` And lo and behold, pressing 1 boots to Linux! I'm assuming that's because it's first in the boot order. Commented Sep 18, 2021 at 10:54
  • Yes, it seems your distro already implements It. You can change this "hotkey=$(incr_hotkey)" for any key you want if you want to force it (like hotkey=m" By the way. The language is shell script
    – shaola
    Commented Sep 19, 2021 at 11:25
0

Shout out to @shaola for pointing me in the right direction! Turns out, no config needed, at least on my machine. Turns out grub has these already built in! I got suspicious when I noticed all this already in /etc/grub.d/10_linux:

hotkey=1
incr_hotkey()
{
  [ -z "$hotkey" ] && return
  expr $hotkey + 1
}
print_hotkey()
{
  keys="123456789abdfgijklmnoprtuvwyz"
  if [ -z "$hotkey" ]||[ $hotkey -eq 0 ]||[ $hotkey -gt 30 ]; then
    return
  fi
  echo "--hotkey=$(expr substr $keys $hotkey 1)"
}

linux_entry ()
{
  os="$1"
  version="$2"
  type="$3"
  args="$4"

  if [ -n "${linux_root_device_thisversion}" ]; then
    root_device="root=${linux_root_device_thisversion}"
  else
    root_device=""
  fi

  if [ -z "$boot_device_id" ]; then
      boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")"
  fi
  if [ x$type != xsimple ] ; then
      case $type in
      recovery)
          title="$(gettext_printf "%s, with Linux %s (recovery mode)" "${os}" "${version}")" ;;
      *)
          title="$(gettext_printf "%s, with Linux %s" "${os}" "${version}")" ;;
      esac
      if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
      replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
      quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
      title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
      grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
      fi
      echo "menuentry '$(echo "$title" | grub_quote)' $(print_hotkey) ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
      hotkey=$(incr_hotkey)
  else
      echo "menuentry '$(echo "$os" | grub_quote)' $(print_hotkey) ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
      hotkey=$(incr_hotkey)
  fi      
  if [ x$type != xrecovery ] ; then
      save_default_entry | grub_add_tab
  fi

  # Use ELILO's generic "efifb" when it's known to be available.
  # FIXME: We need an interface to select vesafb in case efifb can't be used.
  if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then
      echo "    load_video" | sed "s/^/$submenu_indentation/"
      if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \
      && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then
      echo "    set gfxpayload=keep" | sed "s/^/$submenu_indentation/"
      fi
  else
      if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then
      echo "    load_video" | sed "s/^/$submenu_indentation/"
      fi
      echo "    set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/"
  fi

  echo "    insmod gzio" | sed "s/^/$submenu_indentation/"

I'm not exactly a brilliant programmer - in fact I can't even figure out of the top of my head what language it is (unless it's its own) but I surmised that there was an auto incrementing hotkey for each item in the list, and that my openSUSE install being at the top of the list meant I just have to mash 1 while booting and wait for signs I'm not being forced into an OS from a company that wants to emulate Apple at taking over my life by loading Linux.

Also if you have a setup like mine (or at least like mine in this way) and want to try @shaola's idea, I had to run grub2-mkconfig instead of grub-update. Probably a distro or version type thing. Definitely not my area of expertise to say.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .