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(a)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