How I wake my dual-booted PC from a distance
Lately, I’ve been trying to use an iPad for all my on-the-go computing needs, to avoid having to lug a laptop around as well. The newer iPad's are incredibly powerful devices, and are more than sufficient for 90% of my use cases. Up until now, there has only been one real obstacle, and that has been the disability to code on an iPad. iPadOS, with its locked down architecture and insufficient file management system, has not yet produced an on-device coding environment that is comparable to one you can create with Visual Studio Code or a full-fledged IDE.
Luckily, Microsoft has lately released Visual Studio Code Server, which allows you to remotely connect to a development environment. The best part is that you can run this on your own development machine, and thus code directly on your own machine!
This however of course requires my PC to be on, and running Linux, where my development environment resides. This would pose no problem, except I sometimes need Windows to be running when I have to run particular programs through RDP. I therefore would like to be able to, from a distance, boot my PC to either Linux or Windows.
Implementation
To do this, I’m going to implement a solution suggested by user arch1t3cht30 via superuser. The implementation of this solution requires a home server (though it can probably also be implemented using a remote server, with a bit of added hassle), for which I’m using a RPI4 running home assistant. The basic idea is that we serve a file on this server, which our PC can then load during the boot process. This file then contains the boot settings for the OS we want our computer to boot.
For this we need to set up a TFTP server, which is a very simple protocol that allows us to serve files over the network. We also need to set up Grub to be able to load the file we serve on the TFTP server. Lastly, we need to create a script that changes the boot settings file we serve and then boots the computer.
TFTP
As mentioned earlier, we need to run a TFTP server. I’m going to do this by creating a new add-on (which is basically a docker container) in home assistant, but if you have a regular Linux home server running it is perhaps easier to install a TFTP server natively. The home assistant Docker set up for the server looks as follows:
ARG BUILD_FROM
FROM $BUILD_FROM
RUN apk add --no-cache tftp-hpa
# Copy data for add-on
COPY run.sh /
RUN chmod a+x /run.sh
CMD [ "/run.sh" ]
It is important to note that in the add-on setup in home assistant, I mapped the share map to the container, and also exposed the needed port (port 69).
The entry point for the container is the run.sh
file, which simply lists the files we're serving and starts the TFTP daemon:
echo "Starting server."
echo "Sharing files:"
ls /share/srv/tftp
in.tftpd -L --secure /share/srv/tftp
We can now add a demo file to the server's share directory and test the server by running the following command:
tftp <server_ip_address> -c get demo_file && cat demo_file
Grub
Next, we need to set up Grub to load our file from the server.
Firstly, it is important to enable the network of your computer during the boot sequence. This is done in the BIOS, and this option is, in most cases, called either Network Stack
or Network boot
. Enabling this allows Grub to use the network, which is needed for what we are going to do next. Then we can try to retrieve a file from our TFTP server. First trying this in the Grub console allows us to test the commands and also see if the BIOS is set up correctly.
The commands that worked for me are:
# Load necessary modules
insmod net
insmod efinet
insmod tftp
# Boot the network and retrieve IP address using DHCP
net_bootp
# Retrieve and apply the TFTP file
source (tftp,<server_ip_address>)/boot_config
After figuring out what commands are needed, these can be added to the end of the grub config at /etc/grub.d/40_custom. Make sure to rebuild the grub configuration and add some grub commands (such as default="2"
) to the boot configuration file on the TFTP server. Now, while booting, these commands should be executed, and you should be able to see this reflected in the grub boot process!
Server script
The last step is to change this boot configuration based on the OS we want to boot. To do this, we just have to write the default="<index>"
command to the configuration file (where index is the index of the item in the grub list we want to boot).
To do this, I created a script in home assistant that sets the default index in the file to 2 (which is the index in Grub for my Linux installation), wakes the computer using a magic packet, waits a certain time to allow grub to boot, and changes the file back to an empty file, which causes Grub to boot the default OS (Windows in my case). As arch1t3cht30 explains, this can also be done with a simple shell script on the server:
echo 'default="<boot-target-index>"' > /share/srv/tftp/boot_config
wol <PC MAC-address>
sleep 15 # wait for GRUB to boot
echo '' > /share/srv/tftp/boot_config
How I boot
In the end, I have set up a home assistant script such that I only have to press one button to boot my computer. Using the home assistant app, I can also add buttons to the home screen of my iPad, to make the booting experience frictionless!