[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