]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Reimported heavily modified version of cpina's grub-mklayout
authorCarles Pina i Estany <carles@pina.cat>
Thu, 19 Aug 2010 00:15:29 +0000 (02:15 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 19 Aug 2010 00:15:29 +0000 (02:15 +0200)
ChangeLog.keyboard_layouts [new file with mode: 0644]
conf/common.rmk
include/grub/at_keyboard.h
include/grub/keyboard_layouts.h [new file with mode: 0644]
include/grub/term.h
term/at_keyboard.c
util/grub-mklayouts.c [new file with mode: 0644]

diff --git a/ChangeLog.keyboard_layouts b/ChangeLog.keyboard_layouts
new file mode 100644 (file)
index 0000000..65af097
--- /dev/null
@@ -0,0 +1,7 @@
+2010-01-18  Carles Pina i Estany  <carles@pina.cat>
+
+       Adds keyboard layouts support.
+
+       * conf/common.rmk (bin_UTILITIES): Add grub-mklayouts rules.
+       * include/grub/keyboard_layouts.h: New file.
+       * util/grub-mklayouts.c: New file.
index ee6b94032ce515f662dfa1ea763f83e61db03cb7..745b1837e70776d017b3a86a38c3f2c5577cd071 100644 (file)
@@ -80,6 +80,10 @@ endif
 bin_UTILITIES += grub-mkrelpath
 grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c
 
+# For grub-mklayouts.
+bin_UTILITIES += grub-mklayouts
+grub_mklayouts_SOURCES = gnulib/progname.c util/grub-mklayouts.c util/misc.c kern/emu/misc.c
+
 bin_UTILITIES += grub-bin2h
 grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c
 
index 3f72fa879d3b630e50d7d5742a999c659f8d44b1..8bb090d2a88e4dc0bb2fcfd49c790005456eb08a 100644 (file)
@@ -52,7 +52,7 @@
 #endif
 
 #define GRUB_AT_KEY_KEYBOARD_MAP(name)                                   \
-static const int name[128] =                                             \
+static const unsigned name[128] =                                        \
 {                                                                        \
   '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6',                     \
   '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB,      \
@@ -75,4 +75,17 @@ static const int name[128] =                                           \
   OLPC_RIGHT                                                              \
 }
 
+#define GRUB_AT_KEY_KEYBOARD_MAP_SHIFT(name)   \
+static unsigned name[128] =                     \
+{                                               \
+  '\0', '\0', '!', '@', '#', '$', '%', '^',     \
+  '&', '*', '(', ')', '_', '+', '\0', '\0',     \
+  'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',       \
+  'O', 'P', '{', '}', '\n', '\0', 'A', 'S',     \
+  'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',       \
+  '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',     \
+  'B', 'N', 'M', '<', '>', '?',                 \
+  [0x56] = GRUB_TERM_KEY_SHIFT_102              \
+}
+
 #endif
diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h
new file mode 100644 (file)
index 0000000..1d263e2
--- /dev/null
@@ -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_LAYOUTS_H
+#define GRUB_KEYBOARD_LAYOUTS_H 1
+
+#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO"
+#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1)
+#define GRUB_KEYBOARD_LAYOUTS_VERSION 2
+
+#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 256
+
+#endif /* GRUB_KEYBOARD_LAYOUTS  */
index dbafef0e1aca217af4f45a6235ca6ca4fbf920c7..fa813d1b576e044dd5fe35566b011f2aaa6eba34 100644 (file)
@@ -53,8 +53,8 @@
 #define GRUB_TERM_KEY_INSERT    (GRUB_TERM_EXTENDED | 22)
 
 /* Used by keylayouts code. Never returned in grub_getkey.  */
-#define GRUB_TERM_KEY_102       (GRUB_TERM_EXTENDED | 23)
-#define GRUB_TERM_KEY_SHIFT_102 (GRUB_TERM_EXTENDED | 24)
+#define GRUB_TERM_KEY_102       0x80
+#define GRUB_TERM_KEY_SHIFT_102 0x81
 
 #define GRUB_TERM_ESC          '\e'
 #define GRUB_TERM_TAB          '\t'
index e89f3bf5b969ece15f907c2ba53d255fab9a74cf..4c9c2a23a108dea96281c6fc6417f7eb972cf297 100644 (file)
@@ -42,18 +42,7 @@ static grub_uint8_t led_status;
 #define KEYBOARD_LED_CAPS              (1 << 2)
 
 GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map);
-
-static int keyboard_map_shift[128] =
-{
-  '\0', '\0', '!', '@', '#', '$', '%', '^',
-  '&', '*', '(', ')', '_', '+', '\0', '\0',
-  'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
-  'O', 'P', '{', '}', '\n', '\0', 'A', 'S',
-  'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
-  '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
-  'B', 'N', 'M', '<', '>', '?',
-  [0x56] = GRUB_TERM_KEY_SHIFT_102
-};
+GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (keyboard_map_shift);
 
 static grub_uint8_t grub_keyboard_controller_orig;
 
diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c
new file mode 100644 (file)
index 0000000..48b17e7
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  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/i18n.h>
+#include <grub/term.h>
+#include <grub/keyboard_layouts.h>
+#include <grub/at_keyboard.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#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;
+  grub_uint32_t grub;
+};
+
+static struct console_grub_equivalence console_grub_equivalences[] = {
+  {"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'}
+};
+
+GRUB_AT_KEY_KEYBOARD_MAP (us_keyboard_map);
+GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (us_keyboard_map_shifted);
+
+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.gkb\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);
+}
+
+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, grub_uint32_t *keyboard_map)
+{
+  FILE *fp_output;
+  grub_uint32_t version;
+  unsigned i;
+
+  version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION);
+  
+  for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++)
+    keyboard_map[i] = grub_cpu_to_le32 (keyboard_map[i]);
+
+  fp_output = fopen (filename, "w");
+  
+  if (!fp_output)
+    {
+      grub_util_error ("cannot open `%s'", filename);
+      exit (1);
+    }
+
+  fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1,
+         GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, fp_output);
+  fwrite (&version, sizeof (version), 1, fp_output);
+  fwrite (keyboard_map, sizeof (keyboard_map[0]),
+         GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output);
+  fclose (fp_output);
+}
+
+void
+write_keymaps (char *keymap, char *file_basename)
+{
+  grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE];
+
+  char line[2048];
+  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 (keyboard_map, 0, sizeof (keyboard_map));
+
+  /* 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)
+       {
+         unsigned keycode;
+         char normal[64];
+         char shift[64];
+         sscanf (line, "keycode %u = %60s %60s", &keycode, normal, shift);
+         if (keycode < ARRAY_SIZE (us_keyboard_map)
+             && us_keyboard_map[keycode] < ARRAY_SIZE (keyboard_map))
+           {
+             keyboard_map[us_keyboard_map[keycode]] = get_grub_code (normal);
+             ok = 1;
+           }
+         if (keycode < ARRAY_SIZE (us_keyboard_map_shifted)
+             && us_keyboard_map_shifted[keycode] < ARRAY_SIZE (keyboard_map))
+           {
+             keyboard_map[us_keyboard_map_shifted[keycode]]
+               = get_grub_code (shift);
+             ok = 1;
+           }
+       }
+    }
+
+  if (ok == 0)
+    {
+      fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n",
+              CKBCOMP, keymap);
+      exit (1);
+    }
+
+  write_file (file_basename, keyboard_map);
+}
+
+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 = xasprintf ("%s.gkb", argv[optind]);
+      write_keymaps (argv[optind], file_basename);
+      free (file_basename);
+    }
+  else
+    write_keymaps (argv[optind], file_basename);
+
+  return 0;
+}