In principle, GRUB2 allows you to change the keyboard layout through its
'at_keyboard' input terminal.
You can use the 'grub-mklayout' utility to create a GRUB keyboard
layout, e.g., for dvorak:
ckbcomp dvorak | grub-mklayout -o dvorak.gkb
Create a 'layouts' subdirectory under your 'grub' directory, and copy
the GRUB keyboard layout to it, e.g.:
mkdir /boot/grub/layouts
cp dvorak.gkb /boot/grub/layouts
The 'keymap' command under GRUB (e.g., in your 'grub.cfg') will then
load the keymap:
keymap dvorak
To actually use the keymap, you will have to switch the the
'at_keyboard' input terminal:
terminal_input at_keyboard
Trouble is, under a PC BIOS system, the 'at_keyboard' input terminal is
broken.
It is unclear to me how (or even, whether) it can be fixed.
Since I, too, got frustrated that I couldn't change the keyboard layout,
I decided to try and create my own 'ext_kbd' input terminal, for
personal use.
The 'ext_kbd' input terminal implements something akin to the 'setkey'
command that was available under what is now known as GRUB Legacy.
It won't go into upstream, since it deviates from the infrastructure
that GRUB already provides for changing the keyboard layout.
In any case, I'll attach a patch that will add support for my 'ext_kbd'
module to GRUB, in case anyone is interested enough to try it.
If you decide to apply the patch, then you will subsequently have to run
'./autogen.sh' before you run './configure'. Otherwise, the build
process will not pick up the definition of the 'ext_kbd' module that the
patch adds to the 'grub-core/Makefile.core.def' file.
I'm afraid that this is the best that I can do for now.
-- Luc.
diff -Naur grub.orig/docs/grub.texi grub/docs/grub.texi
--- grub.orig/docs/grub.texi 2015-07-23 12:11:11.000000000 +0200
+++ grub/docs/grub.texi 2015-07-26 14:10:24.956277000 +0200
@@ -3660,13 +3660,57 @@
Commands usable anywhere in the menu and in the command-line.
@menu
+* keymap:: Load a keyboard layout
* serial:: Set up a serial device
+* setkey:: Change the keyboard map
+* setnumpad:: Change the numeric keypad behavior
* terminal_input:: Manage input terminals
* terminal_output:: Manage output terminals
* terminfo:: Define terminal type
@end menu
+@node keymap
+@subsection keymap
+
+@deffn Command keymap LAYOUT
+Load a keyboard layout.
+
+If @var{LAYOUT} is just the identifier of a keyboard layout, then GRUB will
+look for file @file{$prefix/layouts/@var{LAYOUT}.gkb}.
+Alternatively, @var{LAYOUT} may be the full path to a GRUB keyboard layout file.
+
+This command will have no effect unless and until you use the
+@command{terminal_input} command to activate either the @samp{at_keyboard}
+input terminal:
+
+@example
+terminal_input at_keyboard
+@end example
+
+or the @samp{usb_keyboard} input terminal:
+
+@example
+terminal_input usb_keyboard
+@end example
+
+@table @asis
+@item Creating a GRUB keyboard layout file:
+
+To generate a GRUB keyboard layout file, you can use the @command{grub-mklayout}
+command-line utility, which takes a Linux console keyboard layout description
+as input, and converts it to a format that GRUB can understand.
+
+For instance, if you use the @samp{dvorak} keyboard layout, then the following
+command will create the @file{dvorak.gkb} file for use with GRUB:
+
+@example
+ckbcomp dvorak | grub-mklayout -o dvorak.gkb
+@end example
+@end table
+@end deffn
+
+
@node serial
@subsection serial
@@ -3689,6 +3733,112 @@
@end deffn
+@node setkey
+@subsection setkey
+
+@deffn Command setkey [[TO_KEY] FROM_KEY]
+Change the keyboard map.
+
+With no arguments, reset the keyboard map to its default U.S. layout.
+
+When only the @var{FROM_KEY} argument is given, or when @var{TO_KEY} is equal to
+@var{FROM_KEY}, the mapping entry for the specified key will be cleared.
+Keep in mind that @var{FROM_KEY} identifies the position of the key under the default
+U.S. layout.
+
+With two unequal arguments, the key @var{FROM_KEY} will be mapped to @var{TO_KEY}.
+In effect, the @var{FROM_KEY} argument identifies the position of the key under the
+default U.S. layout, and @var{TO_KEY} specifies how the key should behave under your
+local keyboard layout.
+
+A key must be:
+@itemize @bullet
+@item
+a lowercase letter;
+@item
+an uppercase letter;
+@item
+a decimal digit;
+@item
+a function key---i.e., @kbd{F1} through @kbd{F12};
+@end itemize
+
+or one of the following:
+
+@verbatim
+ ampersand barx delete less question
+ asterisk braceleft dollar minus quote
+ at braceright doublequote numbersign semicolon
+ backslash bracketleft enter parenleft slash
+ backslashx bracketright equal parenright space
+ backquote caret escape percent tab
+ backspace colon exclam period tilde
+ bar comma greater plus underscore
+@end verbatim
+
+This command is only available on PC BIOS systems. It will have no effect unless
+and until you use the @command{terminal_input} command to activate the @samp{ext_kbd}
+input terminal:
+
+@example
+terminal_input ext_kbd
+@end example
+
+Differences with the @command{setkey} command under GRUB Legacy:
+
+@itemize @bullet
+@item
+This @command{setkey} command does not support the modifier keys---i.e., @kbd{shift},
+@kbd{control}, @kbd{alt}, @kbd{capslock}.
+
+@item
+This @command{setkey} command supports all twelve function keys.
+
+@item
+Depending on your keyboard layout, there may be an extra key between the @key{Left Shift}
+key and the row of letter keys to its right. This extra key will output a backslash (i.e.,
+@kbd{@backslashchar{}}) or, when shifted, a vertical bar (i.e., @kbd{|}), by default.
+
+This @command{setkey} command will not affect this extra key when you remap the
+@kbd{backslash} or @kbd{bar} keys. You can instead remap the key separately, using the
+@kbd{backslashx} or @kbd{barx} values for the @var{FROM_KEY} argument.
+
+For instance, under the Belgian keyboard layout, this key will output a @kbd{<} or, when
+shifted, a @kbd{>} character. The following GRUB commands will, then, appropriately remap
+the key:
+
+@example
+setkey less backslashx
+setkey greater barx
+@end example
+@end itemize
+@end deffn
+
+
+@node setnumpad
+@subsection setnumpad
+
+@deffn Command setnumpad [@option{--force}|@option{--noforce}]
+Change the behavior of the numeric keypad.
+
+With @option{--force}, make the keys on the numeric keypad emit the numeric
+characters on their keycaps, irrespective of the @key{NumLock} and @key{Shift}
+key states.
+
+With @option{--noforce}, or if no option is given, restore default behavior
+of the keys on the numeric keypad, which depends on the @key{NumLock} and
+@key{Shift} states.
+
+This command is only available on PC BIOS systems. It will have no effect unless
+and until you use the @command{terminal_input} command to activate the @samp{ext_kbd}
+input terminal:
+
+@example
+terminal_input ext_kbd
+@end example
+@end deffn
+
+
@node terminal_input
@subsection terminal_input
diff -Naur grub.orig/grub-core/Makefile.core.def grub/grub-core/Makefile.core.def
--- grub.orig/grub-core/Makefile.core.def 2015-07-23 12:11:11.000000000 +0200
+++ grub/grub-core/Makefile.core.def 2015-07-26 14:15:05.476288703 +0200
@@ -2313,3 +2313,9 @@
common = loader/i386/xen_file64.c;
extra_dist = loader/i386/xen_fileXX.c;
};
+
+module = {
+ name = ext_kbd;
+ i386_pc = term/i386/pc/ext_kbd.c;
+ enable = i386_pc;
+};
diff -Naur grub.orig/grub-core/term/i386/pc/ext_kbd.c grub/grub-core/term/i386/pc/ext_kbd.c
--- grub.orig/grub-core/term/i386/pc/ext_kbd.c 1970-01-01 01:00:00.000000000 +0100
+++ grub/grub-core/term/i386/pc/ext_kbd.c 2015-07-26 14:10:31.492277000 +0200
@@ -0,0 +1,658 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2002,2003,2005,2007,2008,2009 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/dl.h>
+#include <grub/machine/memory.h>
+#include <grub/term.h>
+#include <grub/extcmd.h>
+#include <grub/types.h>
+#include <grub/machine/int.h>
+
+#define GRUB_SETKEY_KEYMAP_TABLE_SIZE 128
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static const struct grub_arg_option options_setkey[] =
+ {
+ /********************************************************************************************************/
+ /* */
+ /* The 'setkey' command does not provide any specific options. */
+ /* This entry is required, however, to make the '--help' and '--usage' options work. */
+ /* */
+ /********************************************************************************************************/
+ { 0 , /* const char *longarg */
+ 0 , /* int shortarg */
+ 0 , /* int flags */
+ 0 , /* const char *doc */
+ 0 , /* const char *arg */
+ 0 /* grub_arg_type_t type */
+ } /******************************/
+ } ;
+
+static const struct grub_arg_option options_setnumpad[] =
+ {
+ /********************************************************************************************************/
+ /* */
+ /* The '--force' option. */
+ /* */
+ /********************************************************************************************************/
+ { "force" , /* const char *longarg */
+ 'f' , /* int shortarg */
+ 0 , /* int flags */
+ N_("Force the keys on the numeric keypad " /* const char *doc */
+ "to emit the numeric characters on their keycaps, " /* */
+ "irrespective of the NumLock and the Shift key states.") , /* */
+ 0 , /* const char *arg */
+ ARG_TYPE_NONE /* grub_arg_type_t type */
+ } , /******************************/
+ /********************************************************************************************************/
+ /* */
+ /* The '--noforce' option. */
+ /* */
+ /********************************************************************************************************/
+ { "noforce" , /* const char *longarg */
+ 'n' , /* int shortarg */
+ 0 , /* int flags */
+ N_("(Default) " /* const char *doc */
+ "Restore default behavior of the keys on the numeric keypad, " /* */
+ "which depends on the NumLock and the Shift key states.") , /* */
+ 0 , /* const char *arg */
+ ARG_TYPE_NONE /* grub_arg_type_t type */
+ } , /******************************/
+ /********************************************************************************************************/
+ /* */
+ /* End of option definitions. */
+ /* */
+ /********************************************************************************************************/
+ { 0 , /* const char *longarg */
+ 0 , /* int shortarg */
+ 0 , /* int flags */
+ 0 , /* const char *doc */
+ 0 , /* const char *arg */
+ 0 /* grub_arg_type_t type */
+ } /******************************/
+ } ;
+
+static const struct grub_setkey_numpad_entry
+ {
+ grub_uint16_t keycode;
+ grub_uint16_t keycode_shifted;
+ int grubkey;
+ int grubkey_shifted;
+ }
+ numpad_table[] =
+ {
+ { 0x4f00 , 0x4f31 , 0x0080004f , 0x00000031 } , /* Numeric Keypad '1'. */
+ { 0x5000 , 0x5032 , 0x00800050 , 0x00000032 } , /* Numeric Keypad '2'. */
+ { 0x5100 , 0x5133 , 0x00800051 , 0x00000033 } , /* Numeric Keypad '3'. */
+ { 0x4b00 , 0x4b34 , 0x0080004b , 0x00000034 } , /* Numeric Keypad '4'. */
+ { 0x4c00 , 0x4c35 , 0x0080004c , 0x00000035 } , /* Numeric Keypad '5'. */
+ { 0x4d00 , 0x4d36 , 0x0080004d , 0x00000036 } , /* Numeric Keypad '6'. */
+ { 0x4700 , 0x4737 , 0x00800047 , 0x00000037 } , /* Numeric Keypad '7'. */
+ { 0x4800 , 0x4838 , 0x00800048 , 0x00000038 } , /* Numeric Keypad '8'. */
+ { 0x4900 , 0x4939 , 0x00800049 , 0x00000039 } , /* Numeric Keypad '9'. */
+ { 0x5200 , 0x5230 , 0x00800052 , 0x00000030 } , /* Numeric Keypad '0'. */
+ { 0x5300 , 0x532e , 0x00800053 , 0x0000002e } , /* Numeric Keypad '.'. */
+ { 0xe02f , 0xe02f , 0x0000002f , 0x0000002f } , /* Numeric Keypad '/'. */
+ { 0x372a , 0x372a , 0x0000002a , 0x0000002a } , /* Numeric Keypad '*'. */
+ { 0x4a2d , 0x4a2d , 0x0000002d , 0x0000002d } , /* Numeric Keypad '-'. */
+ { 0x4e2b , 0x4e2b , 0x0000002b , 0x0000002b } , /* Numeric Keypad '+'. */
+ { 0xe00d , 0xe00d , 0x0000000d , 0x0000000d } /* Numeric Keypad 'Enter'. */
+ } ;
+
+static const struct grub_setkey_keysym_entry
+ {
+ const char *name;
+ grub_uint16_t keycode;
+ }
+ keysym_table[] =
+ {
+ { "a" , 0x1e61 } ,
+ { "b" , 0x3062 } ,
+ { "c" , 0x2e63 } ,
+ { "d" , 0x2064 } ,
+ { "e" , 0x1265 } ,
+ { "f" , 0x2166 } ,
+ { "g" , 0x2267 } ,
+ { "h" , 0x2368 } ,
+ { "i" , 0x1769 } ,
+ { "j" , 0x246a } ,
+ { "k" , 0x256b } ,
+ { "l" , 0x266c } ,
+ { "m" , 0x326d } ,
+ { "n" , 0x316e } ,
+ { "o" , 0x186f } ,
+ { "p" , 0x1970 } ,
+ { "q" , 0x1071 } ,
+ { "r" , 0x1372 } ,
+ { "s" , 0x1f73 } ,
+ { "t" , 0x1474 } ,
+ { "u" , 0x1675 } ,
+ { "v" , 0x2f76 } ,
+ { "w" , 0x1177 } ,
+ { "x" , 0x2d78 } ,
+ { "y" , 0x1579 } ,
+ { "z" , 0x2c7a } ,
+ { "A" , 0x1e41 } ,
+ { "B" , 0x3042 } ,
+ { "C" , 0x2e43 } ,
+ { "D" , 0x2044 } ,
+ { "E" , 0x1245 } ,
+ { "F" , 0x2146 } ,
+ { "G" , 0x2247 } ,
+ { "H" , 0x2348 } ,
+ { "I" , 0x1749 } ,
+ { "J" , 0x244a } ,
+ { "K" , 0x254b } ,
+ { "L" , 0x264c } ,
+ { "M" , 0x324d } ,
+ { "N" , 0x314e } ,
+ { "O" , 0x184f } ,
+ { "P" , 0x1950 } ,
+ { "Q" , 0x1051 } ,
+ { "R" , 0x1352 } ,
+ { "S" , 0x1f53 } ,
+ { "T" , 0x1454 } ,
+ { "U" , 0x1655 } ,
+ { "V" , 0x2f56 } ,
+ { "W" , 0x1157 } ,
+ { "X" , 0x2d58 } ,
+ { "Y" , 0x1559 } ,
+ { "Z" , 0x2c5a } ,
+ { "0" , 0x0b30 } ,
+ { "1" , 0x0231 } ,
+ { "2" , 0x0332 } ,
+ { "3" , 0x0433 } ,
+ { "4" , 0x0534 } ,
+ { "5" , 0x0635 } ,
+ { "6" , 0x0736 } ,
+ { "7" , 0x0837 } ,
+ { "8" , 0x0938 } ,
+ { "9" , 0x0a39 } ,
+ { "ampersand" , 0x0826 } ,
+ { "asterisk" , 0x092a } ,
+ { "at" , 0x0340 } ,
+ { "backslash" , 0x2b5c } ,
+ { "backslashx" , 0x565c } ,
+ { "backquote" , 0x2960 } ,
+ { "backspace" , 0x0e08 } ,
+ { "bar" , 0x2b7c } ,
+ { "barx" , 0x567c } ,
+ { "braceleft" , 0x1a7b } ,
+ { "braceright" , 0x1b7d } ,
+ { "bracketleft" , 0x1a5b } ,
+ { "bracketright" , 0x1b5d } ,
+ { "caret" , 0x075e } ,
+ { "colon" , 0x273a } ,
+ { "comma" , 0x332c } ,
+ { "delete" , 0x53e0 } ,
+ { "dollar" , 0x0524 } ,
+ { "doublequote" , 0x2822 } ,
+ { "enter" , 0x1c0d } ,
+ { "equal" , 0x0d3d } ,
+ { "escape" , 0x011b } ,
+ { "exclam" , 0x0221 } ,
+ { "greater" , 0x343e } ,
+ { "less" , 0x333c } ,
+ { "minus" , 0x0c2d } ,
+ { "numbersign" , 0x0423 } ,
+ { "parenleft" , 0x0a28 } ,
+ { "parenright" , 0x0b29 } ,
+ { "percent" , 0x0625 } ,
+ { "period" , 0x342e } ,
+ { "plus" , 0x0d2b } ,
+ { "question" , 0x353f } ,
+ { "quote" , 0x2827 } ,
+ { "semicolon" , 0x273b } ,
+ { "slash" , 0x352f } ,
+ { "space" , 0x3920 } ,
+ { "tab" , 0x0f09 } ,
+ { "tilde" , 0x297e } ,
+ { "underscore" , 0x0c5f } ,
+ { "F1" , 0x3b00 } ,
+ { "F2" , 0x3c00 } ,
+ { "F3" , 0x3d00 } ,
+ { "F4" , 0x3e00 } ,
+ { "F5" , 0x3f00 } ,
+ { "F6" , 0x4000 } ,
+ { "F7" , 0x4100 } ,
+ { "F8" , 0x4200 } ,
+ { "F9" , 0x4300 } ,
+ { "F10" , 0x4400 } ,
+ { "F11" , 0x8500 } ,
+ { "F12" , 0x8600 }
+ } ;
+
+static const grub_uint16_t bypass_table[] =
+ {
+ 0x0e00 | '\b' , /* Backspace. */
+ 0x0100 | '\e' , /* Escape. */
+ 0x1c00 | '\n' , /* Line Feed. */
+ 0x1c00 | '\r' , /* Carriage Return. */
+ 0x0f00 | '\t' /* Tab. */
+ } ;
+
+static int numpad_force = 0;
+
+static struct grub_setkey_keymap_entry
+ {
+ grub_uint16_t keycode_from;
+ grub_uint16_t keycode_to;
+ }
+ keymap_table[GRUB_SETKEY_KEYMAP_TABLE_SIZE];
+
+/*
+ * grubkey_numpad - For a key code that corresponds to a key on the
+ * numeric keypad, return the GRUB key value. If the
+ * 'setnumpad --force' option is in effect, then return
+ * the printable ASCII character, irrespective of the
+ * NumLock and the Shift key states; otherwise, do not
+ * remap the key code.
+ * For a key code that does not belong to the numeric
+ * keypad, return 0.
+ */
+static int
+grubkey_numpad (grub_uint16_t key)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (numpad_table); i++)
+ if (key == numpad_table[i].keycode)
+ if (numpad_force)
+ return numpad_table[i].grubkey_shifted;
+ else
+ return numpad_table[i].grubkey;
+ else if (key == numpad_table[i].keycode_shifted)
+ return numpad_table[i].grubkey_shifted;
+ return 0;
+}
+
+/*
+ * grubkey_mapkey - If a mapping entry was set up for the given key code,
+ * then return the remapped key code.
+ * Otherwise, return the given key code unchanged.
+ */
+static grub_uint16_t
+grubkey_mapkey (grub_uint16_t key)
+{
+ unsigned int i;
+
+ for (i = 0; i < GRUB_SETKEY_KEYMAP_TABLE_SIZE; i++)
+ if (!keymap_table[i].keycode_from)
+ break;
+ else if (key == keymap_table[i].keycode_from)
+ return keymap_table[i].keycode_to;
+ return (key);
+}
+
+/*
+ * grubkey_bypass - For a key code that produces a 'well-known' ASCII
+ * control character (cfr. 'bypass_table', above), return
+ * the ASCII character value.
+ * For any other key code, return 0.
+ */
+static int
+grubkey_bypass (grub_uint16_t key)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (bypass_table); i++)
+ if (key == bypass_table[i])
+ return key & 0xff;
+ return 0;
+}
+
+/*
+ * grub_ext_kbd_xlat - Convert a key code to a GRUB key value, while
+ * taking into account any key mapping entries that
+ * were requested by the 'setkey' and the 'setnumpad'
+ * commands.
+ * If the key code corresponds to a key on the
+ * numeric keypad, then:
+ * - If the '--force' option of the 'setnumpad'
+ * command is in effect, then return the numeric
+ * ASCII character for the key, irrespective of
+ * the NumLock and Shift key states.
+ * - Otherwise, return either the printable ASCII
+ * character, or the extended GRUB key value,
+ * depending on the NumLock and Shift key states.
+ * Any other key will first be remapped according to
+ * the mapping entries set up through the 'setkey'
+ * command. Then:
+ * - If the key code does not produce an ASCII
+ * character, then return its extended GRUB key
+ * value.
+ * - If the key code produces a printable ASCII
+ * character (including DEL), then return that.
+ * - Otherwise, the key code will produce an ASCII
+ * control character.
+ * For a 'well-known' ASCII control character,
+ * return its ASCII character value; for any
+ * other ASCII control character, return the
+ * GRUB control key value.
+ *
+ * This function will be called by the 'ext_kbd'
+ * input terminal whenever it reads a keystroke from
+ * the keyboard.
+ */
+static int
+grub_ext_kbd_xlat (grub_uint16_t key)
+{
+ int grubkey;
+
+ /*
+ * Handle the keys on the numeric keypad. These should not be remapped,
+ * except according to the 'numpad_force' setting.
+ */
+ if ((grubkey = grubkey_numpad (key)))
+ return grubkey;
+
+ /*
+ * Remap the key according to the keymap table.
+ */
+ key = grubkey_mapkey (key);
+
+ /*
+ * Handle extended keys, i.e., those for which the ASCII character is
+ * either null (0x00) or the extended key indicator (0xe0).
+ * Note that, instead of testing for the extact value of 0xe0, the code
+ * here simply tests if the high-order bit of the ASCII character is
+ * set. (No other value with the high-order bit set should ever appear
+ * for a correctly functioning keyboard.)
+ */
+ if ((!(key & 0xff)) || (key & 0x80))
+ return (key >> 8) | GRUB_TERM_EXTENDED;
+
+
+ /*
+ * Handle printable ASCII characters (including DEL).
+ */
+ if ((key & 0xff) >= ' ')
+ return key & 0xff;
+
+ /*
+ * Handle well-known control characters.
+ */
+ if ((grubkey = grubkey_bypass (key)))
+ return grubkey;
+
+ /*
+ * Handle the less common control characters.
+ */
+ return (key & 0xff) + (('a' - 1) | GRUB_TERM_CTRL);
+}
+
+/*
+ * grub_keysym_code - Return the key code that corresponds to the given
+ * name (cfr. 'keysym_table', above).
+ * If an invalid name is given, then return 0.
+ */
+static grub_uint16_t
+grub_keysym_code (char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (keysym_table); i++)
+ if (!grub_strcmp (name, keysym_table[i].name))
+ return keysym_table[i].keycode;
+ return 0;
+}
+
+/*
+ * grubkey_map_entry - Return the subscript of the keymap entry for which
+ * the keycode_from value is equal to the given key
+ * code.
+ * If no keymap entry exists for the given key code,
+ * then return the subscript of the first empty entry.
+ *
+ * Since the keymap table should be large enough to
+ * hold an entry for all supported keycode values,
+ * plus at least one terminating null entry, the
+ * subscript returned by this function should not
+ * go out of range.
+ */
+static unsigned int
+grubkey_map_entry (grub_uint16_t key)
+{
+ unsigned int i;
+
+ for (i = 0; i < GRUB_SETKEY_KEYMAP_TABLE_SIZE; i++)
+ if (!keymap_table[i].keycode_from)
+ break;
+ else if (key == keymap_table[i].keycode_from)
+ break;
+ return i;
+}
+
+/*
+ * grub_cmd_setkey - Implement the 'setkey' command.
+ * If no arguments are given, then clear any key mapping
+ * entries that were set up.
+ * With one argument (or with two equal arguments),
+ * delete the mapping entry for the given key.
+ * With two (unequal) arguments, set up a key mapping
+ * entry for the key that corresponds to the second
+ * argument string (i.e., FROM_KEY), and make it output
+ * the key code that corresponds to the first argument
+ * string instead (i.e., TO_KEY).
+ */
+static grub_err_t
+grub_cmd_setkey (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char *args[])
+{
+ if (argc > 2)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("too many parameters"));
+ if (!argc)
+ /*
+ * Clear the keymap table.
+ */
+ grub_memset (keymap_table, 0, GRUB_SETKEY_KEYMAP_TABLE_SIZE * sizeof (keymap_table[0]));
+ else
+ {
+ grub_uint16_t keycode_from;
+ grub_uint16_t keycode_to;
+ unsigned int i_keymap;
+
+ /*
+ * CAUTION: The argc value is decremented here.
+ * Consequently, if two arguments were given, then argc
+ * will be set to 1 from this point on.
+ * Otherwise, only one argument was present, and argc will
+ * be 0.
+ * All other cases were excluded by the code above.
+ * Note also that args[argc] will reference the last
+ * argument string.
+ */
+ argc--;
+ /*
+ * The last argument string is FROM_KEY.
+ */
+ keycode_from = grub_keysym_code (args[argc]);
+ keycode_to = 0;
+ if (argc && grub_strcmp (args[0], args[1]))
+ /*
+ * The first argument string is TO_KEY.
+ */
+ if (!(keycode_to = grub_keysym_code (args[0])))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter `%s'"), args[0]);
+ if (!keycode_from)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter `%s'"), args[argc]);
+ if ((i_keymap = grubkey_map_entry (keycode_from)) >= GRUB_SETKEY_KEYMAP_TABLE_SIZE)
+ /*
+ * This should not happen, since the keymap table should be large
+ * enough to hold a keymap entry for all supported keycode values,
+ * plus at least one terminating null entry.
+ */
+ {
+ if (keycode_to)
+ return grub_error (GRUB_ERR_BUG, N_("keymap table full"));
+ }
+ else if (keycode_to)
+ {
+ keymap_table[i_keymap].keycode_from = keycode_from;
+ keymap_table[i_keymap].keycode_to = keycode_to;
+ }
+ else if (keymap_table[i_keymap].keycode_from)
+ grub_memmove (keymap_table + i_keymap, keymap_table + (i_keymap + 1),
+ (GRUB_SETKEY_KEYMAP_TABLE_SIZE - i_keymap - 1) * sizeof (keymap_table[0]));
+ }
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * grub_cmd_setnumpad - Implement the 'setnumpad' command.
+ * When the '--force' option is given, make the
+ * numeric keypad output printable ASCII characters,
+ * irrespective of the NumLock and the Shift key
+ * states.
+ * With the '--noforce' option, or when no option is
+ * specified, the default behavior of the numeric
+ * keypad (depending on the NumLock and the Shift key
+ * key states) will be restored.
+ */
+static grub_err_t
+grub_cmd_setnumpad (grub_extcmd_context_t ctxt, int argc, char *args[] __attribute__ ((unused)))
+{
+ if (argc)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("too many parameters"));
+ if ((ctxt->state[0].set) && (ctxt->state[1].set))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("conflicting options"));
+ numpad_force = ctxt->state[0].set;
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * grub_ext_kbd_getkey - If a character is pending, then return it.
+ * Otherwise, return GRUB_TERM_NO_KEY (i.e., -1).
+ *
+ * BIOS call 'INT 16H Function 11H' checks whether
+ * a character is pending, supporting so-called
+ * 'extended' key codes.
+ * Call this function with:
+ * - %ah = 0x11.
+ * When the function returns:
+ * - If a character is pending, then:
+ * - Zero flag is clear.
+ * - %ah = keyboard scan code.
+ * - %al = ASCII character.
+ * - If there is no character pending, then:
+ * - Zero flag is set.
+ *
+ * BIOS call 'INT 16H Function 10H' gets a character
+ * from the keyboard, again supporting 'extended'
+ * key codes.
+ * Call this function with:
+ * - %ah = 0x10.
+ * When the function returns:
+ * - %ah = keyboard scan code.
+ * - %al = ASCII character.
+ */
+static int
+grub_ext_kbd_getkey (struct grub_term_input *term __attribute__ ((unused)))
+{
+ struct grub_bios_int_registers regs;
+
+ /*
+ * Check if a character is pending.
+ */
+ regs.eax = 0x1100;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x16, ®s);
+ if (regs.flags & GRUB_CPU_INT_FLAGS_ZERO)
+ return GRUB_TERM_NO_KEY;
+
+ /*
+ * Read the character that is pending.
+ */
+ regs.eax = 0x1000;
+ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
+ grub_bios_interrupt (0x16, ®s);
+
+ /*
+ * Process the key code that was read from the keyboard, and return the
+ * corresponding GRUB key code.
+ */
+ return grub_ext_kbd_xlat (regs.eax);
+}
+
+static const struct grub_machine_bios_data_area *bios_data_area =
+ (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR;
+
+/*
+ * grub_ext_kbd_getkeystatus - Return the Shift, Ctrl, and Alt modifier
+ * states.
+ */
+static int
+grub_ext_kbd_getkeystatus (struct grub_term_input *term __attribute__ ((unused)))
+{
+ /* conveniently GRUB keystatus is modelled after BIOS one. */
+ return bios_data_area->keyboard_flag_lower & ~0x80;
+}
+
+static struct grub_term_input grub_ext_kbd_term_input =
+ {
+ .name = "ext_kbd",
+ .getkey = grub_ext_kbd_getkey,
+ .getkeystatus = grub_ext_kbd_getkeystatus
+ };
+
+static grub_extcmd_t cmd_setkey;
+static grub_extcmd_t cmd_setnumpad;
+
+GRUB_MOD_INIT(ext_kbd)
+{
+ grub_term_register_input ("ext_kbd", &grub_ext_kbd_term_input);
+ cmd_setkey = grub_register_extcmd ( /* const char *name */ "setkey"
+ , /* grub_extcmd_func_t func */ grub_cmd_setkey
+ , /* grub_command_flags_t flags */ 0
+ , /* const char *summary */ N_("[[TO_KEY] FROM_KEY]")
+ , /* const char *description */ N_("Change the keyboard map.\n"
+ "The key FROM_KEY is mapped to the key TO_KEY.\n"
+ "If TO_KEY is missing, or if it is equal to FROM_KEY, "
+ "then remove the mapping entry.\n"
+ "If no parameters are specified, then remove all key mappings.\n\n"
+ "A key must be:\n"
+ " - a lowercase letter;\n"
+ " - an uppercase letter;\n"
+ " - a decimal digit;\n"
+ " - a function key, F1 through F12;\n"
+ "or one of the following:\n"
+ " ampersand barx delete less question\n"
+ " asterisk braceleft dollar minus quote\n"
+ " at braceright doublequote numbersign semicolon\n"
+ " backslash bracketleft enter parenleft slash\n"
+ " backslashx bracketright equal parenright space\n"
+ " backquote caret escape percent tab\n"
+ " backspace colon exclam period tilde\n"
+ " bar comma greater plus underscore")
+ , /* const struct grub_arg_option *parser */ options_setkey
+ ) ;
+ cmd_setnumpad = grub_register_extcmd ( /* const char *name */ "setnumpad"
+ , /* grub_extcmd_func_t func */ grub_cmd_setnumpad
+ , /* grub_command_flags_t flags */ 0
+ , /* const char *summary */ N_("[--force|--noforce]")
+ , /* const char *description */ N_("Change the behavior of the numeric keypad.\n")
+ , /* const struct grub_arg_option *parser */ options_setnumpad
+ ) ;
+}
+
+GRUB_MOD_FINI(ext_kbd)
+{
+ grub_unregister_extcmd (cmd_setnumpad);
+ grub_unregister_extcmd (cmd_setkey);
+ grub_term_unregister_input (&grub_ext_kbd_term_input);
+}
diff -Naur grub.orig/include/grub/i386/pc/memory.h grub/include/grub/i386/pc/memory.h
--- grub.orig/include/grub/i386/pc/memory.h 2015-07-23 12:11:11.000000000 +0200
+++ grub/include/grub/i386/pc/memory.h 2015-07-26 14:10:24.952277000 +0200
@@ -45,7 +45,7 @@
#ifndef ASM_FILE
-/* See http://heim.ifi.uio.no/~stanisls/helppc/bios_data_area.html for a
+/* See http://stanislavs.org/helppc/bios_data_area.html for a
description of the BIOS Data Area layout. */
struct grub_machine_bios_data_area
{