Hi there, I've been trying to set up my grub for my Dvorak keyboard. It seems that everywhere I look points to something like:
insmod keylayouts keymap /boot/grub/bepo.gkb In practice however, this does NOT work at all. After some debugging, here's what I've found: - grub-core/commands/keylayouts.c has grub_term_map_key() which does the actual mapping. - This function is only referred by - grub-core/term/at_keyboard.c (via ps2.c) - grub-core/term/usb_keyboard.c In my case, at GRUB command prompt, terminal_input tells: - Current terminal is console. - Neither at_keyboard nor usb_keyboard are available. So no wonder the keymap does not work... I drafted the attached patch to grub-core/term/efi/console.c and grub-core/i386/pc/console.c, which should make use of grub_term_map_key() and fix the problem. I unfortunately can't test it because of this Ubuntu build issue https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1914953/comments/7 ... separate issue though. Anyhow, any advice on whether this patch would / would not work? It seems reasonable to me that keyboard mapping should happen at grub-core/kern/term.c at grub_getkey_noblock() instead though, as fixing it there (immediately after term->getkey (term) call), in theory, would fix things for all cases. WDYT? Thanks. Fabio Pugliese Ornellas
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 715994872..e24603c32 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -205,6 +205,7 @@ kernel = { efi = kern/efi/init.c; efi = kern/efi/mm.c; efi = term/efi/console.c; + efi = commands/keylayouts.c; efi = kern/acpi.c; efi = kern/efi/acpi.c; efi = kern/efi/sb.c; @@ -269,6 +270,7 @@ kernel = { i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; i386_pc = term/i386/pc/console.c; + i386_pc = commands/keylayouts.c; i386_qemu = bus/pci.c; i386_qemu = kern/vga_init.c; diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c index a3622e4fe..37d5a971b 100644 --- a/grub-core/term/efi/console.c +++ b/grub-core/term/efi/console.c @@ -23,6 +23,7 @@ #include <grub/efi/efi.h> #include <grub/efi/api.h> #include <grub/efi/console.h> +#include <grub/keyboard_layouts.h> typedef enum { GRUB_TEXT_MODE_UNDEFINED = -1, @@ -374,13 +375,25 @@ grub_efi_console_input_init (struct grub_term_input *term) static int grub_console_getkey (struct grub_term_input *term) { + int key; + int status = 0; + if (grub_efi_is_finished) return 0; if (term->data) - return grub_console_getkey_ex(term); + key = grub_console_getkey_ex(term); else - return grub_console_getkey_con(term); + key = grub_console_getkey_con(term); + + if (key & GRUB_TERM_SHIFT) + status |= GRUB_TERM_STATUS_RSHIFT; + if (key & GRUB_TERM_ALT) + status |= GRUB_TERM_STATUS_RALT; + if (key & GRUB_TERM_CTRL) + status |= GRUB_TERM_STATUS_RCTRL + + return grub_term_map_key(key & GRUB_TERM_KEY_MASK, status); } static struct grub_term_coordinate diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c index 9403390f1..b7b3bfc12 100644 --- a/grub-core/term/i386/pc/console.c +++ b/grub-core/term/i386/pc/console.c @@ -21,6 +21,7 @@ #include <grub/term.h> #include <grub/types.h> #include <grub/machine/int.h> +#include <grub/keyboard_layouts.h> static grub_uint8_t grub_console_cur_color = 0x7; @@ -183,6 +184,21 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), grub_bios_interrupt (0x10, ®s); } +static int +map_key (int key) +{ + int status = 0; + + if (key & GRUB_TERM_SHIFT) + status |= GRUB_TERM_STATUS_RSHIFT; + if (key & GRUB_TERM_ALT) + status |= GRUB_TERM_STATUS_RALT; + if (key & GRUB_TERM_CTRL) + status |= GRUB_TERM_STATUS_RCTRL; + + return grub_term_map_key(key & GRUB_TERM_KEY_MASK, status); +} + /* * if there is a character pending, return it; otherwise return -1 * BIOS call "INT 16H Function 01H" to check whether a character is pending @@ -226,16 +242,16 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x16, ®s); if (!(regs.eax & 0xff)) - return ((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED; + return map_key (((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED); if ((regs.eax & 0xff) >= ' ') - return regs.eax & 0xff; + return map_key (regs.eax & 0xff); for (i = 0; i < ARRAY_SIZE (bypass_table); i++) if (bypass_table[i] == (regs.eax & 0xffff)) - return regs.eax & 0xff; + return map_key (regs.eax & 0xff); - return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL); + return map_key ((regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL)); } static int
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel