[SeaBIOS] [PATCH] boot: add serial-friendly alternatives for invoking the boot menu

Paolo Bonzini pbonzini at redhat.com
Wed Mar 4 17:57:02 CET 2015


F11 and F12 are trapped by some terminal emulators, and sgabios does
not always recognize function keys very well.

Real-world machines often provide replacements for function keys for
use on the serial console: ESC+1...ESC+0 for F1...F10, ESC+SHIFT+1 and
ESC+SHIFT+2 for F11...F12.  Accept all of them, which can be useful in
case the user has set boot-menu-key.

Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
---
 src/boot.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/src/boot.c b/src/boot.c
index f23e9e1..3f1ea4a 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -422,7 +422,21 @@ get_raw_keystroke(void)
     memset(&br, 0, sizeof(br));
     br.flags = F_IF;
     call16_int(0x16, &br);
-    return br.ah;
+    return br.ax;
+}
+
+// Read a keystroke - waiting up to 'msec' milliseconds.
+static int
+get_keystroke_ascii(int msec)
+{
+    u32 end = irqtimer_calc(msec);
+    for (;;) {
+        if (check_for_keystroke())
+            return get_raw_keystroke() & 255;
+        if (irqtimer_check(end))
+            return -1;
+        yield_toirq();
+    }
 }
 
 // Read a keystroke - waiting up to 'msec' milliseconds.
@@ -432,7 +446,7 @@ get_keystroke(int msec)
     u32 end = irqtimer_calc(msec);
     for (;;) {
         if (check_for_keystroke())
-            return get_raw_keystroke();
+            return get_raw_keystroke() >> 8;
         if (irqtimer_check(end))
             return -1;
         yield_toirq();
@@ -446,6 +460,35 @@ get_keystroke(int msec)
 
 #define DEFAULT_BOOTMENU_WAIT 2500
 
+static int
+get_bootmenu_keystroke(void)
+{
+    u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
+    int scan_code = get_keystroke(menutime);
+    if (scan_code == 0x01) {
+        while (get_keystroke(0) >= 0)
+            ;
+        int ascii = get_keystroke_ascii(menutime * 2);
+        switch (ascii) {
+        case '1' ... '9':
+            scan_code = 0x3a + ascii - '0';
+            break;
+        case '0':
+            scan_code = 0x3a + 10;
+            break;
+        case '!':
+            scan_code = 0x85;
+            break;
+        case '@':
+            scan_code = 0x86;
+            break;
+        default:
+            break;
+        }
+    }
+    return scan_code;
+}
+
 // Show IPL option menu.
 void
 interactive_bootmenu(void)
@@ -460,12 +503,11 @@ interactive_bootmenu(void)
 
     char *bootmsg = romfile_loadfile("etc/boot-menu-message", NULL);
     int menukey = romfile_loadint("etc/boot-menu-key", 0x86);
-    printf("%s", bootmsg ?: "\nPress F12 for boot menu.\n\n");
+    printf("%s", bootmsg ?: "\nPress ESC+@ or F12 for boot menu.\n\n");
     free(bootmsg);
 
-    u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
     enable_bootsplash();
-    int scan_code = get_keystroke(menutime);
+    int scan_code = get_bootmenu_keystroke();
     disable_bootsplash();
     if (scan_code != menukey)
         return;
-- 
2.3.0




More information about the SeaBIOS mailing list