[SLOF] [PATCH 3/4] bootmenu: Implement keyboard handling and boot menu selection
Nikunj A Dadhania
nikunj at linux.vnet.ibm.com
Mon Jun 5 15:42:17 AEST 2017
Thomas Huth <thuth at redhat.com> writes:
> 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;
With this we can have 1-9, a-z and A-Z, 10 + 26 + 26 = 62 selection.
Though displaying them on one screen is difficult. MAX_DEVS is set to 36
though.
> + 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