[U-Boot] [PATCH 5/6] efi_loader: rework event handling for console
Heinrich Schuchardt
xypron.glpk at gmx.de
Sun Sep 9 05:57:03 UTC 2018
Preread the next key in the console timer event.
The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL requires to trigger registered key
notification functions based on the prefetched key.
Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
lib/efi_loader/efi_console.c | 204 ++++++++++++++++++++++++++---------
1 file changed, 153 insertions(+), 51 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 8c45290b2e..1dbf73afc2 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -396,34 +396,12 @@ struct efi_simple_text_output_protocol efi_con_out = {
.mode = (void*)&efi_con_mode,
};
-static void efi_set_keymap(void)
-{
- char *penv;
-
- /* Init keyboard device (default US layout) */
- keymap = KBD_US;
- penv = env_get("keymap");
- if (penv) {
- if (strncmp(penv, "de", 3) == 0)
- keymap = KBD_GER;
- }
-}
-
-static efi_status_t EFIAPI efi_cin_reset(
- struct efi_simple_text_input_protocol *this,
- bool extended_verification)
-{
- EFI_ENTRY("%p, %d", this, extended_verification);
-
- /* Empty input buffer */
- while (tstc())
- getc();
-
- return EFI_EXIT(EFI_SUCCESS);
-}
+static bool key_available;
+static struct efi_input_key next_key;
-/*
- * Analyze modifiers (shift, alt, ctrl) for function keys.
+/**
+ * skip_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
+ *
* This gets called when we have already parsed CSI.
*
* @modifiers: bitmask (shift, alt, ctrl)
@@ -464,9 +442,13 @@ out:
return ret;
}
-static efi_status_t EFIAPI efi_cin_read_key_stroke(
- struct efi_simple_text_input_protocol *this,
- struct efi_input_key *key)
+/**
+ * efi_cin_read_key() - read a key from the console input
+ *
+ * @key: - key received
+ * Return: - status code
+ */
+static efi_status_t efi_cin_read_key(struct efi_input_key *key)
{
struct efi_input_key pressed_key = {
.scan_code = 0,
@@ -474,11 +456,6 @@ static efi_status_t EFIAPI efi_cin_read_key_stroke(
};
int ch;
- EFI_ENTRY("%p, %p", this, key);
-
- /* We don't do interrupts, so check for timers cooperatively */
- efi_timer_check();
-
if (!tstc())
/* No key pressed */
goto error;
@@ -622,9 +599,127 @@ static efi_status_t EFIAPI efi_cin_read_key_stroke(
pressed_key.unicode_char = ch;
*key = pressed_key;
- return EFI_EXIT(EFI_SUCCESS);
+ return EFI_SUCCESS;
error:
- return EFI_EXIT(EFI_NOT_READY);
+ return EFI_NOT_READY;
+}
+
+/**
+ * efi_cin_check() - check if keyboard input is available
+ */
+static void efi_cin_check(void)
+{
+ efi_status_t ret;
+
+ if (key_available) {
+ efi_signal_event(efi_con_in.wait_for_key, true);
+ return;
+ }
+
+ if (tstc()) {
+ ret = efi_cin_read_key(&next_key);
+ if (ret == EFI_SUCCESS) {
+ key_available = true;
+
+ /* Queue the wait for key event */
+ efi_signal_event(efi_con_in.wait_for_key, true);
+ }
+ }
+}
+
+/**
+ * efi_set_keymap() - determine the keyboard layout
+ */
+static void efi_set_keymap(void)
+{
+ char *penv;
+
+ /* Init keyboard device (default US layout) */
+ keymap = KBD_US;
+ penv = env_get("keymap");
+ if (penv) {
+ if (strncmp(penv, "de", 3) == 0)
+ keymap = KBD_GER;
+ }
+}
+
+/**
+ * efi_cin_reset() - drain the input buffer
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @extended_verification: allow for exhaustive verification
+ * Return: status code
+ *
+ * This function implements the Reset service of the
+ * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_reset(
+ struct efi_simple_text_input_protocol *this,
+ bool extended_verification)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %d", this, extended_verification);
+
+ /* Check parameters */
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Empty input buffer */
+ while (tstc())
+ getc();
+ key_available = false;
+out:
+ return EFI_EXIT(ret);
+}
+
+/**
+ * efi_cin_reset() - drain the input buffer
+ *
+ * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ * @key: key read from console
+ * Return: status code
+ *
+ * This function implements the ReadKeyStroke service of the
+ * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ */
+static efi_status_t EFIAPI efi_cin_read_key_stroke(
+ struct efi_simple_text_input_protocol *this,
+ struct efi_input_key *key)
+{
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %p", this, key);
+
+ /* Check parameters */
+ if (!this || !key) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* We don't do interrupts, so check for timers cooperatively */
+ efi_timer_check();
+
+ /* Enable console input after ExitBootServices */
+ efi_cin_check();
+
+ if (!key_available) {
+ ret = EFI_NOT_READY;
+ goto out;
+ }
+ *key = next_key;
+ key_available = false;
+ efi_con_in.wait_for_key->is_signaled = false;
+out:
+ return EFI_EXIT(ret);
}
struct efi_simple_text_input_protocol efi_con_in = {
@@ -635,31 +730,38 @@ struct efi_simple_text_input_protocol efi_con_in = {
static struct efi_event *console_timer_event;
-static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
-{
-}
-
/*
- * Notification function of the console timer event.
+ * efi_console_timer_notify() - notify the console timer event
*
- * event: console timer event
- * context: not used
+ * @event: console timer event
+ * @context: not used
*/
static void EFIAPI efi_console_timer_notify(struct efi_event *event,
void *context)
{
EFI_ENTRY("%p, %p", event, context);
+ efi_cin_check();
+ EFI_EXIT(EFI_SUCCESS);
+}
- /* Check if input is available */
- if (tstc()) {
- /* Queue the wait for key event */
- efi_con_in.wait_for_key->is_signaled = true;
- efi_signal_event(efi_con_in.wait_for_key, true);
- }
+/**
+ * efi_key_notify() - notify the wait for key event
+ *
+ * @event: wait for key event
+ * @context: not used
+ */
+static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
+{
+ EFI_ENTRY("%p, %p", event, context);
+ efi_cin_check();
EFI_EXIT(EFI_SUCCESS);
}
-/* This gets called from do_bootefi_exec(). */
+/**
+ * efi_console_register() - install the console protocols
+ *
+ * This function is called from do_bootefi_exec().
+ */
int efi_console_register(void)
{
efi_status_t r;
--
2.18.0
More information about the U-Boot
mailing list