2020-11-24

Simplifying rebooting into windows, Part 1: efibootmgr script

    While Linux is great, and Windows is not, sometimes you may need to have a Windows installation with enough disk space on it (coung, gaming, cough). Thankfully, nowadays there are fast SSD's with a ton of storage on them (well not for UE5 games it seems like) that are allowing you to (re)boot really fast.

    I have a decent Asus ROG notebook (cough, definitely not for gaming, cough), and it comes with this useless "gaming" button, that launches something useless on Windows and simply does nothing on Linux. We can use it to reboot into Windows! (totally makes sense btw, cough)

    First of all, we need to reboot exactly into Windows somehow, because if you have to choose it in booloader menu then our "gaming" button is no different from a simple reboot one.

    Okay, so modern bootloaders - called EFI for Extensible Firmware Interface and sometimes UEFI (U standing for Unified) operate on a set of variables stored somewhere in your BIOS that are known as EFI variables. The EFI variable that we are interested in is called BootNext - it tells the BIOS to choose some specific boot entry once and then return back to default behavior. This is how your system is able to reboot into BIOS menu - it sets the BootNext to the appropriate entry and simply reboots.

    In our script we will do just the same, set the BootNext to a Windows boot entry and just call reboot.

    We will need the efibootmgr program though, as manipulating EFI variables is not really something you can do without it. It is pretty ubiquitous and is present in most repositories under this name, so you can use your package manager to install it - for me it was sudo pacman -Sy efibootmgr for you it could be like sudo apt install efibootmgr or something.

    Anyway, now that we have it we can actually make a script with it:

1
2
3
4
5
6
7
8
#!/bin/bash

# set the windows to boot next
sudo efibootmgr -n $(efibootmgr | grep -i windows | cut -c5-8)

# and just reboot
reboot


    There are a couple of things happening in this script.

    If you type  man efibootmgr (and you have man-db installed) in your terminal, you can see that is has a bunch of commandline switches.
You can press the '/' button (a vi-like keybind) to enter search mode and type something like 'BootNext' and hit enter - it highlights all occurences of the search query and moves you to the first of them.
Also you can press 'n' and 'N' to go to the next/prev occurence accordingly, but this is not needed as the first result yielded exactly what we needed - a switch to set the BootNext efivar.

    You can use either --bootnext for clarity, or -n for brewity, this is just a matter of taste.

    Anyway, it requires an argument that is the entry that we want to be booted next. As you can see in the man(ual), it needs a code - four consecutive hexadecimal numbers that correspond to the boot entry ID.

    If you read the man top to bottom, you can find out that if you just run efibootmgr to see the values the most used efivars - there is a lot of them actually - for me it works even without the root (despite what is said on the possibly-outdated man page), as it should probably do when not changing anything and just reading out information.

    After some values like BootOrder or Timeout it just prints out all of the currently existing entries in form BootXXXX* boot entry name, where the X'es are exactly the code we need.

    As you can see in the script, we pipe the output (|) of the efibootmgr command into a grep command, which filters out lines that do not contain the word 'windows' ignoring the case (-i flag) and the output of that we pipe once again into a cut command which cuts out characters from 5 to 8 inclusive (you guessed it, the -c flag) - the part of BootXXXX which we are interested in, the X'es.

    If you are new to bash and the linux terminal - you'll quickly get the hang of it and it will seem dead-simple to you, and if you are already - I am sorry for being a bit boring here :)

    At last, we plug this command with two pipes that will yield us the code directly as the parameter to the sudo efibootmgr -n command, using Bash command substitution syntax (the $(...) part).

    After that, we have succesfully set the BootNext variable, so we just issue a reboot command - if it does not work for you without sudo then you should fix/install the polkit component, and it is definitely not the topic for this blog post. And you need sudo privileges for setting the BootNext variable anyway, so you can just reboot with sudo for now.

    Now, after making the script (you copied it from here into a 'windows.sh' file, right?) executable with chmod +x windows.sh command, you should be able to run it with ./windows.sh - it'll ask you for password (we used sudo, remember?) and get you rebooted into windows, hurray.

    In the next parts we will make this script keybindable (running sudo from a keybind is tricky), add an 'are you sure?' check for accidental button presses, and even dive deeper into things like temporaroly enabling Windows autologin (so you won't have to use pin/password, but only when rebooting from Linux) and more.



2020-05-07

hello world

Yeah, yeah, stupid cliche name for the first post.

Anyway, I've made it just to test some of my changes to the Blogger theme, wanted it to look nice for whatever reason ¯\_(ツ)_/¯

And for the blog - I will (although very rarely as I am not a fan of typing tons of text) make posts here about some of my projects and scripts and stuff, made while doing my hobby - playing with configs, programming stuff, and everything in between (imo Lua is the best 'config format').