[SLOF] [PATCH 3/4] bootmenu: Implement keyboard handling and boot menu selection

Thomas Huth thuth at redhat.com
Fri Jun 2 01:25:41 AEST 2017


Wait for a key and return the selected boot device on the Forth stack.

Signed-off-by: Thomas Huth <thuth at redhat.com>
---
 lib/libbootmenu/bootmenu.c    | 74 +++++++++++++++++++++++++++++++++++++++++++
 lib/libbootmenu/bootmenu.code |  2 +-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/lib/libbootmenu/bootmenu.c b/lib/libbootmenu/bootmenu.c
index 649e518..979cdc4 100644
--- a/lib/libbootmenu/bootmenu.c
+++ b/lib/libbootmenu/bootmenu.c
@@ -12,10 +12,12 @@
  *     Thomas Huth, Red Hat Inc. - initial implementation
  *****************************************************************************/
 
+#include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <paflof.h>
+#include <helpers.h>
 #include "bootmenu.h"
 
 #define MAX_DEVS 36        /* Enough for 10 digits + 26 letters */
@@ -93,15 +95,87 @@ static void bootmenu_show_devs(void)
 	}
 }
 
+static bool has_key(void)
+{
+	forth_eval("key?");
+	return forth_pop();
+}
+
+static char get_key(void)
+{
+	forth_eval("key");
+	return forth_pop();
+}
+
+/* Flush pending key presses */
+static void flush_keys(void)
+{
+	uint32_t start;
+
+	start = SLOF_GetTimer();
+	while (SLOF_GetTimer() - start < 10) {
+		if (has_key()) {
+			get_key();
+			start = SLOF_GetTimer();
+		}
+	}
+}
+
+static int bootmenu_get_selection(void)
+{
+	char key = 0;
+	int sel;
+
+	do {
+		sel = -1;
+		if (!has_key())
+			continue;
+		key = get_key();
+		switch (key) {
+		case '0':
+			return -1;
+		case '1' ... '9':
+			sel = key - '1';
+			break;
+		case 'a' ... 'z':
+			sel = key - 'a' + 9;
+			break;
+		case 'A' ... 'Z':
+			sel = key - 'A' + 9;
+			break;
+		default:
+			/* Might be another escape code (F12) ... skip it */
+			flush_keys();
+			break;
+		}
+	} while (sel < 0 || sel >= nr_devs);
+
+	return sel;
+}
+
 void bootmenu(void)
 {
+	int sel;
+
 	bootmenu_populate_devs();
 	if (!nr_devs) {
 		puts("No available boot devices!");
 		return;
 	}
 
+	puts("\nSelect boot device (or press '0' to abort):");
 	bootmenu_show_devs();
 
+	if (has_key())		/* In case the user hammered on F12 */
+		flush_keys();
+
+	sel = bootmenu_get_selection();
+	if (sel < 0) {
+		forth_push(0);
+	} else {
+		forth_push((unsigned long)bootdevs[sel].alias);
+		forth_push(strlen(bootdevs[sel].alias));
+	}
+
 	bootmenu_free_devs();
 }
diff --git a/lib/libbootmenu/bootmenu.code b/lib/libbootmenu/bootmenu.code
index f51784d..2a55c09 100644
--- a/lib/libbootmenu/bootmenu.code
+++ b/lib/libbootmenu/bootmenu.code
@@ -14,7 +14,7 @@
 
 #include "bootmenu.h"
 
-// ( -- )
+// ( -- [str] len|0 )
 PRIM(boot_X2d_menu)
 	bootmenu();
 MIRP
-- 
1.8.3.1



More information about the SLOF mailing list