This a collection of notes and files used in my quest to create "Reboot to Windows" and "Reboot to Linux" scripts (and desktop shortcuts) for Linux and Windows respectively that automatically reboot my system and instruct rEFInd to auto-select the appropriate OS entry.
The key for achieving this is to modify the EFI Variable PreviousBoot
with GUID 36d08fa7-cf0b-42f5-8f14-68df73ed3740
, which rEFInd uses to store the last entry selected in the menu and, if using the +
default entry, will be used to select the default OS. By doing this, we trick rEFInd into booting the OS we choose without having to be physically there to press the keyboard.
This variable seems to use the following format:
- 4 bytes,
07 00 00 00
(although Windows ignores this) - The text string of the entry, in UTF-16 Little Endian (no BOM)
- 4 bytes,
20 00 00 00
(effectively: a space and a NUL character)
The variable doesn't need to contain the full text of the entry, either: Any substring will match. I don't know what rEFInd does in case of multiple matches; I believe it stops after the first. It's up to you to put everything in there or just a substring.
Linux exposes all EFI variables via efivarfs
in the directory /sys/firmware/efi/efivars/
, with file names {NAME}-{GUID}
. Specifically, the relevant variable is at /sys/firmware/efi/efivars/PreviousBoot-36d08fa7-cf0b-42f5-8f14-68df73ed3740
. These files contain the value of the variable in NVRAM and can be modified (by root
only). Most of them will have the immutable flag set, to prevent errors, so you must call chattr -i /path/to/efivar
before attempting to modify them.
This is enough to edit the default rEFInd entry: Write to the efivar file with the format specified in the previous point and the name of the entry you want selected and you're done. See the linux.refind-next-boot.py
file below for a ready to use script that will set the value to this variable to its first command line argument with the appropriate format.
If you place that script (renamed to refind-next-boot
) in your $PATH
and give it the appropriate file permissions, you can just run:
sudo refind-next-boot 'Microsoft'
systemctl reboot
Those two commands can be conviniently placed in a script or desktop launcher so that you can reboot to Windows directly. You might want to add yourself to the sudoers file so that you can run that command with no password, in wich case remember to adequately secure the script: Set root
as its owner and group and set permissions to 0755
or more restrictive.
And this is it. That was the easy part.
Ok, this is where it gets tricky. Windows has no way of giving you access to the EFI variables other than using the Windows API, specifically via GetFirmwareEnvironmentVariable
/SetFirmwareEnvironmentVariable
. These functions bot receive the name of the variable, its GUID surrounded by curly braces, a buffer to read/write from/to, respectively, and the length of the buffer or the data.
To call those two functions, the running process needs elevated privileges and a modification to the user access token, which aparently is a thing in Windows. All of this is only available via the Windows API, of course, so you'll need to write some C/C++ code.
Below is a script program that works essentially like the python script but for Windows. It needs to be compiled, which I painfully did using Visual Studio, a experience I wouldn't want to repeat. It works the same: Just call it with the name of the entry you want to boot or a substring of that set. Afterwards, you are free to power off or shut down your system using whatever method and rEFInd will just select the correct entry.
Of course, Windows being Windows, creating a desktop shortcut that has an icon and is just double-click-and-forget is a bit more tricky than the Linux equivalent. First, you'll need to place the compiled program someplace and set it to run as administrator (right click, Propertied, Compatibility, check Run as administrator). After that, in that same folder, create a .bat
file that calls our program and restarts:
refind-next-boot "linux"
shutdown -t 0 -r
Now create a shortcut to that .bat
file, place it in your desktop, give it a proper icon and name and voilà, a "Reboot to Linux" button! It will bother you with a few console windows and a UAC dialog, yes, but it's better than nothing.
I stumbled on this thread while I was looking for an rEFInd next boot only solution. As a non-developer, any solution that involves compiling a code is beyond my capability. Now, I have come up with a work-around and decided to share the idea in case another noob like me is still searching for a solution.
In the refind.conf file, if one uses the following statement, he can boot to the OS of his choice within the specified time.
default_selection OS_of_your_choice current_time current_time_plus_one_minute
For example,
default_selection Windows 06:00 06:01
will boot Windows between 6 and 6:01AM.
By limiting this window to only 1 minute before I reboot, I basically achieve the objective of next boot only!
Don't forget to insert
default_selection your_default_OS
BEFORE the previous statement so that when the time windowed statement is invalid, rEFInd knows what to do than defaulting to last OS booted. The time windowed statement must be the LAST statement, or it will not execute even if you are within the valid time frame.
This is a work-around and not a solution. For example, you cannot reboot from Windows to Windows. After you reboot, it goes back to your default OS. If you want to boot to Windows again, you would need to adjust the time frame in the default_selection statement.
As inelegant as it is, it does offer you the capability to boot to Windows remotely when you need to and most importantly not get stuck in Windows when you need to switch to other OS but you don't have easy access to ESP and you are not sitting in front of the machine to click another OS!
A minor inconvenience is if rebooting at exact same time again tomorrow, it will boot to Windows regardless of it is my intention or not. However, since there are 1440 minutes a day, the probability for this to happen is very low. Personally I leave it alone. If I every get anal retentive, I will just write a batch file that would execute at boot time to restore a refind.conf template file to rid of this windowed statement.
Hope this helps those who don't know how to compile a code but need to reboot his dual-boot machine remotely from time to time.