All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Graf <agraf@suse.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/6] efi_loader: support Unicode text input
Date: Mon, 10 Sep 2018 12:05:35 +0200	[thread overview]
Message-ID: <f3f48ad2-5ff0-a1d0-f112-d03aa86c498e@suse.de> (raw)
In-Reply-To: <20180909055704.1994-3-xypron.glpk@gmx.de>

On 09/09/2018 07:57 AM, Heinrich Schuchardt wrote:
> 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@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;

I'm not terribly happy with this. It's very i8042 specific. Currently 
U-Boot only implements the keymap variable there. Couldn't we add an 
extended getc() that reads a full 32bit unicode value from the target 
device? That way we could add an interim layer that everyone - not just 
efi_loader - can use to extract keycodes coherently from any input.

> +	}
> +}
> +
>   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;

All of the logic above for example really shouldn't live inside of 
efi_loader. It belongs somewhere more generic.


Alex

> +	} 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();
>   

  reply	other threads:[~2018-09-10 10:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-09  5:56 [U-Boot] [PATCH 0/6] efi_loader: fixes for EFI_SIMPLE_TEXT_INPUT_PROTOCOL Heinrich Schuchardt
2018-09-09  5:56 ` [U-Boot] [PATCH 1/6] efi_loader: global symbol for code page 437 Heinrich Schuchardt
2018-09-09  5:57 ` [U-Boot] [PATCH 2/6] efi_loader: support Unicode text input Heinrich Schuchardt
2018-09-10 10:05   ` Alexander Graf [this message]
2018-09-10 13:01     ` Alexander Graf
2018-09-09  5:57 ` [U-Boot] [PATCH 3/6] test/py: Unicode w/ EFI_SIMPLE_TEXT_INPUT_PROTOCOL Heinrich Schuchardt
2018-09-09  5:57 ` [U-Boot] [PATCH 4/6] efi_selftest: refactor text input test Heinrich Schuchardt
2018-09-09  5:57 ` [U-Boot] [PATCH 5/6] efi_loader: rework event handling for console Heinrich Schuchardt
2018-09-09  5:57 ` [U-Boot] [PATCH 6/6] efi_selftest: use WaitForKey to test text input Heinrich Schuchardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f3f48ad2-5ff0-a1d0-f112-d03aa86c498e@suse.de \
    --to=agraf@suse.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.