Hi,

As commented a couple of days ago: attached a diff between the branch
bzr.savannah.gnu.org/srv/bzr/grub/people/cpina/keyboard_layouts/ and
trunk.

If someone wants to test the USB needs:
grub-mklayout es
This will generate es.at and es.usb

Then I use:
set keymaps_dir=/boot/grub/keymaps

(where I have the files mentioned above)

insmod uhci; insmod usb_keyboard; terminal_input usb_keyboard
insmod usb_keyboard_layouts
usb_load_layout es

For AT is similar:
insmod at_keyboard
terminal_input at_keyboard
at_load_layout es

Comments, suggestions?
The code is the one already reviewed/changed a bit but splitted with
keyboard_layouts.c, at_keyboard_layouts.c and usb_keyboard_layouts.c
plus the changes needed in term/usb_keyboard.c (not lot of changes).

-- 
Carles Pina i Estany
        http://pinux.info
=== added file 'ChangeLog.keyboard_layouts'
--- ChangeLog.keyboard_layouts	1970-01-01 00:00:00 +0000
+++ ChangeLog.keyboard_layouts	2010-02-13 23:49:34 +0000
@@ -0,0 +1,31 @@
+2010-01-18  Carles Pina i Estany  <car...@pina.cat>
+
+	Adds keyboard layouts support (AT and USB)
+
+	* conf/common.rmk (bin_UTILITIES): Add grub-mklayouts rules.
+	(pkglib_MODULES): Add module `at_keyboard_layouts.mod' and
+	`usb_keyboard_layouts.mod'.
+	* include/grub/at_keyboard.h: Include `"keyboard.h"'. New EXPORT_VAR
+	`grub_keyboard_map'.
+	* include/grub/keyboard.h: New file.
+	* include/grub/keyboard_layouts.h: New file.
+	* include/grub/term.h: Move macros from here ...
+	* include/grub/keys.h: ... to here. New file.
+	* include/grub/usb_keyboard.h: New file.
+	* keyboard_layouts/keyboard_layouts.c: New file.
+	* keyboard_layouts/at_keyboard_layouts.c: New file.
+	* keyboard_layouts/usb_keyboard_layouts.c: New file.
+	* term/at_keyboard.c: Include `<grub/mm.h>'.
+	(grub_at_keyboard_map): Declare.
+	(keyboard_map_normal): Renamed from keyboard_map.
+	(grub_at_keyboard_getkey_noblock): Use `grub_keyboard_map' instead of
+	`keyboard_map' and `keyboard_map_shift'.
+	(GRUB_MOD_INIT): Initialise `grub_at_keyboard_map'.
+	* term/usb_keyboard.c: Include `<grub/mm.h>' and
+	`<grub/usb_keyboard.h>'.
+	(grub_usb_keyboard_map): Declare.
+	(keyboard_map_normal): Renamed from keyboard_map.
+	(grub_usb_keyboard_checkkey): Use `keyboard_map_normal' instead of
+	`keyboard_map'.
+	(GRUB_MOD_INIT): Initialise `grub_usb_keyboard_map'.
+	* util/grub-mklayouts.c: New file.

=== modified file 'conf/common.rmk'
--- conf/common.rmk	2010-02-06 14:37:23 +0000
+++ conf/common.rmk	2010-02-13 23:35:33 +0000
@@ -91,6 +91,10 @@ grub_mkrelpath_SOURCES = gnulib/progname
 bin_UTILITIES += grub-bin2h
 grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c
 
+# For grub-mklayouts.
+bin_UTILITIES += grub-mklayouts
+grub_mklayouts_SOURCES = gnulib/progname.c util/grub-mklayouts.c util/misc.c
+
 # For grub-script-check.
 bin_UTILITIES += grub-script-check
 util/grub-script-check.c_DEPENDENCIES = grub_script_check_init.h
@@ -105,6 +109,18 @@ grub_script.tab.c grub_script.tab.h: scr
 	$(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/parser.y
 DISTCLEANFILES += grub_script.tab.c grub_script.tab.h
 
+# For at_keyboard_layouts.mod
+pkglib_MODULES += at_keyboard_layouts.mod
+at_keyboard_layouts_mod_SOURCES = keyboard_layouts/at_keyboard_layouts.c 
+at_keyboard_layouts_mod_CFLAGS = $(COMMON_CFLAGS)
+at_keyboard_layouts_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For usb_keyboard_layouts.mod
+pkglib_MODULES += usb_keyboard_layouts.mod
+usb_keyboard_layouts_mod_SOURCES = keyboard_layouts/usb_keyboard_layouts.c 
+usb_keyboard_layouts_mod_CFLAGS = $(COMMON_CFLAGS)
+usb_keyboard_layouts_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
 # For grub-script-check.
 grub_script_check_init.lst: geninit.sh $(filter-out grub_script_check_init.c,$(grub_script_check_SOURCES))
 	rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@

=== modified file 'include/grub/at_keyboard.h'
--- include/grub/at_keyboard.h	2009-12-25 22:29:47 +0000
+++ include/grub/at_keyboard.h	2010-02-13 23:05:39 +0000
@@ -19,6 +19,10 @@
 #ifndef GRUB_AT_KEYBOARD_HEADER
 #define GRUB_AT_KEYBOARD_HEADER	1
 
+#include "keyboard.h"
+
+extern struct grub_keyboard_map_s *EXPORT_VAR(grub_at_keyboard_map);
+
 #define SHIFT_L		0x2a
 #define SHIFT_R		0x36
 #define CTRL		0x1d

=== added file 'include/grub/keyboard.h'
--- include/grub/keyboard.h	1970-01-01 00:00:00 +0000
+++ include/grub/keyboard.h	2010-02-13 23:29:48 +0000
@@ -0,0 +1,28 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KEYBOARD_HEADER
+#define GRUB_KEYBOARD_HEADER 1
+
+struct grub_keyboard_map_s
+{
+  char *normal;
+  char *shift;
+};
+
+#endif

=== added file 'include/grub/keyboard_layouts.h'
--- include/grub/keyboard_layouts.h	1970-01-01 00:00:00 +0000
+++ include/grub/keyboard_layouts.h	2010-02-05 18:58:05 +0000
@@ -0,0 +1,25 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KEYBOARD_LAYOUTS_H
+#define GRUB_KEYBOARD_LAYOUTS_H 1
+
+#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO"
+#define GRUB_KEYBOARD_LAYOUTS_VERSION 1
+
+#endif /* GRUB_KEYBOARD_LAYOUTS  */

=== added file 'include/grub/keys.h'
--- include/grub/keys.h	1970-01-01 00:00:00 +0000
+++ include/grub/keys.h	2010-01-17 18:21:42 +0000
@@ -0,0 +1,36 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_KEYS_HEADER
+#define GRUB_KEYS_HEADER	1
+
+/* Internal codes used by GRUB to represent terminal input.  */
+#define GRUB_TERM_LEFT          2
+#define GRUB_TERM_RIGHT         6
+#define GRUB_TERM_UP            16
+#define GRUB_TERM_DOWN          14
+#define GRUB_TERM_HOME          1
+#define GRUB_TERM_END           5
+#define GRUB_TERM_DC            4
+#define GRUB_TERM_PPAGE         7
+#define GRUB_TERM_NPAGE         3
+#define GRUB_TERM_ESC           '\e'
+#define GRUB_TERM_TAB           '\t'
+#define GRUB_TERM_BACKSPACE     8
+
+#endif /* ! GRUB_KEYS_HEADER */

=== modified file 'include/grub/term.h'
--- include/grub/term.h	2010-02-03 00:24:07 +0000
+++ include/grub/term.h	2010-01-29 23:31:29 +0000
@@ -19,19 +19,7 @@
 #ifndef GRUB_TERM_HEADER
 #define GRUB_TERM_HEADER	1
 
-/* Internal codes used by GRUB to represent terminal input.  */
-#define GRUB_TERM_LEFT		2
-#define GRUB_TERM_RIGHT		6
-#define GRUB_TERM_UP		16
-#define GRUB_TERM_DOWN		14
-#define GRUB_TERM_HOME		1
-#define GRUB_TERM_END		5
-#define GRUB_TERM_DC		4
-#define GRUB_TERM_PPAGE		7
-#define GRUB_TERM_NPAGE		3
-#define GRUB_TERM_ESC		'\e'
-#define GRUB_TERM_TAB		'\t'
-#define GRUB_TERM_BACKSPACE	8
+#include <grub/keys.h>
 
 #ifndef ASM_FILE
 

=== added file 'include/grub/usb_keyboard.h'
--- include/grub/usb_keyboard.h	1970-01-01 00:00:00 +0000
+++ include/grub/usb_keyboard.h	2010-02-13 23:29:58 +0000
@@ -0,0 +1,26 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_USB_KEYBOARD_HEADER
+#define GRUB_USB_KEYBOARD_HEADER	1
+
+#include "keyboard.h"
+
+extern struct grub_keyboard_map_s *EXPORT_VAR(grub_usb_keyboard_map);
+
+#endif

=== added directory 'keyboard_layouts'
=== added file 'keyboard_layouts/at_keyboard_layouts.c'
--- keyboard_layouts/at_keyboard_layouts.c	1970-01-01 00:00:00 +0000
+++ keyboard_layouts/at_keyboard_layouts.c	2010-02-13 23:22:51 +0000
@@ -0,0 +1,6 @@
+#define DO_AT_KEYBOARD_LAYOUT 1
+#define COMMAND_NAME_LOAD "at_load_layout"
+#define COMMAND_NAME_SHOW "at_show_layout"
+#define COMMAND_NAME_RESTORE "at**"
+#define FILE_SUFFIX ".at"
+#include "keyboard_layouts.c"

=== added file 'keyboard_layouts/keyboard_layouts.c'
--- keyboard_layouts/keyboard_layouts.c	1970-01-01 00:00:00 +0000
+++ keyboard_layouts/keyboard_layouts.c	2010-02-13 23:24:16 +0000
@@ -0,0 +1,213 @@
+/* at_keyboard_layouts.c - at_keyboard_layouts module */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/file.h>
+#include <grub/kernel.h>
+#include <grub/i18n.h>
+
+#ifdef DO_AT_KEYBOARD_LAYOUT
+  #include <grub/at_keyboard.h>
+#else
+  #include <grub/usb_keyboard.h>
+#endif
+
+#include <grub/keyboard_layouts.h>
+
+#include <grub/term.h>
+
+static char original_keyboard_layout_normal[128];
+static char original_keyboard_layout_shift[128];
+
+static char *active_layout;
+
+static struct grub_keyboard_map_s *keyboard_map;
+
+static grub_err_t
+grub_cmd_load_layout(grub_command_t cmd __attribute__ ((unused)),
+			      int argc, char **args)
+{
+  char magic[8];
+  int check;
+  char *filename;
+  char *prefix;
+  int filename_length;
+
+  if (argc != 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "usage: load_layout LAYOUT");
+
+  prefix = grub_env_get ("keymaps_dir");
+  if (!prefix)
+    return grub_error (GRUB_ERR_READ_ERROR,
+		       "`keymaps_dir' variable not set up");
+
+  filename_length = grub_strlen (prefix) + grub_strlen ("/") +
+                    grub_strlen (args[0]) + grub_strlen(FILE_SUFFIX) + 1;
+
+  filename =
+    grub_malloc (filename_length);
+  
+  if (! filename)
+    return grub_errno;
+
+  grub_snprintf (filename, filename_length, "%s/%s%s", prefix, args[0],
+  						       FILE_SUFFIX);
+
+  grub_file_t keyboard_file;
+  keyboard_file = grub_file_open (filename);
+
+  if (!keyboard_file)
+    {
+      return grub_error (GRUB_ERR_READ_ERROR, "cannot open file `%s'",
+			 filename);
+      return 0;
+    }
+
+  check =
+    grub_file_read (keyboard_file, magic,
+		    sizeof (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1);
+
+  if (check != sizeof (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1)
+    {
+      return grub_error (GRUB_ERR_READ_ERROR,
+			 "cannot read the file header from `%s'", filename);
+    }
+
+  if (grub_memcmp
+      (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC,
+       sizeof (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) != 0)
+    {
+      grub_file_close (keyboard_file);
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE, "file not recognised (`%s')",
+			 filename);
+    }
+  grub_uint32_t version;
+  check = grub_file_read (keyboard_file, &version, 4);
+
+  if (check != 4)
+    {
+      grub_file_close (keyboard_file);
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+			 "cannot check file version (`%s')", filename);
+    }
+
+  version = grub_be_to_cpu32 (version);
+  if (version != GRUB_KEYBOARD_LAYOUTS_VERSION)
+    {
+      grub_file_close (keyboard_file);
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+			 "invalid file version: %d (`%s')", version,
+			 filename);
+    }
+
+
+
+  check = grub_file_read (keyboard_file, keyboard_map->normal, 128);
+  if (check != 128)
+    {
+      grub_file_close (keyboard_file);
+      return grub_error (GRUB_ERR_READ_ERROR,
+			 "problem reading normal keyboard from `%s'",
+			 filename);
+    }
+
+  check = grub_file_read (keyboard_file, keyboard_map->shift, 128);
+  if (check != 128)
+    {
+      grub_file_close (keyboard_file);
+      return grub_error (GRUB_ERR_READ_ERROR,
+			 "problem reading shift keyboard from `%s'",
+			 filename);
+    }
+
+  grub_free (active_layout);
+  active_layout = grub_strdup (args[0]);
+
+  grub_file_close (keyboard_file);
+  return 0;
+}
+
+static grub_err_t
+grub_cmd_show_active_keyboardlayout (grub_command_t cmd
+				     __attribute__ ((unused)), int argc
+				     __attribute__ ((unused)), char **args
+				     __attribute__ ((unused)))
+{
+  grub_printf ("Active layout: `%s'.\n", active_layout);
+  return 0;
+}
+
+static void
+set_default_keyboard(void)
+{
+  grub_free (active_layout);
+  active_layout = grub_strdup("default");
+  grub_memcpy (keyboard_map->normal, original_keyboard_layout_normal,
+	       128);
+  grub_memcpy (keyboard_map->shift, original_keyboard_layout_shift, 128);
+}
+
+static grub_err_t
+grub_cmd_set_default_keyboard (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
+{
+  set_default_keyboard();
+  grub_printf_ (N_("Reverted to default keymap layout.\n"));
+  return 0;
+}
+
+#ifdef DO_AT_KEYBOARD_LAYOUT
+GRUB_MOD_INIT (at_keyboard_layouts)
+#else
+GRUB_MOD_INIT (usb_keyboard_layouts)
+#endif
+{
+#ifdef DO_AT_KEYBOARD_LAYOUT
+  keyboard_map = grub_at_keyboard_map;
+#else
+  keyboard_map = grub_usb_keyboard_map;
+#endif
+
+  grub_memcpy (original_keyboard_layout_normal, keyboard_map->normal,
+	       128);
+  grub_memcpy (original_keyboard_layout_shift, keyboard_map->shift, 128);
+
+  active_layout = grub_strdup("default");
+
+  grub_register_command_p1 (COMMAND_NAME_LOAD, grub_cmd_load_layout,
+			    N_("LAYOUT"), N_("Set up the new layout."));
+
+  grub_register_command_p1 (COMMAND_NAME_SHOW,
+			    grub_cmd_show_active_keyboardlayout, 0,
+			    N_("Show the active layout."));
+
+  grub_register_command_p1 (COMMAND_NAME_RESTORE,
+  			    grub_cmd_set_default_keyboard, 0,
+			    N_("Set up the default keyboard."));
+
+}
+
+GRUB_MOD_FINI (at_keyboard_layouts)
+{
+  set_default_keyboard();
+}

=== added file 'keyboard_layouts/usb_keyboard_layouts.c'
--- keyboard_layouts/usb_keyboard_layouts.c	1970-01-01 00:00:00 +0000
+++ keyboard_layouts/usb_keyboard_layouts.c	2010-02-13 23:22:53 +0000
@@ -0,0 +1,6 @@
+#define DO_USB_KEYBOARD_LAYOUT 1
+#define COMMAND_NAME_LOAD "usb_load_layout"
+#define COMMAND_NAME_SHOW "usb_show_layout"
+#define COMMAND_NAME_RESTORE "usb**"
+#define FILE_SUFFIX ".usb"
+#include "keyboard_layouts.c"

=== modified file 'term/at_keyboard.c'
--- term/at_keyboard.c	2010-01-10 12:34:48 +0000
+++ term/at_keyboard.c	2010-02-13 23:05:51 +0000
@@ -22,6 +22,9 @@
 #include <grub/cpu/io.h>
 #include <grub/misc.h>
 #include <grub/term.h>
+#include <grub/mm.h>
+
+struct grub_keyboard_map_s *grub_at_keyboard_map = NULL;
 
 static short at_keyboard_status = 0;
 static int pending_key = -1;
@@ -41,7 +44,7 @@ static grub_uint8_t led_status;
 #define KEYBOARD_LED_NUM		(1 << 1)
 #define KEYBOARD_LED_CAPS		(1 << 2)
 
-static char keyboard_map[128] =
+static char keyboard_map_normal[128] =
 {
   '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',
   '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,
@@ -214,12 +217,12 @@ grub_at_keyboard_getkey_noblock (void)
 	break;
       default:
 	if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R))
-	  key = keyboard_map[code] - 'a' + 1;
+	  key = grub_at_keyboard_map->normal[code] - 'a' + 1;
 	else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R))
-	    && keyboard_map_shift[code])
-	  key = keyboard_map_shift[code];
+	    && grub_at_keyboard_map->shift[code])
+	  key = grub_at_keyboard_map->shift[code];
 	else
-	  key = keyboard_map[code];
+	  key = grub_at_keyboard_map->normal[code];
 
 	if (key == 0)
 	  grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code);
@@ -295,6 +298,9 @@ static struct grub_term_input grub_at_ke
 GRUB_MOD_INIT(at_keyboard)
 {
   grub_term_register_input ("at_keyboard", &grub_at_keyboard_term);
+
+  grub_at_keyboard_map->normal = keyboard_map_normal;
+  grub_at_keyboard_map->shift = keyboard_map_shift;
 }
 
 GRUB_MOD_FINI(at_keyboard)

=== modified file 'term/usb_keyboard.c'
--- term/usb_keyboard.c	2009-12-02 09:00:54 +0000
+++ term/usb_keyboard.c	2010-02-13 23:05:58 +0000
@@ -26,9 +26,14 @@
 #include <grub/usb.h>
 #include <grub/dl.h>
 #include <grub/time.h>
+#include <grub/mm.h>
+#include <grub/usb_keyboard.h>
 
 
-static char keyboard_map[128] =
+
+struct grub_keyboard_map_s *grub_usb_keyboard_map = NULL;
+
+static char keyboard_map_normal[128] =
   {
     '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd',
     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
@@ -152,11 +157,11 @@ grub_usb_keyboard_checkkey (void)
 
   /* Check if the Control or Shift key was pressed.  */
   if (data[0] & 0x01 || data[0] & 0x10)
-    key = keyboard_map[data[2]] - 'a' + 1;
+    key = keyboard_map_normal[data[2]] - 'a' + 1;
   else if (data[0] & 0x02 || data[0] & 0x20)
     key = keyboard_map_shift[data[2]];
   else
-    key = keyboard_map[data[2]];
+    key = keyboard_map_normal[data[2]];
 
   if (key == 0)
     grub_printf ("Unknown key 0x%x detected\n", data[2]);
@@ -321,6 +326,9 @@ GRUB_MOD_INIT(usb_keyboard)
 {
   grub_usb_hid ();
   grub_term_register_input ("usb_keyboard", &grub_usb_keyboard_term);
+
+  grub_usb_keyboard_map->normal = keyboard_map_normal;
+  grub_usb_keyboard_map->shift = keyboard_map_shift;
 }
 
 GRUB_MOD_FINI(usb_keyboard)

=== added file 'util/grub-mklayouts.c'
--- util/grub-mklayouts.c	1970-01-01 00:00:00 +0000
+++ util/grub-mklayouts.c	2010-01-31 18:08:14 +0000
@@ -0,0 +1,396 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/util/misc.h>
+#include <grub/keys.h>
+#include <grub/i18n.h>
+#include <grub/keyboard_layouts.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include "progname.h"
+
+#define CKBCOMP "ckbcomp"
+
+static int at_to_usb_map_normal[128] =
+{
+  0, 41, 30, 31, 32, 33, 34, 35, 
+  36, 37, 38, 39, 45, 46, 42, 43, 
+  20, 26, 8, 21, 23, 28, 24, 12, 
+  18, 19, 47, 48, 40, 0, 4, 22, 
+  7, 9, 10, 11, 13, 14, 15, 51, 
+  52, 53, 0, 49, 29, 27, 6, 25, 
+  5, 17, 16, 54, 55, 56, 0, 0, 
+  0, 44, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 74, 
+  82, 78, 45, 80, 0, 79, 0, 77, 
+  81, 75, 0, 76, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0, 
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int at_to_usb_map_shift[128] =
+{
+  0, 0, 30, 31, 32, 33, 34, 35, 
+  36, 37, 38, 39, 45, 46, 0, 0, 
+  20, 26, 8, 21, 23, 28, 24, 12, 
+  18, 19, 47, 48, 40, 0, 4, 22, 
+  7, 9, 10, 11, 13, 14, 15, 51, 
+  52, 0, 0, 49, 29, 27, 6, 25, 
+  5, 17, 16, 54, 55, 56,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static struct option options[] = {
+  {"output", required_argument, 0, 'o'},
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+struct console_grub_equivalence
+{
+  char *layout;
+  char grub;
+};
+
+static struct console_grub_equivalence console_grub_equivalences[] = {
+  {"Escape", GRUB_TERM_ESC},
+  {"Tab", GRUB_TERM_TAB},
+  {"Delete", GRUB_TERM_BACKSPACE},
+
+  {"KP_1", '1'},
+  {"KP_2", '2'},
+  {"KP_3", '3'},
+  {"KP_4", '4'},
+  {"KP_5", '5'},
+  {"KP_6", '6'},
+  {"KP_7", '7'},
+  {"KP_8", '8'},
+  {"KP_9", '9'},
+
+  {"KP_Multiply", '*'},
+  {"KP_Substract", '-'},
+  {"KP_Add", '+'},
+  {"KP_Divide", '/'},
+
+  {"KP_Enter", '\n'},
+  {"Return", '\n'},
+  {"", '\0'}
+};
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
+  else
+    printf ("\
+Usage: %s [OPTIONS] LAYOUT\n\
+  -o, --output		set output base name file. Default is LAYOUT\n\
+  			.at or .usb suffixes will be automatically added.\n\
+  -h, --help		display this message and exit.\n\
+  -V, --version		print version information and exit.\n\
+  -v, --verbose		print verbose messages.\n\
+\n\
+Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+void
+add_special_keys (char keyboard_map[128])
+{
+  keyboard_map[71] = GRUB_TERM_HOME;
+  keyboard_map[72] = GRUB_TERM_UP;
+  keyboard_map[73] = GRUB_TERM_NPAGE;
+  keyboard_map[75] = GRUB_TERM_LEFT;
+  keyboard_map[77] = GRUB_TERM_RIGHT;
+  keyboard_map[79] = GRUB_TERM_END;
+  keyboard_map[80] = GRUB_TERM_DOWN;
+  keyboard_map[81] = GRUB_TERM_PPAGE;
+  keyboard_map[83] = GRUB_TERM_DC;
+
+/*
+ * TODO: defined in include/grub/i386/at_keyboard.h
+  keyboard_map[101] = OLPC_UP;
+  keyboard_map[102] = OLPC_DOWN;
+  keyboard_map[103] = OLPC_LEFT;
+  keyboard_map[104] = OLPC_RIGHT;
+*/
+
+}
+
+char
+lookup (char *code)
+{
+  int i;
+
+  for (i = 0; console_grub_equivalences[i].grub != '\0'; i++)
+    {
+      if (strcmp (code, console_grub_equivalences[i].layout) == 0)
+	{
+	  return console_grub_equivalences[i].grub;
+	}
+    }
+
+  return '\0';
+}
+
+unsigned int
+get_grub_code (char *layout_code)
+{
+  unsigned int code;
+
+  if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0)
+    {
+      sscanf (layout_code, "U+%x", &code);
+    }
+  else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0)
+    {
+      sscanf (layout_code, "+U+%x", &code);
+    }
+  else
+    {
+      code = lookup (layout_code);
+    }
+  return code;
+}
+
+void
+write_file (char* filename, char keyboard_map_normal[128],
+	    char keyboard_map_shift[128])
+{
+  FILE *fp_output;
+  int version;
+  int i;
+
+  fp_output = fopen (filename, "w");
+  
+  if (!fp_output)
+    {
+      grub_util_error ("cannot open `%s'", filename);
+      exit (1);
+    }
+  
+  version = GRUB_KEYBOARD_LAYOUTS_VERSION;
+  version = grub_cpu_to_be32 (version);
+
+  grub_util_write_image (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC,
+			 sizeof (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1,
+			 fp_output);
+
+  grub_util_write_image ((char *) &version, 4, fp_output);
+
+  for (i = 0; i < 128; i++)
+    {
+      fprintf (fp_output, "%c", keyboard_map_normal[i]);
+    }
+
+  for (i = 0; i < 128; i++)
+    {
+      fprintf (fp_output, "%c", keyboard_map_shift[i]);
+    }
+  fclose (fp_output);
+
+}
+
+void
+write_files_at_usb (char* base_filename, char at_keyboard_map_normal[128],
+		  char at_keyboard_map_shift[128])
+{
+  char *at_file;
+  char *usb_file;
+  int i;
+  char usb_keyboard_map_normal[128];
+  char usb_keyboard_map_shift[128];
+
+  /* AT layout.  */
+  at_file = (char*) xmalloc (strlen(base_filename) + strlen(".at") + 1);
+  sprintf (at_file, "%s.at", base_filename);
+
+  write_file (at_file, at_keyboard_map_normal, at_keyboard_map_shift);
+  free (at_file);
+
+  /* Convert and write USB layout.  */
+  memset (usb_keyboard_map_normal, 0, 128);
+  memset (usb_keyboard_map_shift, 0, 128);
+
+  usb_file = (char*) xmalloc (strlen(base_filename) + strlen(".usb") + 1); 
+  sprintf (usb_file, "%s.usb", base_filename);
+
+  for (i=0; i<128; i++)
+    {
+      usb_keyboard_map_normal[at_to_usb_map_normal[i] ] = 
+      				at_keyboard_map_normal[i];
+
+      usb_keyboard_map_shift[at_to_usb_map_shift[i] ] =
+      				at_keyboard_map_shift[i];
+    }
+
+  write_file (usb_file, usb_keyboard_map_normal, usb_keyboard_map_shift);
+  free (usb_file);
+}
+
+void
+write_keymaps (char *keymap, char *file_basename)
+{
+  char at_keyboard_map_normal[128];
+  char at_keyboard_map_shift[128];
+
+  char line[2048];
+  char normal[64];
+  char shift[64];
+  int key_code;
+  pid_t pid;
+  int pipe_communication[2];
+  int ok;
+
+  FILE *fp_pipe;
+
+  if (pipe (pipe_communication) == -1)
+    {
+      grub_util_error ("cannot prepare the pipe");
+      exit (2);
+    }
+
+  pid = fork ();
+  if (pid < 0)
+    {
+      grub_util_error ("cannot fork");
+      exit (2);
+    }
+  else if (pid == 0)
+    {
+      close (1);
+      dup (pipe_communication[1]);
+      close (pipe_communication[0]);
+      execlp (CKBCOMP, CKBCOMP, keymap, NULL);
+      grub_util_error ("%s %s cannot be executed", CKBCOMP, keymap);
+      exit (3);
+    }
+  close (pipe_communication[1]);
+  fp_pipe = fdopen (pipe_communication[0], "r");
+
+  memset (at_keyboard_map_normal, 0, 128);
+  memset (at_keyboard_map_shift, 0, 128);
+
+  /* Process the ckbcomp output and prepare the layouts.  */
+  ok = 0;
+  while (fgets (line, sizeof (line), fp_pipe))
+    {
+      if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0)
+	{
+	  sscanf (line, "keycode %d = %s %s", &key_code, normal, shift);
+	  if (key_code < 128)
+	    {
+	      at_keyboard_map_normal[key_code] = (char) get_grub_code (normal);
+	      at_keyboard_map_shift[key_code] = (char) get_grub_code (shift);
+	      ok = 1;
+	    }
+	}
+    }
+
+  add_special_keys (at_keyboard_map_normal);
+
+  if (ok == 0)
+    {
+      fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n",
+	       CKBCOMP, keymap);
+      exit (1);
+    }
+
+  write_files_at_usb (file_basename, at_keyboard_map_normal,
+  		      at_keyboard_map_shift);
+}
+
+int
+main (int argc, char *argv[])
+{
+  int verbosity;
+  char *file_basename = NULL;
+
+  set_program_name (argv[0]);
+
+  verbosity = 0;
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "o:hVv", options, 0);
+
+      if (c == -1)
+	break;
+      else
+	switch (c)
+	  {
+	  case 'h':
+	    usage (0);
+	    break;
+
+	  case 'o':
+	    file_basename = optarg;
+	    break;
+
+	  case 'V':
+	    printf ("%s (%s) %s\n", program_name, PACKAGE_NAME,
+		    PACKAGE_VERSION);
+	    return 0;
+
+	  case 'v':
+	    verbosity++;
+	    break;
+
+	  default:
+	    usage (1);
+	    break;
+	  }
+    }
+
+  /* Obtain LAYOUT.  */
+  if (optind >= argc)
+    {
+      fprintf (stderr, "No layout is specified.\n");
+      usage (1);
+    }
+
+  if (file_basename == NULL)
+    {
+      file_basename = argv[optind];
+    }
+
+  write_keymaps (argv[optind], file_basename);
+
+  return 0;
+}

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

Reply via email to