diff -urN grub2um/commands/boot.c grub2m/commands/boot.c --- grub2um/commands/boot.c 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/commands/boot.c 2005-07-25 16:58:11.000000000 +0200 @@ -23,13 +23,23 @@ #include #include #include +#include +#include + +static grub_prebootfn_t *grub_preboots = 0; +static int grub_preboot_cnt = 0; static grub_err_t grub_cmd_boot (struct grub_arg_list *state __attribute__ ((unused)), int argc, char **args __attribute__ ((unused))) { + int i; + if (argc) return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments"); + + for (i = 0; i < grub_preboot_cnt; i++) + grub_preboots[i] (); grub_loader_boot (); @@ -38,6 +48,46 @@ +grub_err_t +grub_preboot_add (grub_prebootfn_t fn) +{ + grub_prebootfn_t *tmp; + tmp = (grub_prebootfn_t *) grub_realloc (grub_preboots, (grub_preboot_cnt + 1) * sizeof(grub_prebootfn_t)); + if (!tmp) + return grub_errno; + grub_preboots = tmp; + grub_preboots[grub_preboot_cnt] = fn; + grub_preboot_cnt++; + + return 0; +} + + + +grub_err_t +grub_preboot_remove (grub_prebootfn_t fn) +{ + int i; + for (i = 0; i < grub_preboot_cnt; i++) + if (grub_preboots[i] == fn) + break; + + if (i == grub_preboot_cnt) + { + return grub_error (GRUB_ERR_BAD_ARGUMENT, "fn not found"); + } + + for (; i < grub_preboot_cnt - 1; i++) + grub_preboots[i] = grub_preboots[i + 1]; + + grub_preboots = (grub_prebootfn_t *) grub_realloc (grub_preboots, (--grub_preboot_cnt) * sizeof(grub_prebootfn_t)); + + return 0; + +} + + + #ifdef GRUB_UTIL void grub_boot_init (void) diff -urN grub2um/commands/ls.c grub2m/commands/ls.c --- grub2um/commands/ls.c 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/commands/ls.c 2005-07-30 13:42:04.000000000 +0200 @@ -84,16 +84,18 @@ grub_printf (", Filesystem type %s", fs ? fs->name : "Unknown"); - - (fs->label) (dev, &label); - if (grub_errno == GRUB_ERR_NONE) + if (fs && fs->label) { - if (label && grub_strlen (label)) - grub_printf (", Label: %s", label); - grub_free (label); + (fs->label) (dev, &label); + if (grub_errno == GRUB_ERR_NONE) + { + if (label && grub_strlen (label)) + grub_printf (", Label: %s", label); + grub_free (label); + } + else + grub_errno = GRUB_ERR_NONE; } - else - grub_errno = GRUB_ERR_NONE; } grub_putchar ('\n'); @@ -108,6 +110,7 @@ } grub_device_close (dev); + } return 0; @@ -223,6 +226,19 @@ grub_printf ("(%s): Filesystem is %s.\n", device_name, fs ? fs->name : "unknown"); + if (fs && fs->label) + { + char *label; + (fs->label) (dev, &label); + if (grub_errno == GRUB_ERR_NONE) + { + if (label && grub_strlen (label)) + grub_printf (", Label: %s", label); + grub_free (label); + } + else + grub_errno = GRUB_ERR_NONE; + } } else if (fs) { @@ -267,6 +283,7 @@ } fail: + if (dev) grub_device_close (dev); diff -urN grub2um/conf/i386-pc.mk grub2m/conf/i386-pc.mk --- grub2um/conf/i386-pc.mk 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/conf/i386-pc.mk 2005-07-25 15:25:29.000000000 +0200 @@ -989,7 +989,7 @@ font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod \ terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod \ apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \ - help.mod default.mod timeout.mod configfile.mod + help.mod default.mod timeout.mod configfile.mod keystroke.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -1781,6 +1781,51 @@ hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For keystroke.mod. +keystroke_mod_SOURCES = keystroke/keystroke.c +CLEANFILES += keystroke.mod mod-keystroke.o mod-keystroke.c pre-keystroke.o keystroke_mod-keystroke_keystroke.o def-keystroke.lst und-keystroke.lst +MOSTLYCLEANFILES += keystroke_mod-keystroke_keystroke.d +DEFSYMFILES += def-keystroke.lst +UNDSYMFILES += und-keystroke.lst + +keystroke.mod: pre-keystroke.o mod-keystroke.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-keystroke.o: keystroke_mod-keystroke_keystroke.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + +mod-keystroke.o: mod-keystroke.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(keystroke_mod_CFLAGS) -c -o $@ $< + +mod-keystroke.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'keystroke' $< > $@ || (rm -f $@; exit 1) + +def-keystroke.lst: pre-keystroke.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 keystroke/' > $@ + +und-keystroke.lst: pre-keystroke.o + echo 'keystroke' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +keystroke_mod-keystroke_keystroke.o: keystroke/keystroke.c + $(CC) -Ikeystroke -I$(srcdir)/keystroke $(CPPFLAGS) $(CFLAGS) $(keystroke_mod_CFLAGS) -c -o $@ $< + +keystroke_mod-keystroke_keystroke.d: keystroke/keystroke.c + set -e; $(CC) -Ikeystroke -I$(srcdir)/keystroke $(CPPFLAGS) $(CFLAGS) $(keystroke_mod_CFLAGS) -M $< | sed 's,keystroke\.o[ :]*,keystroke_mod-keystroke_keystroke.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include keystroke_mod-keystroke_keystroke.d + +CLEANFILES += cmd-keystroke.lst +COMMANDFILES += cmd-keystroke.lst + +cmd-keystroke.lst: keystroke/keystroke.c gencmdlist.sh + set -e; $(CC) -Ikeystroke -I$(srcdir)/keystroke $(CPPFLAGS) $(CFLAGS) $(keystroke_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh keystroke > $@ || (rm -f $@; exit 1) + +keystroke_mod_CFLAGS = $(COMMON_CFLAGS) + # For boot.mod. boot_mod_SOURCES = commands/boot.c CLEANFILES += boot.mod mod-boot.o mod-boot.c pre-boot.o boot_mod-commands_boot.o def-boot.lst und-boot.lst diff -urN grub2um/conf/i386-pc.rmk grub2m/conf/i386-pc.rmk --- grub2um/conf/i386-pc.rmk 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/conf/i386-pc.rmk 2005-07-25 15:25:29.000000000 +0200 @@ -102,7 +102,7 @@ font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod \ terminal.mod fshelp.mod chain.mod multiboot.mod amiga.mod \ apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \ - help.mod default.mod timeout.mod configfile.mod + help.mod default.mod timeout.mod configfile.mod keystroke.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -163,6 +163,10 @@ hello_mod_SOURCES = hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For keystroke.mod. +keystroke_mod_SOURCES = keystroke/keystroke.c +keystroke_mod_CFLAGS = $(COMMON_CFLAGS) + # For boot.mod. boot_mod_SOURCES = commands/boot.c boot_mod_CFLAGS = $(COMMON_CFLAGS) diff -urN grub2um/fs/fat.c grub2m/fs/fat.c --- grub2um/fs/fat.c 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/fs/fat.c 2005-07-30 14:26:32.000000000 +0200 @@ -629,7 +629,7 @@ struct grub_fat_data *data = 0; grub_disk_t disk = device->disk; grub_size_t len; - char *dirname; + char *dirname = 0; char *p; #ifndef GRUB_UTIL @@ -660,8 +660,10 @@ fail: - grub_free (dirname); - grub_free (data); + if (dirname) + grub_free (dirname); + if (data) + grub_free (data); #ifndef GRUB_UTIL grub_dl_unref (my_mod); diff -urN grub2um/include/grub/normal.h grub2m/include/grub/normal.h --- grub2um/include/grub/normal.h 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/include/grub/normal.h 2005-07-25 15:25:29.000000000 +0200 @@ -44,6 +44,9 @@ /* Not loaded yet. Used for auto-loading. */ #define GRUB_COMMAND_FLAG_NOT_LOADED 0x20 +/* Preboot function declaration. */ +typedef void (*grub_prebootfn_t) (void); + /* The command description. */ struct grub_command { @@ -178,6 +181,8 @@ grub_menu_t grub_context_get_current_menu (void); grub_menu_t grub_context_push_menu (grub_menu_t menu); void grub_context_pop_menu (void); +grub_err_t grub_preboot_add (grub_prebootfn_t fn); +grub_err_t grub_preboot_remove (grub_prebootfn_t fn); #ifdef GRUB_UTIL void grub_normal_init (void); diff -urN grub2um/kern/disk.c grub2m/kern/disk.c --- grub2um/kern/disk.c 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/kern/disk.c 2005-07-30 12:14:34.000000000 +0200 @@ -535,7 +535,7 @@ grub_printf ("\tPartition num:%s, Filesystem type %s", partname, fs ? fs->name : "Unknown"); - if (fs) + if (fs && fs->label) { (fs->label) (part, &label); if (grub_errno == GRUB_ERR_NONE) diff -urN grub2um/keystroke/keystroke.c grub2m/keystroke/keystroke.c --- grub2um/keystroke/keystroke.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2m/keystroke/keystroke.c 2005-07-28 16:59:19.000000000 +0200 @@ -0,0 +1,406 @@ +/* keystroke.c - test module for dynamic loading */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005 Free Software Foundation, Inc. + * Copyright (C) 2005 Vladimir Serbinenko serbinenko.vova@bk.ru + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define RAW_ADDR(a) ((void *)(a)) +struct +keysym +{ + char *unshifted_name; /* the name in unshifted state */ + char *shifted_name; /* the name in shifted state */ + unsigned char unshifted_ascii; /* the ascii code in unshifted state */ + unsigned char shifted_ascii; /* the ascii code in shifted state */ + unsigned char keycode; /* keyboard scancode */ +}; + +char keystroke[32]; +int keylen=0; +/* The sum of: + x << y x - action y - flag + x: 0x0 - turn off, 0x1 - turn on , 0x3 - keep + y: + 0x0 - numlock mode, + 0x1 - capslock mode, + 0x2 - scrolllock mode, + 0x3 - insert mode, + 0x4 - wait mode, + 0x5 - left shift key, + 0x6 - right shift key, + 0x7 - left alt key, + 0x8 - right alt key, + 0x9 - left ctrl key, + 0xa - right ctrl key, + 0xb - sysreq key, + 0xc - numlock key, + 0xd - capslock key, + 0xe - scrolllock key, + 0xf - insert key + */ +unsigned long kbflags=0; +int noled = 1; + +/* The table for key symbols. If the "shifted" member of an entry is + NULL, the entry does not have shifted state. Copied from GRUB Legacy setkey fuction */ +static struct keysym keysym_table[] = +{ + {"escape", 0, 0x1b, 0, 0x01}, + {"1", "exclam", '1', '!', 0x02}, + {"2", "at", '2', '@', 0x03}, + {"3", "numbersign", '3', '#', 0x04}, + {"4", "dollar", '4', '$', 0x05}, + {"5", "percent", '5', '%', 0x06}, + {"6", "caret", '6', '^', 0x07}, + {"7", "ampersand", '7', '&', 0x08}, + {"8", "asterisk", '8', '*', 0x09}, + {"9", "parenleft", '9', '(', 0x0a}, + {"0", "parenright", '0', ')', 0x0b}, + {"minus", "underscore", '-', '_', 0x0c}, + {"equal", "plus", '=', '+', 0x0d}, + {"backspace", 0, '\b', 0, 0x0e}, + {"tab", 0, '\t', 0, 0x0f}, + {"q", "Q", 'q', 'Q', 0x10}, + {"w", "W", 'w', 'W', 0x11}, + {"e", "E", 'e', 'E', 0x12}, + {"r", "R", 'r', 'R', 0x13}, + {"t", "T", 't', 'T', 0x14}, + {"y", "Y", 'y', 'Y', 0x15}, + {"u", "U", 'u', 'U', 0x16}, + {"i", "I", 'i', 'I', 0x17}, + {"o", "O", 'o', 'O', 0x18}, + {"p", "P", 'p', 'P', 0x19}, + {"bracketleft", "braceleft", '[', '{', 0x1a}, + {"bracketright", "braceright", ']', '}', 0x1b}, + {"enter", 0, '\r', 0, 0x1c}, + {"control", 0, 0, 0, 0x1d}, + {"a", "A", 'a', 'A', 0x1e}, + {"s", "S", 's', 'S', 0x1f}, + {"d", "D", 'd', 'D', 0x20}, + {"f", "F", 'f', 'F', 0x21}, + {"g", "G", 'g', 'G', 0x22}, + {"h", "H", 'h', 'H', 0x23}, + {"j", "J", 'j', 'J', 0x24}, + {"k", "K", 'k', 'K', 0x25}, + {"l", "L", 'l', 'L', 0x26}, + {"semicolon", "colon", ';', ':', 0x27}, + {"quote", "doublequote", '\'', '"', 0x28}, + {"backquote", "tilde", '`', '~', 0x29}, + {"shift", 0, 0, 0, 0x2a}, + {"backslash", "bar", '\\', '|', 0x2b}, + {"z", "Z", 'z', 'Z', 0x2c}, + {"x", "X", 'x', 'X', 0x2d}, + {"c", "C", 'c', 'C', 0x2e}, + {"v", "V", 'v', 'V', 0x2f}, + {"b", "B", 'b', 'B', 0x30}, + {"n", "N", 'n', 'N', 0x31}, + {"m", "M", 'm', 'M', 0x32}, + {"comma", "less", ',', '<', 0x33}, + {"period", "greater", '.', '>', 0x34}, + {"slash", "question", '/', '?', 0x35}, + {"rshift", 0, 0, 0, 0x36}, + {"numasterisk", 0, '*', 0, 0x37}, + {"alt", 0, 0, 0, 0x38}, + {"space", 0, ' ', 0, 0x39}, + {"capslock", 0, 0, 0, 0x3a}, + {"F1", 0, 0, 0, 0x3b}, + {"F2", 0, 0, 0, 0x3c}, + {"F3", 0, 0, 0, 0x3d}, + {"F4", 0, 0, 0, 0x3e}, + {"F5", 0, 0, 0, 0x3f}, + {"F6", 0, 0, 0, 0x40}, + {"F7", 0, 0, 0, 0x41}, + {"F8", 0, 0, 0, 0x42}, + {"F9", 0, 0, 0, 0x43}, + {"F10", 0, 0, 0, 0x44}, + {"num7", "numhome", '7', 0, 0x47}, + {"num8", "numup", '8', 0, 0x48}, + {"num9", "numpgup", '9', 0, 0x49}, + {"numminus", 0, '-', 0, 0x4a}, + {"num4", "numleft", '4', 0, 0x4b}, + {"num5", "num5numlock", '5', 0, 0x4c}, + {"num6", "numright", '6', 0, 0x4d}, + {"numplus", 0, '-', 0, 0x4e}, + {"num1", "numend", '1', 0, 0x4f}, + {"num2", "numdown", '2', 0, 0x50}, + {"num3", "numpgdown", '3', 0, 0x51}, + {"num0", "numinsert", '0', 0, 0x52}, + {"numperiod", "numdelete", 0, 0x7f, 0x53}, + {"F11", 0, 0, 0, 0x57}, + {"F12", 0, 0, 0, 0x58}, + {"numenter", 0, '\r', 0, 0xe0}, + {"numslash", 0, '/', 0, 0xe0}, + {"delete", 0, 0x7f, 0, 0xe0}, + {"insert", 0, 0xe0, 0, 0x52}, + {"home", 0, 0xe0, 0, 0x47}, + {"end", 0, 0xe0, 0, 0x4f}, + {"pgdown", 0, 0xe0, 0, 0x51}, + {"pgup", 0, 0xe0, 0, 0x49}, + {"down", 0, 0xe0, 0, 0x50}, + {"up", 0, 0xe0, 0, 0x48}, + {"left", 0, 0xe0, 0, 0x4b}, + {"right", 0, 0xe0, 0, 0x4d} +}; + +/* Send a character VALUE to port PORT */ +static void +outportb (char value, int port) { + asm volatile ("outb %%al,%%dx": :"a" (value),"d" (port)); + return; +} + +/* Read a byte from port PORT */ +static unsigned char +inb (unsigned int port) +{ + unsigned char ret; + asm volatile ("inb %%dx,%%al":"=a" (ret):"d" (port)); + return ret; + +} + +/* Set a simple flag in flags variable + flags - where to set, + outoffset - offset of flag in FLAGS, + inoffset - offset of flag in kbflags +*/ +static void +grub_keystroke_set_simple_flag (unsigned long *flags, int outoffset, int inoffset) +{ + /* previous state of flag */ + int prevstat = (*flags >> outoffset) & 1; + /* what to do with flag*/ + int operation = (kbflags >> inoffset) & 3; + /* new state */ + int newstat = (operation == 1) || (operation == 2 && prevstat); + /* Set new state */ + *flags = (*flags & (~(1 << outoffset))) | (newstat << outoffset); +} + +/* Set a double flag (ctrl/alt) in flags variable + flags - where to set, + outoffsetc - offset of common flag in FLAGS, + outoffsetl - offset of "left" flag in FLAGS, + inoffsetr - offset of "right" flag in kbflags, + inoffsetl - offset of "left" flag in kbflags, +*/ +static void +grub_keystroke_set_double_flag (unsigned long *flags, int outoffsetc, int outoffsetl, int inoffsetr, int inoffsetl) +{ + /* previous state of flag */ + int prevstatc = (*flags >> outoffsetc) & 1; + int prevstatl = (*flags >> outoffsetl) & 1; + int prevstatr = prevstatc && (!prevstatl); + /* what to do with flag*/ + int operationr = (kbflags >> inoffsetr) & 3; + int operationl = (kbflags >> inoffsetl) & 3; + /* new state */ + int newstatl = (operationl == 1) || (operationl == 2 && prevstatl); + int newstatr = (operationr == 1) || (operationr == 2 && prevstatr); + int newstatc = newstatr || newstatr; + /* Set new state */ + *flags = (*flags & (~(1 << outoffsetl))) | (newstatl << outoffsetl); + *flags = (*flags & (~(1 << outoffsetc))) | (newstatc << outoffsetc); +} + + +/* Set keyboard buffer to our keystroke */ +static void +grub_keystroke_preboot (void) +{ + + int i; + /* For convenion: pointer to flags */ + unsigned long *flags = (unsigned long *) RAW_ADDR (0x417); + + /* Set the keystroke */ + *((char *) RAW_ADDR (0x41a)) = 0x1e; + *((char *) RAW_ADDR (0x41c)) = keylen+0x1e; + for(i = 0; i < 0x20; i++) + ((char *) RAW_ADDR (0x41e))[i] = keystroke[i]; + + /* Set the flags. For more information reffer to technical specification*/ + grub_keystroke_set_simple_flag (flags, 5, 0 * 2); // numlock mode + grub_keystroke_set_simple_flag (flags, 6, 1 * 2); // capslock mode + grub_keystroke_set_simple_flag (flags, 4, 2 * 2); // scrolllock mode + grub_keystroke_set_simple_flag (flags, 7, 3 * 2); // insert mode + grub_keystroke_set_simple_flag (flags, 11, 4 * 2); // wait mode + grub_keystroke_set_simple_flag (flags, 1, 5 * 2); // left shift + grub_keystroke_set_simple_flag (flags, 0, 6 * 2); // right shift + grub_keystroke_set_simple_flag (flags, 10, 0xb * 2); // sysreq + grub_keystroke_set_simple_flag (flags, 13, 0xc * 2); // numlock key + grub_keystroke_set_simple_flag (flags, 14, 0xd * 2); // capslock key + grub_keystroke_set_simple_flag (flags, 12, 0xe * 2); // scrolllock key + grub_keystroke_set_simple_flag (flags, 15, 0xf * 2); // insert key + + /*Set ctrl and alt*/ + grub_keystroke_set_double_flag (flags, 2, 8, 0xa * 2, 9 * 2); //Ctrl + grub_keystroke_set_double_flag (flags, 3, 9, 8 * 2, 7 * 2); //Alt + + /* Write new LED state */ + if (!noled) + { + int value = 0; + int failed; + /* Try 5 times */ + for (failed = 0; failed < 5; failed++) + { + value = 0; + /* Send command change LEDs */ + outportb (0xed, 0x60); + + /* Wait */ + while ((value != 0xfa) && (value != 0xfe)) + value = inb (0x60); + + if (value == 0xfa) + { + /* Set new LEDs*/ + outportb ((flags[0] >> 4) & 7, 0x60); + break; + } + } + } +} + + /* 0x0 - numlock mode, + 0x1 - capslock mode, + 0x2 - scrolllock mode, + 0x3 - insert mode, + 0x4 - wait mode, + 0x5 - left shift key, + 0x6 - right shift key, + 0x7 - left alt key, + 0x8 - right alt key, + 0x9 - left ctrl key, + 0xa - right ctrl key, + 0xb - sysreq key, + 0xc - numlock key, + 0xd - capslock key, + 0xe - scrolllock key, + 0xf - insert key*/ + +/*Parse keystroke */ +static grub_err_t +grub_cmd_keystroke (struct grub_arg_list *state, + int argc, + char **args) +{ + + /* To stop warning */ + auto int find_key_code (char *key); + auto int find_ascii_code (char *key); + + auto int find_key_code (char *key) + { + unsigned i; + + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + { + if (keysym_table[i].unshifted_name && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].keycode; + else if (keysym_table[i].shifted_name && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].keycode; + } + + return 0; + } + + auto int find_ascii_code (char *key) + { + unsigned i; + + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + { + if (keysym_table[i].unshifted_name && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].unshifted_ascii; + else if (keysym_table[i].shifted_name && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].shifted_ascii; + } + + return 0; + } + + int i; + + /* Set keystroke and keylen variables*/ + keylen = 0; + + for (i = 0; i < argc && keylen < 0x20; i++) + { + if (find_key_code (args[i])) + { + keystroke[keylen++] = find_ascii_code (args[i]); + keystroke[keylen++] = find_key_code (args[i]); + } + } + + /* Set kbflags */ + kbflags = 0; + for (i = 0; i <= 15; i++) + kbflags |= (state[i].set ? grub_strtoul (state[i].arg, 0, 0) : 2) << (2*i); + + noled = state[16].set; + + return 0; +} + +static const struct grub_arg_option options[] = + { + {"numlock", 'n', GRUB_ARG_OPTION_OPTIONAL, "set numlock mode (2=keep, 0=off, 1=on)", "2", ARG_TYPE_INT}, + {"capslock", 'c', GRUB_ARG_OPTION_OPTIONAL, "set capslock mode (2=keep, 0=off, 1=on)", "2", ARG_TYPE_INT}, + {"scrolllock", 's', GRUB_ARG_OPTION_OPTIONAL, "set scrolllock mode (2=keep, 0=off, 1=on)", "2", ARG_TYPE_INT}, + {"insert", 'i', GRUB_ARG_OPTION_OPTIONAL, "set insert mode (2=keep, 0=off, 1=on)", "2", ARG_TYPE_INT}, + {"wait", 0 , GRUB_ARG_OPTION_OPTIONAL, "set wait mode (pause) (2=keep, 0=off, 1=on)", "2", ARG_TYPE_INT}, + {"lshift", 'l', GRUB_ARG_OPTION_OPTIONAL, "block left shift key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"rshift", 'r', GRUB_ARG_OPTION_OPTIONAL, "block right shift key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"lalt", 0 , GRUB_ARG_OPTION_OPTIONAL, "block left alt key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"ralt", 'a', GRUB_ARG_OPTION_OPTIONAL, "block right alt key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"lctrl", 0 , GRUB_ARG_OPTION_OPTIONAL, "block left ctrl key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"rctrl", 0 , GRUB_ARG_OPTION_OPTIONAL, "block right ctrl key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"sysreq", 0 , GRUB_ARG_OPTION_OPTIONAL, "block sys req key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"numkey", 0 , GRUB_ARG_OPTION_OPTIONAL, "block numlock key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"capskey", 0 , GRUB_ARG_OPTION_OPTIONAL, "block capslock key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"scrkey", 0 , GRUB_ARG_OPTION_OPTIONAL, "block scrolllock key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"inskey", 0 , GRUB_ARG_OPTION_OPTIONAL, "block insert key (2=no, 0=unpress, 1=press)", "2", ARG_TYPE_INT}, + {"noled", 0 , 0, "Don't try to set LEDs. Try if blocks.", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +GRUB_MOD_INIT +{ + (void)mod; /* To stop warning. */ + grub_register_command ("keystroke", grub_cmd_keystroke, GRUB_COMMAND_FLAG_BOTH, + "keystroke [options] [KEY1 [KEY2 ...[KEY16]...]]", +"Send a keystroke to OS. Set keyboard mode and block some keys as pressed/unpressed. Keys are unblocked on next press.", options); + grub_preboot_add (grub_keystroke_preboot); +} + +GRUB_MOD_FINI +{ + grub_unregister_command ("keystroke"); + grub_preboot_remove (grub_keystroke_preboot); +}