[U-Boot] [PATCH 2/6] efi_loader: support Unicode text input
Heinrich Schuchardt
xypron.glpk at gmx.de
Sun Sep 9 05:57:00 UTC 2018
Up to now the EFI_TEXT_INPUT_PROTOCOL only supported ASCII characters.
With the patch it can consume UTF-8 from the serial console or
codepage 437 special characters from the local keyboard.
Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
lib/efi_loader/efi_console.c | 80 ++++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 4 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 3ca6fe536c..8c45290b2e 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -15,12 +15,18 @@
#define EFI_COUT_MODE_2 2
#define EFI_MAX_COUT_MODE 3
+/* Keyboard layouts */
+#define KBD_US 0 /* default US layout */
+#define KBD_GER 1 /* German layout */
+
struct cout_mode {
unsigned long columns;
unsigned long rows;
int present;
};
+static int keymap = KBD_US;
+
static struct cout_mode efi_cout_modes[] = {
/* EFI Mode 0 is 80x25 and always present */
{
@@ -390,6 +396,19 @@ 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)
@@ -453,17 +472,16 @@ static efi_status_t EFIAPI efi_cin_read_key_stroke(
.scan_code = 0,
.unicode_char = 0,
};
- char ch;
+ int ch;
EFI_ENTRY("%p, %p", this, key);
/* We don't do interrupts, so check for timers cooperatively */
efi_timer_check();
- if (!tstc()) {
+ if (!tstc())
/* No key pressed */
- return EFI_EXIT(EFI_NOT_READY);
- }
+ goto error;
ch = getc();
if (ch == cESC) {
@@ -550,12 +568,63 @@ static efi_status_t EFIAPI efi_cin_read_key_stroke(
} else if (ch == 0x7f) {
/* Backspace */
ch = 0x08;
+ } else if (keymap == KBD_US && ch >= 0xc2 && ch <= 0xf4) {
+ /*
+ * Unicode
+ *
+ * We assume here that the serial console is using UTF-8.
+ * This of cause depends on the terminal settings.
+ */
+ int code = 0;
+
+ if (ch >= 0xe0) {
+ if (ch >= 0xf0) {
+ /* 0xf0 - 0xf4 */
+ ch &= 0x07;
+ code = ch << 18;
+ ch = getc();
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ ch &= 0x3f;
+ } else {
+ /* 0xe0 - 0xef */
+ ch &= 0x0f;
+ }
+ code += ch << 12;
+ if ((code >= 0xD800 && code <= 0xDFFF) ||
+ code >= 0x110000)
+ goto error;
+ ch = getc();
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ }
+ /* 0xc0 - 0xdf or continuation byte (0x80 - 0xbf) */
+ ch &= 0x3f;
+ code += ch << 6;
+ ch = getc();
+ if (ch < 0x80 || ch > 0xbf)
+ goto error;
+ ch &= 0x3f;
+ ch += code;
+ } else if (keymap != KBD_US && ch >= 0x80 && ch <= 0xff) {
+ /*
+ * Code page 437 special characters
+ *
+ * The keyboard drivers emit code page 437 characters. Support
+ * for German language special characters can be enabled via
+ * environment variable 'keymap' in the i8042 driver.
+ */
+ ch = codepage_437[ch - 0x80];
+ } else if (ch >= 0x80) {
+ goto error;
}
if (!pressed_key.scan_code)
pressed_key.unicode_char = ch;
*key = pressed_key;
return EFI_EXIT(EFI_SUCCESS);
+error:
+ return EFI_EXIT(EFI_NOT_READY);
}
struct efi_simple_text_input_protocol efi_con_in = {
@@ -597,6 +666,9 @@ int efi_console_register(void)
struct efi_object *efi_console_output_obj;
struct efi_object *efi_console_input_obj;
+ /* Set keymap */
+ efi_set_keymap();
+
/* Set up mode information */
query_console_size();
--
2.18.0
More information about the U-Boot
mailing list