[Concept,21/22] efi: Move key decoding into a shared file

Message ID 20250925174753.3429102-22-sjg@u-boot.org
State New
Headers
Series efi: Tidy up some commands and provide a keyboard driver |

Commit Message

Simon Glass Sept. 25, 2025, 5:47 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Create a new file in lib/efi to handle conversion of keys from EFI
format to characters, so we can use it from multiple places. Update the
serial_efi driver accordingly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/serial/serial_efi.c | 15 +-------------
 include/efi.h               | 32 +++++++++++++++++++++++++++++
 lib/efi/Makefile            |  1 +
 lib/efi/input.c             | 40 +++++++++++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+), 14 deletions(-)
 create mode 100644 lib/efi/input.c
  

Patch

diff --git a/drivers/serial/serial_efi.c b/drivers/serial/serial_efi.c
index b506bb18ffb..6645520e2ca 100644
--- a/drivers/serial/serial_efi.c
+++ b/drivers/serial/serial_efi.c
@@ -73,7 +73,6 @@  static int serial_efi_get_key(struct serial_efi_priv *priv)
 static int serial_efi_getc(struct udevice *dev)
 {
 	struct serial_efi_priv *priv = dev_get_priv(dev);
-	char conv_scan[10] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
 	int ret, ch;
 
 	ret = serial_efi_get_key(priv);
@@ -81,19 +80,7 @@  static int serial_efi_getc(struct udevice *dev)
 		return ret;
 
 	priv->have_key = false;
-	ch = priv->key.unicode_char;
-
-	/*
-	 * Unicode char 8 (for backspace) is never returned. Instead we get a
-	 * key scan code of 8. Handle this so that backspace works correctly
-	 * in the U-Boot command line.
-	 */
-	if (!ch && priv->key.scan_code < sizeof(conv_scan)) {
-		ch = conv_scan[priv->key.scan_code];
-		if (ch >= 'a')
-			ch -= 'a' - 1;
-	}
-	debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
+	ch = efi_decode_key(&priv->key);
 
 	return ch;
 }
diff --git a/include/efi.h b/include/efi.h
index 52f3a014f1d..3d983bd69a4 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -24,6 +24,8 @@ 
 #endif
 
 struct abuf;
+struct efi_input_key;
+struct efi_key_data;
 struct udevice;
 
 /* Type INTN in UEFI specification */
@@ -912,4 +914,34 @@  int efi_read_var(const u16 *name, const efi_guid_t *guid, u32 *attrp,
 
 uint16_t *efi_dp_str(struct efi_device_path *dp);
 
+/**
+ * efi_decode_key() - Convert EFI input key to character
+ *
+ * Converts an EFI input key structure to a character code, handling
+ * both unicode characters and scan codes for special keys like arrow keys
+ * and backspace.
+ *
+ * Unicode characters are returned as-is, with the exception that carriage
+ * return ('\r') is converted to newline ('\n') for consistency with U-Boot
+ * conventions.
+ *
+ * @key: Pointer to EFI input key structure
+ * Return: Character code (0-255), or 0 if no valid character
+ */
+int efi_decode_key(struct efi_input_key *key);
+
+/**
+ * efi_decode_key_ex() - Convert EFI extended input key to character
+ *
+ * Converts an EFI extended key data structure to a character code by
+ * extracting the basic input key and calling efi_decode_key().
+ *
+ * This function provides a convenient wrapper for handling EFI Simple Text
+ * Input EX Protocol key data, which includes modifier keys (currently ignored)
+ *
+ * @key_data: Pointer to EFI extended key data structure
+ * Return: Character code (0-255), or 0 if no valid character
+ */
+int efi_decode_key_ex(struct efi_key_data *key_data);
+
 #endif /* _LINUX_EFI_H */
diff --git a/lib/efi/Makefile b/lib/efi/Makefile
index 842067dcab3..c2e56df7144 100644
--- a/lib/efi/Makefile
+++ b/lib/efi/Makefile
@@ -6,6 +6,7 @@ 
 obj-y += basename.o
 obj-y += device_path.o
 obj-y += helper.o
+obj-y += input.o
 obj-y += load_options.o
 obj-y += memory.o
 obj-y += run.o
diff --git a/lib/efi/input.c b/lib/efi/input.c
new file mode 100644
index 00000000000..4d6b81bf183
--- /dev/null
+++ b/lib/efi/input.c
@@ -0,0 +1,40 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * EFI input key decoding functions
+ *
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY	LOGC_EFI
+
+#include <efi.h>
+#include <efi_api.h>
+#include <cli.h>
+
+int efi_decode_key(struct efi_input_key *key)
+{
+	static const char conv_scan[] = {0, 'p', 'n', 'f', 'b', 'a', 'e', 0, 8};
+	int ch;
+
+	ch = key->unicode_char;
+
+	/*
+	 * Unicode char 8 (for backspace) is never returned. Instead we get a
+	 * key scan code of 8. Handle this so that backspace works correctly
+	 * in the U-Boot command line.
+	 */
+	if (!ch && key->scan_code < sizeof(conv_scan)) {
+		ch = conv_scan[key->scan_code];
+		if (ch >= 'a')
+			ch -= 'a' - 1;
+	}
+	log_debug(" [%x %x %x] ", ch, key->unicode_char, key->scan_code);
+
+	return ch;
+}
+
+int efi_decode_key_ex(struct efi_key_data *key_data)
+{
+	return efi_decode_key(&key_data->key);
+}