You are not logged in.
Pages: 1
I read that you can do a bit of scripting with GRUB2, and also it can read Serial. I have a Raspberry Pi Zero and a Arduino Uno, how can i make to add an actual switch to my case, and use it to select a boot option? I'm willing to use a 3 state button to boot the option 1, the option 2 or wait to select one of the three other options.
Edit: The motherboard has an internal COM1 port
Last edited by daviddavo (2016-06-20 18:30:14)
Offline
It is not obvious what you are trying to do. Are you trying to allow a microcontroller to use the serial port of your Arch Linux box to control what Grub boots? Yes that is possible, but you won't likely have much luck using the Uno -- It's serial port is really a serial stream over USB that looks like a serial port. That won;t work until your are booted and the device is enumerated on the USB bus.
Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way
Offline
It is not obvious what you are trying to do. Are you trying to allow a microcontroller to use the serial port of your Arch Linux box to control what Grub boots? Yes that is possible, but you won't likely have much luck using the Uno -- It's serial port is really a serial stream over USB that looks like a serial port. That won;t work until your are booted and the device is enumerated on the USB bus.
And using the Raspberry Pi Zero?
Offline
Should be fine.
Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way
Offline
Arduino Uno has native serial port. You just need TTL to RS232 converter to plug it to PC COM port, such as MAX3222.
The issue is can grub take terminal input from serial port and keyboard simultaneously?
Offline
Arduino Uno has native serial port.
You are correct. I was thinking Leonardo.
Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way
Offline
Yes, grub can. You can setup terminal to serial and console both. Grub should write some unique char sequence to console. Controller's program should detect this sequence and answer with proper boot option name or do nothing in third case.
Offline
Yes, grub can. You can setup terminal to serial and console both. Grub should write some unique char sequence to console. Controller's program should detect this sequence and answer with proper boot option name or do nothing in third case.
Thanks, now, to do some scripting.
Offline
Well, i had some free time and implemented something close to your design. For testing i used VirtualBox with host device serial port and ATtiny2313 as hardware.
First of all, setup grub to use serial port as console. This is my grub.conf:
GRUB_DEFAULT=0
GRUB_TIMEOUT=-1
GRUB_DISTRIBUTOR="Arch"
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX=""
# Preload both GPT and MBR modules so that they are not missed
GRUB_PRELOAD_MODULES="part_gpt part_msdos"
# Uncomment to enable Hidden Menu, and optionally hide the timeout count
#GRUB_HIDDEN_TIMEOUT=5
#GRUB_HIDDEN_TIMEOUT_QUIET=true
# Uncomment to use basic console
GRUB_SERIAL_COMMAND="serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1"
GRUB_TERMINAL="console serial"
GRUB_VIDEO_BACKEND=vga
# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=auto
# Uncomment to allow the kernel use the same resolution used by grub
#GRUB_GFXPAYLOAD_LINUX=keep
# Uncomment if you want GRUB to pass to the Linux kernel the old parameter
# format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx"
#GRUB_DISABLE_LINUX_UUID=true
# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY=true
# Uncomment and set to the desired menu colors. Used by normal and wallpaper
# modes only. Entries specified as foreground/background.
#GRUB_COLOR_NORMAL="light-blue/black"
#GRUB_COLOR_HIGHLIGHT="light-cyan/blue"
# Uncomment one of them for the gfx desired, a image background or a gfxtheme
#GRUB_BACKGROUND="/path/to/wallpaper"
#GRUB_THEME="/path/to/gfxtheme"
# Uncomment to get a beep at GRUB start
#GRUB_INIT_TUNE="480 440 1"
#GRUB_SAVEDEFAULT="true"
GRUB_DISABLE_SUBMENU=y
Then, here is patch for /etc/grub.d directory to generate sequentional hotkeys for each menu entry:
diff -ru /etc/grub.d/10_linux /home/dimich/vbox/grub/grub.d/10_linux
--- /etc/grub.d/10_linux 2015-12-15 17:36:16.000000000 +0200
+++ /home/dimich/vbox/grub/grub.d/10_linux 2016-06-26 07:27:09.000000000 +0300
@@ -98,9 +98,11 @@
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
fi
- echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
+ echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/"
else
- echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
+ echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/"
fi
if [ x$type != xrecovery ] ; then
save_default_entry | grub_add_tab
diff -ru /etc/grub.d/20_linux_xen /home/dimich/vbox/grub/grub.d/20_linux_xen
--- /etc/grub.d/20_linux_xen 2015-12-15 17:36:16.000000000 +0200
+++ /home/dimich/vbox/grub/grub.d/20_linux_xen 2016-06-26 07:27:33.000000000 +0300
@@ -98,10 +98,12 @@
title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
fi
- echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
+ echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-$version-$type-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/"
else
title="$(gettext_printf "%s, with Xen hypervisor" "${os}")"
- echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
+ echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/"
fi
if [ x$type != xrecovery ] ; then
save_default_entry | grub_add_tab | sed "s/^/$submenu_indentation/"
diff -ru /etc/grub.d/30_os-prober /home/dimich/vbox/grub/grub.d/30_os-prober
--- /etc/grub.d/30_os-prober 2015-12-15 17:36:16.000000000 +0200
+++ /home/dimich/vbox/grub/grub.d/30_os-prober 2016-06-26 07:28:29.000000000 +0300
@@ -51,8 +51,9 @@
fi
# TRANSLATORS: it refers on the OS residing on device %s
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
-menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' {
+menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | grub_add_tab
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
@@ -140,8 +141,9 @@
chain)
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
-menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' {
+menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | grub_add_tab
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
@@ -228,8 +230,9 @@
fi
if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
-menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' {
+menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | grub_add_tab
printf '%s\n' "${prepare_boot_cache}"
@@ -248,8 +251,9 @@
is_top_level=false
fi
title="${LLABEL} $onstr"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
- menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {
+ menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"
printf '%s\n' "${prepare_boot_cache}" | grub_add_tab
@@ -283,8 +287,9 @@
;;
hurd)
onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
-menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' {
+menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | grub_add_tab
prepare_grub_to_access_device ${DEVICE} | grub_add_tab
@@ -308,8 +313,9 @@
EOF
;;
minix)
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
-menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" {
+menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" --hotkey=${MENUENTRY_HOTKEY} {
EOF
save_default_entry | sed -e "s/^/\t/"
prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/"
diff -ru /etc/grub.d/60_memtest86+ /home/dimich/vbox/grub/grub.d/60_memtest86+
--- /etc/grub.d/60_memtest86+ 2015-12-15 17:36:21.000000000 +0200
+++ /home/dimich/vbox/grub/grub.d/60_memtest86+ 2016-06-26 07:28:53.000000000 +0300
@@ -21,9 +21,10 @@
_GRUB_MEMTEST_HINTS_STRING="$(${grub_probe} --target=hints_string ${MEMTEST86_IMAGE})"
_GRUB_MEMTEST_FS_UUID="$(${grub_probe} --target=fs_uuid ${MEMTEST86_IMAGE})"
_GRUB_MEMTEST_REL_PATH="$(make_system_path_relative_to_its_root ${MEMTEST86_IMAGE})"
+ MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1)
cat << EOF
if [ "\${grub_platform}" == "pc" ]; then
- menuentry "Memory Tester (memtest86+)" ${CLASS} {
+ menuentry "Memory Tester (memtest86+)" ${CLASS} --hotkey=${MENUENTRY_HOTKEY} {
search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
}
And the last thing: program for AVR:
#include <avr/io.h>
#include <util/delay.h>
#define BAUDRATE 9600
static char uart_getc(void) {
while ((UCSRA & (1<<RXC)) == 0);
return UDR;
}
static void uart_putc(char c) {
while ((UCSRA & (1<<UDRE)) == 0);
UDR = c;
}
static void uart_init(void) {
UBRRH = (F_CPU/(16L*BAUDRATE)-1) >> 8;
UBRRL = (F_CPU/(16L*BAUDRATE)-1) & 0xFF;
UCSRC = 3<<UCSZ0;
UCSRB = (1<<RXEN) | (1<<TXEN);
}
static int get_switch_state(void) {
return PINB & 0b00000011;
}
static int wait_for_str(const char *s) {
const char *p = s;
char c;
while (*p != '\0') {
c = uart_getc();
if (c == *p) {
++p;
} else {
p = s;
if (c == *p) {
++p;
}
}
}
return 0;
}
int main(void) {
PORTB |= 0b00000011;
uart_init();
for (;;) {
wait_for_str("GNU GRUB");
_delay_ms(2000);
switch (get_switch_state()) {
case 2:
uart_putc('1');
break;
case 1:
uart_putc('2');
break;
default:
break;
}
}
return 0;
}
If PB0 only is connected to ground then grub boots first menu entry, if PB1 only is connected to ground then second menu entry is booted. Grub waits for user input in all other states of PB0/PB1.
Last edited by dimich (2016-07-06 13:59:21)
Offline
Well, i had some free time and implemented something close to your design. For testing i used VirtualBox with host device serial port and ATtiny2313 as hardware.
First of all, setup grub to use serial port as console. This is my grub.conf:
GRUB_DEFAULT=0 GRUB_TIMEOUT=-1 GRUB_DISTRIBUTOR="Arch" GRUB_CMDLINE_LINUX_DEFAULT="" GRUB_CMDLINE_LINUX="" # Preload both GPT and MBR modules so that they are not missed GRUB_PRELOAD_MODULES="part_gpt part_msdos" # Uncomment to enable Hidden Menu, and optionally hide the timeout count #GRUB_HIDDEN_TIMEOUT=5 #GRUB_HIDDEN_TIMEOUT_QUIET=true # Uncomment to use basic console GRUB_SERIAL_COMMAND="serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1" GRUB_TERMINAL="console serial" GRUB_VIDEO_BACKEND=vga # The resolution used on graphical terminal # note that you can use only modes which your graphic card supports via VBE # you can see them in real GRUB with the command `vbeinfo' #GRUB_GFXMODE=auto # Uncomment to allow the kernel use the same resolution used by grub #GRUB_GFXPAYLOAD_LINUX=keep # Uncomment if you want GRUB to pass to the Linux kernel the old parameter # format "root=/dev/xxx" instead of "root=/dev/disk/by-uuid/xxx" #GRUB_DISABLE_LINUX_UUID=true # Uncomment to disable generation of recovery mode menu entries #GRUB_DISABLE_RECOVERY=true # Uncomment and set to the desired menu colors. Used by normal and wallpaper # modes only. Entries specified as foreground/background. #GRUB_COLOR_NORMAL="light-blue/black" #GRUB_COLOR_HIGHLIGHT="light-cyan/blue" # Uncomment one of them for the gfx desired, a image background or a gfxtheme #GRUB_BACKGROUND="/path/to/wallpaper" #GRUB_THEME="/path/to/gfxtheme" # Uncomment to get a beep at GRUB start #GRUB_INIT_TUNE="480 440 1" #GRUB_SAVEDEFAULT="true" GRUB_DISABLE_SUBMENU=y
Then, here is patch for /etc/grub.d directory to generate sequentional hotkeys for each menu entry:
diff -ru /etc/grub.d/10_linux /home/dimich/vbox/grub/grub.d/10_linux --- /etc/grub.d/10_linux 2015-12-15 17:36:16.000000000 +0200 +++ /home/dimich/vbox/grub/grub.d/10_linux 2016-06-26 07:27:09.000000000 +0300 @@ -98,9 +98,11 @@ title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" fi - echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/" else - echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) + echo "menuentry '$(echo "$os" | grub_quote)' ${CLASS} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/" fi if [ x$type != xrecovery ] ; then save_default_entry | grub_add_tab diff -ru /etc/grub.d/20_linux_xen /home/dimich/vbox/grub/grub.d/20_linux_xen --- /etc/grub.d/20_linux_xen 2015-12-15 17:36:16.000000000 +0200 +++ /home/dimich/vbox/grub/grub.d/20_linux_xen 2016-06-26 07:27:33.000000000 +0300 @@ -98,10 +98,12 @@ title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" fi - echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-$version-$type-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/" else title="$(gettext_printf "%s, with Xen hypervisor" "${os}")" - echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) + echo "menuentry '$(echo "$title" | grub_quote)' ${CLASS} \$menuentry_id_option 'xen-gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} {" | sed "s/^/$submenu_indentation/" fi if [ x$type != xrecovery ] ; then save_default_entry | grub_add_tab | sed "s/^/$submenu_indentation/" diff -ru /etc/grub.d/30_os-prober /home/dimich/vbox/grub/grub.d/30_os-prober --- /etc/grub.d/30_os-prober 2015-12-15 17:36:16.000000000 +0200 +++ /home/dimich/vbox/grub/grub.d/30_os-prober 2016-06-26 07:28:29.000000000 +0300 @@ -51,8 +51,9 @@ fi # TRANSLATORS: it refers on the OS residing on device %s onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF -menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' { +menuentry '$(echo "${LONGNAME} $bitstr $onstr" | grub_quote)' --class osx --class darwin --class os \$menuentry_id_option 'osprober-xnu-$2-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | grub_add_tab prepare_grub_to_access_device ${DEVICE} | grub_add_tab @@ -140,8 +141,9 @@ chain) onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF -menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' { +menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-chain-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | grub_add_tab prepare_grub_to_access_device ${DEVICE} | grub_add_tab @@ -228,8 +230,9 @@ fi if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF -menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' { +menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | grub_add_tab printf '%s\n' "${prepare_boot_cache}" @@ -248,8 +251,9 @@ is_top_level=false fi title="${LLABEL} $onstr" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF - menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' { + menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | sed -e "s/^/$grub_tab$grub_tab/" printf '%s\n' "${prepare_boot_cache}" | grub_add_tab @@ -283,8 +287,9 @@ ;; hurd) onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF -menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' { +menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class hurd --class gnu --class os \$menuentry_id_option 'osprober-gnuhurd-/boot/gnumach.gz-false-$(grub_get_device_id "${DEVICE}")' --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | grub_add_tab prepare_grub_to_access_device ${DEVICE} | grub_add_tab @@ -308,8 +313,9 @@ EOF ;; minix) + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF -menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" { +menuentry "${LONGNAME} (on ${DEVICE}, Multiboot)" --hotkey=${MENUENTRY_HOTKEY} { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" diff -ru /etc/grub.d/60_memtest86+ /home/dimich/vbox/grub/grub.d/60_memtest86+ --- /etc/grub.d/60_memtest86+ 2015-12-15 17:36:21.000000000 +0200 +++ /home/dimich/vbox/grub/grub.d/60_memtest86+ 2016-06-26 07:28:53.000000000 +0300 @@ -21,9 +21,10 @@ _GRUB_MEMTEST_HINTS_STRING="$(${grub_probe} --target=hints_string ${MEMTEST86_IMAGE})" _GRUB_MEMTEST_FS_UUID="$(${grub_probe} --target=fs_uuid ${MEMTEST86_IMAGE})" _GRUB_MEMTEST_REL_PATH="$(make_system_path_relative_to_its_root ${MEMTEST86_IMAGE})" + MENUENTRY_HOTKEY=$(expr ${MENUENTRY_HOTKEY} + 1) cat << EOF if [ "\${grub_platform}" == "pc" ]; then - menuentry "Memory Tester (memtest86+)" ${CLASS} { + menuentry "Memory Tester (memtest86+)" ${CLASS} --hotkey=${MENUENTRY_HOTKEY} { search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID} linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86} }
And the last thing: program for AVR:
#include <avr/io.h> #include <util/delay.h> #define BAUDRATE 9600 static char uart_getc(void) { while ((UCSRA & (1<<RXC)) == 0); return UDR; } static void uart_putc(char c) { while ((UCSRA & (1<<UDRE)) == 0); UDR = c; } static void uart_init(void) { UBRRH = (F_CPU/(16L*BAUDRATE)-1) >> 8; UBRRL = (F_CPU/(16L*BAUDRATE)-1) & 0xFF; UCSRC = 3<<UCSZ0; UCSRB = (1<<RXEN) | (1<<TXEN); } static int get_switch_state(void) { return PINB & 0b00000011; } static int wait_for_str(const char *s) { const char *p = s; char c; while (*p != '\0') { c = uart_getc(); if (c == *p) { ++p; } else { p = s; if (c == *p) { ++p; } } } return 0; } int main(void) { PORTB |= 0b00000011; uart_init(); for (;;) { wait_for_str("GNU GRUB"); _delay_ms(2000); switch (get_switch_state()) { case 2: uart_putc('1'); break; case 1: uart_putc('2'); break; default: break; } } return 0; }
If PB0 only is connected to ground then grub boots first menu entry, if PB1 only is connected to ground then second menu entry is booted. Grub waits for user input in all other states of PB0/PB1.
Thanks, I'm not programmer so I was strugglin a bit with the scripting.
Offline
I did something but a little bit more tricky and less expert.
I used no programming, no arduino, nothing. Only a physical switch and a usb key.
I have a dual boot, Windows on a ssd, Linux on a hdd. The boot priority is 'USB' > 'SSD' > 'Other'.
On the ssd there is the windows boot.
On the usb key there is grub installed, with first choice on Linux, and timeout set to 0. This usb key is connected to the switch and the motherboard.
Result : If i turn on the switch it boot on Linux, if i turn off the switch it boot Windows.
You could imagine something with an other usb key and a 3 states switch to do exactly what you want.
Offline
All genius things are simple
Offline
Pages: 1