diff -urpN grub2um/ChangeLog grub2m/ChangeLog --- grub2um/ChangeLog 2005-08-01 11:44:43.000000000 +0200 +++ grub2m/ChangeLog 2005-08-02 18:39:10.000000000 +0200 @@ -1,3 +1,18 @@ +2005-08-02 Vladimir Serbinenko + + Sendkey, activate and parttype modules(pc) and preboots + + * commands/boot.c: Added support for preboot functions + * conf/i386.rmk (sendkey): new module + (activate): Likewise + (parttype): Likewise + * commands/i386/pc/sendkey.c: New file + * commands/i386/pc/parttype.c: Likewise + * commands/i386/pc/activate.c: Likewise + * kern/misc.c (grub_split_cmdline): more bash-like quotes and + doublequotes handle + * include/grub/normal.h: new headers and types for preboots + 2005-07-31 Yoshinori K. Okuji * loader/i386/pc/multiboot.c (grub_multiboot_is_elf32): New diff -urpN 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_cmd_boot (struct grub_arg_list *sta +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 -urpN grub2um/commands/i386/pc/activate.c grub2m/commands/i386/pc/activate.c --- grub2um/commands/i386/pc/activate.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2m/commands/i386/pc/activate.c 2005-08-01 18:55:15.000000000 +0200 @@ -0,0 +1,114 @@ +/* activate.c - activate pc partition */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003 NIIBE Yutaka + * + * 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 +#include +#include +#include + +static grub_err_t +grub_cmd_activate (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + + grub_device_t dev; + struct grub_pc_partition_mbr mbr; + grub_partition_t part; + + int i, index; + + if (argc > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments"); + + if (!argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments"); + + dev = grub_device_open (args[0]); + + if (!dev) + return grub_errno; + + if (!dev->disk) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk"); + } + + if (!dev->disk->partition) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a partition"); + } + + if (grub_strcmp (dev->disk->partition->partmap->name, "pc_partition_map")) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a pc partition"); + } + + if (dev->disk->partition->offset) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a primary partition"); + } + + index = dev->disk->partition->index; + part = dev->disk->partition; + dev->disk->partition = 0; + + /* Read the MBR. */ + if (grub_disk_read (dev->disk, 0, 0, sizeof (mbr), (char *) &mbr)) + { + dev->disk->partition = part; + grub_device_close (dev); + return grub_errno; + } + + for (i = 0; i < 4; i++) + mbr.entries[i].flag = 0x0; + + mbr.entries[index].flag = 0x80; + + /* Write the MBR. */ + grub_disk_write (dev->disk, 0, 0, sizeof (mbr), (char *) &mbr); + dev->disk->partition = part; + grub_device_close (dev); + return grub_errno; + +} + +GRUB_MOD_INIT +{ + (void)mod; /* To stop warning. */ + grub_register_command ("activate", grub_cmd_activate, GRUB_COMMAND_FLAG_BOTH, + "activate PARTITION", "set active flag to PARTITION", 0); +} + +GRUB_MOD_FINI +{ + grub_unregister_command ("activate"); +} diff -urpN grub2um/commands/i386/pc/parttype.c grub2m/commands/i386/pc/parttype.c --- grub2um/commands/i386/pc/parttype.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2m/commands/i386/pc/parttype.c 2005-08-02 18:25:09.000000000 +0200 @@ -0,0 +1,165 @@ +/* activate.c - activate pc partition */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003 NIIBE Yutaka + * + * 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 +#include +#include +#include + + +/* Set the partition type. Special values of PARTTYPE: + -1 - set hidden flag + -2 - unset hidden flag*/ +static grub_err_t +grub_setparttype (int parttype, int argc, char **args) +{ + + grub_device_t dev; + struct grub_pc_partition_mbr pmap; + grub_partition_t part; + + int index; + unsigned long offset; + + if (argc > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments"); + + if (!argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments"); + + dev = grub_device_open (args[0]); + + if (!dev) + return grub_errno; + + if (!dev->disk) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk"); + } + + if (!dev->disk->partition) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a partition"); + } + + if (grub_strcmp (dev->disk->partition->partmap->name, "pc_partition_map")) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a pc partition"); + } + + offset = dev->disk->partition->offset; + + index = dev->disk->partition->index; + part = dev->disk->partition; + dev->disk->partition = 0; + + /* Read the partition map. */ + if (grub_disk_read (dev->disk, offset, 0, sizeof (pmap), (char *) &pmap)) + { + dev->disk->partition = part; + grub_device_close (dev); + return grub_errno; + } + + switch (parttype) + { + case -1: + pmap.entries[index].type |= GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG; + break; + + case -2: + pmap.entries[index].type &= ~GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG; + break; + + default: + pmap.entries[index].type = parttype; + break; + } + + + /* Write the partition map. */ + grub_disk_write (dev->disk, offset, 0, sizeof (pmap), (char *) &pmap); + dev->disk->partition = part; + grub_device_close (dev); + return grub_errno; + +} + +static grub_err_t +grub_cmd_hide (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + return grub_setparttype (-1, argc, args); +} + +static grub_err_t +grub_cmd_unhide (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + return grub_setparttype (-2, argc, args); +} + +static grub_err_t +grub_cmd_parttype (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + char *rest = 0; + int type; + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments"); + if (argc > 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments"); + + type = grub_strtoul (args[0], &rest, 0); + if (rest && *rest) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "second argument must be integer"); + + return grub_setparttype (type, 1, args + 1); +} + + +GRUB_MOD_INIT +{ + (void)mod; /* To stop warning. */ + grub_register_command ("hide", grub_cmd_hide, GRUB_COMMAND_FLAG_BOTH, + "hide PARTITION", "hide PARTITION from OS (set hidden flag)", 0); + grub_register_command ("unhide", grub_cmd_unhide, GRUB_COMMAND_FLAG_BOTH, + "unhide PARTITION", "unhide PARTITION from OS (unset hidden flag)", 0); + grub_register_command ("parttype", grub_cmd_parttype, GRUB_COMMAND_FLAG_BOTH, + "parttype PARTITION TYPE", "set PARTITION type to TYPE", 0); +} + +GRUB_MOD_FINI +{ + grub_unregister_command ("hide"); + grub_unregister_command ("unhide"); + grub_unregister_command ("parttype"); +} diff -urpN grub2um/commands/i386/pc/sendkey.c grub2m/commands/i386/pc/sendkey.c --- grub2um/commands/i386/pc/sendkey.c 1970-01-01 01:00:00.000000000 +0100 +++ grub2m/commands/i386/pc/sendkey.c 2005-08-02 14:21:38.000000000 +0200 @@ -0,0 +1,394 @@ +/* sendkey.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 +#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 */ +}; + +/* 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, + OP - action id +*/ +static void +grub_sendkey_set_simple_flag (unsigned long *flags, int outoffset, int op) +{ + /* previous state of flag */ + int prevstat = (*flags >> outoffset) & 1; + /* new state */ + int newstat = (op == 1) || (op == 2 && prevstat); + /* Set new state */ + *flags = (*flags & (~(1 << outoffset))) | (newstat << outoffset); +} + +/* Set a double flag (ctrl/alt) in flags variable + FLAGS - where to set, + OUTOFFSETR - offset of common flag in FLAGS, + OUTOFFSETL - offset of "left" flag in FLAGS, + OPR - operation for "right" flag, + OPL - operation for "left" flag +*/ +static void +grub_sendkey_set_double_flag (unsigned long *flags, int outoffsetc, int outoffsetl, int opr, int opl) +{ + /* previous state of flag */ + int prevstatc = (*flags >> outoffsetc) & 1; + int prevstatl = (*flags >> outoffsetl) & 1; + int prevstatr = prevstatc && (!prevstatl); + /* new state */ + int newstatl = (opl == 1) || (opl == 2 && prevstatl); + int newstatr = (opr == 1) || (opr == 2 && prevstatr); + int newstatc = newstatr || newstatr; + /* Set new state */ + *flags = (*flags & (~(1 << outoffsetl))) | (newstatl << outoffsetl); + *flags = (*flags & (~(1 << outoffsetc))) | (newstatc << outoffsetc); +} + +static int +grub_sendkey_parse_op (char *name) +{ + char *var; + + var = grub_env_get (name); + + if (!var) + return 2; + + if (!grub_strcmp (var, "off") || !grub_strcmp (var, "0") || !grub_strcmp (var, "unpress")) + return 0; + + if (!grub_strcmp (var, "on") || !grub_strcmp (var, "1") || !grub_strcmp (var, "press")) + return 1; + + return 2; +} + +/* Set keyboard buffer to our sendkey */ +static void +grub_sendkey_preboot (void) +{ + + /* Length of sendkey */ + int keylen = 0; + char sendkey[0x20]; + /* For convenion: pointer to flags */ + unsigned long *flags = (unsigned long *) RAW_ADDR (0x417); + char *next, ch, *sendkeyvar; + int noled = 0; + + /* 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; + } + + sendkeyvar = grub_env_get ("sendkey"); + + if (sendkeyvar) + do + { + next = grub_strchr (sendkeyvar, ' '); + if (next) + { + ch = *next; + *next = 0; + } + if (find_key_code (sendkeyvar)) + { + sendkey[keylen++] = find_ascii_code (sendkeyvar); + sendkey[keylen++] = find_key_code (sendkeyvar); + } + if (next) + { + *next = ch; + sendkeyvar = next + 1; + } + } + while (next && keylen < 0x20); + + { + int i; + /* Set the sendkey */ + *((char *) RAW_ADDR (0x41a)) = 0x1e; + *((char *) RAW_ADDR (0x41c)) = keylen + 0x1e; + for(i = 0; i < 0x20; i++) + ((char *) RAW_ADDR (0x41e))[i] = sendkey[i]; + } + + /* Set the flags. For more information reffer to technical specification*/ + grub_sendkey_set_simple_flag (flags, 5, grub_sendkey_parse_op("kb_num")); // numlock mode + grub_sendkey_set_simple_flag (flags, 6, grub_sendkey_parse_op("kb_caps")); // capslock mode + grub_sendkey_set_simple_flag (flags, 4, grub_sendkey_parse_op("kb_scroll")); // scrolllock mode + grub_sendkey_set_simple_flag (flags, 7, grub_sendkey_parse_op("kb_insert")); // insert mode + grub_sendkey_set_simple_flag (flags, 11, grub_sendkey_parse_op("kb_wait")); // wait mode + grub_sendkey_set_simple_flag (flags, 1, grub_sendkey_parse_op("kb_lshift")); // left shift + grub_sendkey_set_simple_flag (flags, 0, grub_sendkey_parse_op("kb_rshift")); // right shift + grub_sendkey_set_simple_flag (flags, 10, grub_sendkey_parse_op("kb_sysreq")); // sysreq + grub_sendkey_set_simple_flag (flags, 13, grub_sendkey_parse_op("kb_numkey")); // numlock key + grub_sendkey_set_simple_flag (flags, 14, grub_sendkey_parse_op("kb_capskey")); // capslock key + grub_sendkey_set_simple_flag (flags, 12, grub_sendkey_parse_op("kb_scrollkey")); // scrolllock key + grub_sendkey_set_simple_flag (flags, 15, grub_sendkey_parse_op("kb_insertkey")); // insert key + + /*Set ctrl and alt*/ + grub_sendkey_set_double_flag (flags, 2, 8, grub_sendkey_parse_op("kb_rctrl"), grub_sendkey_parse_op("kb_lctrl")); //Ctrl + grub_sendkey_set_double_flag (flags, 3, 9, grub_sendkey_parse_op("kb_ralt"), grub_sendkey_parse_op("kb_lalt")); //Alt + + + /* Set noled */ + { + char *var; + + /* set 1 if set explicitely */ + if ((var = grub_env_get ("kb_noled")) && grub_strcmp (var, "0")) + noled = 1; + + /* implicit: when LEDs haven't changed */ + if (!var && grub_sendkey_parse_op("kb_num") == 2 && grub_sendkey_parse_op("kb_caps") == 2 + && grub_sendkey_parse_op("kb_scroll") == 2) + noled = 1; + } + + /* 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; + } + } + } + +} + +GRUB_MOD_INIT +{ + (void)mod; /* To stop warning. */ + unsigned i; + /* List of variables to set to "keep" */ + char list[16][12] = + { + "kb_num", "kb_caps", "kb_scroll", "kb_insert", "kb_wait", "kb_lshift", "kb_rshift", "kb_sysreq", + "kb_numkey", "kb_capskey", "kb_scrollkey", "kb_insertkey", "kb_lalt", "kb_ralt", "kb_lctrl", "kb_rctrl" + }; + + grub_env_set ("sendkey", ""); + grub_env_set ("kb_noled", "0"); + + for (i = 0; i < sizeof (list) / sizeof (list[0]); i++) + grub_env_set (list[i], "keep"); + + grub_preboot_add (grub_sendkey_preboot); +} + +GRUB_MOD_FINI +{ + + unsigned i; + /* List of variables to unset */ + char list[19][12] = + { + "kb_num", "kb_caps", "kb_scroll", "kb_insert", "kb_wait", "kb_lshift", "kb_rshift", "kb_sysreq", + "kb_numkey", "kb_capskey", "kb_scrollkey", "kb_insertkey", "kb_lalt", "kb_ralt", "kb_lctrl", "kb_rctrl", + "sendkey", "kb_noled" + }; + + for (i = 0; i < sizeof (list) / sizeof (list[0]); i++) + grub_env_unset (list[i]); + + grub_preboot_remove (grub_sendkey_preboot); +} diff -urpN 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-08-02 14:03:45.000000000 +0200 @@ -989,7 +989,8 @@ pkgdata_MODULES = _chain.mod _linux.mod 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 sendkey.mod \ + activate.mod parttype.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -1781,6 +1782,156 @@ fs-hello.lst: hello/hello.c genfslist.sh hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For sendkey.mod. +sendkey_mod_SOURCES = commands/i386/pc/sendkey.c +CLEANFILES += sendkey.mod mod-sendkey.o mod-sendkey.c pre-sendkey.o sendkey_mod-commands_i386_pc_sendkey.o def-sendkey.lst und-sendkey.lst +MOSTLYCLEANFILES += sendkey_mod-commands_i386_pc_sendkey.d +DEFSYMFILES += def-sendkey.lst +UNDSYMFILES += und-sendkey.lst + +sendkey.mod: pre-sendkey.o mod-sendkey.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-sendkey.o: sendkey_mod-commands_i386_pc_sendkey.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + +mod-sendkey.o: mod-sendkey.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(sendkey_mod_CFLAGS) -c -o $@ $< + +mod-sendkey.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'sendkey' $< > $@ || (rm -f $@; exit 1) + +def-sendkey.lst: pre-sendkey.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sendkey/' > $@ + +und-sendkey.lst: pre-sendkey.o + echo 'sendkey' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +sendkey_mod-commands_i386_pc_sendkey.o: commands/i386/pc/sendkey.c + $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(sendkey_mod_CFLAGS) -c -o $@ $< + +sendkey_mod-commands_i386_pc_sendkey.d: commands/i386/pc/sendkey.c + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(sendkey_mod_CFLAGS) -M $< | sed 's,sendkey\.o[ :]*,sendkey_mod-commands_i386_pc_sendkey.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include sendkey_mod-commands_i386_pc_sendkey.d + +CLEANFILES += cmd-sendkey.lst fs-sendkey.lst +COMMANDFILES += cmd-sendkey.lst +FSFILES += fs-sendkey.lst + +cmd-sendkey.lst: commands/i386/pc/sendkey.c gencmdlist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(sendkey_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh sendkey > $@ || (rm -f $@; exit 1) + +fs-sendkey.lst: commands/i386/pc/sendkey.c genfslist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(sendkey_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh sendkey > $@ || (rm -f $@; exit 1) + + +sendkey_mod_CFLAGS = $(COMMON_CFLAGS) + +# For activate.mod. +activate_mod_SOURCES = commands/i386/pc/activate.c +CLEANFILES += activate.mod mod-activate.o mod-activate.c pre-activate.o activate_mod-commands_i386_pc_activate.o def-activate.lst und-activate.lst +MOSTLYCLEANFILES += activate_mod-commands_i386_pc_activate.d +DEFSYMFILES += def-activate.lst +UNDSYMFILES += und-activate.lst + +activate.mod: pre-activate.o mod-activate.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-activate.o: activate_mod-commands_i386_pc_activate.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + +mod-activate.o: mod-activate.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(activate_mod_CFLAGS) -c -o $@ $< + +mod-activate.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'activate' $< > $@ || (rm -f $@; exit 1) + +def-activate.lst: pre-activate.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 activate/' > $@ + +und-activate.lst: pre-activate.o + echo 'activate' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +activate_mod-commands_i386_pc_activate.o: commands/i386/pc/activate.c + $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(activate_mod_CFLAGS) -c -o $@ $< + +activate_mod-commands_i386_pc_activate.d: commands/i386/pc/activate.c + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(activate_mod_CFLAGS) -M $< | sed 's,activate\.o[ :]*,activate_mod-commands_i386_pc_activate.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include activate_mod-commands_i386_pc_activate.d + +CLEANFILES += cmd-activate.lst fs-activate.lst +COMMANDFILES += cmd-activate.lst +FSFILES += fs-activate.lst + +cmd-activate.lst: commands/i386/pc/activate.c gencmdlist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(activate_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh activate > $@ || (rm -f $@; exit 1) + +fs-activate.lst: commands/i386/pc/activate.c genfslist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(activate_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh activate > $@ || (rm -f $@; exit 1) + + +activate_mod_CFLAGS = $(COMMON_CFLAGS) + +# For parttype.mod. +parttype_mod_SOURCES = commands/i386/pc/parttype.c +CLEANFILES += parttype.mod mod-parttype.o mod-parttype.c pre-parttype.o parttype_mod-commands_i386_pc_parttype.o def-parttype.lst und-parttype.lst +MOSTLYCLEANFILES += parttype_mod-commands_i386_pc_parttype.d +DEFSYMFILES += def-parttype.lst +UNDSYMFILES += und-parttype.lst + +parttype.mod: pre-parttype.o mod-parttype.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-parttype.o: parttype_mod-commands_i386_pc_parttype.o + -rm -f $@ + $(LD) -r -d -o $@ $^ + +mod-parttype.o: mod-parttype.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(parttype_mod_CFLAGS) -c -o $@ $< + +mod-parttype.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'parttype' $< > $@ || (rm -f $@; exit 1) + +def-parttype.lst: pre-parttype.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 parttype/' > $@ + +und-parttype.lst: pre-parttype.o + echo 'parttype' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +parttype_mod-commands_i386_pc_parttype.o: commands/i386/pc/parttype.c + $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(parttype_mod_CFLAGS) -c -o $@ $< + +parttype_mod-commands_i386_pc_parttype.d: commands/i386/pc/parttype.c + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(parttype_mod_CFLAGS) -M $< | sed 's,parttype\.o[ :]*,parttype_mod-commands_i386_pc_parttype.o $@ : ,g' > $@; [ -s $@ ] || rm -f $@ + +-include parttype_mod-commands_i386_pc_parttype.d + +CLEANFILES += cmd-parttype.lst fs-parttype.lst +COMMANDFILES += cmd-parttype.lst +FSFILES += fs-parttype.lst + +cmd-parttype.lst: commands/i386/pc/parttype.c gencmdlist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(parttype_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh parttype > $@ || (rm -f $@; exit 1) + +fs-parttype.lst: commands/i386/pc/parttype.c genfslist.sh + set -e; $(CC) -Icommands/i386/pc -I$(srcdir)/commands/i386/pc $(CPPFLAGS) $(CFLAGS) $(parttype_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh parttype > $@ || (rm -f $@; exit 1) + + +parttype_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 -urpN 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-08-02 14:03:32.000000000 +0200 @@ -102,7 +102,8 @@ pkgdata_MODULES = _chain.mod _linux.mod 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 sendkey.mod \ + activate.mod parttype.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -163,6 +164,18 @@ normal_mod_ASFLAGS = $(COMMON_ASFLAGS) hello_mod_SOURCES = hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) +# For sendkey.mod. +sendkey_mod_SOURCES = commands/i386/pc/sendkey.c +sendkey_mod_CFLAGS = $(COMMON_CFLAGS) + +# For activate.mod. +activate_mod_SOURCES = commands/i386/pc/activate.c +activate_mod_CFLAGS = $(COMMON_CFLAGS) + +# For parttype.mod. +parttype_mod_SOURCES = commands/i386/pc/parttype.c +parttype_mod_CFLAGS = $(COMMON_CFLAGS) + # For boot.mod. boot_mod_SOURCES = commands/boot.c boot_mod_CFLAGS = $(COMMON_CFLAGS) diff -urpN 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_context_t grub_context_get (void); 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 -urpN grub2um/kern/misc.c grub2m/kern/misc.c --- grub2um/kern/misc.c 2005-07-25 15:23:26.000000000 +0200 +++ grub2m/kern/misc.c 2005-08-01 19:01:39.000000000 +0200 @@ -911,41 +911,6 @@ grub_split_cmdline (const char *cmdline, do { switch (c) { - case '"': - /* Double quote. */ - while ((c = getchar ())) - { - if (grub_errno) - return 1; - /* Read in an escaped character. */ - if (c == '\\') - { - c = getchar (); - *(bp++) = c; - continue; - } - else if (c == '"') - break; - /* Read a variable. */ - if (c == '$') - { - getenvvar (); - continue; - } - *(bp++) = c; - } - break; - - case '\'': - /* Single quote. */ - while ((c = getchar ()) != '\'') - { - if (grub_errno) - return 1; - - *(bp++) = c; - } - break; case '\n': /* This was not a argument afterall. */ @@ -971,7 +936,43 @@ grub_split_cmdline (const char *cmdline, c = getchar (); continue; } - *(bp++) = c; + + if (c == '\'') + /* Single quote. */ + while ((c = getchar ()) != '\'') + { + if (grub_errno) + return 1; + + *(bp++) = c; + } + + if (c == '"') + /* Double quote. */ + while ((c = getchar ())) + { + if (grub_errno) + return 1; + /* Read in an escaped character. */ + if (c == '\\') + { + c = getchar (); + *(bp++) = c; + continue; + } + else if (c == '"') + break; + /* Read a variable. */ + if (c == '$') + { + getenvvar (); + continue; + } + *(bp++) = c; + } + + if (c != '"' && c != '\'') + *(bp++) = c; c = getchar (); } unputc (c);