Hardware boot selection switch

A physical switch for my computer to choose between Linux and Windows

Similar projects worth following
After a decade of dual-booting Linux, I got tired of waiting around to change the GRUB boot selection any time I wanted to boot Windows. With a little tinkering, here's a physical switch that determines the OS to boot each time the computer is turned on.

This uses an STM32 microcontroller to act as a USB mass-storage device, serving up a dynamic file. This file can be loaded by the system's boot config to change its boot behaviour based on the physical input:

A full write-up of the process to arrive at this solution is in the project log.

Source code is available on GitHub.

Making one yourself

The entire solution is in code, so all you need is a toggle switch, a USB-capable STM32 microcontroller and an ST-Link programmer. The classic "blue pill" STM32 dev board is already supported (STM32F103). The "black pill" and Adafruit Feather (both STM32F4xx) are capable of this, and support is on the way for those.

Follow the instructions in the GitHub repository to build and flash your chip.

  • 1 × Toggle switch Any kind of electrical switch you like
  • 1 × STM32 microcontroller with USB support F0 and F1 parts with USB support should work without modification,. Other STM32 series will require minor modification to the code to support

  • Hardware OS selection switch

    Stephen Holdaway6 days ago 6 comments

    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?

    Scripting in the boot loader

    GNU GRUB is a popular Linux boot loader - a program that runs before any operating system is loaded to decide what to boot and how to boot it. You'll normally interact with a menu like the one pictured above, but under the hood GRUB is configured by a simplified scripting language. Underneath that it's a system of modules written in C.

    My only hands-on experience with GRUB script to date has been those occasional times where a system fails to boot and you find yourself plunged into a shell with the prompt "grub>". You fairly quickly discover that while this looks like typical Linux shell with ls, cat and tab completion, it is very much not. Running outside of an operating system, GRUB has to supply all of its own tools, so the functionality available is fairly bare-bones.

    Arbitrary USB device access in GRUB?

    My first thought was creating a USB device with a custom ("vendor-specific") interface to read out the switch position, which in non-USB terms is kind of like a bare serial connection. This is straight forward enough to access from an operating system, but I wasn't sure if GRUB could handle it.

    GRUB does implement native USB support in its ehci, uhci and ohci modules, but there's a catch - loading any of these disables the normal mechanism used to access disks through the BIOS to avoid conflicts, leaving you with no disk access. There is a nativedisk module for accessing disks independently of the BIOS, but slowness aside, using this module critically means that GRUB can't chain-load Windows (explanation), making this approach a write-off.

    In short, native access to arbitrary USB devices from GRUB isn't practical for this project, but USB isn't off the table entirely...

    Pretending to be a USB mass-storage device

    Instead of making a custom USB interface, we can leverage the fact that the BIOS already provides GRUB with access to all attached storage devices. All we would need to do is present our device as storage, containing a file whose contents indicate the switch position.

    This is conceptually simple, but there are a few layers to it:

    1. Provide the mass-storage class descriptor, indicating one of several storage protocols to use (SCSI, ATA).
    2. 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.
    3. Emulate a valid filesystem when read from, without actually having any storage medium.

    Using the USB-capable STM32 boards and code I already have from USB Status Light, changing a vendor class device to a mass-storage class device was a matter of changing a few bytes in the existing USB descriptors.

    For the storage protocol layer, I was happy to find that libopencm3 has a built-in SCSI mass-storage implementation with simple read_block(address) and write_block(address) callbacks, hiding the complexity of the storage protocol:

    Thanks to this, I was up and running fairly quickly with a recognisable storage device, even...

    Read more »

View project log

Enjoy this project?



PMercier wrote 21 hours ago point

sweet :) it was in my todolist because i never found one already made. Thank you my todo stack got one entry deleted. Great idea to use the stm as a dynamic mass storage. 

  Are you sure? yes | no

Joonas Pihlajamaa wrote a day ago point

Very cool! Always wanted to do this, but thought a custom grub module would be needed. You could even do "Windows power button" and "Linux button" with ATX power control. I had the power side covered in (still using this, thankfully not currently dual booting)

  Are you sure? yes | no

Stephen Holdaway wrote 10 hours ago point

Nice, that's a cool project. I used to use Wake-on-LAN quite a lot, but it definitely gets fiddly requiring the PC to be in a specific state. Did you ever figure out your up-time issue with the Wemos D1?

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates