File grub.tastaturbelegung.patch of Package grub2
From: Olaf Hering <olaf@aepfle.de>
Date: Wed, 13 Dec 2017 08:14:44 +0000
Subject: tastaturbelegung
---
grub-core/term/efi/console.c | 156 +++++-
grub-core/term/i386/pc/console.c | 210 ++++++++-
2 files changed, 352 insertions(+), 14 deletions(-)
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -195,52 +195,204 @@ grub_console_putchar (struct grub_term_output *term,
}
const unsigned efi_codes[] =
{
0, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_RIGHT,
GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_END, GRUB_TERM_KEY_INSERT,
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, GRUB_TERM_ESC
};
+static const int tastatur_deutsch[] = {
+ /* Reihe 1, ohne Shift */
+ ['`'] = '^',
+ ['1'] = '1',
+ ['2'] = '2',
+ ['3'] = '3',
+ ['4'] = '4',
+ ['5'] = '5',
+ ['6'] = '6',
+ ['7'] = '7',
+ ['8'] = '8',
+ ['9'] = '9',
+ ['0'] = '0',
+ ['-'] = 'ß',
+ ['='] = '´',
+
+ /* Reihe 2, ohne Shift */
+ ['q'] = 'q',
+ ['w'] = 'w',
+ ['e'] = 'e',
+ ['r'] = 'r',
+ ['t'] = 't',
+ ['y'] = 'z',
+ ['u'] = 'u',
+ ['i'] = 'i',
+ ['o'] = 'o',
+ ['p'] = 'p',
+ ['['] = 'ü',
+ [']'] = '+',
+
+ /* Reihe 3, ohne Shift */
+ ['a'] = 'a',
+ ['s'] = 's',
+ ['d'] = 'd',
+ ['f'] = 'f',
+ ['g'] = 'g',
+ ['h'] = 'h',
+ ['j'] = 'j',
+ ['k'] = 'k',
+ ['l'] = 'l',
+ [';'] = 'ö',
+ ['\''] = 'ä',
+ ['\\'] = '#',
+
+ /* Reihe 4, ohne Shift */
+/* ['\\'] = '<', */
+ ['z'] = 'y',
+ ['x'] = 'x',
+ ['c'] = 'c',
+ ['v'] = 'v',
+ ['b'] = 'b',
+ ['n'] = 'n',
+ ['m'] = 'm',
+ [','] = ',',
+ ['.'] = '.',
+ ['/'] = '-',
+
+ /* Reihe 1, mit Shift */
+ ['~'] = '\0',
+ ['!'] = '!',
+ ['@'] = '"',
+ ['#'] = '§',
+ ['$'] = '$',
+ ['%'] = '%',
+ ['^'] = '&',
+ ['&'] = '/',
+ ['*'] = '(',
+ ['('] = ')',
+ [')'] = '=',
+ ['_'] = '?',
+ ['+'] = '`',
+
+ /* Reihe 2, mit Shift */
+ ['Q'] = 'Q',
+ ['W'] = 'W',
+ ['E'] = 'E',
+ ['R'] = 'R',
+ ['T'] = 'T',
+ ['Y'] = 'Z',
+ ['U'] = 'U',
+ ['I'] = 'I',
+ ['O'] = 'O',
+ ['P'] = 'P',
+ ['{'] = 'Ü',
+ ['}'] = '*',
+
+
+ /* Reihe 3, mit Shift */
+ ['A'] = 'A',
+ ['S'] = 'S',
+ ['D'] = 'D',
+ ['F'] = 'F',
+ ['G'] = 'G',
+ ['H'] = 'H',
+ ['J'] = 'J',
+ ['K'] = 'K',
+ ['L'] = 'L',
+ [':'] = 'Ö',
+ ['"'] = 'ä',
+ ['|'] = '#',
+
+ /* Reihe 4, mit Shift */
+/* ['|'] = '>',*/
+ ['Z'] = 'Y',
+ ['X'] = 'X',
+ ['C'] = 'C',
+ ['V'] = 'V',
+ ['B'] = 'B',
+ ['N'] = 'N',
+ ['M'] = 'M',
+ ['<'] = ';',
+ ['>'] = ':',
+ ['?'] = '_',
+
+};
+
+static struct belegung {
+ const char *hinweis;
+ const char *name;
+ const int *map;
+} belegung[] = {
+ {
+ .hinweis = "Tastaturbelegung ist jetzt",
+ .name = "deutsch",
+ .map = tastatur_deutsch,
+ },
+ {
+ .name = "none",
+ .map = NULL,
+ },
+};
+static int *tastatur_belegung;
+
+static int deutsch(grub_efi_char16_t unicode_char)
+{
+ int i, ret;
+ if (!tastatur_belegung) {
+ for (i = 0; belegung[i].map; i++)
+ {
+ if (grub_strcmp("deutsch", belegung[i].name) == 0)
+ {
+ grub_printf("%s %s\n", belegung[i].hinweis ? : "", belegung[i].name);
+ tastatur_belegung = belegung[i].map;
+ }
+ }
+ }
+ ret = i = unicode_char;
+ if (tastatur_belegung && tastatur_belegung[i])
+ ret = tastatur_belegung[i];
+ return ret;
+}
+
static int
grub_efi_translate_key (grub_efi_input_key_t key)
{
if (key.scan_code == 0)
{
/* Some firmware implementations use VT100-style codes against the spec.
This is especially likely if driven by serial.
*/
if (key.unicode_char < 0x20 && key.unicode_char != 0
&& key.unicode_char != '\t' && key.unicode_char != '\b'
&& key.unicode_char != '\n' && key.unicode_char != '\r')
return GRUB_TERM_CTRL | (key.unicode_char - 1 + 'a');
else
- return key.unicode_char;
+ return deutsch(key.unicode_char);
}
/* Some devices use power key (key.scan_code 0x0102, suspend) as Enter. */
else if (key.scan_code == 0x0102)
return '\r';
/* Some devices send enter with scan_code 0x0d (F3) and unicode_char 0x0d. */
else if (key.scan_code == '\r' && key.unicode_char == '\r')
return key.unicode_char;
else if (key.scan_code < ARRAY_SIZE (efi_codes))
return efi_codes[key.scan_code];
if ((key.unicode_char >= 0x20 && key.unicode_char <= 0x7f)
|| key.unicode_char == '\t' || key.unicode_char == '\b'
|| key.unicode_char == '\n' || key.unicode_char == '\r')
- return key.unicode_char;
+ return deutsch(key.unicode_char);
return GRUB_TERM_NO_KEY;
}
static int
grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused)))
{
grub_efi_simple_input_interface_t *i;
grub_efi_input_key_t key;
grub_efi_status_t status;
i = grub_efi_system_table->con_in;
--- a/grub-core/term/i386/pc/console.c
+++ b/grub-core/term/i386/pc/console.c
@@ -11,24 +11,25 @@
* 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/machine/memory.h>
#include <grub/machine/console.h>
#include <grub/term.h>
#include <grub/types.h>
+#include <grub/command.h>
#include <grub/machine/int.h>
static grub_uint8_t grub_console_cur_color = 0x7;
static void
int10_9 (grub_uint8_t ch, grub_uint16_t n)
{
struct grub_bios_int_registers regs;
regs.eax = ch | 0x0900;
regs.ebx = grub_console_cur_color & 0xff;
regs.ecx = n;
@@ -114,31 +115,24 @@ grub_console_putchar_real (grub_uint8_t c)
/* check the column with the width */
if (pos.x >= 79)
{
grub_console_putchar_real (0x0d);
grub_console_putchar_real (0x0a);
}
else
grub_console_gotoxy (NULL, (struct grub_term_coordinate) { pos.x + 1,
pos.y });
}
-static void
-grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
- const struct grub_unicode_glyph *c)
-{
- grub_console_putchar_real (c->base);
-}
-
/*
* BIOS call "INT 10H Function 09h" to write character and attribute
* Call with %ah = 0x09
* %al = (character)
* %bh = (page number)
* %bl = (attribute)
* %cx = (number of times)
*/
static void
grub_console_cls (struct grub_term_output *term)
{
/* move the cursor to the beginning */
@@ -191,60 +185,219 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
* If key waiting to be input:
* %ah = keyboard scan code
* %al = ASCII character
* Zero flag = clear
* else
* Zero flag = set
* BIOS call "INT 16H Function 00H" to read character from keyboard
* Call with %ah = 0x0
* Return: %ah = keyboard scan code
* %al = ASCII character
*/
+static const int tastatur_deutsch[] = {
+ /* Reihe 1, ohne Shift */
+ ['`'] = '^',
+ ['1'] = '1',
+ ['2'] = '2',
+ ['3'] = '3',
+ ['4'] = '4',
+ ['5'] = '5',
+ ['6'] = '6',
+ ['7'] = '7',
+ ['8'] = '8',
+ ['9'] = '9',
+ ['0'] = '0',
+ ['-'] = 'ß',
+ ['='] = '´',
+
+ /* Reihe 2, ohne Shift */
+ ['q'] = 'q',
+ ['w'] = 'w',
+ ['e'] = 'e',
+ ['r'] = 'r',
+ ['t'] = 't',
+ ['y'] = 'z',
+ ['u'] = 'u',
+ ['i'] = 'i',
+ ['o'] = 'o',
+ ['p'] = 'p',
+ ['['] = 'ü',
+ [']'] = '+',
+
+ /* Reihe 3, ohne Shift */
+ ['a'] = 'a',
+ ['s'] = 's',
+ ['d'] = 'd',
+ ['f'] = 'f',
+ ['g'] = 'g',
+ ['h'] = 'h',
+ ['j'] = 'j',
+ ['k'] = 'k',
+ ['l'] = 'l',
+ [';'] = 'ö',
+ ['\''] = 'ä',
+ ['\\'] = '#',
+
+ /* Reihe 4, ohne Shift */
+/* ['\\'] = '<', */
+ ['z'] = 'y',
+ ['x'] = 'x',
+ ['c'] = 'c',
+ ['v'] = 'v',
+ ['b'] = 'b',
+ ['n'] = 'n',
+ ['m'] = 'm',
+ [','] = ',',
+ ['.'] = '.',
+ ['/'] = '-',
+
+ /* Reihe 1, mit Shift */
+ ['~'] = '\0',
+ ['!'] = '!',
+ ['@'] = '"',
+ ['#'] = '§',
+ ['$'] = '$',
+ ['%'] = '%',
+ ['^'] = '&',
+ ['&'] = '/',
+ ['*'] = '(',
+ ['('] = ')',
+ [')'] = '=',
+ ['_'] = '?',
+ ['+'] = '`',
+
+ /* Reihe 2, mit Shift */
+ ['Q'] = 'Q',
+ ['W'] = 'W',
+ ['E'] = 'E',
+ ['R'] = 'R',
+ ['T'] = 'T',
+ ['Y'] = 'Z',
+ ['U'] = 'U',
+ ['I'] = 'I',
+ ['O'] = 'O',
+ ['P'] = 'P',
+ ['{'] = 'Ü',
+ ['}'] = '*',
+
+
+ /* Reihe 3, mit Shift */
+ ['A'] = 'A',
+ ['S'] = 'S',
+ ['D'] = 'D',
+ ['F'] = 'F',
+ ['G'] = 'G',
+ ['H'] = 'H',
+ ['J'] = 'J',
+ ['K'] = 'K',
+ ['L'] = 'L',
+ [':'] = 'Ö',
+ ['"'] = 'ä',
+ ['|'] = '#',
+
+ /* Reihe 4, mit Shift */
+/* ['|'] = '>',*/
+ ['Z'] = 'Y',
+ ['X'] = 'X',
+ ['C'] = 'C',
+ ['V'] = 'V',
+ ['B'] = 'B',
+ ['N'] = 'N',
+ ['M'] = 'M',
+ ['<'] = ';',
+ ['>'] = ':',
+ ['?'] = '_',
+
+};
+
+static struct belegung {
+ const char *hinweis;
+ const char *name;
+ const int *map;
+} belegung[] = {
+ {
+ .hinweis = "Tastaturbelegung ist jetzt",
+ .name = "deutsch",
+ .map = tastatur_deutsch,
+ },
+ {
+ .name = "none",
+ .map = NULL,
+ },
+};
+static int *tastatur_belegung;
static int
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
const grub_uint16_t bypass_table[] = {
0x0100 | GRUB_TERM_ESC, 0x0f00 | GRUB_TERM_TAB, 0x0e00 | GRUB_TERM_BACKSPACE, 0x1c00 | '\r', 0x1c00 | '\n'
};
struct grub_bios_int_registers regs;
unsigned i;
+ int ret, orig;
+ static int prev;
/*
* Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would
* cause the machine to hang at the second keystroke. However, we can
* work around this problem by ensuring the presence of keystroke with
* INT 16/AH = 1 before calling INT 16/AH = 0.
*/
regs.eax = 0x0100;
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;
+ {
+ ret = GRUB_TERM_NO_KEY;
+ goto out;
+ }
regs.eax = 0x0000;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x16, ®s);
if (!(regs.eax & 0xff))
- return ((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED;
+{
+orig =
+ ret = ((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED;
+ goto out;
+ }
if ((regs.eax & 0xff) >= ' ')
- return regs.eax & 0xff;
+{
+orig =
+ ret = regs.eax & 0xff;
+ i = ret;
+ if (tastatur_belegung && tastatur_belegung[i])
+ ret = tastatur_belegung[i];
+ goto out;
+ }
for (i = 0; i < ARRAY_SIZE (bypass_table); i++)
if (bypass_table[i] == (regs.eax & 0xffff))
- return regs.eax & 0xff;
+{
+orig =
+ ret = regs.eax & 0xff;
+ goto out;
+ }
- return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL);
+orig =
+ ret = (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL);
+out:
+ if (0 && ret != prev) {
+ grub_printf("\n %04x %04x > %08x > %04x\n ", regs.eax, regs.flags, orig, ret);
+ prev = ret;
+ }
+ return ret;
}
static int
grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused)))
{
const struct grub_machine_bios_data_area *bios_data_area =
(struct grub_machine_bios_data_area *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR);
/* conveniently GRUB keystatus is modelled after BIOS one. */
return bios_data_area->keyboard_flag_lower & ~0x80;
}
static struct grub_term_coordinate
@@ -264,24 +417,55 @@ grub_console_setcolorstate (struct grub_term_output *term
break;
case GRUB_TERM_COLOR_NORMAL:
grub_console_cur_color = grub_term_normal_color & 0x7f;
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
grub_console_cur_color = grub_term_highlight_color & 0x7f;
break;
default:
break;
}
}
+static grub_err_t
+grub_cmd_tastatur_belegung (struct grub_command *cmd __attribute__ ((unused)),
+ int argc, char *argv[])
+{
+ int i;
+ if (argc < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "layout name required");
+
+ for (i = 0; belegung[i].map; i++)
+ {
+ if (grub_strcmp(argv[0], belegung[i].name) == 0)
+ {
+ grub_printf("%s %s\n", belegung[i].hinweis ? : "", belegung[i].name);
+ tastatur_belegung = belegung[i].map;
+ return GRUB_ERR_NONE;
+ }
+ }
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "layout %s not found.", argv[0]);
+}
+
+static grub_command_t cmd;
+static void
+grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)),
+ const struct grub_unicode_glyph *c)
+{
+ if (!cmd)
+ cmd = grub_register_command ("tastatur_belegung", grub_cmd_tastatur_belegung,
+ 0, N_("Set a keyboard layout."));
+ grub_console_putchar_real (c->base);
+}
+
static struct grub_term_input grub_console_term_input =
{
.name = "console",
.getkey = grub_console_getkey,
.getkeystatus = grub_console_getkeystatus
};
static struct grub_term_output grub_console_term_output =
{
.name = "console",
.putchar = grub_console_putchar,
.getwh = grub_console_getwh,
@@ -295,15 +479,17 @@ static struct grub_term_output grub_console_term_output =
};
void
grub_console_init (void)
{
grub_term_register_output ("console", &grub_console_term_output);
grub_term_register_input ("console", &grub_console_term_input);
}
void
grub_console_fini (void)
{
+ if (cmd)
+ grub_unregister_command (cmd);
grub_term_unregister_input (&grub_console_term_input);
grub_term_unregister_output (&grub_console_term_output);
}