diff mbox

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

Message ID 1496330742-18181-4-git-send-email-thuth@redhat.com
State Superseded
Headers show

Commit Message

Thomas Huth June 1, 2017, 3:25 p.m. UTC
Wait for a key and return the selected boot device on the Forth stack.

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

Comments

Nikunj A Dadhania June 5, 2017, 5:42 a.m. UTC | #1
Thomas Huth <thuth@redhat.com> writes:

> Wait for a key and return the selected boot device on the Forth stack.
>
> Signed-off-by: Thomas Huth <thuth@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
Thomas Huth June 5, 2017, 5:54 a.m. UTC | #2
On 05.06.2017 07:42, Nikunj A Dadhania wrote:
> Thomas Huth <thuth@redhat.com> writes:
> 
>> Wait for a key and return the selected boot device on the Forth stack.
>>
>> Signed-off-by: Thomas Huth <thuth@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.

Right, currently I treat the letters case-insensitive. We could increase
MAX_DEVS to 62 by treating the letters case-sensitive instead ...
question is, do we want that, or are 36 possible boot devices enough
(since 62 hardly fit on a screen anyway, as you noted)?

 Thomas
Nikunj A Dadhania June 5, 2017, 6:01 a.m. UTC | #3
Thomas Huth <thuth@redhat.com> writes:

> On 05.06.2017 07:42, Nikunj A Dadhania wrote:
>> Thomas Huth <thuth@redhat.com> writes:
>> 
>>> Wait for a key and return the selected boot device on the Forth stack.
>>>
>>> Signed-off-by: Thomas Huth <thuth@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.
>
> Right, currently I treat the letters case-insensitive.

Ah, i missed that part.

> We could increase MAX_DEVS to 62 by treating the letters
> case-sensitive instead ... question is, do we want that, or are 36
> possible boot devices enough (since 62 hardly fit on a screen anyway,
> as you noted)?

36 should be good enough.

Regards,
Nikunj
Alexey Kardashevskiy June 6, 2017, 9:20 a.m. UTC | #4
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@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
>
diff mbox

Patch

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