=== added file 'ChangeLog.at_keyboard_layouts' --- ChangeLog.at_keyboard_layouts 1970-01-01 00:00:00 +0000 +++ ChangeLog.at_keyboard_layouts 2010-01-30 00:10:48 +0000 @@ -0,0 +1,19 @@ +2010-01-18 Carles Pina i Estany + + Adds keyboard layouts support (only AT). + + * conf/common.rmk (bin_UTILITIES): Add grub-mklayouts rules. + (pkglib_MODULES): Add module `at_keyboard_layouts.mod'. + * include/grub/at_keyboard.h: New struct `grub_keyboard_map_s'. New + EXPORT_VAR `grub_keyboard_map'. + * include/grub/at_keyboard_layouts.h: New file. + * include/grub/keys.h: Move macros from here ... + * include/grub/term.h: ... to here. New file. + * at_keyboard_layouts/at_keyboard_layouts.c: New file. + * term/at_keyboard.c: Include `'. + (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_term_input): Initialise `grub_keyboard_map->normal' and + `grub_keyboard_map->shift'. + * util/grub-mklayouts.c: New file. === added directory 'at_keyboard_layouts' === added file 'at_keyboard_layouts/at_keyboard_layouts.c' --- at_keyboard_layouts/at_keyboard_layouts.c 1970-01-01 00:00:00 +0000 +++ at_keyboard_layouts/at_keyboard_layouts.c 2010-01-29 23:56:38 +0000 @@ -0,0 +1,194 @@ +/* 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static char original_keyboard_layout_normal[128]; +static char original_keyboard_layout_shift[128]; + +static char *active_layout; + +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]) + 1; + + filename = + grub_malloc (filename_length); + + if (! filename) + return grub_errno; + + grub_snprintf (filename, filename_length, "%s/%s", prefix, args[0]); + + 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, grub_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, grub_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 (grub_keyboard_map->normal, original_keyboard_layout_normal, + 128); + grub_memcpy (grub_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; +} + +GRUB_MOD_INIT (at_keyboard_layouts) +{ + grub_memcpy (original_keyboard_layout_normal, grub_keyboard_map->normal, + 128); + grub_memcpy (original_keyboard_layout_shift, grub_keyboard_map->shift, 128); + + active_layout = grub_strdup("default"); + + grub_register_command_p1 ("at_load_layout", grub_cmd_load_layout, + N_("LAYOUT"), N_("Set up the new layout.")); + + grub_register_command_p1 ("at_show_layout", + grub_cmd_show_active_keyboardlayout, 0, + N_("Show the active layout.")); + + grub_register_command_p1 ("at**", + grub_cmd_set_default_keyboard, 0, + N_("Set up the default keyboard.")); + +} + +GRUB_MOD_FINI (at_keyboard_layouts) +{ + set_default_keyboard(); +} === modified file 'conf/common.rmk' --- conf/common.rmk 2010-01-20 20:31:39 +0000 +++ conf/common.rmk 2010-01-29 23:59:46 +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 @@ -104,6 +108,12 @@ 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 = at_keyboard_layouts/at_keyboard_layouts.c +at_keyboard_layouts_mod_CFLAGS = $(COMMON_CFLAGS) +at_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-01-29 23:31:44 +0000 @@ -19,6 +19,14 @@ #ifndef GRUB_AT_KEYBOARD_HEADER #define GRUB_AT_KEYBOARD_HEADER 1 +struct grub_keyboard_map_s +{ + char *normal; + char *shift; +}; + +extern struct grub_keyboard_map_s *EXPORT_VAR(grub_keyboard_map); + #define SHIFT_L 0x2a #define SHIFT_R 0x36 #define CTRL 0x1d === 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-01-29 23:56:15 +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 . + */ + +#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 . + */ + +#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-01-18 19:43:39 +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 #ifndef ASM_FILE === modified file 'term/at_keyboard.c' --- term/at_keyboard.c 2010-01-10 12:34:48 +0000 +++ term/at_keyboard.c 2010-01-29 23:27:11 +0000 @@ -22,6 +22,9 @@ #include #include #include +#include + +struct grub_keyboard_map_s *grub_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_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_keyboard_map->shift[code]) + key = grub_keyboard_map->shift[code]; else - key = keyboard_map[code]; + key = grub_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_keyboard_map->normal = keyboard_map_normal; + grub_keyboard_map->shift = keyboard_map_shift; } GRUB_MOD_FINI(at_keyboard) === modified file 'util/grub-mkconfig.in' --- util/grub-mkconfig.in 2009-12-12 00:43:32 +0000 +++ util/grub-mkconfig.in 2010-01-18 22:44:55 +0000 @@ -220,7 +220,8 @@ export GRUB_DEFAULT \ GRUB_DISABLE_LINUX_UUID \ GRUB_DISABLE_LINUX_RECOVERY \ GRUB_GFXMODE \ - GRUB_DISABLE_OS_PROBER + GRUB_DISABLE_OS_PROBER \ + GRUB_KEYBOARD_LAYOUT if test "x${grub_cfg}" != "x"; then rm -f ${grub_cfg}.new === added file 'util/grub-mklayouts.c' --- util/grub-mklayouts.c 1970-01-01 00:00:00 +0000 +++ util/grub-mklayouts.c 2010-01-29 23:55:55 +0000 @@ -0,0 +1,308 @@ +/* + * 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 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "progname.h" + +#define CKBCOMP "ckbcomp" + +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 file name. Default is LAYOUT.\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_keymap (char *keymap, char *output_file) +{ + char keyboard_map_normal[128]; + char keyboard_map_shift[128]; + + char line[2048]; + char normal[64]; + char shift[64]; + int key_code; + int i; + pid_t pid; + int pipe_communication[2]; + int ok; + + FILE *fp_pipe; + FILE *fp_output; + + 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 (keyboard_map_normal, 0, 128); + memset (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) + { + keyboard_map_normal[key_code] = (char) get_grub_code (normal); + keyboard_map_shift[key_code] = (char) get_grub_code (shift); + ok = 1; + } + } + } + + add_special_keys (keyboard_map_normal); + + if (ok == 0) + { + fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", + CKBCOMP, keymap); + exit (1); + } + + /* Save the layouts to the file. */ + fp_output = fopen (output_file, "w"); + + if (!fp_output) + { + grub_util_error ("cannot open `%s'", output_file); + exit (1); + } + + int version; + 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); +} + +int +main (int argc, char *argv[]) +{ + int verbosity; + char *output_file = 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': + output_file = 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 (output_file == NULL) + { + output_file = argv[optind]; + } + + write_keymap (argv[optind], output_file); + + return 0; +}