Hi Vladimir,

Thanks for the hint, this was obvious now.

Please find attached the new patch which definitely fixes the issue.

It has been tested on various hardware (see git commit details).

In a nutshell the solution is to stick to set 1 if controller is in Translate mode, and use set X otherwise, X being the queried mode.

Additionally, in controller_fini, nothing has to be restored, since nothing was changed. This fixes an issue when switching between at_keyboard, console, and at_keyboard again, in case queried set is not the actual used set.

Renaud.

On 12/11/20 3:08 PM, Vladimir 'phcoder' Serbinenko wrote:
On Fri, Dec 4, 2020 at 5:53 AM Renaud Métrich <rmetr...@redhat.com> wrote:
Hi,

Testing the proposed patch on my old Asus N53SN in Legacy failed: as soon as 
at_keyboard is selected, the keys are corrupted and it's impossible to do 
anything.

Digging into this, it appears that query_mode() returns 2 (so set2 needs to be 
used), but in fact internally the keycode are the ones expected by set1.
This is because the patch doesn't take into account that controller is
in "translate" mode.
@Javier Martinez Canillas : Can you make your patch check whether
KEYBOARD_AT_TRANSLATE is set ?

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel
>From eac16e0623fa99ae5a6642852321cb8f9c74b33d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetr...@redhat.com>
Date: Thu, 3 Dec 2020 09:13:24 +0100
Subject: [PATCH] at_keyboard: use set 1 when keyboard is in Translate mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When keyboard controller acts in Translate mode (0x40 mask), then use
set 1 since translation is done.
Otherwise use the mode queried from the controller (usually set 2).

Added "atkeyb" debugging messages in at_keyboard module as well.

Resolves: rhbz#1897587

Tested on:
- Asus N53SN (set 1 used)
- Dell Precision (set 1 used)
- HP Elitebook (set 2 used)
- HP G5430 (set 1 used, keyboard in XT mode!)
- Lenovo P71 & Lenovo T460s (set 2 used)
- QEMU/KVM (set 1 used)

Signed-off-by: Renaud Métrich <rmetr...@redhat.com>
---
 grub-core/term/at_keyboard.c | 29 ++++++++++++++++++++++++-----
 include/grub/at_keyboard.h   |  4 ++++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
index 597111077..260143826 100644
--- a/grub-core/term/at_keyboard.c
+++ b/grub-core/term/at_keyboard.c
@@ -135,20 +135,28 @@ query_mode (void)
   int e;
 
   e = write_mode (0);
-  if (!e)
+  if (!e) {
+    grub_dprintf("atkeyb", "query_mode: write_mode(0) failed\n");
     return 0;
+  }
 
   do {
     keyboard_controller_wait_until_ready ();
     ret = grub_inb (KEYBOARD_REG_DATA);
   } while (ret == GRUB_AT_ACK);
   /* QEMU translates the set even in no-translate mode.  */
-  if (ret == 0x43 || ret == 1)
+  if (ret == 0x43 || ret == 1) {
+    grub_dprintf("atkeyb", "query_mode: returning 1 (ret=0x%x)\n", ret);
     return 1;
-  if (ret == 0x41 || ret == 2)
+  }
+  if (ret == 0x41 || ret == 2) {
+    grub_dprintf("atkeyb", "query_mode: returning 2 (ret=0x%x)\n", ret);
     return 2;
-  if (ret == 0x3f || ret == 3)
+  }
+  if (ret == 0x3f || ret == 3) {
+    grub_dprintf("atkeyb", "query_mode: returning 3 (ret=0x%x)\n", ret);
     return 3;
+  }
   return 0;
 }
 
@@ -165,7 +173,13 @@ set_scancodes (void)
     }
 
 #if !USE_SCANCODE_SET
-  ps2_state.current_set = 1;
+  if ((grub_keyboard_controller_orig & KEYBOARD_AT_TRANSLATE) == KEYBOARD_AT_TRANSLATE) {
+    grub_dprintf ("atkeyb", "queried set is %d but keyboard in Translate mode, so actually in set 1\n", grub_keyboard_orig_set);
+    ps2_state.current_set = 1;
+  } else {
+    grub_dprintf ("atkeyb", "using queried set %d\n", grub_keyboard_orig_set);
+    ps2_state.current_set = grub_keyboard_orig_set;
+  }
   return;
 #else
 
@@ -266,6 +280,7 @@ grub_keyboard_controller_init (void)
   grub_keyboard_orig_set = 2;
 #else
   grub_keyboard_controller_orig = grub_keyboard_controller_read ();
+  grub_dprintf ("atkeyb", "grub_keyboard_controller_orig = 0x%x\n", grub_keyboard_controller_orig);
   grub_keyboard_orig_set = query_mode ();
 #endif
   set_scancodes ();
@@ -275,11 +290,15 @@ grub_keyboard_controller_init (void)
 static grub_err_t
 grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused)))
 {
+/* In !USE_SCANCODE_SET mode, we didn't change anything, so nothing to restore */
+#if USE_SCANCODE_SET
   if (ps2_state.current_set == 0)
     return GRUB_ERR_NONE;
+  grub_dprintf ("atkeyb", "restoring set %d, controller 0x%x\n", grub_keyboard_orig_set, grub_keyboard_controller_orig);
   if (grub_keyboard_orig_set)
     write_mode (grub_keyboard_orig_set);
   grub_keyboard_controller_write (grub_keyboard_controller_orig);
+#endif
   return GRUB_ERR_NONE;
 }
 
diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h
index bcb4d9ba7..9414dc1b9 100644
--- a/include/grub/at_keyboard.h
+++ b/include/grub/at_keyboard.h
@@ -19,6 +19,10 @@
 #ifndef GRUB_AT_KEYBOARD_HEADER
 #define GRUB_AT_KEYBOARD_HEADER	1
 
+/*
+ * Refer to https://wiki.osdev.org/%228042%22_PS/2_Controller for details.
+ */
+
 /* Used for sending commands to the controller.  */
 #define KEYBOARD_COMMAND_ISREADY(x)	!((x) & 0x02)
 #define KEYBOARD_COMMAND_READ		0x20
-- 
2.29.2

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to