From 96c0bbe5d406b616360a7fce7cee67d7692c0d6d Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Mon, 30 Oct 2023 22:19:21 +0000 Subject: [PATCH 1/1] 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 --- 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