[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