# Author: Cyrus Lien Index: grub2-1.99/grub-core/commands/getfunctionkey.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ grub2-1.99/grub-core/commands/getfunctionkey.c 2012-08-14 16:53:09.779252820 +0800 @@ -0,0 +1,180 @@ +/* getfunctionkey.c - Command to wait a specified number of seconds and get + function key. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 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 + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options[] = + { + {"verbose", 'v', 0, N_("Verbose countdown."), 0, 0}, + {"interruptible", 'i', 0, N_("Interruptible with specified key."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +typedef struct{ + int value; + char *name; +}binding; + +static const binding key_name_table[] = +{ + {GRUB_TERM_KEY_F1, "f1"}, + {GRUB_TERM_KEY_F2, "f2"}, + {GRUB_TERM_KEY_F3, "f3"}, + {GRUB_TERM_KEY_F4, "f4"}, + {GRUB_TERM_KEY_F5, "f5"}, + {GRUB_TERM_KEY_F6, "f6"}, + {GRUB_TERM_KEY_F7, "f7"}, + {GRUB_TERM_KEY_F8, "f8"}, + {GRUB_TERM_KEY_F9, "f9"}, + {GRUB_TERM_KEY_F10, "f10"}, + {GRUB_TERM_KEY_F11, "f11"}, + {GRUB_TERM_KEY_F12, "f12"}, + {0,0} +}; + +static char default_buffer[100]; + +static const char * +lookupname(long value, const binding *table) +{ + const char *name; + + grub_snprintf(default_buffer, sizeof( default_buffer), " "); + name = default_buffer; + + while (table->name) { + if (table->value == value) { + name = table->name; + break; + } + table++; + } + + return(name); +} + +static grub_uint16_t *pos; + +static void +do_print (int n) +{ + grub_term_restore_pos (pos); + /* NOTE: Do not remove the trailing space characters. + They are required to clear the line. */ + grub_printf ("%d ", n); +} + +static int +grub_check_keyboard (char *keyname) +{ + int mods = 0; + + grub_term_input_t term; + + if (grub_term_poll_usb) + grub_term_poll_usb (); + + FOR_ACTIVE_TERM_INPUTS(term) + { + if (term->getkeystatus) + mods |= term->getkeystatus (term); + } + + if (grub_checkkey () >= 0) { + if (!grub_strcmp( keyname, lookupname( grub_getkey(), key_name_table))) + return 1; + } + return 0; +} + +/* Based on grub_millisleep() from kern/generic/millisleep.c. */ +static int +grub_interruptible_millisleep (grub_uint32_t ms, char *keyname) +{ + grub_uint64_t start; + + start = grub_get_time_ms (); + + while (grub_get_time_ms () - start < ms) + if (grub_check_keyboard (keyname)) + return 1; + + return 0; +} + +static grub_err_t +grub_cmd_getfunctionkey (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + int n; + + if ( argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); + + n = grub_strtoul (args[0], 0, 10); + if (n == 0) + { + /* Either `0' or broken input. */ + return 0; + } + + pos = grub_term_save_pos (); + + for (; n; n--) + { + if (state[0].set) + do_print (n); + + if (state[1].set) + { + if (grub_interruptible_millisleep (1000, args[1])) + return 1; + } + else + grub_millisleep (1000); + } + if (state[0].set) + do_print (0); + + return 0; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(getfunctionkey) +{ + cmd = grub_register_extcmd ("getfunctionkey", grub_cmd_getfunctionkey, 0, + N_("-i NUMBER_OF_SECONDS KEY"), + N_("Wait for a specified number of seconds and interrupt when specified function key has been pressed"), + options); +} + +GRUB_MOD_FINI(getfunctionkey) +{ + grub_unregister_extcmd (cmd); +} Index: grub2-1.99/grub-core/Makefile.core.def =================================================================== --- grub2-1.99.orig/grub-core/Makefile.core.def 2012-08-14 16:43:04.816252982 +0800 +++ grub2-1.99/grub-core/Makefile.core.def 2012-08-14 16:52:03.942926371 +0800 @@ -1548,3 +1548,8 @@ name = adler32; common = lib/adler32.c; }; + +module = { + name = getfunctionkey; + common = commands/getfunctionkey.c; +};