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, &regs);
 }
 
+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, &regs);
   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

Reply via email to