Stephen Holdaway has created a switch with “Linux” and “Windows” labels, enabling you to boot into the correct OS with ease. About the reason for creating the switch, he says:
“ Dual-booting Linux and Windows is a great way to get the best of both worlds, but there’s one thing that’s always bothered me. To boot into Linux, I simply press the power button and walk away. To boot into Windows on the other hand requires a tactical, precision-timed strike on the keyboard to change the selection when GRUB briefly reveals itself. Now I could just increase the GRUB selection timeout, or remove it entirely, but I’d still need to wait around to make an operating system selection. I could use the mode in GRUB that remembers the last OS selection, but I’d still need to be around to change it half the time. I could make a “reboot into Windows” action in Linux, but I’m just as often booting from a powered-off state as I am rebooting from Linux. Since I always know which operating system I want ahead of time, why not make a physical switch to select between Linux and Windows?”
For the project, he uses an STM32 microcontroller to act as a USB mass-storage device, which serves up a dynamic file. The file can be loaded by the system’s boot configuration to change its boot behavior based on the physical input.
Instead of him making a custom USB interface, he leverages the fact that the BIOS already enables GRUB, with access to all attached storage devices. All he did was to present the device as storage, containing a file whose contents indicate the switch position. This looks simple. However, there are a few layers to it:
- Provide the mass-storage class descriptor, indicating one of several storage protocols to use (SCSI, ATA).
- Implement the chosen storage protocol. This is a set of commands to interrogate the storage device’s capabilities, capacity, layout and other metadata in addition to standard requests to read and write sectors.
- Emulate a valid filesystem when read from, without actually having any storage medium.
The next thing he did was emulating a filesystem that GRUB could understand. He picked FAT12 because it’s fairly well documented and has a simple layout, which are:
- Boot sector: a fixed structure that describes the name and geometry of the volume
- File Allocation Table: an index of which parts of the disk are used, and how large files are distributed/fragmented
- Root directory entry: file metadata. pointing to where the actual file content lives
- [No fixed structure on the rest of the disk]
After many activities, he had a setup where a list of virtual files could be defined, with the directory entries and file contents generated on the fly when requested by the unsuspecting host. After encountering setbacks because GRUB doesn’t have any built-in support for loading the contents of a file into a variable, nor does it support command substitution as typical Linux shells do, he came up with a better solution. Using GRUB’s “source” command to load additional config from a virtual file. This approach works out of the box, and in theory on any version of GRUB.
After successfully using the switch position in GRUB’s shell, the only thing left for him to do is to modify the system boot configuration to make its boot selection based on this information: In /etc/grub.d/00_header, add this to the generated output (escaping removed to make it easier to read) After running update-grub to generate the new boot configuration, the setup worked perfectly.
For the hardware, he used a little aluminum flat bar, a couple of screws, and some drilling, then he placed the device permanently under the lip of his desk, within arm’s reach. For more information about the project, and how you can make your own switch, visit the project write-up, and his GitHub repository.