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

Alexey Kardashevskiy aik at ozlabs.ru
Tue Jun 6 19:20:45 AEST 2017


On 02/06/17 01:25, Thomas Huth wrote:
> 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 )

Changing lines which were just added in the very same patchset is not
usually right, 2/4 should have done forth_push(0), at least. Or better just
merge all patches into one as suggested in 2/4.


>  PRIM(boot_X2d_menu)
>  	bootmenu();
>  MIRP
> 


-- 
Alexey


More information about the SLOF mailing list