Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Oct 2019 03:24:28 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r353992 - stable/12/stand/efi/libefi
Message-ID:  <201910240324.x9O3OSLv018878@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Thu Oct 24 03:24:28 2019
New Revision: 353992
URL: https://svnweb.freebsd.org/changeset/base/353992

Log:
  MFC r351695-r351696
  
  r351695:
  loader.efi: some systems do not translate scan code 0x8 to backspace
  
  Add scancode translation for backspace.
  
  r351696:
  loader.efi: use and prefer coninex interface
  
  Add support for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.

Modified:
  stable/12/stand/efi/libefi/efi_console.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/stand/efi/libefi/efi_console.c
==============================================================================
--- stable/12/stand/efi/libefi/efi_console.c	Thu Oct 24 03:21:30 2019	(r353991)
+++ stable/12/stand/efi/libefi/efi_console.c	Thu Oct 24 03:24:28 2019	(r353992)
@@ -32,8 +32,10 @@ __FBSDID("$FreeBSD$");
 
 #include "bootstrap.h"
 
+static EFI_GUID simple_input_ex_guid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
 static SIMPLE_TEXT_OUTPUT_INTERFACE	*conout;
 static SIMPLE_INPUT_INTERFACE		*conin;
+static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *coninex;
 
 #ifdef TERM_EMU
 #define	DEFAULT_FGCOLOR	EFI_LIGHTGRAY
@@ -115,6 +117,8 @@ efi_cons_probe(struct console *cp)
 static int
 efi_cons_init(int arg)
 {
+	EFI_STATUS status;
+
 #ifdef TERM_EMU
 	conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
 	    DEFAULT_BGCOLOR));
@@ -125,7 +129,11 @@ efi_cons_init(int arg)
 	bg_c = DEFAULT_BGCOLOR;
 #endif
 	conout->EnableCursor(conout, TRUE);
-	return 0;
+	status = BS->OpenProtocol(ST->ConsoleInHandle, &simple_input_ex_guid,
+	    (void **)&coninex, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (status != EFI_SUCCESS)
+		coninex = NULL;
+	return (0);
 }
 
 static void
@@ -478,27 +486,30 @@ keybuf_inschar(EFI_INPUT_KEY *key)
 {
 
 	switch (key->ScanCode) {
-	case 0x1: /* UP */
+	case SCAN_UP: /* UP */
 		keybuf[0] = 0x1b;	/* esc */
 		keybuf[1] = '[';
 		keybuf[2] = 'A';
 		break;
-	case 0x2: /* DOWN */
+	case SCAN_DOWN: /* DOWN */
 		keybuf[0] = 0x1b;	/* esc */
 		keybuf[1] = '[';
 		keybuf[2] = 'B';
 		break;
-	case 0x3: /* RIGHT */
+	case SCAN_RIGHT: /* RIGHT */
 		keybuf[0] = 0x1b;	/* esc */
 		keybuf[1] = '[';
 		keybuf[2] = 'C';
 		break;
-	case 0x4: /* LEFT */
+	case SCAN_LEFT: /* LEFT */
 		keybuf[0] = 0x1b;	/* esc */
 		keybuf[1] = '[';
 		keybuf[2] = 'D';
 		break;
-	case 0x17:
+	case SCAN_DELETE:
+		keybuf[0] = CHAR_BACKSPACE;
+		break;
+	case SCAN_ESC:
 		keybuf[0] = 0x1b;	/* esc */
 		break;
 	default:
@@ -521,6 +532,40 @@ efi_readkey(void)
 	return (false);
 }
 
+static bool
+efi_readkey_ex(void)
+{
+	EFI_STATUS status;
+	EFI_INPUT_KEY *kp;
+	EFI_KEY_DATA  key_data;
+	uint32_t kss;
+
+	status = coninex->ReadKeyStrokeEx(coninex, &key_data);
+	if (status == EFI_SUCCESS) {
+		kss = key_data.KeyState.KeyShiftState;
+		kp = &key_data.Key;
+		if (kss & EFI_SHIFT_STATE_VALID) {
+
+			/*
+			 * quick mapping to control chars, replace with
+			 * map lookup later.
+			 */
+			if (kss & EFI_RIGHT_CONTROL_PRESSED ||
+			    kss & EFI_LEFT_CONTROL_PRESSED) {
+				if (kp->UnicodeChar >= 'a' &&
+				    kp->UnicodeChar <= 'z') {
+					kp->UnicodeChar -= 'a';
+					kp->UnicodeChar++;
+				}
+			}
+		}
+
+		keybuf_inschar(kp);
+		return (true);
+	}
+	return (false);
+}
+
 int
 efi_cons_getchar(void)
 {
@@ -531,8 +576,13 @@ efi_cons_getchar(void)
 
 	key_pending = 0;
 
-	if (efi_readkey())
-		return (keybuf_getchar());
+	if (coninex == NULL) {
+		if (efi_readkey())
+			return (keybuf_getchar());
+	} else {
+		if (efi_readkey_ex())
+			return (keybuf_getchar());
+	}
 
 	return (-1);
 }
@@ -540,6 +590,7 @@ efi_cons_getchar(void)
 int
 efi_cons_poll(void)
 {
+	EFI_STATUS status;
 
 	if (keybuf_ischar() || key_pending)
 		return (1);
@@ -549,10 +600,21 @@ efi_cons_poll(void)
 	 * WaitForKey().
 	 * CheckEvent() can clear the signaled state.
 	 */
-	if (conin->WaitForKey == NULL)
-		key_pending = efi_readkey();
-	else
-		key_pending = BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS;
+	if (coninex != NULL) {
+		if (coninex->WaitForKeyEx == NULL) {
+			key_pending = efi_readkey_ex();
+		} else {
+			status = BS->CheckEvent(coninex->WaitForKeyEx);
+			key_pending = status == EFI_SUCCESS;
+		}
+	} else {
+		if (conin->WaitForKey == NULL) {
+			key_pending = efi_readkey();
+		} else {
+			status = BS->CheckEvent(conin->WaitForKey);
+			key_pending = status == EFI_SUCCESS;
+		}
+	}
 
 	return (key_pending);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910240324.x9O3OSLv018878>