Skip to content

Commit

Permalink
Added project
Browse files Browse the repository at this point in the history
  • Loading branch information
andrasbiro committed Oct 21, 2024
1 parent 2157189 commit a72e007
Show file tree
Hide file tree
Showing 9 changed files with 783 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build
.vscode
27 changes: 27 additions & 0 deletions 49_switch
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#! /bin/sh
exec tail -n +3 ${0}
# Look for hardware switch device by its hard-coded filesystem ID
search --no-floppy --label --set hdswitch GRUB-SWITCH

# If found, read dynamic config file and select appropriate entry for each position
if [ "${hdswitch}" ] ; then
source ($hdswitch)/switch.cfg

if [ "${os_hw_switch}" == "l" ] ; then
# Boot Linux
set default="0" #change this to your Linux entry number
set timeout=0
elif [ "${os_hw_switch}" == "w" ] ; then
# Boot Windows
set default="2" #change this to your windows entry number
set timeout=0
elif [ "${os_hw_switch}" == "s" ] ; then
# default with infinite timeout
set default="${GRUB_DEFAULT}"
set timeout=-1
else
# Fallback to default
set default="${GRUB_DEFAULT}"
set timeout="${GRUB_TIMEOUT}"
fi
fi
34 changes: 34 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.13...3.27)

set(PROJECT_NAME grubswitch)


#pull in the PICO SDK
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

project(${PROJECT_NAME} C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})

#init the sdk
pico_sdk_init()

add_executable(${PROJECT_NAME}
src/main.c
src/msc_disk.c
src/usb_descriptors.c
)

target_include_directories(${PROJECT_NAME} PRIVATE
src/)

#pull in pico_stdlib
target_link_libraries(${PROJECT_NAME} pico_stdlib tinyusb_device)

# pico_enable_stdio_usb(${PROJECT_NAME} 0)
# pico_enable_stdio_uart(${PROJECT_NAME} 1)

#create uf2
pico_add_extra_outputs(${PROJECT_NAME})
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# GRUB switch

This is a simple physical switch to control GRUB2 inspired by a [simplar project
for STM32](https://github.com/stecman/hw-boot-selection), but implemented on the
Raspberry Pi Pico (developed on RP2040-Zero, but any Pico should be good).

The code is using an SPDT On-Off-On switch, one side selects Linux, the other
Windows, while in the middle selection, the GRUB menu stays on indefinately -
but this should be very easy to modify.

I needed this, because I have a strange dual boot setup where my monitor usually
turns on with the input that is not the default from my UEFI setup.

## Build and install

An uf2 binary is available as release for easy testing.

Install the [pico-SDK](https://github.com/raspberrypi/pico-sdk), cmake and
arm-eabi-gcc.

Make sure to set the environemnt variable PICO_SDK_PATH to point the folder
where your pico-SDK is (e.g. `export PICO_SDK_PATH=/usr/share/pico-sdk`).

Then continue with the usual cmake setup:

```bash
mkdir build
cd build
cmake ..
make
```

Finally, install the generated `build/grubswitch.uf2` on the Pico. It will
reboot as a FAT16 drive, labeled "GRUB-SWITCH".

The switch should be connected to pin28 and pin29 if the code is used
unmodified.

## Setup GRUB

Copy [49_switch](49_switch) to `/etc/grub.d`. Modify the entry numbers
highlighted with comments. Make sure it's executable and run `update-grub` as
root.

## Modification

The letters set by the switch are defined in [msc_disk.h](src/msc_disk.h). The
switch is read in [main.c](src/main.c). The filesystem and filename are defined
in [msc_dis.c](src/msc_disk.c) - although I wouldn't recommend changing this
unless you have to.

## Inspiration

This project was developed based on the following:

* [The ST implementation of the same
idea](https://github.com/stecman/hw-boot-selection)
* [Another pico
implementation](https://www.hackster.io/Madrajib/hardware-boot-select-switch-using-pico-a3e3d5)
I just didn't like that it's a documentation on how to modify an example
* [A nice demonstration project of USB
MSC](https://github.com/brendena/pico_drag_n_drop_programmer) with a lot of
links and explanation video.
66 changes: 66 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "tusb.h"
#include "pico/stdlib.h"
#include "msc_disk.h"

#define GPIO_LINUX 28
#define GPIO_WINDOWS 29

/*------------- MAIN -------------*/
int main(void)
{

// init device stack on configured roothub port
tusb_init();

gpio_init(GPIO_LINUX);
gpio_init(GPIO_WINDOWS);
gpio_set_dir(GPIO_LINUX, false);
gpio_set_dir(GPIO_WINDOWS, false);
gpio_pull_up(GPIO_LINUX);
gpio_pull_up(GPIO_WINDOWS);


while (1)
{
tud_task(); // tinyusb device task

if ( !gpio_get(GPIO_LINUX) && !gpio_get(GPIO_WINDOWS)){
setSwitchValue(CONFIG_DEFAULT);
} else if ( !gpio_get(GPIO_LINUX)){
setSwitchValue(CONFIG_LINUX);
} else if ( !gpio_get(GPIO_WINDOWS)){
setSwitchValue(CONFIG_WINDOWS);
} else { //neither are pulled down, switch in the middle
setSwitchValue(CONFIG_STOP);
}
}

return 0;
}

//--------------------------------------------------------------------+
// Device callbacks
//--------------------------------------------------------------------+

// Invoked when device is mounted
void tud_mount_cb(void)
{
}

// Invoked when device is unmounted
void tud_umount_cb(void)
{
}

// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en)
{
(void) remote_wakeup_en;
}

// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
}
Loading

0 comments on commit a72e007

Please sign in to comment.