1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
From 55d2ea1ebaa6b399736aa24393e08d007fde988c Mon Sep 17 00:00:00 2001
From: Leah Rowe <leah@libreboot.org>
Date: Mon, 30 Oct 2023 22:19:21 +0000
Subject: [PATCH 09/14] at_keyboard coreboot: force scancodes2+translate
Scan code set 2 with translation should be assumed in
every case, as the default starting position.
However, GRUB is trying to detect and use other modes
such as set 2 without translation, or set 1 without
translation from set 2; it also detects no-mode and
assumes mode 1, on really old keyboards.
The current behaviour has been retained, for everything
except GRUB_MACHINE_COREBOOT; for the latter, scan code
set 2 with translation is hardcoded, and forced in code.
This is required to make keyboard initialisation work on
the MEC5035 EC used by the Dell Latitude E6400, when
running GRUB as a coreboot payload on that laptop. The
EC reports scancode set 2 with translation when probed,
but actually only outputs scancode set 1.
Since GRUB is attempting to use it without translation,
and since the machine reports set 2 with translation,
but only ever outputs set 1 scancodes, this results in
wrong keypresses for every key.
This fix fixed that, by forcing set 2 with translation,
treating it as set 1, but only on coreboot. This is the
same behaviour used in GNU+Linux systems and SeaBIOS.
With this change, GRUB keyboard initialisation now works
just fine on those machines.
This has *also* been tested on other coreboot machines
running GRUB; several HP EliteBooks, ThinkPads and
Dell Precision T1650. All seems to work just fine.
Signed-off-by: Leah Rowe <leah@libreboot.org>
---
grub-core/term/at_keyboard.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c
index f8a129eb7..8207225c2 100644
--- a/grub-core/term/at_keyboard.c
+++ b/grub-core/term/at_keyboard.c
@@ -138,6 +138,7 @@ write_mode (int mode)
return (i != GRUB_AT_TRIES);
}
+#if !defined (GRUB_MACHINE_COREBOOT)
static int
query_mode (void)
{
@@ -161,10 +162,12 @@ query_mode (void)
return 3;
return 0;
}
+#endif
static void
set_scancodes (void)
{
+#if !defined (GRUB_MACHINE_COREBOOT)
/* You must have visited computer museum. Keyboard without scancode set
knowledge. Assume XT. */
if (!grub_keyboard_orig_set)
@@ -173,20 +176,33 @@ set_scancodes (void)
ps2_state.current_set = 1;
return;
}
+#endif
#if !USE_SCANCODE_SET
ps2_state.current_set = 1;
return;
-#else
+#endif
+#if defined (GRUB_MACHINE_COREBOOT)
+ /* enable translation */
+ grub_keyboard_controller_write (grub_keyboard_controller_orig
+ & ~KEYBOARD_AT_DISABLE);
+#else
+ /* if not coreboot, disable translation and try mode 2 first, before 1 */
grub_keyboard_controller_write (grub_keyboard_controller_orig
& ~KEYBOARD_AT_TRANSLATE
& ~KEYBOARD_AT_DISABLE);
+#endif
keyboard_controller_wait_until_ready ();
grub_outb (KEYBOARD_COMMAND_ENABLE, KEYBOARD_REG_DATA);
-
write_mode (2);
+
+#if defined (GRUB_MACHINE_COREBOOT)
+ /* mode 2 with translation, so make grub treat as set 1 */
+ ps2_state.current_set = 1;
+#else
+ /* if not coreboot, translation isn't set; test 2 and fall back to 1 */
ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (ps2_state.current_set == 2)
--
2.39.2
|