Initial effort for gfxmenu on multiterm branch

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-12-26 01:49:57 +01:00
commit bee140683a
68 changed files with 5067 additions and 2577 deletions

View file

@ -35,6 +35,7 @@ grub_fstest_init.c
grub_fstest_init.h grub_fstest_init.h
grub-install grub-install
grub-mk* grub-mk*
grub-pbkdf2
grub-pe2elf grub-pe2elf
grub-probe grub-probe
grub_probe_init.c grub_probe_init.c

View file

@ -171,7 +171,7 @@ endif
### General targets. ### General targets.
CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo
pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst
moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk
cat $(DEFSYMFILES) /dev/null \ cat $(DEFSYMFILES) /dev/null \
| $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \
@ -189,12 +189,18 @@ partmap.lst: $(PARTMAPFILES)
handler.lst: $(HANDLERFILES) handler.lst: $(HANDLERFILES)
cat $^ /dev/null | sort > $@ cat $^ /dev/null | sort > $@
terminal.lst: $(TERMINALFILES)
cat $^ /dev/null | sort > $@
parttool.lst: $(PARTTOOLFILES) parttool.lst: $(PARTTOOLFILES)
cat $^ /dev/null | sort | uniq > $@ cat $^ /dev/null | sort | uniq > $@
video.lst: $(VIDEOFILES) video.lst: $(VIDEOFILES)
cat $^ /dev/null | sort | uniq > $@ cat $^ /dev/null | sort | uniq > $@
crypto.lst: lib/libgcrypt-grub/cipher/crypto.lst
cp $^ $@
ifneq (true, $(MAKEINFO)) ifneq (true, $(MAKEINFO))
info_INFOS += docs/grub.info info_INFOS += docs/grub.info
endif endif

View file

@ -25,10 +25,9 @@
#include <grub/command.h> #include <grub/command.h>
static grub_err_t static grub_err_t
grub_cmd_handler (struct grub_command *cmd, grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args) int argc, char **args)
{ {
char *class_name;
void *curr_item = 0; void *curr_item = 0;
grub_handler_class_t head; grub_handler_class_t head;
@ -43,23 +42,19 @@ grub_cmd_handler (struct grub_command *cmd,
return 0; return 0;
} }
class_name = (grub_strcmp (cmd->name, "handler")) ? (char *) cmd->name : 0;
head = grub_handler_class_list; head = grub_handler_class_list;
if ((argc == 0) && (class_name == 0)) if (argc == 0)
{ {
grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item); grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item);
} }
else else
{ {
char *class_name;
grub_handler_class_t class; grub_handler_class_t class;
if (class_name == 0) class_name = args[0];
{ argc--;
class_name = args[0]; args++;
argc--;
args++;
}
class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name); class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name);
if (! class) if (! class)
@ -89,7 +84,7 @@ grub_cmd_handler (struct grub_command *cmd,
return 0; return 0;
} }
static grub_command_t cmd_handler, cmd_terminal_input, cmd_terminal_output; static grub_command_t cmd_handler;
GRUB_MOD_INIT(handler) GRUB_MOD_INIT(handler)
{ {
@ -97,19 +92,9 @@ GRUB_MOD_INIT(handler)
grub_register_command ("handler", grub_cmd_handler, grub_register_command ("handler", grub_cmd_handler,
"handler [class [handler]]", "handler [class [handler]]",
"List or select a handler."); "List or select a handler.");
cmd_terminal_input =
grub_register_command ("terminal_input", grub_cmd_handler,
"terminal_input [handler]",
"List or select an input terminal.");
cmd_terminal_output =
grub_register_command ("terminal_output", grub_cmd_handler,
"terminal_output [handler]",
"List or select an output terminal.");
} }
GRUB_MOD_FINI(handler) GRUB_MOD_FINI(handler)
{ {
grub_unregister_command (cmd_handler); grub_unregister_command (cmd_handler);
grub_unregister_command (cmd_terminal_input);
grub_unregister_command (cmd_terminal_output);
} }

278
commands/hashsum.c Normal file
View file

@ -0,0 +1,278 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/dl.h>
#include <grub/extcmd.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/crypto.h>
#include <grub/normal.h>
static const struct grub_arg_option options[] = {
{"hash", 'h', 0, "Specify hash to use.", "HASH", ARG_TYPE_STRING},
{"check", 'c', 0, "Check hash list file.", "FILE", ARG_TYPE_STRING},
{"prefix", 'p', 0, "Base directory for hash list.", "DIRECTORY",
ARG_TYPE_STRING},
{"keep-going", 'k', 0, "Don't stop after first error.", 0, 0},
{0, 0, 0, 0, 0, 0}
};
struct { const char *name; const char *hashname; } aliases[] =
{
{"sha256sum", "sha256"},
{"sha512sum", "sha512"},
{"md5sum", "md5"},
};
static inline int
hextoval (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
static grub_err_t
hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
{
grub_uint8_t context[hash->contextsize];
char *readbuf[4096];
grub_memset (context, 0, sizeof (context));
hash->init (context);
while (1)
{
grub_ssize_t r;
r = grub_file_read (file, readbuf, sizeof (readbuf));
if (r < 0)
return grub_errno;
if (r == 0)
break;
hash->write (context, readbuf, r);
}
hash->final (context);
grub_memcpy (result, hash->read (context), hash->mdlen);
return GRUB_ERR_NONE;
}
static grub_err_t
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
const char *prefix, int keep)
{
grub_file_t hashlist, file;
char *buf = NULL;
grub_uint8_t expected[hash->mdlen];
grub_uint8_t actual[hash->mdlen];
grub_err_t err;
unsigned i;
unsigned unread = 0, mismatch = 0;
hashlist = grub_file_open (hashfilename);
if (!hashlist)
return grub_errno;
while (grub_free (buf), (buf = grub_file_getline (hashlist)))
{
const char *p = buf;
for (i = 0; i < hash->mdlen; i++)
{
int high, low;
high = hextoval (*p++);
low = hextoval (*p++);
if (high < 0 || low < 0)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
expected[i] = (high << 4) | low;
}
if (*p++ != ' ' || *p++ != ' ')
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list");
if (prefix)
{
char *filename;
filename = grub_malloc (grub_strlen (prefix)
+ grub_strlen (p) + 2);
if (!filename)
return grub_errno;
grub_sprintf (filename, "%s/%s", prefix, p);
file = grub_file_open (filename);
grub_free (filename);
}
else
file = grub_file_open (p);
if (!file)
{
grub_file_close (hashlist);
grub_free (buf);
return grub_errno;
}
err = hash_file (file, hash, actual);
grub_file_close (file);
if (err)
{
grub_printf ("%s: READ ERROR\n", p);
if (!keep)
{
grub_file_close (hashlist);
grub_free (buf);
return err;
}
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
unread++;
continue;
}
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
{
grub_printf ("%s: HASH MISMATCH\n", p);
if (!keep)
{
grub_file_close (hashlist);
grub_free (buf);
return grub_error (GRUB_ERR_TEST_FAILURE,
"hash of '%s' mismatches", p);
}
mismatch++;
continue;
}
grub_printf ("%s: OK\n", p);
}
if (mismatch || unread)
return grub_error (GRUB_ERR_TEST_FAILURE,
"%d files couldn't be read and hash "
"of %d files mismatches", unread, mismatch);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_hashsum (struct grub_extcmd *cmd,
int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
const char *hashname = NULL;
const char *prefix = NULL;
const gcry_md_spec_t *hash;
unsigned i;
int keep = state[3].set;
unsigned unread = 0;
for (i = 0; i < ARRAY_SIZE (aliases); i++)
if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0)
hashname = aliases[i].hashname;
if (state[0].set)
hashname = state[0].arg;
if (!hashname)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no hash specified");
hash = grub_crypto_lookup_md_by_name (hashname);
if (!hash)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown hash");
if (state[2].set)
prefix = state[2].arg;
if (state[1].set)
{
if (argc != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"--check is incompatible with file list");
return check_list (hash, state[1].arg, prefix, keep);
}
for (i = 0; i < (unsigned) argc; i++)
{
grub_uint8_t result[hash->mdlen];
grub_file_t file;
grub_err_t err;
unsigned j;
file = grub_file_open (args[i]);
if (!file)
{
if (!keep)
return grub_errno;
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
unread++;
continue;
}
err = hash_file (file, hash, result);
grub_file_close (file);
if (err)
{
if (!keep)
return err;
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
unread++;
continue;
}
for (j = 0; j < hash->mdlen; j++)
grub_printf ("%02x", result[j]);
grub_printf (" %s\n", args[i]);
}
if (unread)
return grub_error (GRUB_ERR_TEST_FAILURE, "%d files couldn't be read.",
unread);
return GRUB_ERR_NONE;
}
static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512;
GRUB_MOD_INIT(hashsum)
{
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
"hashsum -h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
"Compute or check hash checksum.",
options);
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
"md5sum [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
"Compute or check hash checksum.",
options);
cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
"sha256sum [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
"Compute or check hash checksum.",
options);
cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
"sha512sum [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
"Compute or check hash checksum.",
options);
}
GRUB_MOD_FINI(hashsum)
{
grub_unregister_extcmd (cmd);
grub_unregister_extcmd (cmd_md5);
grub_unregister_extcmd (cmd_sha256);
grub_unregister_extcmd (cmd_sha512);
}

View file

@ -37,18 +37,26 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) &&
(cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE))
{ {
char description[GRUB_TERM_WIDTH / 2]; struct grub_term_output *cur;
int desclen = grub_strlen (cmd->summary); int desclen = grub_strlen (cmd->summary);
FOR_ACTIVE_TERM_OUTPUTS(cur)
{
int width = grub_term_width(cur);
char description[width / 2];
/* Make a string with a length of GRUB_TERM_WIDTH / 2 - 1 filled /* Make a string with a length of GRUB_TERM_WIDTH / 2 - 1 filled
with the description followed by spaces. */ with the description followed by spaces. */
grub_memset (description, ' ', GRUB_TERM_WIDTH / 2 - 1); grub_memset (description, ' ', width / 2 - 1);
description[GRUB_TERM_WIDTH / 2 - 1] = '\0'; description[width / 2 - 1] = '\0';
grub_memcpy (description, cmd->summary, grub_memcpy (description, cmd->summary,
(desclen < GRUB_TERM_WIDTH / 2 - 1 (desclen < width / 2 - 1
? desclen : GRUB_TERM_WIDTH / 2 - 1)); ? desclen : width / 2 - 1));
grub_puts_terminal (description, cur);
grub_printf ("%s%s", description, (cnt++) % 2 ? "\n" : " "); }
if ((cnt++) % 2)
grub_printf ("\n");
else
grub_printf (" ");
} }
return 0; return 0;
} }
@ -73,7 +81,11 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
} }
if (argc == 0) if (argc == 0)
grub_command_iterate (print_command_info); {
grub_command_iterate (print_command_info);
if (!(cnt % 2))
grub_printf ("\n");
}
else else
{ {
int i; int i;

View file

@ -48,13 +48,24 @@ grub_cmd_keystatus (grub_extcmd_t cmd,
if (state[2].set) if (state[2].set)
expect_mods |= GRUB_TERM_STATUS_ALT; expect_mods |= GRUB_TERM_STATUS_ALT;
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods);
/* Without arguments, just check whether getkeystatus is supported at /* Without arguments, just check whether getkeystatus is supported at
all. */ all. */
if (!grub_cur_term_input->getkeystatus) if (expect_mods == 0)
return grub_error (GRUB_ERR_TEST_FAILURE, "false"); {
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); grub_term_input_t term;
if (!expect_mods) int nterms = 0;
return 0;
FOR_ACTIVE_TERM_INPUTS (term)
if (!term->getkeystatus)
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
else
nterms++;
if (!nterms)
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
return 0;
}
mods = grub_getkeystatus (); mods = grub_getkeystatus ();
grub_dprintf ("keystatus", "mods: %d\n", mods); grub_dprintf ("keystatus", "mods: %d\n", mods);

View file

@ -17,6 +17,7 @@
*/ */
#include <grub/auth.h> #include <grub/auth.h>
#include <grub/crypto.h>
#include <grub/list.h> #include <grub/list.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
@ -27,17 +28,10 @@
static grub_dl_t my_mod; static grub_dl_t my_mod;
static grub_err_t static grub_err_t
check_password (const char *user, check_password (const char *user, const char *entered,
void *password) void *password)
{ {
char entered[1024]; if (grub_crypto_memcmp (entered, password, GRUB_AUTH_MAX_PASSLEN) != 0)
grub_memset (entered, 0, sizeof (entered));
if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1))
return GRUB_ACCESS_DENIED;
if (grub_auth_strcmp (entered, password) != 0)
return GRUB_ACCESS_DENIED; return GRUB_ACCESS_DENIED;
grub_auth_authenticate (user); grub_auth_authenticate (user);
@ -51,13 +45,18 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
{ {
grub_err_t err; grub_err_t err;
char *pass; char *pass;
int copylen;
if (argc != 2) if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected."); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
pass = grub_strdup (args[1]); pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN);
if (!pass) if (!pass)
return grub_errno; return grub_errno;
copylen = grub_strlen (args[1]);
if (copylen >= GRUB_AUTH_MAX_PASSLEN)
copylen = GRUB_AUTH_MAX_PASSLEN - 1;
grub_memcpy (pass, args[1], copylen);
err = grub_auth_register_authentication (args[0], check_password, pass); err = grub_auth_register_authentication (args[0], check_password, pass);
if (err) if (err)

196
commands/password_pbkdf2.c Normal file
View file

@ -0,0 +1,196 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/auth.h>
#include <grub/crypto.h>
#include <grub/list.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/normal.h>
#include <grub/dl.h>
static grub_dl_t my_mod;
struct pbkdf2_password
{
grub_uint8_t *salt;
grub_size_t saltlen;
unsigned int c;
grub_uint8_t *expected;
grub_size_t buflen;
};
static grub_err_t
check_password (const char *user, const char *entered, void *pin)
{
grub_uint8_t *buf;
struct pbkdf2_password *pass = pin;
gcry_err_code_t err;
buf = grub_malloc (pass->buflen);
if (!buf)
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) entered,
grub_strlen (entered),
pass->salt, pass->saltlen, pass->c,
buf, pass->buflen);
if (err)
{
grub_free (buf);
return grub_crypto_gcry_error (err);
}
if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
return GRUB_ACCESS_DENIED;
grub_auth_authenticate (user);
return GRUB_ERR_NONE;
}
static inline int
hex2val (char hex)
{
if ('0' <= hex && hex <= '9')
return hex - '0';
if ('a' <= hex && hex <= 'f')
return hex - 'a' + 10;
if ('A' <= hex && hex <= 'F')
return hex - 'A' + 10;
return -1;
}
static grub_err_t
grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
grub_err_t err;
char *ptr, *ptr2;
grub_uint8_t *ptro;
struct pbkdf2_password *pass;
if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
if (grub_memcmp (args[1], "grub.pbkdf2.sha512.",
sizeof ("grub.pbkdf2.sha512.") - 1) != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1;
pass = grub_malloc (sizeof (*pass));
if (!pass)
return grub_errno;
pass->c = grub_strtoul (ptr, &ptr, 0);
if (*ptr != '.')
{
grub_free (pass);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
}
ptr++;
ptr2 = grub_strchr (ptr, '.');
if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1)
{
grub_free (pass);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
}
pass->saltlen = (ptr2 - ptr) >> 1;
pass->buflen = grub_strlen (ptr2 + 1) >> 1;
ptro = pass->salt = grub_malloc (pass->saltlen);
if (!ptro)
{
grub_free (pass);
return grub_errno;
}
while (ptr < ptr2)
{
int hex1, hex2;
hex1 = hex2val (*ptr);
ptr++;
hex2 = hex2val (*ptr);
ptr++;
if (hex1 < 0 || hex2 < 0)
{
grub_free (pass->salt);
grub_free (pass);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Incorrect PBKDF2 password.");
}
*ptro = (hex1 << 4) | hex2;
ptro++;
}
ptro = pass->expected = grub_malloc (pass->buflen);
if (!ptro)
{
grub_free (pass->salt);
grub_free (pass);
return grub_errno;
}
ptr = ptr2 + 1;
ptr2 += grub_strlen (ptr2);
while (ptr < ptr2)
{
int hex1, hex2;
hex1 = hex2val (*ptr);
ptr++;
hex2 = hex2val (*ptr);
ptr++;
if (hex1 < 0 || hex2 < 0)
{
grub_free (pass->expected);
grub_free (pass->salt);
grub_free (pass);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Incorrect PBKDF2 password.");
}
*ptro = (hex1 << 4) | hex2;
ptro++;
}
err = grub_auth_register_authentication (args[0], check_password, pass);
if (err)
{
grub_free (pass);
return err;
}
grub_dl_ref (my_mod);
return GRUB_ERR_NONE;
}
static grub_command_t cmd;
GRUB_MOD_INIT(password_pbkdf2)
{
my_mod = mod;
cmd = grub_register_command ("password_pbkdf2", grub_cmd_password,
"password_pbkdf2 USER PBKDF2_PASSWORD",
"Set user password (PBKDF2). ");
}
GRUB_MOD_FINI(password_pbkdf2)
{
grub_unregister_command (cmd);
}

View file

@ -32,12 +32,12 @@ static const struct grub_arg_option options[] =
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
static grub_uint8_t x, y; static grub_uint16_t *pos;
static void static void
do_print (int n) do_print (int n)
{ {
grub_gotoxy (x, y); grub_term_restore_pos (pos);
/* NOTE: Do not remove the trailing space characters. /* NOTE: Do not remove the trailing space characters.
They are required to clear the line. */ They are required to clear the line. */
grub_printf ("%d ", n); grub_printf ("%d ", n);
@ -63,7 +63,6 @@ static grub_err_t
grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
{ {
struct grub_arg_list *state = cmd->state; struct grub_arg_list *state = cmd->state;
grub_uint16_t xy;
int n; int n;
if (argc != 1) if (argc != 1)
@ -77,9 +76,7 @@ grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
return 0; return 0;
} }
xy = grub_getxy (); pos = grub_term_save_pos ();
x = xy >> 8;
y = xy & 0xff;
for (; n; n--) for (; n; n--)
{ {

364
commands/terminal.c Normal file
View file

@ -0,0 +1,364 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/mm.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/term.h>
#include <grub/i18n.h>
#include <grub/misc.h>
struct grub_term_autoload *grub_term_input_autoload = NULL;
struct grub_term_autoload *grub_term_output_autoload = NULL;
grub_err_t
grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
int i;
grub_term_input_t term;
struct grub_term_autoload *aut;
if (argc == 0)
{
grub_puts_ (N_ ("Active input terminals:"));
FOR_ACTIVE_TERM_INPUTS(term)
grub_printf ("%s ", term->name);
grub_printf ("\n");
grub_puts_ (N_ ("Available input terminals:"));
FOR_DISABLED_TERM_INPUTS(term)
grub_printf ("%s ", term->name);
/* This is quadratic but we don't expect mode than 30 terminal
modules ever. */
for (aut = grub_term_input_autoload; aut; aut = aut->next)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
grub_printf ("%s ", aut->name);
}
grub_printf ("\n");
return GRUB_ERR_NONE;
}
i = 0;
if (grub_strcmp (args[0], "--append") == 0
|| grub_strcmp (args[0], "--remove") == 0)
i++;
if (i == argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
for (; i < argc; i++)
{
int again = 0;
while (1)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term == 0)
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
break;
if (again)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
for (aut = grub_term_input_autoload; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0)
{
grub_dl_t mod;
mod = grub_dl_load (aut->modname);
if (mod)
grub_dl_ref (mod);
grub_errno = GRUB_ERR_NONE;
break;
}
if (!aut)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
again = 1;
}
}
if (grub_strcmp (args[0], "--append") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (args[0], "--remove") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
if (!term->next && term == grub_term_inputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
for (i = 0; i < argc; i++)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
GRUB_AS_LIST (term));
}
}
FOR_ACTIVE_TERM_INPUTS(term)
{
for (i = 0; i < argc; i++)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (i == argc)
{
if (!term->next && term == grub_term_inputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
int i;
grub_term_output_t term;
struct grub_term_autoload *aut;
if (argc == 0)
{
grub_puts_ (N_ ("Active output terminals:"));
FOR_ACTIVE_TERM_OUTPUTS(term)
grub_printf ("%s ", term->name);
grub_printf ("\n");
grub_puts_ (N_ ("Available output terminals:"));
FOR_DISABLED_TERM_OUTPUTS(term)
grub_printf ("%s ", term->name);
/* This is quadratic but we don't expect mode than 30 terminal
modules ever. */
for (aut = grub_term_output_autoload; aut; aut = aut->next)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
grub_printf ("%s ", aut->name);
}
grub_printf ("\n");
return GRUB_ERR_NONE;
}
i = 0;
if (grub_strcmp (args[0], "--append") == 0
|| grub_strcmp (args[0], "--remove") == 0)
i++;
if (i == argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
for (; i < argc; i++)
{
int again = 0;
while (1)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term == 0)
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
break;
if (again)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
for (aut = grub_term_output_autoload; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0)
{
grub_dl_t mod;
mod = grub_dl_load (aut->modname);
if (mod)
grub_dl_ref (mod);
grub_errno = GRUB_ERR_NONE;
break;
}
if (!aut)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
again = 1;
}
}
if (grub_strcmp (args[0], "--append") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (args[0], "--remove") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
if (!term->next && term == grub_term_outputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
for (i = 0; i < argc; i++)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
}
FOR_ACTIVE_TERM_OUTPUTS(term)
{
for (i = 0; i < argc; i++)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (i == argc)
{
if (!term->next && term == grub_term_outputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
static grub_command_t cmd_terminal_input, cmd_terminal_output;
GRUB_MOD_INIT(terminal)
{
cmd_terminal_input =
grub_register_command ("terminal_input", grub_cmd_terminal_input,
"terminal_input [--append|--remove] "
"[TERMINAL1] [TERMINAL2] ...",
"List or select an input terminal.");
cmd_terminal_output =
grub_register_command ("terminal_output", grub_cmd_terminal_output,
"terminal_output [--append|--remove] "
"[TERMINAL1] [TERMINAL2] ...",
"List or select an output terminal.");
}
GRUB_MOD_FINI(terminal)
{
grub_unregister_command (cmd_terminal_input);
grub_unregister_command (cmd_terminal_output);
}

View file

@ -31,12 +31,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/crypto.h>
struct tohash
{
grub_uint8_t prefix[16];
grub_uint64_t serial;
} __attribute__ ((packed));
/* This prefix is used by xnu and boot-132 to hash /* This prefix is used by xnu and boot-132 to hash
together with volume serial. */ together with volume serial. */
@ -44,311 +39,27 @@ static grub_uint8_t hash_prefix[16]
= {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, = {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6,
0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC}; 0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
typedef struct {
grub_uint32_t A,B,C,D; /* chaining variables */
grub_uint32_t nblocks;
grub_uint8_t buf[64];
int count;
} MD5_CONTEXT;
static void
md5_init( void *context )
{
MD5_CONTEXT *ctx = context;
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->nblocks = 0;
ctx->count = 0;
}
/* These are the four functions used in the four steps of the MD5 algorithm
and defined in the RFC 1321. The first function is a little bit optimized
(as found in Colin Plumbs public domain implementation). */
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
#define FF(b, c, d) (d ^ (b & (c ^ d)))
#define FG(b, c, d) FF (d, b, c)
#define FH(b, c, d) (b ^ c ^ d)
#define FI(b, c, d) (c ^ (b | ~d))
/****************
* transform n*64 grub_uint8_ts
*/
static void
transform ( MD5_CONTEXT *ctx, const unsigned char *data )
{
grub_uint32_t correct_words[16];
register grub_uint32_t A = ctx->A;
register grub_uint32_t B = ctx->B;
register grub_uint32_t C = ctx->C;
register grub_uint32_t D = ctx->D;
grub_uint32_t *cwp = correct_words;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
{
int i;
const grub_uint32_t *p = (const grub_uint32_t *) data;
for (i = 0; i < 16; i++)
correct_words[i] = grub_le_to_cpu32 (p[i]);
}
#else
grub_memcpy (correct_words, data, 64);
#endif
#define OP(a, b, c, d, s, T) \
do \
{ \
a += FF (b, c, d) + (*cwp++) + T; \
a = rol(a, s); \
a += b; \
} \
while (0)
/* Before we start, one word about the strange constants.
They are defined in RFC 1321 as
T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
*/
/* Round 1. */
OP (A, B, C, D, 7, 0xd76aa478);
OP (D, A, B, C, 12, 0xe8c7b756);
OP (C, D, A, B, 17, 0x242070db);
OP (B, C, D, A, 22, 0xc1bdceee);
OP (A, B, C, D, 7, 0xf57c0faf);
OP (D, A, B, C, 12, 0x4787c62a);
OP (C, D, A, B, 17, 0xa8304613);
OP (B, C, D, A, 22, 0xfd469501);
OP (A, B, C, D, 7, 0x698098d8);
OP (D, A, B, C, 12, 0x8b44f7af);
OP (C, D, A, B, 17, 0xffff5bb1);
OP (B, C, D, A, 22, 0x895cd7be);
OP (A, B, C, D, 7, 0x6b901122);
OP (D, A, B, C, 12, 0xfd987193);
OP (C, D, A, B, 17, 0xa679438e);
OP (B, C, D, A, 22, 0x49b40821);
#undef OP
#define OP(f, a, b, c, d, k, s, T) \
do \
{ \
a += f (b, c, d) + correct_words[k] + T; \
a = rol(a, s); \
a += b; \
} \
while (0)
/* Round 2. */
OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
OP (FG, D, A, B, C, 6, 9, 0xc040b340);
OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
OP (FG, D, A, B, C, 10, 9, 0x02441453);
OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
/* Round 3. */
OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
OP (FH, D, A, B, C, 8, 11, 0x8771f681);
OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
OP (FH, B, C, D, A, 6, 23, 0x04881d05);
OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
/* Round 4. */
OP (FI, A, B, C, D, 0, 6, 0xf4292244);
OP (FI, D, A, B, C, 7, 10, 0x432aff97);
OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
OP (FI, C, D, A, B, 6, 15, 0xa3014314);
OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
/* Put checksum in context given as argument. */
ctx->A += A;
ctx->B += B;
ctx->C += C;
ctx->D += D;
}
/* The routine updates the message-digest context to
* account for the presence of each of the characters inBuf[0..inLen-1]
* in the message whose digest is being computed.
*/
static void
md5_write( void *context, const void *inbuf_arg , grub_size_t inlen)
{
const unsigned char *inbuf = inbuf_arg;
MD5_CONTEXT *hd = context;
if( hd->count == 64 ) /* flush the buffer */
{
transform( hd, hd->buf );
// _gcry_burn_stack (80+6*sizeof(void*));
hd->count = 0;
hd->nblocks++;
}
if( !inbuf )
return;
if( hd->count )
{
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
md5_write( hd, NULL, 0 );
if( !inlen )
return;
}
// _gcry_burn_stack (80+6*sizeof(void*));
while( inlen >= 64 )
{
transform( hd, inbuf );
hd->count = 0;
hd->nblocks++;
inlen -= 64;
inbuf += 64;
}
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
}
/* The routine final terminates the message-digest computation and
* ends with the desired message digest in mdContext->digest[0...15].
* The handle is prepared for a new MD5 cycle.
* Returns 16 grub_uint8_ts representing the digest.
*/
static void
md5_final( void *context)
{
MD5_CONTEXT *hd = context;
grub_uint32_t t, msb, lsb;
grub_uint32_t *p;
md5_write(hd, NULL, 0); /* flush */;
t = hd->nblocks;
/* multiply by 64 to make a grub_uint8_t count */
lsb = t << 6;
msb = t >> 26;
/* add the count */
t = lsb;
if( (lsb += hd->count) < t )
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
lsb <<= 3;
msb <<= 3;
msb |= t >> 29;
if( hd->count < 56 ) /* enough room */
{
hd->buf[hd->count++] = 0x80; /* pad */
while( hd->count < 56 )
hd->buf[hd->count++] = 0; /* pad */
}
else /* need one extra block */
{
hd->buf[hd->count++] = 0x80; /* pad character */
while( hd->count < 64 )
hd->buf[hd->count++] = 0;
md5_write(hd, NULL, 0); /* flush */;
grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
}
/* append the 64 bit count */
hd->buf[56] = lsb ;
hd->buf[57] = lsb >> 8;
hd->buf[58] = lsb >> 16;
hd->buf[59] = lsb >> 24;
hd->buf[60] = msb ;
hd->buf[61] = msb >> 8;
hd->buf[62] = msb >> 16;
hd->buf[63] = msb >> 24;
transform( hd, hd->buf );
// _gcry_burn_stack (80+6*sizeof(void*));
p = (grub_uint32_t *) hd->buf;
#define X(a) do { *p = grub_le_to_cpu32 (hd->a); p++; } while (0)
X(A);
X(B);
X(C);
X(D);
#undef X
}
/**
* GRUB2 Crypto Interface
* Written by Michael Gorven
*/
static grub_err_t
md5 (const char *in, grub_size_t insize, char *out)
{
MD5_CONTEXT hd;
md5_init (&hd);
md5_write (&hd, in, insize);
md5_final (&hd);
grub_memcpy (out, hd.buf, 16);
return GRUB_ERR_NONE;
}
static grub_err_t static grub_err_t
grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args) int argc, char **args)
{ {
struct tohash hashme; grub_uint64_t serial;
grub_uint8_t xnu_uuid[16]; grub_uint8_t *xnu_uuid;
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
char *ptr; char *ptr;
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
hashme.serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix));
GRUB_MD_MD5->init (&ctx);
GRUB_MD_MD5->write (&ctx, hash_prefix, sizeof (hash_prefix));
GRUB_MD_MD5->write (&ctx, &serial, sizeof (serial));
GRUB_MD_MD5->final (&ctx);
xnu_uuid = GRUB_MD_MD5->read (&ctx);
md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid);
grub_sprintf (uuid_string, grub_sprintf (uuid_string,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
(unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1], (unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1],

View file

@ -24,10 +24,10 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
kern/partition.c kern/reader.c kern/term.c \ kern/partition.c kern/reader.c kern/term.c \
kern/rescue_reader.c kern/rescue_parser.c \ kern/rescue_reader.c kern/rescue_parser.c \
lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \ lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \
normal/handler.c normal/auth.c normal/autofs.c \ normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \
normal/completion.c normal/main.c normal/color.c \ normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \ normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/menu_text.c \ normal/menu_text.c normal/crypto.c normal/term.c \
script/main.c script/execute.c script/function.c \ script/main.c script/execute.c script/function.c \
script/lexer.c script/script.c grub_script.tab.c \ script/lexer.c script/script.c grub_script.tab.c \
partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \
@ -59,7 +59,10 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \ disk/raid.c disk/raid5_recover.c disk/raid6_recover.c \
disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \ disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
commands/parttool.c parttool/msdospart.c \ commands/parttool.c parttool/msdospart.c \
lib/libgcrypt-grub/cipher/md5.c \
grub_emu_init.c gnulib/progname.c grub_emu_init.c gnulib/progname.c
grub_emu_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap
ifeq ($(target_cpu), i386) ifeq ($(target_cpu), i386)
grub_emu_SOURCES += commands/i386/cpuid.c grub_emu_SOURCES += commands/i386/cpuid.c

View file

@ -579,7 +579,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
normal/auth.c normal/autofs.c normal/handler.c \ normal/auth.c normal/autofs.c normal/handler.c \
normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \ normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
normal/misc.c normal/misc.c normal/crypto.c normal/term.c
normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
@ -697,3 +697,35 @@ pkglib_MODULES += charset.mod
charset_mod_SOURCES = lib/charset.c charset_mod_SOURCES = lib/charset.c
charset_mod_CFLAGS = $(COMMON_CFLAGS) charset_mod_CFLAGS = $(COMMON_CFLAGS)
charset_mod_LDFLAGS = $(COMMON_LDFLAGS) charset_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += terminal.mod
terminal_mod_SOURCES = commands/terminal.c
terminal_mod_CFLAGS = $(COMMON_CFLAGS)
terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += crypto.mod
crypto_mod_SOURCES = lib/crypto.c
crypto_mod_CFLAGS = $(COMMON_CFLAGS)
crypto_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += hashsum.mod
hashsum_mod_SOURCES = commands/hashsum.c
hashsum_mod_CFLAGS = $(COMMON_CFLAGS)
hashsum_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += pbkdf2.mod
pbkdf2_mod_SOURCES = lib/pbkdf2.c
pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS)
pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS)
# For password_pbkdf2.mod.
pkglib_MODULES += password_pbkdf2.mod
password_pbkdf2_mod_SOURCES = commands/password_pbkdf2.c
password_pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS)
password_pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS)
bin_UTILITIES += grub-mkpasswd-pbkdf2
grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c
grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1
include $(srcdir)/conf/gcry.mk

View file

@ -16,8 +16,4 @@
module=$1 module=$1
grep -v "^#" | sed -n \ grep -v "^#" | sed -n \
-e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" \ -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}"
-e "/grub_reader_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/reader.\1: $module/;p;}" \
-e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_input.\1: $module/;p;}" \
-e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_output.\1: $module/;p;}" \
-e "/grub_menu_viewer_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/menu_viewer.\1: $module/;p;}"

View file

@ -192,6 +192,7 @@ endif
fs = 'fs-' + obj.suffix('lst') fs = 'fs-' + obj.suffix('lst')
partmap = 'partmap-' + obj.suffix('lst') partmap = 'partmap-' + obj.suffix('lst')
handler = 'handler-' + obj.suffix('lst') handler = 'handler-' + obj.suffix('lst')
terminal = 'terminal-' + obj.suffix('lst')
parttool = 'parttool-' + obj.suffix('lst') parttool = 'parttool-' + obj.suffix('lst')
video = 'video-' + obj.suffix('lst') video = 'video-' + obj.suffix('lst')
dep = deps[i] dep = deps[i]
@ -213,6 +214,7 @@ FSFILES += #{fs}
PARTTOOLFILES += #{parttool} PARTTOOLFILES += #{parttool}
PARTMAPFILES += #{partmap} PARTMAPFILES += #{partmap}
HANDLERFILES += #{handler} HANDLERFILES += #{handler}
TERMINALFILES += #{terminal}
VIDEOFILES += #{video} VIDEOFILES += #{video}
#{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh #{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh
@ -240,6 +242,11 @@ VIDEOFILES += #{video}
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
| sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
#{terminal}: #{src} $(#{src}_DEPENDENCIES) genterminallist.sh
set -e; \
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
| sh $(srcdir)/genterminallist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
#{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh #{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh
set -e; \ set -e; \
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \

22
genterminallist.sh Normal file
View file

@ -0,0 +1,22 @@
#! /bin/sh
#
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect command names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \
-e "/grub_term_register_input_active *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \
-e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}" \
-e "/grub_term_register_output_active *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}"

View file

@ -37,199 +37,58 @@
#include <grub/gfxmenu_view.h> #include <grub/gfxmenu_view.h>
#include <grub/time.h> #include <grub/time.h>
static void switch_to_text_menu (void) void
grub_gfxmenu_viewer_fini (void *data)
{ {
grub_env_set ("menuviewer", "text"); grub_gfxmenu_view_t view = data;
grub_gfxmenu_view_destroy (view);
} }
static void /* FIXME: 't' and 'c'. */
process_key_press (int c, grub_err_t
grub_gfxmenu_model_t model, grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
grub_gfxmenu_view_t view,
int nested,
int *should_exit)
{ {
/* When a key is pressed, stop the timeout. */
grub_gfxmenu_model_clear_timeout (model);
switch (c)
{
case 'j':
case GRUB_TERM_DOWN:
{
int i = grub_gfxmenu_model_get_selected_index (model);
int num_items = grub_gfxmenu_model_get_num_entries (model);
if (i < num_items - 1)
{
i++;
grub_gfxmenu_model_set_selected_index (model, i);
grub_gfxmenu_redraw_menu (view);
}
}
break;
case 'k':
case GRUB_TERM_UP:
{
int i = grub_gfxmenu_model_get_selected_index (model);
if (i > 0)
{
i--;
grub_gfxmenu_model_set_selected_index (model, i);
grub_gfxmenu_redraw_menu (view);
}
}
break;
case '\r':
case '\n':
case GRUB_TERM_RIGHT:
{
int selected = grub_gfxmenu_model_get_selected_index (model);
int num_entries = grub_gfxmenu_model_get_num_entries (model);
if (selected >= 0 && selected < num_entries)
{
grub_menu_entry_t entry =
grub_gfxmenu_model_get_entry (model, selected);
grub_gfxmenu_view_execute_entry (view, entry);
}
}
break;
case 'c':
grub_gfxmenu_view_run_terminal (view);
break;
case 't':
/* The write hook for 'menuviewer' will cause
* grub_menu_viewer_should_return to return nonzero. */
switch_to_text_menu ();
*should_exit = 1;
break;
case GRUB_TERM_ESC:
if (nested)
*should_exit = 1;
break;
}
if (grub_errno != GRUB_ERR_NONE)
*should_exit = 1;
}
static void
handle_key_events (grub_gfxmenu_model_t model,
grub_gfxmenu_view_t view,
int nested,
int *should_exit)
{
while ((! *should_exit) && (grub_checkkey () != -1))
{
int key = grub_getkey ();
int c = GRUB_TERM_ASCII_CHAR (key);
process_key_press (c, model, view, nested, should_exit);
}
}
static grub_err_t
show_menu (grub_menu_t menu, int nested)
{
grub_gfxmenu_model_t model;
grub_gfxmenu_view_t view; grub_gfxmenu_view_t view;
const char *theme_path; const char *theme_path;
struct grub_menu_viewer *instance;
theme_path = grub_env_get ("theme"); theme_path = grub_env_get ("theme");
if (! theme_path) if (! theme_path)
{ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified");
switch_to_text_menu ();
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified");
}
model = grub_gfxmenu_model_new (menu); instance = grub_zalloc (sizeof (*instance));
if (! model) if (!instance)
{ return grub_errno;
switch_to_text_menu ();
return grub_errno;
}
/* Create the view. */ /* Create the view. */
view = grub_gfxmenu_view_new (theme_path, model); view = grub_gfxmenu_view_new (theme_path, menu, entry, nested);
if (! view) if (! view)
{ {
grub_print_error (); grub_free (instance);
grub_gfxmenu_model_destroy (model);
switch_to_text_menu ();
return grub_errno; return grub_errno;
} }
/* Initially select the default menu entry. */
int default_index = grub_menu_get_default_entry_index (menu);
grub_gfxmenu_model_set_selected_index (model, default_index);
/* Start the timer to execute the default entry. */
grub_gfxmenu_model_set_timeout (model);
/* Main event loop. */
int exit_requested = 0;
grub_gfxmenu_view_draw (view); grub_gfxmenu_view_draw (view);
grub_video_swap_buffers ();
if (view->double_repaint)
grub_gfxmenu_view_draw (view);
while ((! exit_requested) && (! grub_menu_viewer_should_return ())) instance->data = view;
{ instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry;
grub_gfxmenu_redraw_timeout (view); instance->fini = grub_gfxmenu_viewer_fini;
if (grub_gfxmenu_model_timeout_expired (model)) instance->print_timeout = grub_gfxmenu_print_timeout;
{ instance->clear_timeout = grub_gfxmenu_clear_timeout;
grub_gfxmenu_model_clear_timeout (model);
int i = grub_gfxmenu_model_get_selected_index (model);
grub_menu_entry_t e = grub_gfxmenu_model_get_entry (model, i);
grub_gfxmenu_view_execute_with_fallback (view, e);
continue;
}
handle_key_events (model, view, nested, &exit_requested); grub_menu_register_viewer (instance);
grub_cpu_idle ();
}
grub_gfxmenu_view_destroy (view); return GRUB_ERR_NONE;
grub_gfxmenu_model_destroy (model);
return grub_errno;
} }
static grub_err_t
grub_cmd_gfxmenu (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_menu_t menu = grub_env_get_data_slot ("menu");
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
return show_menu (menu, 1);
}
static struct grub_menu_viewer menu_viewer =
{
.name = "gfxmenu",
.show_menu = show_menu
};
static grub_command_t cmd;
GRUB_MOD_INIT (gfxmenu) GRUB_MOD_INIT (gfxmenu)
{ {
(void) mod; /* To stop warning. */ grub_gfxmenu_try_hook = grub_gfxmenu_try;
grub_menu_viewer_register (&menu_viewer);
cmd = grub_register_command ("gfxmenu", grub_cmd_gfxmenu,
"gfxmenu",
"Show graphical menu interface");
} }
GRUB_MOD_FINI (gfxmenu) GRUB_MOD_FINI (gfxmenu)
{ {
grub_unregister_command (cmd); grub_gfxmenu_try_hook = NULL;
} }

View file

@ -140,11 +140,15 @@ circprog_paint (void *vself, const grub_video_rect_t *region)
center_width, center_height); center_width, center_height);
int radius = width / 2 - tick_width / 2 - 1; int radius = width / 2 - tick_width / 2 - 1;
int nticks = (self->num_ticks int nticks;
* (self->value - self->start)
/ (self->end - self->start));
int tick_begin; int tick_begin;
int tick_end; int tick_end;
if (self->end == self->start)
nticks = 0;
else
nticks = (self->num_ticks
* (self->value - self->start)
/ (self->end - self->start));
/* Do ticks appear or disappear as the value approached the end? */ /* Do ticks appear or disappear as the value approached the end? */
if (self->ticks_disappear) if (self->ticks_disappear)
{ {

View file

@ -67,7 +67,8 @@ struct grub_gui_list_impl
grub_gfxmenu_box_t selected_item_box; grub_gfxmenu_box_t selected_item_box;
grub_gfxmenu_icon_manager_t icon_manager; grub_gfxmenu_icon_manager_t icon_manager;
grub_gfxmenu_model_t menu;
grub_gfxmenu_view_t view;
}; };
typedef struct grub_gui_list_impl *list_impl_t; typedef struct grub_gui_list_impl *list_impl_t;
@ -93,7 +94,7 @@ list_destroy (void *vself)
static int static int
get_num_shown_items (list_impl_t self) get_num_shown_items (list_impl_t self)
{ {
int n = grub_gfxmenu_model_get_num_entries (self->menu); int n = self->view->menu->size;
if (self->min_items_shown != -1 && n < self->min_items_shown) if (self->min_items_shown != -1 && n < self->min_items_shown)
n = self->min_items_shown; n = self->min_items_shown;
if (self->max_items_shown != -1 && n > self->max_items_shown) if (self->max_items_shown != -1 && n > self->max_items_shown)
@ -157,7 +158,7 @@ static struct grub_video_bitmap *
get_item_icon (list_impl_t self, int item_index) get_item_icon (list_impl_t self, int item_index)
{ {
grub_menu_entry_t entry; grub_menu_entry_t entry;
entry = grub_gfxmenu_model_get_entry (self->menu, item_index); entry = grub_menu_get_entry (self->view->menu, item_index);
if (! entry) if (! entry)
return 0; return 0;
@ -167,7 +168,7 @@ get_item_icon (list_impl_t self, int item_index)
static void static void
make_selected_item_visible (list_impl_t self) make_selected_item_visible (list_impl_t self)
{ {
int selected_index = grub_gfxmenu_model_get_selected_index (self->menu); int selected_index = self->view->selected;
if (selected_index < 0) if (selected_index < 0)
return; /* No item is selected. */ return; /* No item is selected. */
int num_shown_items = get_num_shown_items (self); int num_shown_items = get_num_shown_items (self);
@ -222,7 +223,7 @@ draw_menu (list_impl_t self)
int descent = grub_font_get_descent (self->item_font); int descent = grub_font_get_descent (self->item_font);
int item_height = self->item_height; int item_height = self->item_height;
int total_num_items = grub_gfxmenu_model_get_num_entries (self->menu); int total_num_items = self->view->menu->size;
int num_shown_items = get_num_shown_items (self); int num_shown_items = get_num_shown_items (self);
grub_gfxmenu_box_t box = self->menu_box; grub_gfxmenu_box_t box = self->menu_box;
int width = self->bounds.width; int width = self->bounds.width;
@ -256,8 +257,7 @@ draw_menu (list_impl_t self)
visible_index < num_shown_items && menu_index < total_num_items; visible_index < num_shown_items && menu_index < total_num_items;
visible_index++, menu_index++) visible_index++, menu_index++)
{ {
int is_selected = int is_selected = (menu_index == self->view->selected);
(menu_index == grub_gfxmenu_model_get_selected_index (self->menu));
if (is_selected) if (is_selected)
{ {
@ -282,7 +282,7 @@ draw_menu (list_impl_t self)
0, 0, self->icon_width, self->icon_height); 0, 0, self->icon_width, self->icon_height);
const char *item_title = const char *item_title =
grub_gfxmenu_model_get_entry_title (self->menu, menu_index); grub_menu_get_entry (self->view->menu, menu_index)->title;
grub_font_t font = grub_font_t font =
(is_selected && self->selected_item_font (is_selected && self->selected_item_font
? self->selected_item_font ? self->selected_item_font
@ -530,12 +530,12 @@ list_set_property (void *vself, const char *name, const char *value)
/* Set necessary information that the gfxmenu view provides. */ /* Set necessary information that the gfxmenu view provides. */
static void static void
list_set_view_info (void *vself, list_set_view_info (void *vself,
const char *theme_path, grub_gfxmenu_view_t view)
grub_gfxmenu_model_t menu)
{ {
list_impl_t self = vself; list_impl_t self = vself;
grub_gfxmenu_icon_manager_set_theme_path (self->icon_manager, theme_path); grub_gfxmenu_icon_manager_set_theme_path (self->icon_manager,
self->menu = menu; view->theme_path);
self->view = view;
} }
static struct grub_gui_list_ops list_ops = static struct grub_gui_list_ops list_ops =

View file

@ -139,11 +139,16 @@ draw_pixmap_bar (grub_gui_progress_bar_t self)
int bar_v_pad = bar_t_pad + bar_b_pad; int bar_v_pad = bar_t_pad + bar_b_pad;
int tracklen = w - bar_h_pad; int tracklen = w - bar_h_pad;
int trackheight = h - bar_v_pad; int trackheight = h - bar_v_pad;
int barwidth;
if (self->end == self->start)
return;
bar->set_content_size (bar, tracklen, trackheight); bar->set_content_size (bar, tracklen, trackheight);
int barwidth = (tracklen barwidth = (tracklen * (self->value - self->start)
* (self->value - self->start) / (self->end - self->start));
/ (self->end - self->start));
hl->set_content_size (hl, barwidth, h - bar_v_pad); hl->set_content_size (hl, barwidth, h - bar_v_pad);
bar->draw (bar, 0, 0); bar->draw (bar, 0, 0);
@ -174,12 +179,13 @@ static void
progress_bar_paint (void *vself, const grub_video_rect_t *region) progress_bar_paint (void *vself, const grub_video_rect_t *region)
{ {
grub_gui_progress_bar_t self = vself; grub_gui_progress_bar_t self = vself;
grub_video_rect_t vpsave;
if (! self->visible) if (! self->visible)
return; return;
if (!grub_video_have_common_points (region, &self->bounds)) if (!grub_video_have_common_points (region, &self->bounds))
return; return;
grub_video_rect_t vpsave;
grub_gui_set_viewport (&self->bounds, &vpsave); grub_gui_set_viewport (&self->bounds, &vpsave);
if (check_pixmaps (self)) if (check_pixmaps (self))

View file

@ -1,191 +0,0 @@
/* model.c - Graphical menu interface MVC model. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/normal.h>
#include <grub/menu.h>
#include <grub/time.h>
#include <grub/gfxmenu_model.h>
/* Model type definition. */
struct grub_gfxmenu_model
{
grub_menu_t menu;
int num_entries;
grub_menu_entry_t *entries;
int selected_entry_index;
int timeout_set;
grub_uint64_t timeout_start;
grub_uint64_t timeout_at;
};
grub_gfxmenu_model_t
grub_gfxmenu_model_new (grub_menu_t menu)
{
grub_gfxmenu_model_t model;
model = grub_malloc (sizeof (*model));
if (! model)
return 0;
model->menu = menu;
model->num_entries = menu->size;
model->entries = 0;
model->selected_entry_index = 0;
model->timeout_set = 0;
model->timeout_at = 0;
if (model->num_entries > 0)
{
model->entries = grub_malloc (model->num_entries
* sizeof (*model->entries));
if (! model->entries)
goto fail_and_free;
int i;
grub_menu_entry_t cur;
for (i = 0, cur = menu->entry_list;
i < model->num_entries;
i++, cur = cur->next)
{
model->entries[i] = cur;
}
}
return model;
fail_and_free:
grub_free (model->entries);
grub_free (model);
return 0;
}
void
grub_gfxmenu_model_destroy (grub_gfxmenu_model_t model)
{
if (! model)
return;
grub_free (model->entries);
model->entries = 0;
grub_free (model);
}
grub_menu_t
grub_gfxmenu_model_get_menu (grub_gfxmenu_model_t model)
{
return model->menu;
}
void
grub_gfxmenu_model_set_timeout (grub_gfxmenu_model_t model)
{
int timeout_sec = grub_menu_get_timeout ();
if (timeout_sec >= 0)
{
model->timeout_start = grub_get_time_ms ();
model->timeout_at = model->timeout_start + timeout_sec * 1000;
model->timeout_set = 1;
}
else
{
model->timeout_set = 0;
}
}
void
grub_gfxmenu_model_clear_timeout (grub_gfxmenu_model_t model)
{
model->timeout_set = 0;
grub_menu_set_timeout (-1);
}
int
grub_gfxmenu_model_get_timeout_ms (grub_gfxmenu_model_t model)
{
if (!model->timeout_set)
return -1;
return model->timeout_at - model->timeout_start;
}
int
grub_gfxmenu_model_get_timeout_remaining_ms (grub_gfxmenu_model_t model)
{
if (!model->timeout_set)
return -1;
return model->timeout_at - grub_get_time_ms ();
}
int
grub_gfxmenu_model_timeout_expired (grub_gfxmenu_model_t model)
{
if (model->timeout_set
&& grub_get_time_ms () >= model->timeout_at)
return 1;
return 0;
}
int
grub_gfxmenu_model_get_num_entries (grub_gfxmenu_model_t model)
{
return model->num_entries;
}
int
grub_gfxmenu_model_get_selected_index (grub_gfxmenu_model_t model)
{
return model->selected_entry_index;
}
void
grub_gfxmenu_model_set_selected_index (grub_gfxmenu_model_t model, int index)
{
model->selected_entry_index = index;
}
const char *
grub_gfxmenu_model_get_entry_title (grub_gfxmenu_model_t model, int index)
{
if (index < 0 || index >= model->num_entries)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid menu index");
return 0;
}
return model->entries[index]->title;
}
grub_menu_entry_t
grub_gfxmenu_model_get_entry (grub_gfxmenu_model_t model, int index)
{
if (index < 0 || index >= model->num_entries)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid menu index");
return 0;
}
return model->entries[index];
}

View file

@ -25,7 +25,6 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/normal.h> #include <grub/normal.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/gui_string_util.h>
#include <grub/gfxterm.h> #include <grub/gfxterm.h>
#include <grub/bitmap.h> #include <grub/bitmap.h>
#include <grub/bitmap_scale.h> #include <grub/bitmap_scale.h>
@ -35,24 +34,25 @@
#include <grub/menu.h> #include <grub/menu.h>
#include <grub/menu_viewer.h> #include <grub/menu_viewer.h>
#include <grub/gfxmenu_view.h> #include <grub/gfxmenu_view.h>
#include <grub/gui.h> #include <grub/gui_string_util.h>
#include <grub/icon_manager.h> #include <grub/icon_manager.h>
/* The component ID identifying GUI components to be updated as the timeout /* The component ID identifying GUI components to be updated as the timeout
status changes. */ status changes. */
#define TIMEOUT_COMPONENT_ID "__timeout__" #define TIMEOUT_COMPONENT_ID "__timeout__"
#if 0
static grub_gfxmenu_view_t term_view; static grub_gfxmenu_view_t term_view;
#endif
static void init_terminal (grub_gfxmenu_view_t view);
static void destroy_terminal (void);
static grub_err_t set_graphics_mode (void); static grub_err_t set_graphics_mode (void);
static grub_err_t set_text_mode (void); static grub_err_t set_text_mode (void);
/* Create a new view object, loading the theme specified by THEME_PATH and /* Create a new view object, loading the theme specified by THEME_PATH and
associating MODEL with the view. */ associating MODEL with the view. */
grub_gfxmenu_view_t grub_gfxmenu_view_t
grub_gfxmenu_view_new (const char *theme_path, grub_gfxmenu_model_t model) grub_gfxmenu_view_new (const char *theme_path, grub_menu_t menu, int entry,
int nested)
{ {
grub_gfxmenu_view_t view; grub_gfxmenu_view_t view;
grub_err_t err; grub_err_t err;
@ -96,8 +96,11 @@ grub_gfxmenu_view_new (const char *theme_path, grub_gfxmenu_model_t model)
default_fg_color = grub_gui_color_rgb (0, 0, 0); default_fg_color = grub_gui_color_rgb (0, 0, 0);
default_bg_color = grub_gui_color_rgb (255, 255, 255); default_bg_color = grub_gui_color_rgb (255, 255, 255);
view->model = model;
view->canvas = 0; view->canvas = 0;
view->selected = entry;
view->menu = menu;
view->nested = nested;
view->first_timeout = -1;
view->title_font = default_font; view->title_font = default_font;
view->message_font = default_font; view->message_font = default_font;
@ -111,7 +114,6 @@ grub_gfxmenu_view_new (const char *theme_path, grub_gfxmenu_model_t model)
view->title_text = grub_strdup ("GRUB Boot Menu"); view->title_text = grub_strdup ("GRUB Boot Menu");
view->progress_message_text = 0; view->progress_message_text = 0;
view->theme_path = 0; view->theme_path = 0;
view->last_seconds_remaining = -2;
/* Set the timeout bar's frame. */ /* Set the timeout bar's frame. */
view->progress_message_frame.width = view->screen.width * 4 / 5; view->progress_message_frame.width = view->screen.width * 4 / 5;
@ -127,7 +129,9 @@ grub_gfxmenu_view_new (const char *theme_path, grub_gfxmenu_model_t model)
return 0; return 0;
} }
#if 0
init_terminal (view); init_terminal (view);
#endif
return view; return view;
} }
@ -148,9 +152,12 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
grub_free (view); grub_free (view);
set_text_mode (); set_text_mode ();
#if 0
destroy_terminal (); destroy_terminal ();
#endif
} }
#if 0
/* Sets MESSAGE as the progress message for the view. /* Sets MESSAGE as the progress message for the view.
MESSAGE can be 0, in which case no message is displayed. */ MESSAGE can be 0, in which case no message is displayed. */
static void static void
@ -162,6 +169,7 @@ set_progress_message (grub_gfxmenu_view_t view, const char *message)
else else
view->progress_message_text = 0; view->progress_message_text = 0;
} }
#endif
static void static void
redraw_background (grub_gfxmenu_view_t view, redraw_background (grub_gfxmenu_view_t view,
@ -224,18 +232,15 @@ update_timeout_visit (grub_gui_component_t component,
component->ops->set_property (component, "text", pv->text); component->ops->set_property (component, "text", pv->text);
} }
void
static inline void grub_gfxmenu_print_timeout (int timeout, void *data)
update_timeout (grub_gfxmenu_view_t view, int is_init)
{ {
char startbuf[20]; char valuebuf[sizeof ("-XXXXXXXXXXX")];
char valuebuf[20]; char startbuf[sizeof ("-XXXXXXXXXXX")];
char msgbuf[120]; char msgbuf[120];
struct grub_gfxmenu_view *view = data;
int timeout;
int remaining;
struct progress_value_data pv; struct progress_value_data pv;
int seconds_remaining_rounded_up;
auto void redraw_timeout_visit (grub_gui_component_t component, auto void redraw_timeout_visit (grub_gui_component_t component,
void *userdata __attribute__ ((unused))); void *userdata __attribute__ ((unused)));
@ -248,52 +253,62 @@ update_timeout (grub_gfxmenu_view_t view, int is_init)
grub_gfxmenu_view_redraw (view, &bounds); grub_gfxmenu_view_redraw (view, &bounds);
} }
timeout = grub_gfxmenu_model_get_timeout_ms (view->model); if (view->first_timeout == -1)
if (timeout > 0) view->first_timeout = timeout;
{
remaining = grub_gfxmenu_model_get_timeout_remaining_ms (view->model);
seconds_remaining_rounded_up = (remaining + 999) / 1000;
}
else
{
seconds_remaining_rounded_up = -1;
remaining = -1;
}
if (view->last_seconds_remaining == seconds_remaining_rounded_up && !is_init) pv.visible = "true";
return; grub_sprintf (startbuf, "%d", -(view->first_timeout + 1));
view->last_seconds_remaining = seconds_remaining_rounded_up;
pv.visible = timeout > 0 ? "true" : "false";
grub_sprintf (startbuf, "%d", -timeout);
pv.start = startbuf; pv.start = startbuf;
pv.end = "0"; pv.end = "0";
grub_sprintf (valuebuf, "%d", remaining > 0 ? -remaining : 0); grub_sprintf (valuebuf, "%d", -timeout);
pv.value = valuebuf; pv.value = valuebuf;
grub_sprintf (msgbuf, grub_sprintf (msgbuf,
"The highlighted entry will be booted automatically in %d s.", "The highlighted entry will be booted automatically in %d s.",
seconds_remaining_rounded_up); timeout);
pv.text = msgbuf; pv.text = msgbuf;
grub_gui_find_by_id ((grub_gui_component_t) view->canvas, grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv); TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv);
if (!is_init) grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
{ TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
grub_gui_find_by_id ((grub_gui_component_t) view->canvas, grub_video_swap_buffers ();
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv); if (view->double_repaint)
grub_video_swap_buffers (); grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
if (view->double_repaint) TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
}
} }
void void
grub_gfxmenu_redraw_timeout (grub_gfxmenu_view_t view) grub_gfxmenu_clear_timeout (void *data)
{ {
update_timeout (view, 0); struct progress_value_data pv;
struct grub_gfxmenu_view *view = data;
auto void redraw_timeout_visit (grub_gui_component_t component,
void *userdata __attribute__ ((unused)));
auto void redraw_timeout_visit (grub_gui_component_t component,
void *userdata __attribute__ ((unused)))
{
grub_video_rect_t bounds;
component->ops->get_bounds (component, &bounds);
grub_gfxmenu_view_redraw (view, &bounds);
}
pv.visible = "false";
pv.start = "1";
pv.end = "0";
pv.value = "0";
pv.text = "";
grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv);
grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
grub_video_swap_buffers ();
if (view->double_repaint)
grub_gui_find_by_id ((grub_gui_component_t) view->canvas,
TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv);
} }
static void static void
@ -305,7 +320,7 @@ update_menu_visit (grub_gui_component_t component,
if (component->ops->is_instance (component, "list")) if (component->ops->is_instance (component, "list"))
{ {
grub_gui_list_t list = (grub_gui_list_t) component; grub_gui_list_t list = (grub_gui_list_t) component;
list->ops->set_view_info (list, view->theme_path, view->model); list->ops->set_view_info (list, view);
} }
} }
@ -361,7 +376,6 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
void void
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
{ {
update_timeout (view, 1);
update_menu_components (view); update_menu_components (view);
grub_gfxmenu_view_redraw (view, &view->screen); grub_gfxmenu_view_redraw (view, &view->screen);
@ -402,6 +416,16 @@ grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view)
} }
} }
void
grub_gfxmenu_set_chosen_entry (int entry, void *data)
{
grub_gfxmenu_view_t view = data;
view->selected = entry;
grub_gfxmenu_redraw_menu (view);
}
static grub_err_t static grub_err_t
set_graphics_mode (void) set_graphics_mode (void)
{ {
@ -417,6 +441,8 @@ set_text_mode (void)
return grub_video_restore (); return grub_video_restore ();
} }
/* FIXME */
#if 0
static int term_target_width; static int term_target_width;
static int term_target_height; static int term_target_height;
static int term_initialized; static int term_initialized;
@ -487,7 +513,6 @@ static void destroy_terminal (void)
grub_term_set_current_output (term_original); grub_term_set_current_output (term_original);
} }
static void static void
notify_booting (grub_menu_entry_t entry, void *userdata) notify_booting (grub_menu_entry_t entry, void *userdata)
{ {
@ -537,59 +562,4 @@ static struct grub_menu_execute_callback execute_callback =
.notify_failure = notify_execution_failure .notify_failure = notify_execution_failure
}; };
int #endif
grub_gfxmenu_view_execute_with_fallback (grub_gfxmenu_view_t view,
grub_menu_entry_t entry)
{
draw_terminal_box (view);
grub_menu_execute_with_fallback (grub_gfxmenu_model_get_menu (view->model),
entry, &execute_callback, (void *) view);
if (set_graphics_mode () != GRUB_ERR_NONE)
return 0; /* Failure. */
/* If we returned, there was a failure. */
set_progress_message (view,
"Unable to automatically boot. "
"Press SPACE to continue.");
grub_gfxmenu_view_draw (view);
while (GRUB_TERM_ASCII_CHAR(grub_getkey ()) != ' ')
{
/* Wait for SPACE to be pressed. */
}
set_progress_message (view, 0); /* Clear the message. */
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
grub_video_swap_buffers ();
if (view->double_repaint)
grub_gfxmenu_view_redraw (view, &view->progress_message_frame);
return 1; /* Ok. */
}
int
grub_gfxmenu_view_execute_entry (grub_gfxmenu_view_t view,
grub_menu_entry_t entry)
{
draw_terminal_box (view);
grub_menu_execute_entry (entry);
if (grub_errno != GRUB_ERR_NONE)
grub_wait_after_message ();
if (set_graphics_mode () != GRUB_ERR_NONE)
return 0; /* Failure. */
grub_gfxmenu_view_draw (view);
return 1; /* Ok. */
}
void
grub_gfxmenu_view_run_terminal (grub_gfxmenu_view_t view)
{
draw_terminal_box (view);
grub_cmdline_run (1);
grub_gfxmenu_view_draw (view);
}

View file

@ -15,24 +15,15 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef GRUB_AURH_HEADER #ifndef GRUB_AUTH_HEADER
#define GRUB_AUTH_HEADER 1 #define GRUB_AUTH_HEADER 1
#include <grub/err.h> #include <grub/err.h>
#include <grub/i18n.h> #include <grub/crypto.h>
/* Macros for indistinguishibility. */ #define GRUB_AUTH_MAX_PASSLEN 1024
#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
#define GRUB_GET_PASSWORD(string, len) grub_cmdline_get (N_("Enter password:"), \
string, len, \
'*', 0, 0)
/* Like strcmp but untimeable. Accepts NULL as second argument. */ typedef grub_err_t (*grub_auth_callback_t) (const char *, const char *, void *);
int grub_auth_strcmp (const char *user_input, const char *template);
/* Like strcmp but untimeable and ignores commas in needle. */
int grub_auth_strword (const char *haystack, const char *needle);
typedef grub_err_t (*grub_auth_callback_t) (const char*, void *);
grub_err_t grub_auth_register_authentication (const char *user, grub_err_t grub_auth_register_authentication (const char *user,
grub_auth_callback_t callback, grub_auth_callback_t callback,

View file

@ -109,4 +109,13 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
return dest; return dest;
} }
/* Convert UCS-4 to UTF-8. */
char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size);
int
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize);
int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position);
#endif #endif

275
include/grub/crypto.h Normal file
View file

@ -0,0 +1,275 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
* 2007, 2008, 2009 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/>.
*/
/* Contains elements based on gcrypt-module.h and gcrypt.h.in.
If it's changed please update this file. */
#ifndef GRUB_CRYPTO_HEADER
#define GRUB_CRYPTO_HEADER 1
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/err.h>
typedef enum
{
GPG_ERR_NO_ERROR,
GPG_ERR_BAD_MPI,
GPG_ERR_BAD_SECKEY,
GPG_ERR_BAD_SIGNATURE,
GPG_ERR_CIPHER_ALGO,
GPG_ERR_CONFLICT,
GPG_ERR_DECRYPT_FAILED,
GPG_ERR_DIGEST_ALGO,
GPG_ERR_GENERAL,
GPG_ERR_INTERNAL,
GPG_ERR_INV_ARG,
GPG_ERR_INV_CIPHER_MODE,
GPG_ERR_INV_FLAG,
GPG_ERR_INV_KEYLEN,
GPG_ERR_INV_OBJ,
GPG_ERR_INV_OP,
GPG_ERR_INV_SEXP,
GPG_ERR_INV_VALUE,
GPG_ERR_MISSING_VALUE,
GPG_ERR_NO_ENCRYPTION_SCHEME,
GPG_ERR_NO_OBJ,
GPG_ERR_NO_PRIME,
GPG_ERR_NO_SIGNATURE_SCHEME,
GPG_ERR_NOT_FOUND,
GPG_ERR_NOT_IMPLEMENTED,
GPG_ERR_NOT_SUPPORTED,
GPG_ERROR_CFLAGS,
GPG_ERR_PUBKEY_ALGO,
GPG_ERR_SELFTEST_FAILED,
GPG_ERR_TOO_SHORT,
GPG_ERR_UNSUPPORTED,
GPG_ERR_WEAK_KEY,
GPG_ERR_WRONG_KEY_USAGE,
GPG_ERR_WRONG_PUBKEY_ALGO,
GPG_ERR_OUT_OF_MEMORY
} gcry_err_code_t;
#define gpg_err_code_t gcry_err_code_t
#define gpg_error_t gcry_err_code_t
enum gcry_cipher_modes
{
GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */
GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */
GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */
GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */
GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */
GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */
GCRY_CIPHER_MODE_CTR = 6 /* Counter. */
};
/* Type for the cipher_setkey function. */
typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
const unsigned char *key,
unsigned keylen);
/* Type for the cipher_encrypt function. */
typedef void (*gcry_cipher_encrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf);
/* Type for the cipher_decrypt function. */
typedef void (*gcry_cipher_decrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf);
/* Type for the cipher_stencrypt function. */
typedef void (*gcry_cipher_stencrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf,
unsigned int n);
/* Type for the cipher_stdecrypt function. */
typedef void (*gcry_cipher_stdecrypt_t) (void *c,
unsigned char *outbuf,
const unsigned char *inbuf,
unsigned int n);
typedef struct gcry_cipher_oid_spec
{
const char *oid;
int mode;
} gcry_cipher_oid_spec_t;
/* Module specification structure for ciphers. */
typedef struct gcry_cipher_spec
{
const char *name;
const char **aliases;
gcry_cipher_oid_spec_t *oids;
grub_size_t blocksize;
grub_size_t keylen;
grub_size_t contextsize;
gcry_cipher_setkey_t setkey;
gcry_cipher_encrypt_t encrypt;
gcry_cipher_decrypt_t decrypt;
gcry_cipher_stencrypt_t stencrypt;
gcry_cipher_stdecrypt_t stdecrypt;
struct gcry_cipher_spec *next;
} gcry_cipher_spec_t;
/* Type for the md_init function. */
typedef void (*gcry_md_init_t) (void *c);
/* Type for the md_write function. */
typedef void (*gcry_md_write_t) (void *c, const void *buf, grub_size_t nbytes);
/* Type for the md_final function. */
typedef void (*gcry_md_final_t) (void *c);
/* Type for the md_read function. */
typedef unsigned char *(*gcry_md_read_t) (void *c);
typedef struct gcry_md_oid_spec
{
const char *oidstring;
} gcry_md_oid_spec_t;
/* Module specification structure for message digests. */
typedef struct gcry_md_spec
{
const char *name;
unsigned char *asnoid;
int asnlen;
gcry_md_oid_spec_t *oids;
grub_size_t mdlen;
gcry_md_init_t init;
gcry_md_write_t write;
gcry_md_final_t final;
gcry_md_read_t read;
grub_size_t contextsize; /* allocate this amount of context */
/* Block size, needed for HMAC. */
grub_size_t blocksize;
struct gcry_md_spec *next;
} gcry_md_spec_t;
struct grub_crypto_cipher_handle
{
const struct gcry_cipher_spec *cipher;
char ctx[0];
};
typedef struct grub_crypto_cipher_handle *grub_crypto_cipher_handle_t;
struct grub_crypto_hmac_handle;
const gcry_cipher_spec_t *
grub_crypto_lookup_cipher_by_name (const char *name);
grub_crypto_cipher_handle_t
grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher);
gcry_err_code_t
grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
const unsigned char *key,
unsigned keylen);
void
grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher);
void
grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size);
gcry_err_code_t
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size);
gcry_err_code_t
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size);
gcry_err_code_t
grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv_in);
gcry_err_code_t
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv);
void
grub_cipher_register (gcry_cipher_spec_t *cipher);
void
grub_cipher_unregister (gcry_cipher_spec_t *cipher);
void
grub_md_register (gcry_md_spec_t *digest);
void
grub_md_unregister (gcry_md_spec_t *cipher);
void
grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
grub_size_t inlen);
const gcry_md_spec_t *
grub_crypto_lookup_md_by_name (const char *name);
grub_err_t
grub_crypto_gcry_error (gcry_err_code_t in);
void grub_burn_stack (grub_size_t size);
struct grub_crypto_hmac_handle *
grub_crypto_hmac_init (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen);
void
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
grub_size_t datalen);
gcry_err_code_t
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
gcry_err_code_t
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen,
void *data, grub_size_t datalen, void *out);
extern gcry_md_spec_t _gcry_digest_spec_md5;
extern gcry_md_spec_t _gcry_digest_spec_sha1;
extern gcry_md_spec_t _gcry_digest_spec_sha256;
extern gcry_md_spec_t _gcry_digest_spec_sha512;
#define GRUB_MD_MD5 ((const gcry_md_spec_t *) &_gcry_digest_spec_md5)
#define GRUB_MD_SHA1 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha1)
#define GRUB_MD_SHA256 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha256)
#define GRUB_MD_SHA512 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha512)
/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant
of digest supplied by MD. Inputs are the password P of length PLEN,
the salt S of length SLEN, the iteration counter C (> 0), and the
desired derived output length DKLEN. Output buffer is DK which
must have room for at least DKLEN octets. The output buffer will
be filled with the derived data. */
gcry_err_code_t
grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
const grub_uint8_t *P, grub_size_t Plen,
const grub_uint8_t *S, grub_size_t Slen,
unsigned int c,
grub_uint8_t *DK, grub_size_t dkLen);
int
grub_crypto_memcmp (const void *a, const void *b, grub_size_t n);
int
grub_password_get (char buf[], unsigned buf_size);
/* For indistinguishibility. */
#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.")
extern void (*grub_crypto_autoload_hook) (const char *name);
#endif

View file

@ -42,6 +42,7 @@ enum grub_disk_dev_id
GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_PXE_ID,
GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_SCSI_ID,
GRUB_DISK_DEVICE_FILE_ID, GRUB_DISK_DEVICE_FILE_ID,
GRUB_DISK_DEVICE_LUKS_ID
}; };
struct grub_disk; struct grub_disk;

View file

@ -1,59 +1 @@
/* gfxmenu_model.h - gfxmenu model interface. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_GFXMENU_MODEL_HEADER
#define GRUB_GFXMENU_MODEL_HEADER 1
#include <grub/menu.h>
struct grub_gfxmenu_model; /* Forward declaration of opaque type. */
typedef struct grub_gfxmenu_model *grub_gfxmenu_model_t;
grub_gfxmenu_model_t grub_gfxmenu_model_new (grub_menu_t menu);
void grub_gfxmenu_model_destroy (grub_gfxmenu_model_t model);
grub_menu_t grub_gfxmenu_model_get_menu (grub_gfxmenu_model_t model);
void grub_gfxmenu_model_set_timeout (grub_gfxmenu_model_t model);
void grub_gfxmenu_model_clear_timeout (grub_gfxmenu_model_t model);
int grub_gfxmenu_model_get_timeout_ms (grub_gfxmenu_model_t model);
int grub_gfxmenu_model_get_timeout_remaining_ms (grub_gfxmenu_model_t model);
int grub_gfxmenu_model_timeout_expired (grub_gfxmenu_model_t model);
int grub_gfxmenu_model_get_num_entries (grub_gfxmenu_model_t model);
int grub_gfxmenu_model_get_selected_index (grub_gfxmenu_model_t model);
void grub_gfxmenu_model_set_selected_index (grub_gfxmenu_model_t model,
int index);
const char *grub_gfxmenu_model_get_entry_title (grub_gfxmenu_model_t model,
int index);
grub_menu_entry_t grub_gfxmenu_model_get_entry (grub_gfxmenu_model_t model,
int index);
#endif /* GRUB_GFXMENU_MODEL_HEADER */

View file

@ -24,7 +24,6 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/menu.h> #include <grub/menu.h>
#include <grub/font.h> #include <grub/font.h>
#include <grub/gfxmenu_model.h>
#include <grub/gfxwidgets.h> #include <grub/gfxwidgets.h>
struct grub_gfxmenu_view; /* Forward declaration of opaque type. */ struct grub_gfxmenu_view; /* Forward declaration of opaque type. */
@ -32,7 +31,8 @@ typedef struct grub_gfxmenu_view *grub_gfxmenu_view_t;
grub_gfxmenu_view_t grub_gfxmenu_view_new (const char *theme_path, grub_gfxmenu_view_t grub_gfxmenu_view_new (const char *theme_path,
grub_gfxmenu_model_t model); grub_menu_t menu, int entry,
int nested);
void grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view); void grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view);
@ -64,6 +64,13 @@ void
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
const grub_video_rect_t *region); const grub_video_rect_t *region);
void
grub_gfxmenu_clear_timeout (void *data);
void
grub_gfxmenu_print_timeout (int timeout, void *data);
void
grub_gfxmenu_set_chosen_entry (int entry, void *data);
/* Implementation details -- this should not be used outside of the /* Implementation details -- this should not be used outside of the
view itself. */ view itself. */
@ -93,13 +100,17 @@ struct grub_gfxmenu_view
grub_gui_container_t canvas; grub_gui_container_t canvas;
grub_gfxmenu_model_t model;
int last_seconds_remaining;
int double_repaint; int double_repaint;
int selected;
grub_video_rect_t progress_message_frame; grub_video_rect_t progress_message_frame;
grub_menu_t menu;
int nested;
int first_timeout;
}; };
#endif /* ! GRUB_GFXMENU_VIEW_HEADER */ #endif /* ! GRUB_GFXMENU_VIEW_HEADER */

View file

@ -21,7 +21,7 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/bitmap.h> #include <grub/bitmap.h>
#include <grub/gfxmenu_model.h> #include <grub/gfxmenu_view.h>
#ifndef GRUB_GUI_H #ifndef GRUB_GUI_H
#define GRUB_GUI_H 1 #define GRUB_GUI_H 1
@ -73,8 +73,7 @@ struct grub_gui_list_ops
{ {
struct grub_gui_component_ops component_ops; struct grub_gui_component_ops component_ops;
void (*set_view_info) (void *self, void (*set_view_info) (void *self,
const char *theme_path, grub_gfxmenu_view_t view);
grub_gfxmenu_model_t menu);
}; };
struct grub_gui_component struct grub_gui_component

View file

@ -83,6 +83,9 @@ typedef struct grub_menu_execute_callback
} }
*grub_menu_execute_callback_t; *grub_menu_execute_callback_t;
extern grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested);
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no); grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
int grub_menu_get_timeout (void); int grub_menu_get_timeout (void);

View file

@ -27,22 +27,18 @@
struct grub_menu_viewer struct grub_menu_viewer
{ {
/* The menu viewer name. */
const char *name;
grub_err_t (*show_menu) (grub_menu_t menu, int nested);
struct grub_menu_viewer *next; struct grub_menu_viewer *next;
void *data;
void (*set_chosen_entry) (int entry, void *data);
void (*print_timeout) (int timeout, void *data);
void (*clear_timeout) (void *data);
void (*fini) (void *fini);
}; };
typedef struct grub_menu_viewer *grub_menu_viewer_t;
void grub_menu_viewer_init (void); void grub_menu_register_viewer (struct grub_menu_viewer *viewer);
void grub_menu_viewer_register (grub_menu_viewer_t viewer); grub_err_t grub_menu_register_viewer_init (void (*callback) (int entry,
grub_menu_t menu,
grub_err_t grub_menu_viewer_show_menu (grub_menu_t menu, int nested); int nested));
/* Return nonzero iff the menu viewer should clean up and return ASAP. */
int grub_menu_viewer_should_return (void);
#endif /* GRUB_MENU_VIEWER_HEADER */ #endif /* GRUB_MENU_VIEWER_HEADER */

View file

@ -232,11 +232,11 @@ int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ ((
int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args); int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args);
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, grub_size_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest,
grub_size_t destsize, grub_size_t destsize,
const grub_uint8_t *src, const grub_uint8_t *src,
grub_size_t srcsize, grub_size_t srcsize,
const grub_uint8_t **srcend); const grub_uint8_t **srcend);
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint32_t d, grub_uint32_t *r); grub_uint32_t d, grub_uint32_t *r);

View file

@ -20,6 +20,7 @@
#ifndef GRUB_NORMAL_HEADER #ifndef GRUB_NORMAL_HEADER
#define GRUB_NORMAL_HEADER 1 #define GRUB_NORMAL_HEADER 1
#include <grub/term.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/env.h> #include <grub/env.h>
@ -45,21 +46,21 @@ enum grub_completion_type
typedef enum grub_completion_type grub_completion_type_t; typedef enum grub_completion_type grub_completion_type_t;
extern struct grub_menu_viewer grub_normal_text_menu_viewer; extern struct grub_menu_viewer grub_normal_text_menu_viewer;
extern int grub_normal_exit_level;
/* Defined in `main.c'. */ /* Defined in `main.c'. */
void grub_enter_normal_mode (const char *config); void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested, int batch); void grub_normal_execute (const char *config, int nested, int batch);
void grub_normal_init_page (void); void grub_menu_init_page (int nested, int edit,
void grub_menu_init_page (int nested, int edit); struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term);
grub_err_t grub_normal_add_menu_entry (int argc, const char **args, grub_err_t grub_normal_add_menu_entry (int argc, const char **args,
const char *sourcecode); const char *sourcecode);
char *grub_file_getline (grub_file_t file); char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested); void grub_cmdline_run (int nested);
/* Defined in `cmdline.c'. */ /* Defined in `cmdline.c'. */
int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, char *grub_cmdline_get (const char *prompt);
int echo_char, int readline, int history);
grub_err_t grub_set_history (int newsize); grub_err_t grub_set_history (int newsize);
/* Defined in `completion.c'. */ /* Defined in `completion.c'. */
@ -76,14 +77,19 @@ void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
/* Defined in `menu_text.c'. */ /* Defined in `menu_text.c'. */
void grub_wait_after_message (void); void grub_wait_after_message (void);
int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position);
void grub_print_ucs4 (const grub_uint32_t * str, void grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position); const grub_uint32_t * last_position,
struct grub_term_output *term);
grub_ssize_t grub_getstringwidth (grub_uint32_t * str, grub_ssize_t grub_getstringwidth (grub_uint32_t * str,
const grub_uint32_t * last_position); const grub_uint32_t * last_position,
struct grub_term_output *term);
void grub_print_message_indented (const char *msg, int margin_left, void grub_print_message_indented (const char *msg, int margin_left,
int margin_right); int margin_right,
struct grub_term_output *term);
void
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
grub_err_t
grub_show_menu (grub_menu_t menu, int nested);
/* Defined in `handler.c'. */ /* Defined in `handler.c'. */
void read_handler_list (void); void read_handler_list (void);
@ -95,6 +101,11 @@ void read_command_list (void);
/* Defined in `autofs.c'. */ /* Defined in `autofs.c'. */
void read_fs_list (void); void read_fs_list (void);
void read_crypto_list (void);
void read_terminal_list (void);
void grub_set_more (int onoff);
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
void grub_normal_init (void); void grub_normal_init (void);

View file

@ -22,6 +22,7 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/handler.h>
#include <grub/reader.h> #include <grub/reader.h>
/* All the states for the command line. */ /* All the states for the command line. */

View file

@ -20,60 +20,10 @@
#ifndef GRUB_READER_HEADER #ifndef GRUB_READER_HEADER
#define GRUB_READER_HEADER 1 #define GRUB_READER_HEADER 1
#include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/handler.h>
typedef grub_err_t (*grub_reader_getline_t) (char **, int); typedef grub_err_t (*grub_reader_getline_t) (char **, int);
struct grub_reader void grub_rescue_run (void);
{
/* The next reader. */
struct grub_parser *next;
/* The reader name. */
const char *name;
/* Initialize the reader. */
grub_err_t (*init) (void);
/* Clean up the reader. */
grub_err_t (*fini) (void);
grub_reader_getline_t read_line;
};
typedef struct grub_reader *grub_reader_t;
extern struct grub_handler_class EXPORT_VAR(grub_reader_class);
grub_err_t EXPORT_FUNC(grub_reader_loop) (grub_reader_getline_t getline);
static inline void
grub_reader_register (const char *name __attribute__ ((unused)),
grub_reader_t reader)
{
grub_handler_register (&grub_reader_class, GRUB_AS_HANDLER (reader));
}
static inline void
grub_reader_unregister (grub_reader_t reader)
{
grub_handler_unregister (&grub_reader_class, GRUB_AS_HANDLER (reader));
}
static inline grub_reader_t
grub_reader_get_current (void)
{
return (grub_reader_t) grub_reader_class.cur_handler;
}
static inline grub_err_t
grub_reader_set_current (grub_reader_t reader)
{
return grub_handler_set_current (&grub_reader_class,
GRUB_AS_HANDLER (reader));
}
void grub_register_rescue_reader (void);
#endif /* ! GRUB_READER_HEADER */ #endif /* ! GRUB_READER_HEADER */

View file

@ -68,8 +68,6 @@ grub_term_color_state;
#define GRUB_TERM_NO_EDIT (1 << 1) #define GRUB_TERM_NO_EDIT (1 << 1)
/* Set when the terminal cannot do fancy things. */ /* Set when the terminal cannot do fancy things. */
#define GRUB_TERM_DUMB (1 << 2) #define GRUB_TERM_DUMB (1 << 2)
/* Set when the terminal needs to be initialized. */
#define GRUB_TERM_NEED_INIT (1 << 16)
/* Bitmasks for modifier keys returned by grub_getkeystatus. */ /* Bitmasks for modifier keys returned by grub_getkeystatus. */
@ -93,10 +91,6 @@ grub_term_color_state;
/* Menu-related geometrical constants. */ /* Menu-related geometrical constants. */
/* FIXME: Ugly way to get them form terminal. */
#define GRUB_TERM_WIDTH ((grub_getwh()&0xFF00)>>8)
#define GRUB_TERM_HEIGHT (grub_getwh()&0xFF)
/* The number of lines of "GRUB version..." at the top. */ /* The number of lines of "GRUB version..." at the top. */
#define GRUB_TERM_INFO_HEIGHT 1 #define GRUB_TERM_INFO_HEIGHT 1
@ -113,37 +107,12 @@ grub_term_color_state;
/* The X position of the left border. */ /* The X position of the left border. */
#define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN #define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN
/* The width of the border. */
#define GRUB_TERM_BORDER_WIDTH (GRUB_TERM_WIDTH \
- GRUB_TERM_MARGIN * 3 \
- GRUB_TERM_SCROLL_WIDTH)
/* The number of lines of messages at the bottom. */ /* The number of lines of messages at the bottom. */
#define GRUB_TERM_MESSAGE_HEIGHT 8 #define GRUB_TERM_MESSAGE_HEIGHT 8
/* The height of the border. */
#define GRUB_TERM_BORDER_HEIGHT (GRUB_TERM_HEIGHT \
- GRUB_TERM_TOP_BORDER_Y \
- GRUB_TERM_MESSAGE_HEIGHT)
/* The number of entries shown at a time. */
#define GRUB_TERM_NUM_ENTRIES (GRUB_TERM_BORDER_HEIGHT - 2)
/* The Y position of the first entry. */ /* The Y position of the first entry. */
#define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1) #define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1)
/* The max column number of an entry. The last "-1" is for a
continuation marker. */
#define GRUB_TERM_ENTRY_WIDTH (GRUB_TERM_BORDER_WIDTH - 2 \
- GRUB_TERM_MARGIN * 2 - 1)
/* The standard X position of the cursor. */
#define GRUB_TERM_CURSOR_X (GRUB_TERM_LEFT_BORDER_X \
+ GRUB_TERM_BORDER_WIDTH \
- GRUB_TERM_MARGIN \
- 1)
struct grub_term_input struct grub_term_input
{ {
/* The next terminal. */ /* The next terminal. */
@ -224,80 +193,217 @@ struct grub_term_output
}; };
typedef struct grub_term_output *grub_term_output_t; typedef struct grub_term_output *grub_term_output_t;
extern struct grub_handler_class EXPORT_VAR(grub_term_input_class); extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
extern struct grub_handler_class EXPORT_VAR(grub_term_output_class); extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
static inline void
grub_term_register_input_active (const char *name __attribute__ ((unused)),
grub_term_input_t term)
{
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
}
static inline void static inline void
grub_term_register_input (const char *name __attribute__ ((unused)), grub_term_register_input (const char *name __attribute__ ((unused)),
grub_term_input_t term) grub_term_input_t term)
{ {
grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term)); grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
static inline void
grub_term_register_output_active (const char *name __attribute__ ((unused)),
grub_term_output_t term)
{
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term));
} }
static inline void static inline void
grub_term_register_output (const char *name __attribute__ ((unused)), grub_term_register_output (const char *name __attribute__ ((unused)),
grub_term_output_t term) grub_term_output_t term)
{ {
grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term)); grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
} }
static inline void static inline void
grub_term_unregister_input (grub_term_input_t term) grub_term_unregister_input (grub_term_input_t term)
{ {
grub_handler_unregister (&grub_term_input_class, GRUB_AS_HANDLER (term)); grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
} }
static inline void static inline void
grub_term_unregister_output (grub_term_output_t term) grub_term_unregister_output (grub_term_output_t term)
{ {
grub_handler_unregister (&grub_term_output_class, GRUB_AS_HANDLER (term)); grub_list_remove (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
} }
static inline grub_err_t #define FOR_ACTIVE_TERM_INPUTS(var) for (var = grub_term_inputs; var; var = var->next)
grub_term_set_current_input (grub_term_input_t term) #define FOR_DISABLED_TERM_INPUTS(var) for (var = grub_term_inputs_disabled; var; var = var->next)
{ #define FOR_ACTIVE_TERM_OUTPUTS(var) for (var = grub_term_outputs; var; var = var->next)
return grub_handler_set_current (&grub_term_input_class, #define FOR_DISABLED_TERM_OUTPUTS(var) for (var = grub_term_outputs_disabled; var; var = var->next)
GRUB_AS_HANDLER (term));
}
static inline grub_err_t
grub_term_set_current_output (const struct grub_term_output *term)
{
return grub_handler_set_current (&grub_term_output_class,
GRUB_AS_HANDLER (term));
}
static inline grub_term_input_t
grub_term_get_current_input (void)
{
return (grub_term_input_t) grub_term_input_class.cur_handler;
}
static inline grub_term_output_t
grub_term_get_current_output (void)
{
return (grub_term_output_t) grub_term_output_class.cur_handler;
}
void EXPORT_FUNC(grub_putchar) (int c); void EXPORT_FUNC(grub_putchar) (int c);
void EXPORT_FUNC(grub_putcode) (grub_uint32_t code); void EXPORT_FUNC(grub_putcode) (grub_uint32_t code,
grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code); struct grub_term_output *term);
int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_getkey) (void);
int EXPORT_FUNC(grub_checkkey) (void); int EXPORT_FUNC(grub_checkkey) (void);
int EXPORT_FUNC(grub_getkeystatus) (void); int EXPORT_FUNC(grub_getkeystatus) (void);
grub_uint16_t EXPORT_FUNC(grub_getwh) (void);
grub_uint16_t EXPORT_FUNC(grub_getxy) (void);
void EXPORT_FUNC(grub_gotoxy) (grub_uint8_t x, grub_uint8_t y);
void EXPORT_FUNC(grub_cls) (void); void EXPORT_FUNC(grub_cls) (void);
void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state); void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state);
void EXPORT_FUNC(grub_setcolor) (grub_uint8_t normal_color,
grub_uint8_t highlight_color);
void EXPORT_FUNC(grub_getcolor) (grub_uint8_t *normal_color,
grub_uint8_t *highlight_color);
int EXPORT_FUNC(grub_setcursor) (int on);
int EXPORT_FUNC(grub_getcursor) (void);
void EXPORT_FUNC(grub_refresh) (void); void EXPORT_FUNC(grub_refresh) (void);
void EXPORT_FUNC(grub_set_more) (int onoff); void grub_puts_terminal (const char *str, struct grub_term_output *term);
grub_uint16_t *grub_term_save_pos (void);
void grub_term_restore_pos (grub_uint16_t *pos);
static inline unsigned grub_term_width (struct grub_term_output *term)
{
return ((term->getwh()&0xFF00)>>8);
}
static inline unsigned grub_term_height (struct grub_term_output *term)
{
return (term->getwh()&0xFF);
}
/* The width of the border. */
static inline unsigned
grub_term_border_width (struct grub_term_output *term)
{
return grub_term_width (term) - GRUB_TERM_MARGIN * 3 - GRUB_TERM_SCROLL_WIDTH;
}
/* The max column number of an entry. The last "-1" is for a
continuation marker. */
static inline int
grub_term_entry_width (struct grub_term_output *term)
{
return grub_term_border_width (term) - 2 - GRUB_TERM_MARGIN * 2 - 1;
}
/* The height of the border. */
static inline unsigned
grub_term_border_height (struct grub_term_output *term)
{
return grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y
- GRUB_TERM_MESSAGE_HEIGHT;
}
/* The number of entries shown at a time. */
static inline int
grub_term_num_entries (struct grub_term_output *term)
{
return grub_term_border_height (term) - 2;
}
static inline int
grub_term_cursor_x (struct grub_term_output *term)
{
return (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN - 1);
}
static inline grub_uint16_t
grub_term_getxy (struct grub_term_output *term)
{
return term->getxy ();
}
static inline void
grub_term_refresh (struct grub_term_output *term)
{
if (term->refresh)
term->refresh ();
}
static inline void
grub_term_gotoxy (struct grub_term_output *term, grub_uint8_t x, grub_uint8_t y)
{
term->gotoxy (x, y);
}
static inline void
grub_term_setcolorstate (struct grub_term_output *term,
grub_term_color_state state)
{
if (term->setcolorstate)
term->setcolorstate (state);
}
/* Set the normal color and the highlight color. The format of each
color is VGA's. */
static inline void
grub_term_setcolor (struct grub_term_output *term,
grub_uint8_t normal_color, grub_uint8_t highlight_color)
{
if (term->setcolor)
term->setcolor (normal_color, highlight_color);
}
/* Turn on/off the cursor. */
static inline void
grub_term_setcursor (struct grub_term_output *term, int on)
{
if (term->setcursor)
term->setcursor (on);
}
static inline void
grub_term_cls (struct grub_term_output *term)
{
if (term->cls)
(term->cls) ();
else
{
grub_putcode ('\n', term);
grub_term_refresh (term);
}
}
static inline grub_ssize_t
grub_term_getcharwidth (struct grub_term_output *term, grub_uint32_t c)
{
if (term->getcharwidth)
return term->getcharwidth (c);
else
return 1;
}
static inline void
grub_term_getcolor (struct grub_term_output *term,
grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
{
if (term->getcolor)
term->getcolor (normal_color, highlight_color);
else
{
*normal_color = 0x07;
*highlight_color = 0x07;
}
}
extern void (*EXPORT_VAR (grub_newline_hook)) (void);
struct grub_term_autoload
{
struct grub_term_autoload *next;
char *name;
char *modname;
};
extern struct grub_term_autoload *grub_term_input_autoload;
extern struct grub_term_autoload *grub_term_output_autoload;
/* For convenience. */ /* For convenience. */
#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff) #define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff)

View file

@ -21,15 +21,17 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/term.h>
char *grub_terminfo_get_current (void); char *grub_terminfo_get_current (void);
grub_err_t grub_terminfo_set_current (const char *); grub_err_t grub_terminfo_set_current (const char *);
void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y); void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y,
void grub_terminfo_cls (void); grub_term_output_t oterm);
void grub_terminfo_reverse_video_on (void); void grub_terminfo_cls (grub_term_output_t oterm);
void grub_terminfo_reverse_video_off (void); void grub_terminfo_reverse_video_on (grub_term_output_t oterm);
void grub_terminfo_cursor_on (void); void grub_terminfo_reverse_video_off (grub_term_output_t oterm);
void grub_terminfo_cursor_off (void); void grub_terminfo_cursor_on (grub_term_output_t oterm);
void grub_terminfo_cursor_off (grub_term_output_t oterm);
#endif /* ! GRUB_TERMINFO_HEADER */ #endif /* ! GRUB_TERMINFO_HEADER */

View file

@ -169,9 +169,8 @@ grub_main (void)
grub_register_core_commands (); grub_register_core_commands ();
grub_register_rescue_parser (); grub_register_rescue_parser ();
grub_register_rescue_reader ();
grub_load_config (); grub_load_config ();
grub_load_normal_mode (); grub_load_normal_mode ();
grub_reader_loop (0); grub_rescue_run ();
} }

View file

@ -878,10 +878,10 @@ grub_sprintf (char *str, const char *fmt, ...)
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string. bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
Return the number of characters converted. DEST must be able to hold Return the number of characters converted. DEST must be able to hold
at least DESTSIZE characters. If an invalid sequence is found, return -1. at least DESTSIZE characters.
If SRCEND is not NULL, then *SRCEND is set to the next byte after the If SRCEND is not NULL, then *SRCEND is set to the next byte after the
last byte used in SRC. */ last byte used in SRC. */
grub_ssize_t grub_size_t
grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend) const grub_uint8_t **srcend)
@ -903,7 +903,8 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
if ((c & 0xc0) != 0x80) if ((c & 0xc0) != 0x80)
{ {
/* invalid */ /* invalid */
return -1; code = '?';
count = 0;
} }
else else
{ {
@ -945,7 +946,11 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
code = c & 0x01; code = c & 0x01;
} }
else else
return -1; {
/* invalid */
code = '?';
count = 0;
}
} }
if (count == 0) if (count == 0)
@ -964,15 +969,14 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
void void
grub_abort (void) grub_abort (void)
{ {
if (grub_term_get_current_output ()) grub_printf ("\nAborted.");
{
grub_printf ("\nAborted.");
if (grub_term_get_current_input ()) #ifndef GRUB_UTIL
{ if (grub_term_inputs)
grub_printf (" Press any key to exit."); #endif
grub_getkey (); {
} grub_printf (" Press any key to exit.");
grub_getkey ();
} }
grub_exit (); grub_exit ();

View file

@ -22,28 +22,3 @@
#include <grub/reader.h> #include <grub/reader.h>
#include <grub/parser.h> #include <grub/parser.h>
struct grub_handler_class grub_reader_class =
{
.name = "reader"
};
grub_err_t
grub_reader_loop (grub_reader_getline_t getline)
{
while (1)
{
char *line;
grub_reader_getline_t func;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
func = (getline) ? : grub_reader_get_current ()->read_line;
if ((func (&line, 0)) || (! line))
return grub_errno;
grub_parser_get_current ()->parse_line (line, func);
grub_free (line);
}
}

View file

@ -19,20 +19,15 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/reader.h> #include <grub/reader.h>
#include <grub/parser.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/mm.h>
#define GRUB_RESCUE_BUF_SIZE 256 #define GRUB_RESCUE_BUF_SIZE 256
static char linebuf[GRUB_RESCUE_BUF_SIZE]; static char linebuf[GRUB_RESCUE_BUF_SIZE];
static grub_err_t
grub_rescue_init (void)
{
grub_printf ("Entering rescue mode...\n");
return 0;
}
/* Prompt to input a command and read the line. */ /* Prompt to input a command and read the line. */
static grub_err_t static grub_err_t
grub_rescue_read_line (char **line, int cont) grub_rescue_read_line (char **line, int cont)
@ -74,15 +69,24 @@ grub_rescue_read_line (char **line, int cont)
return 0; return 0;
} }
static struct grub_reader grub_rescue_reader =
{
.name = "rescue",
.init = grub_rescue_init,
.read_line = grub_rescue_read_line
};
void void
grub_register_rescue_reader (void) grub_rescue_run (void)
{ {
grub_reader_register ("rescue", &grub_rescue_reader); grub_printf ("Entering rescue mode...\n");
while (1)
{
char *line;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_rescue_read_line (&line, 0);
if (! line)
continue;
grub_parser_get_current ()->parse_line (line, grub_rescue_read_line);
grub_free (line);
}
} }

View file

@ -21,79 +21,33 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/cpu/time.h>
/* The amount of lines counted by the pager. */ struct grub_term_output *grub_term_outputs_disabled;
static int grub_more_lines; struct grub_term_input *grub_term_inputs_disabled;
struct grub_term_output *grub_term_outputs;
struct grub_term_input *grub_term_inputs;
/* If the more pager is active. */ void (*grub_newline_hook) (void) = NULL;
static int grub_more;
/* The current cursor state. */
static int cursor_state = 1;
struct grub_handler_class grub_term_input_class =
{
.name = "terminal_input"
};
struct grub_handler_class grub_term_output_class =
{
.name = "terminal_output"
};
#define grub_cur_term_input grub_term_get_current_input ()
#define grub_cur_term_output grub_term_get_current_output ()
/* Put a Unicode character. */ /* Put a Unicode character. */
void void
grub_putcode (grub_uint32_t code) grub_putcode (grub_uint32_t code, struct grub_term_output *term)
{ {
int height = grub_getwh () & 255; if (code == '\t' && term->getxy)
if (code == '\t' && grub_cur_term_output->getxy)
{ {
int n; int n;
n = 8 - ((grub_getxy () >> 8) & 7); n = 8 - ((term->getxy () >> 8) & 7);
while (n--) while (n--)
grub_putcode (' '); grub_putcode (' ', term);
return; return;
} }
(grub_cur_term_output->putchar) (code);
if (code == '\n') if (code == '\n')
{ (term->putchar) ('\r');
grub_putcode ('\r'); (term->putchar) (code);
grub_more_lines++;
if (grub_more && grub_more_lines == height - 1)
{
char key;
int pos = grub_getxy ();
/* Show --MORE-- on the lower left side of the screen. */
grub_gotoxy (1, height - 1);
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_printf ("--MORE--");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
key = grub_getkey ();
/* Remove the message. */
grub_gotoxy (1, height - 1);
grub_printf (" ");
grub_gotoxy (pos >> 8, pos & 0xFF);
/* Scroll one lines or an entire page, depending on the key. */
if (key == '\r' || key =='\n')
grub_more_lines--;
else
grub_more_lines = 0;
}
}
} }
/* Put a character. C is one byte of a UTF-8 stream. /* Put a character. C is one byte of a UTF-8 stream.
@ -104,137 +58,103 @@ grub_putchar (int c)
static grub_size_t size = 0; static grub_size_t size = 0;
static grub_uint8_t buf[6]; static grub_uint8_t buf[6];
grub_uint32_t code; grub_uint32_t code;
grub_ssize_t ret; grub_size_t ret;
buf[size++] = c; buf[size++] = c;
ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0); ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0);
if (ret > 0) if (ret != 0)
{ {
struct grub_term_output *term;
size = 0; size = 0;
grub_putcode (code); FOR_ACTIVE_TERM_OUTPUTS(term)
grub_putcode (code, term);
if (code == '\n' && grub_newline_hook)
grub_newline_hook ();
} }
else if (ret < 0)
{
size = 0;
grub_putcode ('?');
}
}
/* Return the number of columns occupied by the character code CODE. */
grub_ssize_t
grub_getcharwidth (grub_uint32_t code)
{
return (grub_cur_term_output->getcharwidth) (code);
} }
int int
grub_getkey (void) grub_getkey (void)
{ {
grub_term_input_t term;
grub_refresh (); grub_refresh ();
return (grub_cur_term_input->getkey) ();
while (1)
{
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey ();
if (key != -1)
return term->getkey ();
}
grub_cpu_idle ();
}
} }
int int
grub_checkkey (void) grub_checkkey (void)
{ {
return (grub_cur_term_input->checkkey) (); grub_term_input_t term;
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey ();
if (key != -1)
return key;
}
return -1;
} }
int int
grub_getkeystatus (void) grub_getkeystatus (void)
{ {
if (grub_cur_term_input->getkeystatus) int status = 0;
return (grub_cur_term_input->getkeystatus) (); grub_term_input_t term;
else
return 0;
}
grub_uint16_t FOR_ACTIVE_TERM_INPUTS(term)
grub_getxy (void) {
{ if (term->getkeystatus)
return (grub_cur_term_output->getxy) (); status |= term->getkeystatus ();
} }
grub_uint16_t return status;
grub_getwh (void)
{
return (grub_cur_term_output->getwh) ();
}
void
grub_gotoxy (grub_uint8_t x, grub_uint8_t y)
{
(grub_cur_term_output->gotoxy) (x, y);
} }
void void
grub_cls (void) grub_cls (void)
{ {
if ((grub_cur_term_output->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) struct grub_term_output *term;
{
grub_putchar ('\n'); FOR_ACTIVE_TERM_OUTPUTS(term)
grub_refresh (); {
} if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
else {
(grub_cur_term_output->cls) (); grub_putcode ('\n', term);
grub_term_refresh (term);
}
else
(term->cls) ();
}
} }
void void
grub_setcolorstate (grub_term_color_state state) grub_setcolorstate (grub_term_color_state state)
{ {
if (grub_cur_term_output->setcolorstate) struct grub_term_output *term;
(grub_cur_term_output->setcolorstate) (state);
}
void FOR_ACTIVE_TERM_OUTPUTS(term)
grub_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color) grub_term_setcolorstate (term, state);
{
if (grub_cur_term_output->setcolor)
(grub_cur_term_output->setcolor) (normal_color, highlight_color);
}
void
grub_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
{
if (grub_cur_term_output->getcolor)
(grub_cur_term_output->getcolor) (normal_color, highlight_color);
}
int
grub_setcursor (int on)
{
int ret = cursor_state;
if (grub_cur_term_output->setcursor)
{
(grub_cur_term_output->setcursor) (on);
cursor_state = on;
}
return ret;
}
int
grub_getcursor (void)
{
return cursor_state;
} }
void void
grub_refresh (void) grub_refresh (void)
{ {
if (grub_cur_term_output->refresh) struct grub_term_output *term;
(grub_cur_term_output->refresh) ();
}
void FOR_ACTIVE_TERM_OUTPUTS(term)
grub_set_more (int onoff) grub_term_refresh (term);
{
if (onoff == 1)
grub_more++;
else
grub_more--;
grub_more_lines = 0;
} }

View file

@ -24,6 +24,8 @@
last byte used in SRC. */ last byte used in SRC. */
#include <grub/charset.h> #include <grub/charset.h>
#include <grub/mm.h>
#include <grub/misc.h>
grub_ssize_t grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
@ -114,3 +116,154 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
*srcend = src; *srcend = src;
return p - dest; return p - dest;
} }
/* Convert UCS-4 to UTF-8. */
char *
grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size)
{
grub_size_t remaining;
grub_uint32_t *ptr;
grub_size_t cnt = 0;
grub_uint8_t *ret, *dest;
remaining = size;
ptr = src;
while (remaining--)
{
grub_uint32_t code = *ptr++;
if (code <= 0x007F)
cnt++;
else if (code <= 0x07FF)
cnt += 2;
else if ((code >= 0xDC00 && code <= 0xDFFF)
|| (code >= 0xD800 && code <= 0xDBFF))
/* No surrogates in UCS-4... */
cnt++;
else
cnt += 3;
}
cnt++;
ret = grub_malloc (cnt);
if (!ret)
return 0;
dest = ret;
remaining = size;
ptr = src;
while (remaining--)
{
grub_uint32_t code = *ptr++;
if (code <= 0x007F)
*dest++ = code;
else if (code <= 0x07FF)
{
*dest++ = (code >> 6) | 0xC0;
*dest++ = (code & 0x3F) | 0x80;
}
else if ((code >= 0xDC00 && code <= 0xDFFF)
|| (code >= 0xD800 && code <= 0xDBFF))
{
/* No surrogates in UCS-4... */
*dest++ = '?';
}
else
{
*dest++ = (code >> 12) | 0xE0;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
}
*dest = 0;
return (char *) ret;
}
int
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize)
{
grub_uint32_t code = 0;
int count = 0;
while (srcsize)
{
grub_uint32_t c = *src++;
if (srcsize != (grub_size_t)-1)
srcsize--;
if (count)
{
if ((c & 0xc0) != 0x80)
{
/* invalid */
return 0;
}
else
{
code <<= 6;
code |= (c & 0x3f);
count--;
}
}
else
{
if (c == 0)
break;
if ((c & 0x80) == 0x00)
code = c;
else if ((c & 0xe0) == 0xc0)
{
count = 1;
code = c & 0x1f;
}
else if ((c & 0xf0) == 0xe0)
{
count = 2;
code = c & 0x0f;
}
else if ((c & 0xf8) == 0xf0)
{
count = 3;
code = c & 0x07;
}
else if ((c & 0xfc) == 0xf8)
{
count = 4;
code = c & 0x03;
}
else if ((c & 0xfe) == 0xfc)
{
count = 5;
code = c & 0x01;
}
else
return 0;
}
}
return 1;
}
int
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position)
{
grub_size_t msg_len = grub_strlen (msg);
*unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t));
if (!*unicode_msg)
{
grub_printf ("utf8_to_ucs4 ERROR1: %s", msg);
return -1;
}
msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len,
(grub_uint8_t *) msg, -1, 0);
*last_position = *unicode_msg + msg_len;
return msg_len;
}

447
lib/crypto.c Normal file
View file

@ -0,0 +1,447 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
* 2007, 2008, 2009 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/crypto.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/term.h>
struct grub_crypto_hmac_handle
{
const struct gcry_md_spec *md;
void *ctx;
void *opad;
};
static gcry_cipher_spec_t *grub_ciphers = NULL;
static gcry_md_spec_t *grub_digests = NULL;
void (*grub_crypto_autoload_hook) (const char *name) = NULL;
/* Based on libgcrypt-1.4.4/src/misc.c. */
void
grub_burn_stack (grub_size_t size)
{
char buf[64];
grub_memset (buf, 0, sizeof (buf));
if (size > sizeof (buf))
grub_burn_stack (size - sizeof (buf));
}
void
grub_cipher_register (gcry_cipher_spec_t *cipher)
{
cipher->next = grub_ciphers;
grub_ciphers = cipher;
}
void
grub_cipher_unregister (gcry_cipher_spec_t *cipher)
{
gcry_cipher_spec_t **ciph;
for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
if (*ciph == cipher)
*ciph = (*ciph)->next;
}
void
grub_md_register (gcry_md_spec_t *digest)
{
digest->next = grub_digests;
grub_digests = digest;
}
void
grub_md_unregister (gcry_md_spec_t *cipher)
{
gcry_md_spec_t **ciph;
for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
if (*ciph == cipher)
*ciph = (*ciph)->next;
}
void
grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
grub_size_t inlen)
{
grub_uint8_t ctx[hash->contextsize];
hash->init (&ctx);
hash->write (&ctx, in, inlen);
hash->final (&ctx);
grub_memcpy (out, hash->read (&ctx), hash->mdlen);
}
const gcry_md_spec_t *
grub_crypto_lookup_md_by_name (const char *name)
{
const gcry_md_spec_t *md;
int first = 1;
while (1)
{
for (md = grub_digests; md; md = md->next)
if (grub_strcasecmp (name, md->name) == 0)
return md;
if (grub_crypto_autoload_hook && first)
grub_crypto_autoload_hook (name);
else
return NULL;
first = 0;
}
}
const gcry_cipher_spec_t *
grub_crypto_lookup_cipher_by_name (const char *name)
{
const gcry_cipher_spec_t *ciph;
int first = 1;
while (1)
{
for (ciph = grub_ciphers; ciph; ciph = ciph->next)
{
const char **alias;
if (grub_strcasecmp (name, ciph->name) == 0)
return ciph;
if (!ciph->aliases)
continue;
for (alias = ciph->aliases; *alias; alias++)
if (grub_strcasecmp (name, *alias) == 0)
return ciph;
}
if (grub_crypto_autoload_hook && first)
grub_crypto_autoload_hook (name);
else
return NULL;
first = 0;
}
}
grub_crypto_cipher_handle_t
grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
{
grub_crypto_cipher_handle_t ret;
ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
if (!ret)
return NULL;
ret->cipher = cipher;
return ret;
}
gcry_err_code_t
grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
const unsigned char *key,
unsigned keylen)
{
return cipher->cipher->setkey (cipher->ctx, key, keylen);
}
void
grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
{
grub_free (cipher);
}
void
grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
{
const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
grub_uint8_t *outptr = out;
while (size--)
{
*outptr = *in1ptr ^ *in2ptr;
in1ptr++;
in2ptr++;
outptr++;
}
}
gcry_err_code_t
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size)
{
grub_uint8_t *inptr, *outptr, *end;
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size)
{
grub_uint8_t *inptr, *outptr, *end;
if (!cipher->cipher->encrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv_in)
{
grub_uint8_t *inptr, *outptr, *end;
void *iv;
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
iv = iv_in;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
{
grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
iv = outptr;
}
grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv)
{
grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize];
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
{
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
grub_memcpy (iv, ivt, cipher->cipher->blocksize);
}
return GPG_ERR_NO_ERROR;
}
/* Based on gcry/cipher/md.c. */
struct grub_crypto_hmac_handle *
grub_crypto_hmac_init (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen)
{
grub_uint8_t *helpkey = NULL;
grub_uint8_t *ipad = NULL, *opad = NULL;
void *ctx = NULL;
struct grub_crypto_hmac_handle *ret = NULL;
unsigned i;
if (md->mdlen > md->blocksize)
return NULL;
ctx = grub_malloc (md->contextsize);
if (!ctx)
goto err;
if ( keylen > md->blocksize )
{
helpkey = grub_malloc (md->mdlen);
if (!helpkey)
goto err;
grub_crypto_hash (md, helpkey, key, keylen);
key = helpkey;
keylen = md->mdlen;
}
ipad = grub_zalloc (md->blocksize);
if (!ipad)
goto err;
opad = grub_zalloc (md->blocksize);
if (!opad)
goto err;
grub_memcpy ( ipad, key, keylen );
grub_memcpy ( opad, key, keylen );
for (i=0; i < md->blocksize; i++ )
{
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
grub_free (helpkey);
helpkey = NULL;
md->init (ctx);
md->write (ctx, ipad, md->blocksize); /* inner pad */
grub_memset (ipad, 0, md->blocksize);
grub_free (ipad);
ipad = NULL;
ret = grub_malloc (sizeof (*ret));
if (!ret)
goto err;
ret->md = md;
ret->ctx = ctx;
ret->opad = opad;
return ret;
err:
grub_free (helpkey);
grub_free (ctx);
grub_free (ipad);
grub_free (opad);
return NULL;
}
void
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
grub_size_t datalen)
{
hnd->md->write (hnd->ctx, data, datalen);
}
gcry_err_code_t
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
{
grub_uint8_t *p;
grub_uint8_t *ctx2;
ctx2 = grub_malloc (hnd->md->contextsize);
if (!ctx2)
return GPG_ERR_OUT_OF_MEMORY;
hnd->md->final (hnd->ctx);
hnd->md->read (hnd->ctx);
p = hnd->md->read (hnd->ctx);
hnd->md->init (ctx2);
hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
hnd->md->write (ctx2, p, hnd->md->mdlen);
hnd->md->final (ctx2);
grub_memset (hnd->opad, 0, hnd->md->blocksize);
grub_free (hnd->opad);
grub_memset (hnd->ctx, 0, hnd->md->contextsize);
grub_free (hnd->ctx);
grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
grub_memset (ctx2, 0, hnd->md->contextsize);
grub_free (ctx2);
grub_memset (hnd, 0, sizeof (*hnd));
grub_free (hnd);
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
const void *key, grub_size_t keylen,
void *data, grub_size_t datalen, void *out)
{
struct grub_crypto_hmac_handle *hnd;
hnd = grub_crypto_hmac_init (md, key, keylen);
if (!hnd)
return GPG_ERR_OUT_OF_MEMORY;
grub_crypto_hmac_write (hnd, data, datalen);
return grub_crypto_hmac_fini (hnd, out);
}
grub_err_t
grub_crypto_gcry_error (gcry_err_code_t in)
{
if (in == GPG_ERR_NO_ERROR)
return GRUB_ERR_NONE;
return GRUB_ACCESS_DENIED;
}
int
grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
{
register grub_size_t counter = 0;
const grub_uint8_t *pa, *pb;
for (pa = a, pb = b; n; pa++, pb++, n--)
{
if (*pa != *pb)
counter++;
}
return !!counter;
}
#ifndef GRUB_MKPASSWD
int
grub_password_get (char buf[], unsigned buf_size)
{
unsigned cur_len = 0;
int key;
while (1)
{
key = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (key == '\n' || key == '\r')
break;
if (key == '\e')
{
cur_len = 0;
break;
}
if (key == '\b')
{
cur_len--;
continue;
}
if (!grub_isprint (key))
continue;
if (cur_len + 2 < buf_size)
buf[cur_len++] = key;
}
grub_memset (buf + cur_len, 0, buf_size - cur_len);
grub_putchar ('\n');
grub_refresh ();
return (key != '\e');
}
#endif

View file

@ -0,0 +1,86 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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_GCRY_WRAP_HEADER
#define GRUB_GCRY_WRAP_HEADER 1
#include <grub/types.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/crypto.h>
#define __GNU_LIBRARY__
#define DIM ARRAY_SIZE
typedef grub_uint64_t u64;
typedef grub_uint32_t u32;
typedef grub_uint16_t u16;
typedef grub_uint8_t byte;
typedef grub_size_t size_t;
#define U64_C(c) (c ## ULL)
#define _gcry_burn_stack grub_burn_stack
#define log_error(fmt, args...) grub_dprintf ("crypto", fmt, ## args)
#define PUBKEY_FLAG_NO_BLINDING (1 << 0)
#define CIPHER_INFO_NO_WEAK_KEY 1
#define HAVE_U64_TYPEDEF 1
typedef union {
int a;
short b;
char c[1];
long d;
#ifdef HAVE_U64_TYPEDEF
u64 e;
#endif
float f;
double g;
} PROPERLY_ALIGNED_TYPE;
#define gcry_assert(x) grub_assert_real(__FILE__, __LINE__, x)
static inline void
grub_assert_real (const char *file, int line, int cond)
{
if (!cond)
grub_fatal ("Assertion failed at %s:%d\n", file, line);
}
/* Selftests are in separate modules. */
static inline char *
selftest (void)
{
return NULL;
}
static inline int
fips_mode (void)
{
return 0;
}
#define memset grub_memset
#endif

102
lib/pbkdf2.c Normal file
View file

@ -0,0 +1,102 @@
/* gc-pbkdf2-sha1.c --- Password-Based Key Derivation Function a'la PKCS#5
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Simon Josefsson. */
/* Imported from gnulib. */
#include <grub/crypto.h>
#include <grub/mm.h>
#include <grub/misc.h>
/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant
of digest supplied by MD. Inputs are the password P of length PLEN,
the salt S of length SLEN, the iteration counter C (> 0), and the
desired derived output length DKLEN. Output buffer is DK which
must have room for at least DKLEN octets. The output buffer will
be filled with the derived data. */
gcry_err_code_t
grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
const grub_uint8_t *P, grub_size_t Plen,
const grub_uint8_t *S, grub_size_t Slen,
unsigned int c,
grub_uint8_t *DK, grub_size_t dkLen)
{
unsigned int hLen = md->mdlen;
grub_uint8_t U[md->mdlen];
grub_uint8_t T[md->mdlen];
unsigned int u;
unsigned int l;
unsigned int r;
unsigned int i;
unsigned int k;
gcry_err_code_t rc;
grub_uint8_t *tmp;
grub_size_t tmplen = Slen + 4;
if (c == 0)
return GPG_ERR_INV_ARG;
if (dkLen == 0)
return GPG_ERR_INV_ARG;
if (dkLen > 4294967295U)
return GPG_ERR_INV_ARG;
l = ((dkLen - 1) / hLen) + 1;
r = dkLen - (l - 1) * hLen;
tmp = grub_malloc (tmplen);
if (tmp == NULL)
return GPG_ERR_OUT_OF_MEMORY;
grub_memcpy (tmp, S, Slen);
for (i = 1; i <= l; i++)
{
grub_memset (T, 0, hLen);
for (u = 1; u <= c; u++)
{
if (u == 1)
{
tmp[Slen + 0] = (i & 0xff000000) >> 24;
tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
tmp[Slen + 3] = (i & 0x000000ff) >> 0;
rc = grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U);
}
else
rc = grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U);
if (rc != GPG_ERR_NO_ERROR)
{
grub_free (tmp);
return rc;
}
for (k = 0; k < hLen; k++)
T[k] ^= U[k];
}
grub_memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
}
grub_free (tmp);
return GPG_ERR_NO_ERROR;
}

View file

@ -33,6 +33,7 @@
#include <grub/video_fb.h> #include <grub/video_fb.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/i386/pc/vbe.h> #include <grub/i386/pc/vbe.h>
#include <grub/i386/pc/console.h>
#define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_OFFSET 0x1000
#define GRUB_LINUX_CL_END_OFFSET 0x2000 #define GRUB_LINUX_CL_END_OFFSET 0x2000
@ -547,8 +548,30 @@ grub_linux_boot (void)
/* Initialize these last, because terminal position could be affected by printfs above. */ /* Initialize these last, because terminal position could be affected by printfs above. */
if (params->have_vga == GRUB_VIDEO_TYPE_TEXT) if (params->have_vga == GRUB_VIDEO_TYPE_TEXT)
{ {
params->video_cursor_x = grub_getxy () >> 8; grub_term_output_t term;
params->video_cursor_y = grub_getxy () & 0xff; int found = 0;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "vga_text") == 0)
{
grub_uint16_t pos = grub_term_getxy (term);
params->video_cursor_x = pos >> 8;
params->video_cursor_y = pos & 0xff;
found = 1;
}
if (!found)
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "console") == 0)
{
grub_uint16_t pos = grub_term_getxy (term);
params->video_cursor_x = pos >> 8;
params->video_cursor_y = pos & 0xff;
found = 1;
}
if (!found)
{
params->video_cursor_x = 0;
params->video_cursor_y = 0;
}
} }
#ifdef __x86_64__ #ifdef __x86_64__

View file

@ -36,58 +36,6 @@ struct grub_auth_user
struct grub_auth_user *users = NULL; struct grub_auth_user *users = NULL;
int
grub_auth_strcmp (const char *s1, const char *s2)
{
int ret;
grub_uint64_t end;
end = grub_get_time_ms () + 100;
ret = grub_strcmp (s1, s2);
/* This prevents an attacker from deriving information about the
password from the time it took to execute this function. */
while (grub_get_time_ms () < end);
return ret;
}
static int
grub_iswordseparator (int c)
{
return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
}
int
grub_auth_strword (const char *haystack, const char *needle)
{
const char *n_pos = needle;
int found = 0;
while (grub_iswordseparator (*haystack))
haystack++;
while (*haystack)
{
int ok = 1;
/* Crawl both the needle and the haystack word we're on. */
while(*haystack && !grub_iswordseparator (*haystack))
{
if (*haystack == *n_pos && ok)
n_pos++;
else
ok = 0;
haystack++;
}
if (ok)
found = 1;
}
return found;
}
grub_err_t grub_err_t
grub_auth_register_authentication (const char *user, grub_auth_register_authentication (const char *user,
grub_auth_callback_t callback, grub_auth_callback_t callback,
@ -194,8 +142,8 @@ is_authenticated (const char *userlist)
return 0; return 0;
name = ((struct grub_auth_user *) item)->name; name = ((struct grub_auth_user *) item)->name;
return (userlist && grub_auth_strword (userlist, name)) return (userlist && grub_strword (userlist, name))
|| grub_auth_strword (superusers, name); || grub_strword (superusers, name);
} }
superusers = grub_env_get ("superusers"); superusers = grub_env_get ("superusers");
@ -206,6 +154,49 @@ is_authenticated (const char *userlist)
return grub_list_iterate (GRUB_AS_LIST (users), hook); return grub_list_iterate (GRUB_AS_LIST (users), hook);
} }
static int
grub_username_get (char buf[], unsigned buf_size)
{
unsigned cur_len = 0;
int key;
while (1)
{
key = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (key == '\n' || key == '\r')
break;
if (key == '\e')
{
cur_len = 0;
break;
}
if (key == '\b')
{
cur_len--;
grub_printf ("\b");
continue;
}
if (!grub_isprint (key))
continue;
if (cur_len + 2 < buf_size)
{
buf[cur_len++] = key;
grub_putchar (key);
}
}
grub_memset (buf + cur_len, 0, buf_size - cur_len);
grub_putchar ('\n');
grub_refresh ();
return (key != '\e');
}
grub_err_t grub_err_t
grub_auth_check_authentication (const char *userlist) grub_auth_check_authentication (const char *userlist)
{ {
@ -213,11 +204,12 @@ grub_auth_check_authentication (const char *userlist)
struct grub_auth_user *cur = NULL; struct grub_auth_user *cur = NULL;
grub_err_t err; grub_err_t err;
static unsigned long punishment_delay = 1; static unsigned long punishment_delay = 1;
char entered[GRUB_AUTH_MAX_PASSLEN];
auto int hook (grub_list_t item); auto int hook (grub_list_t item);
int hook (grub_list_t item) int hook (grub_list_t item)
{ {
if (grub_auth_strcmp (login, ((struct grub_auth_user *) item)->name) == 0) if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
cur = (struct grub_auth_user *) item; cur = (struct grub_auth_user *) item;
return 0; return 0;
} }
@ -238,26 +230,22 @@ grub_auth_check_authentication (const char *userlist)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
if (!grub_cmdline_get (N_("Enter username:"), login, sizeof (login) - 1, grub_puts_ (N_("Enter username: "));
0, 0, 0))
if (!grub_username_get (login, sizeof (login) - 1))
goto access_denied;
grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
goto access_denied; goto access_denied;
grub_list_iterate (GRUB_AS_LIST (users), hook); grub_list_iterate (GRUB_AS_LIST (users), hook);
if (!cur || ! cur->callback) if (!cur || ! cur->callback)
{ goto access_denied;
grub_list_iterate (GRUB_AS_LIST (users), hook_any);
/* No users present at all. */ err = cur->callback (login, entered, cur->arg);
if (!cur)
goto access_denied;
/* Display any of available authentication schemes. */
err = cur->callback (login, 0);
goto access_denied;
}
err = cur->callback (login, cur->arg);
if (is_authenticated (userlist)) if (is_authenticated (userlist))
{ {
punishment_delay = 1; punishment_delay = 1;

View file

@ -27,11 +27,12 @@
#include <grub/file.h> #include <grub/file.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
static char *kill_buf; static grub_uint32_t *kill_buf;
static int hist_size; static int hist_size;
static char **hist_lines = 0; static grub_uint32_t **hist_lines = 0;
static int hist_pos = 0; static int hist_pos = 0;
static int hist_end = 0; static int hist_end = 0;
static int hist_used = 0; static int hist_used = 0;
@ -39,8 +40,8 @@ static int hist_used = 0;
grub_err_t grub_err_t
grub_set_history (int newsize) grub_set_history (int newsize)
{ {
char **old_hist_lines = hist_lines; grub_uint32_t **old_hist_lines = hist_lines;
hist_lines = grub_malloc (sizeof (char *) * newsize); hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
/* Copy the old lines into the new buffer. */ /* Copy the old lines into the new buffer. */
if (old_hist_lines) if (old_hist_lines)
@ -67,16 +68,16 @@ grub_set_history (int newsize)
if (hist_pos < hist_end) if (hist_pos < hist_end)
grub_memmove (hist_lines, old_hist_lines + hist_pos, grub_memmove (hist_lines, old_hist_lines + hist_pos,
(hist_end - hist_pos) * sizeof (char *)); (hist_end - hist_pos) * sizeof (grub_uint32_t *));
else if (hist_used) else if (hist_used)
{ {
/* Copy the older part. */ /* Copy the older part. */
grub_memmove (hist_lines, old_hist_lines + hist_pos, grub_memmove (hist_lines, old_hist_lines + hist_pos,
(hist_size - hist_pos) * sizeof (char *)); (hist_size - hist_pos) * sizeof (grub_uint32_t *));
/* Copy the newer part. */ /* Copy the newer part. */
grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines, grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines,
hist_end * sizeof (char *)); hist_end * sizeof (grub_uint32_t *));
} }
} }
@ -90,17 +91,43 @@ grub_set_history (int newsize)
/* Get the entry POS from the history where `0' is the newest /* Get the entry POS from the history where `0' is the newest
entry. */ entry. */
static char * static grub_uint32_t *
grub_history_get (int pos) grub_history_get (int pos)
{ {
pos = (hist_pos + pos) % hist_size; pos = (hist_pos + pos) % hist_size;
return hist_lines[pos]; return hist_lines[pos];
} }
static grub_size_t
strlen_ucs4 (const grub_uint32_t *s)
{
const grub_uint32_t *p = s;
while (*p)
p++;
return p - s;
}
/* Replace the history entry on position POS with the string S. */
static void
grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
{
grub_free (hist_lines[pos]);
hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
if (!hist_lines[pos])
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
return ;
}
grub_memcpy (hist_lines[pos], s, len * sizeof (grub_uint32_t));
hist_lines[pos][len] = 0;
}
/* Insert a new history line S on the top of the history. */ /* Insert a new history line S on the top of the history. */
static void static void
grub_history_add (char *s) grub_history_add (grub_uint32_t *s, grub_size_t len)
{ {
/* Remove the oldest entry in the history to make room for a new /* Remove the oldest entry in the history to make room for a new
entry. */ entry. */
@ -121,16 +148,15 @@ grub_history_add (char *s)
hist_pos = hist_size + hist_pos; hist_pos = hist_size + hist_pos;
/* Insert into history. */ /* Insert into history. */
hist_lines[hist_pos] = grub_strdup (s); hist_lines[hist_pos] = NULL;
grub_history_set (hist_pos, s, len);
} }
/* Replace the history entry on position POS with the string S. */ /* Replace the history entry on position POS with the string S. */
static void static void
grub_history_replace (int pos, char *s) grub_history_replace (int pos, grub_uint32_t *s, grub_size_t len)
{ {
pos = (hist_pos + pos) % hist_size; grub_history_set ((hist_pos + pos) % hist_size, s, len);
grub_free (hist_lines[pos]);
hist_lines[pos] = grub_strdup (s);
} }
/* A completion hook to print items. */ /* A completion hook to print items. */
@ -176,70 +202,109 @@ print_completion (const char *item, grub_completion_type_t type, int count)
grub_printf (" %s", item); grub_printf (" %s", item);
} }
/* Get a command-line. If ECHO_CHAR is not zero, echo it instead of input struct cmdline_term
characters. If READLINE is non-zero, readline-like key bindings are {
available. If ESC is pushed, return zero, otherwise return non-zero. */ unsigned xpos, ypos, ystart, width, height;
/* FIXME: The dumb interface is not supported yet. */ struct grub_term_output *term;
int };
grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
int echo_char, int readline, int history) /* Get a command-line. If ESC is pushed, return zero,
otherwise return command line. */
/* FIXME: The dumb interface is not supported yet. */
char *
grub_cmdline_get (const char *prompt)
{ {
unsigned xpos, ypos, ystart;
grub_size_t lpos, llen; grub_size_t lpos, llen;
grub_size_t plen; grub_size_t plen;
char buf[max_len]; grub_uint32_t *buf;
grub_size_t max_len = 256;
int key; int key;
int histpos = 0; int histpos = 0;
auto void cl_insert (const char *str); auto void cl_insert (const grub_uint32_t *str);
auto void cl_delete (unsigned len); auto void cl_delete (unsigned len);
auto void cl_print (int pos, int c); auto void cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c);
auto void cl_set_pos (void); auto void cl_set_pos (struct cmdline_term *cl_term);
auto void cl_print_all (int pos, grub_uint32_t c);
auto void cl_set_pos_all (void);
const char *prompt_translated = _(prompt); const char *prompt_translated = _(prompt);
struct cmdline_term *cl_terms;
char *ret;
unsigned nterms;
void cl_set_pos (void) void cl_set_pos (struct cmdline_term *cl_term)
{
cl_term->xpos = (plen + lpos) % (cl_term->width - 1);
cl_term->ypos = cl_term->ystart + (plen + lpos) / (cl_term->width - 1);
grub_term_gotoxy (cl_term->term, cl_term->xpos, cl_term->ypos);
}
void cl_set_pos_all ()
{
unsigned i;
for (i = 0; i < nterms; i++)
cl_set_pos (&cl_terms[i]);
}
void cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c)
{ {
xpos = (plen + lpos) % 79; grub_uint32_t *p;
ypos = ystart + (plen + lpos) / 79;
grub_gotoxy (xpos, ypos);
}
void cl_print (int pos, int c) for (p = buf + pos; p < buf + llen; p++)
{
char *p;
for (p = buf + pos; *p; p++)
{ {
if (xpos++ > 78) if (cl_term->xpos++ > cl_term->width - 2)
{ {
grub_putchar ('\n'); grub_putcode ('\n', cl_term->term);
xpos = 1; cl_term->xpos = 1;
if (ypos == (unsigned) (grub_getxy () & 0xFF)) if (cl_term->ypos == (unsigned) (cl_term->height))
ystart--; cl_term->ystart--;
else else
ypos++; cl_term->ypos++;
} }
if (c) if (c)
grub_putchar (c); grub_putcode (c, cl_term->term);
else else
grub_putchar (*p); grub_putcode (*p, cl_term->term);
} }
} }
void cl_insert (const char *str) void cl_print_all (int pos, grub_uint32_t c)
{
unsigned i;
for (i = 0; i < nterms; i++)
cl_print (&cl_terms[i], pos, c);
}
void cl_insert (const grub_uint32_t *str)
{ {
grub_size_t len = grub_strlen (str); grub_size_t len = strlen_ucs4 (str);
if (len + llen >= max_len)
{
grub_uint32_t *nbuf;
max_len *= 2;
nbuf = grub_realloc (buf, sizeof (grub_uint32_t) * max_len);
if (nbuf)
buf = nbuf;
else
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
max_len /= 2;
}
}
if (len + llen < max_len) if (len + llen < max_len)
{ {
grub_memmove (buf + lpos + len, buf + lpos, llen - lpos + 1); grub_memmove (buf + lpos + len, buf + lpos,
grub_memmove (buf + lpos, str, len); (llen - lpos + 1) * sizeof (grub_uint32_t));
grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t));
llen += len; llen += len;
lpos += len; lpos += len;
cl_print (lpos - len, echo_char); cl_print_all (lpos - len, 0);
cl_set_pos (); cl_set_pos_all ();
} }
} }
@ -250,182 +315,256 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
grub_size_t saved_lpos = lpos; grub_size_t saved_lpos = lpos;
lpos = llen - len; lpos = llen - len;
cl_set_pos (); cl_set_pos_all ();
cl_print (lpos, ' '); cl_print_all (lpos, ' ');
lpos = saved_lpos; lpos = saved_lpos;
cl_set_pos (); cl_set_pos_all ();
grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1); grub_memmove (buf + lpos, buf + lpos + len,
sizeof (grub_uint32_t) * (llen - lpos + 1));
llen -= len; llen -= len;
cl_print (lpos, echo_char); cl_print_all (lpos, 0);
cl_set_pos (); cl_set_pos_all ();
} }
} }
void init_clterm (struct cmdline_term *cl_term_cur)
{
cl_term_cur->xpos = plen;
cl_term_cur->ypos = (grub_term_getxy (cl_term_cur->term) & 0xFF);
cl_term_cur->ystart = cl_term_cur->ypos;
cl_term_cur->width = grub_term_width (cl_term_cur->term);
cl_term_cur->height = grub_term_height (cl_term_cur->term);
}
void init_clterm_all (void)
{
unsigned i;
for (i = 0; i < nterms; i++)
init_clterm (&cl_terms[i]);
}
buf = grub_malloc (max_len * sizeof (grub_uint32_t));
if (!buf)
return 0;
plen = grub_strlen (prompt_translated); plen = grub_strlen (prompt_translated);
lpos = llen = 0; lpos = llen = 0;
buf[0] = '\0'; buf[0] = '\0';
if ((grub_getxy () >> 8) != 0) {
grub_putchar ('\n'); grub_term_output_t term;
FOR_ACTIVE_TERM_OUTPUTS(term)
if ((grub_term_getxy (term) >> 8) != 0)
grub_putcode ('\n', term);
}
grub_printf ("%s", prompt_translated); grub_printf ("%s", prompt_translated);
xpos = plen; {
ystart = ypos = (grub_getxy () & 0xFF); struct cmdline_term *cl_term_cur;
struct grub_term_output *cur;
nterms = 0;
FOR_ACTIVE_TERM_OUTPUTS(cur)
nterms++;
cl_insert (cmdline); cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
if (!cl_terms)
return 0;
cl_term_cur = cl_terms;
FOR_ACTIVE_TERM_OUTPUTS(cur)
{
cl_term_cur->term = cur;
init_clterm (cl_term_cur);
cl_term_cur++;
}
}
if (history && hist_used == 0) if (hist_used == 0)
grub_history_add (buf); grub_history_add (buf, llen);
grub_refresh (); grub_refresh ();
while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
{ {
if (readline)
{
switch (key)
{
case 1: /* Ctrl-a */
lpos = 0;
cl_set_pos ();
break;
case 2: /* Ctrl-b */
if (lpos > 0)
{
lpos--;
cl_set_pos ();
}
break;
case 5: /* Ctrl-e */
lpos = llen;
cl_set_pos ();
break;
case 6: /* Ctrl-f */
if (lpos < llen)
{
lpos++;
cl_set_pos ();
}
break;
case 9: /* Ctrl-i or TAB */
{
char *insert;
int restore;
/* Backup the next character and make it 0 so it will
be easy to use string functions. */
char backup = buf[lpos];
buf[lpos] = '\0';
insert = grub_normal_do_completion (buf, &restore,
print_completion);
/* Restore the original string. */
buf[lpos] = backup;
if (restore)
{
/* Restore the prompt. */
grub_printf ("\n%s %s", prompt_translated, buf);
xpos = plen;
ystart = ypos = (grub_getxy () & 0xFF);
}
if (insert)
{
cl_insert (insert);
grub_free (insert);
}
}
break;
case 11: /* Ctrl-k */
if (lpos < llen)
{
if (kill_buf)
grub_free (kill_buf);
kill_buf = grub_strdup (buf + lpos);
grub_errno = GRUB_ERR_NONE;
cl_delete (llen - lpos);
}
break;
case 14: /* Ctrl-n */
{
char *hist;
lpos = 0;
if (histpos > 0)
{
grub_history_replace (histpos, buf);
histpos--;
}
cl_delete (llen);
hist = grub_history_get (histpos);
cl_insert (hist);
break;
}
case 16: /* Ctrl-p */
{
char *hist;
lpos = 0;
if (histpos < hist_used - 1)
{
grub_history_replace (histpos, buf);
histpos++;
}
cl_delete (llen);
hist = grub_history_get (histpos);
cl_insert (hist);
}
break;
case 21: /* Ctrl-u */
if (lpos > 0)
{
grub_size_t n = lpos;
if (kill_buf)
grub_free (kill_buf);
kill_buf = grub_malloc (n + 1);
grub_errno = GRUB_ERR_NONE;
if (kill_buf)
{
grub_memcpy (kill_buf, buf, n);
kill_buf[n] = '\0';
}
lpos = 0;
cl_set_pos ();
cl_delete (n);
}
break;
case 25: /* Ctrl-y */
if (kill_buf)
cl_insert (kill_buf);
break;
}
}
switch (key) switch (key)
{ {
case 1: /* Ctrl-a */
lpos = 0;
cl_set_pos_all ();
break;
case 2: /* Ctrl-b */
if (lpos > 0)
{
lpos--;
cl_set_pos_all ();
}
break;
case 5: /* Ctrl-e */
lpos = llen;
cl_set_pos_all ();
break;
case 6: /* Ctrl-f */
if (lpos < llen)
{
lpos++;
cl_set_pos_all ();
}
break;
case 9: /* Ctrl-i or TAB */
{
int restore;
char *insertu8;
char *bufu8;
buf[lpos] = '\0';
bufu8 = grub_ucs4_to_utf8_alloc (buf, lpos);
if (!bufu8)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
break;
}
insertu8 = grub_normal_do_completion (bufu8, &restore,
print_completion);
grub_free (bufu8);
if (restore)
{
/* Restore the prompt. */
grub_printf ("\n%s", prompt_translated);
init_clterm_all ();
cl_print_all (0, 0);
}
if (insertu8)
{
grub_size_t insertlen;
grub_ssize_t t;
grub_uint32_t *insert;
insertlen = grub_strlen (insertu8);
insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t));
if (!insert)
{
grub_free (insertu8);
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
break;
}
t = grub_utf8_to_ucs4 (insert, insertlen,
(grub_uint8_t *) insertu8,
insertlen, 0);
if (t > 0)
{
insert[t] = 0;
cl_insert (insert);
}
grub_free (insertu8);
grub_free (insert);
}
}
break;
case 11: /* Ctrl-k */
if (lpos < llen)
{
if (kill_buf)
grub_free (kill_buf);
kill_buf = grub_malloc ((llen - lpos + 1)
* sizeof (grub_uint32_t));
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
else
{
grub_memcpy (kill_buf, buf + lpos,
(llen - lpos + 1) * sizeof (grub_uint32_t));
kill_buf[llen - lpos] = 0;
}
cl_delete (llen - lpos);
}
break;
case 14: /* Ctrl-n */
{
grub_uint32_t *hist;
lpos = 0;
if (histpos > 0)
{
grub_history_replace (histpos, buf, llen);
histpos--;
}
cl_delete (llen);
hist = grub_history_get (histpos);
cl_insert (hist);
break;
}
case 16: /* Ctrl-p */
{
grub_uint32_t *hist;
lpos = 0;
if (histpos < hist_used - 1)
{
grub_history_replace (histpos, buf, llen);
histpos++;
}
cl_delete (llen);
hist = grub_history_get (histpos);
cl_insert (hist);
}
break;
case 21: /* Ctrl-u */
if (lpos > 0)
{
grub_size_t n = lpos;
if (kill_buf)
grub_free (kill_buf);
kill_buf = grub_malloc (n + 1);
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
if (kill_buf)
{
grub_memcpy (kill_buf, buf, n);
kill_buf[n] = '\0';
}
lpos = 0;
cl_set_pos_all ();
cl_delete (n);
}
break;
case 25: /* Ctrl-y */
if (kill_buf)
cl_insert (kill_buf);
break;
case '\e': case '\e':
return 0; return 0;
@ -433,7 +572,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
if (lpos > 0) if (lpos > 0)
{ {
lpos--; lpos--;
cl_set_pos (); cl_set_pos_all ();
} }
else else
break; break;
@ -447,7 +586,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
default: default:
if (grub_isprint (key)) if (grub_isprint (key))
{ {
char str[2]; grub_uint32_t str[2];
str[0] = key; str[0] = key;
str[1] = '\0'; str[1] = '\0';
@ -462,23 +601,20 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
grub_putchar ('\n'); grub_putchar ('\n');
grub_refresh (); grub_refresh ();
/* If ECHO_CHAR is NUL, remove leading spaces. */ /* Remove leading spaces. */
lpos = 0; lpos = 0;
if (! echo_char) while (buf[lpos] == ' ')
while (buf[lpos] == ' ') lpos++;
lpos++;
if (history) histpos = 0;
if (strlen_ucs4 (buf) > 0)
{ {
histpos = 0; grub_uint32_t empty[] = { 0 };
if (grub_strlen (buf) > 0) grub_history_replace (histpos, buf, llen);
{ grub_history_add (empty, 0);
grub_history_replace (histpos, buf);
grub_history_add ("");
}
} }
grub_memcpy (cmdline, buf + lpos, llen - lpos + 1); ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1);
grub_free (buf);
return 1; return ret;
} }

View file

@ -103,23 +103,31 @@ free_and_return:
grub_free (fg_name); grub_free (fg_name);
} }
static grub_uint8_t color_normal, color_highlight;
static void
set_colors (void)
{
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
/* Reloads terminal `normal' and `highlight' colors. */
grub_term_setcolor (term, color_normal, color_highlight);
/* Propagates `normal' color to terminal current color. */
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
}
}
/* Replace default `normal' colors with the ones specified by user (if any). */ /* Replace default `normal' colors with the ones specified by user (if any). */
char * char *
grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)),
const char *val) const char *val)
{ {
grub_uint8_t color_normal, color_highlight;
/* Use old settings in case grub_parse_color_name_pair() has no effect. */
grub_getcolor (&color_normal, &color_highlight);
grub_parse_color_name_pair (&color_normal, val); grub_parse_color_name_pair (&color_normal, val);
/* Reloads terminal `normal' and `highlight' colors. */ set_colors ();
grub_setcolor (color_normal, color_highlight);
/* Propagates `normal' color to terminal current color. */
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
return grub_strdup (val); return grub_strdup (val);
} }
@ -129,21 +137,9 @@ char *
grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)),
const char *val) const char *val)
{ {
grub_uint8_t color_normal, color_highlight;
/* Use old settings in case grub_parse_color_name_pair() has no effect. */
grub_getcolor (&color_normal, &color_highlight);
grub_parse_color_name_pair (&color_highlight, val); grub_parse_color_name_pair (&color_highlight, val);
/* Reloads terminal `normal' and `highlight' colors. */ set_colors ();
grub_setcolor (color_normal, color_highlight);
/* Propagates `normal' color to terminal current color.
Note: Using GRUB_TERM_COLOR_NORMAL here rather than
GRUB_TERM_COLOR_HIGHLIGHT is intentional. We don't want to switch
to highlight state just because color was reloaded. */
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
return grub_strdup (val); return grub_strdup (val);
} }

153
normal/crypto.c Normal file
View file

@ -0,0 +1,153 @@
/* crypto.c - support crypto autoload */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/dl.h>
#include <grub/mm.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/crypto.h>
#include <grub/normal.h>
struct load_spec
{
struct load_spec *next;
char *name;
char *modname;
};
struct load_spec *crypto_specs = NULL;
static void
grub_crypto_autoload (const char *name)
{
struct load_spec *cur;
grub_dl_t mod;
for (cur = crypto_specs; cur; cur = cur->next)
if (grub_strcasecmp (name, cur->name) == 0)
{
mod = grub_dl_load (cur->modname);
if (mod)
grub_dl_ref (mod);
grub_errno = GRUB_ERR_NONE;
}
}
static void
grub_crypto_spec_free (void)
{
struct load_spec *cur, *next;
for (cur = crypto_specs; cur; cur = next)
{
next = cur->next;
grub_free (cur->name);
grub_free (cur->modname);
grub_free (cur);
}
crypto_specs = NULL;
}
/* Read the file crypto.lst for auto-loading. */
void
read_crypto_list (void)
{
const char *prefix;
char *filename;
grub_file_t file;
char *buf = NULL;
prefix = grub_env_get ("prefix");
if (!prefix)
{
grub_errno = GRUB_ERR_NONE;
return;
}
filename = grub_malloc (grub_strlen (prefix) + sizeof ("/crypto.lst"));
if (!filename)
{
grub_errno = GRUB_ERR_NONE;
return;
}
grub_sprintf (filename, "%s/crypto.lst", prefix);
file = grub_file_open (filename);
if (!file)
{
grub_errno = GRUB_ERR_NONE;
return;
}
/* Override previous commands.lst. */
grub_crypto_spec_free ();
for (;; grub_free (buf))
{
char *p, *name;
struct load_spec *cur;
buf = grub_file_getline (file);
if (! buf)
break;
name = buf;
p = grub_strchr (name, ':');
if (! p)
continue;
*p = '\0';
while (*++p == ' ')
;
cur = grub_malloc (sizeof (*cur));
if (!cur)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
cur->name = grub_strdup (name);
if (! name)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
continue;
}
cur->modname = grub_strdup (p);
if (! cur->modname)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
grub_free (cur->name);
continue;
}
cur->next = crypto_specs;
crypto_specs = cur;
}
grub_file_close (file);
grub_errno = GRUB_ERR_NONE;
grub_crypto_autoload_hook = grub_crypto_autoload;
}

View file

@ -30,9 +30,13 @@
#include <grub/menu_viewer.h> #include <grub/menu_viewer.h>
#include <grub/auth.h> #include <grub/auth.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
#define GRUB_DEFAULT_HISTORY_SIZE 50 #define GRUB_DEFAULT_HISTORY_SIZE 50
static int nested_level = 0;
int grub_normal_exit_level = 0;
/* Read a line from the file FILE. */ /* Read a line from the file FILE. */
char * char *
grub_file_getline (grub_file_t file) grub_file_getline (grub_file_t file)
@ -372,7 +376,21 @@ read_config_file (const char *config)
if (! file) if (! file)
return 0; return 0;
grub_reader_loop (getline); while (1)
{
char *line;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
if ((getline (&line, 0)) || (! line))
break;
grub_parser_get_current ()->parse_line (line, getline);
grub_free (line);
}
grub_file_close (file); grub_file_close (file);
if (old_parser) if (old_parser)
@ -383,7 +401,7 @@ read_config_file (const char *config)
/* Initialize the screen. */ /* Initialize the screen. */
void void
grub_normal_init_page (void) grub_normal_init_page (struct grub_term_output *term)
{ {
int msg_len; int msg_len;
int posx; int posx;
@ -391,14 +409,13 @@ grub_normal_init_page (void)
char *msg_formatted = grub_malloc (grub_strlen(msg) + char *msg_formatted = grub_malloc (grub_strlen(msg) +
grub_strlen(PACKAGE_VERSION)); grub_strlen(PACKAGE_VERSION));
grub_cls ();
grub_sprintf (msg_formatted, msg, PACKAGE_VERSION);
grub_uint32_t *unicode_msg; grub_uint32_t *unicode_msg;
grub_uint32_t *last_position; grub_uint32_t *last_position;
grub_term_cls (term);
grub_sprintf (msg_formatted, msg, PACKAGE_VERSION);
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted, msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
&unicode_msg, &last_position); &unicode_msg, &last_position);
@ -407,17 +424,15 @@ grub_normal_init_page (void)
return; return;
} }
posx = grub_getstringwidth (unicode_msg, last_position); posx = grub_getstringwidth (unicode_msg, last_position, term);
posx = (GRUB_TERM_WIDTH - posx) / 2; posx = (grub_term_width (term) - posx) / 2;
grub_gotoxy (posx, 1); grub_term_gotoxy (term, posx, 1);
grub_print_ucs4 (unicode_msg, last_position); grub_print_ucs4 (unicode_msg, last_position, term);
grub_printf("\n\n"); grub_printf("\n\n");
grub_free (unicode_msg); grub_free (unicode_msg);
} }
static int reader_nested;
/* Read the config file CONFIG and execute the menu interface or /* Read the config file CONFIG and execute the menu interface or
the command line interface if BATCH is false. */ the command line interface if BATCH is false. */
void void
@ -428,10 +443,10 @@ grub_normal_execute (const char *config, int nested, int batch)
read_command_list (); read_command_list ();
read_fs_list (); read_fs_list ();
read_handler_list (); read_handler_list ();
read_crypto_list ();
read_terminal_list ();
grub_command_execute ("parser.grub", 0, 0); grub_command_execute ("parser.grub", 0, 0);
reader_nested = nested;
if (config) if (config)
{ {
menu = read_config_file (config); menu = read_config_file (config);
@ -444,7 +459,7 @@ grub_normal_execute (const char *config, int nested, int batch)
{ {
if (menu && menu->size) if (menu && menu->size)
{ {
grub_menu_viewer_show_menu (menu, nested); grub_show_menu (menu, nested);
if (nested) if (nested)
free_menu (menu); free_menu (menu);
} }
@ -455,21 +470,24 @@ grub_normal_execute (const char *config, int nested, int batch)
void void
grub_enter_normal_mode (const char *config) grub_enter_normal_mode (const char *config)
{ {
nested_level++;
grub_normal_execute (config, 0, 0); grub_normal_execute (config, 0, 0);
grub_cmdline_run (0);
nested_level--;
if (grub_normal_exit_level)
grub_normal_exit_level--;
} }
/* Enter normal mode from rescue mode. */ /* Enter normal mode from rescue mode. */
static grub_err_t static grub_err_t
grub_cmd_normal (struct grub_command *cmd, grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
grub_unregister_command (cmd);
if (argc == 0) if (argc == 0)
{ {
/* Guess the config filename. It is necessary to make CONFIG static, /* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */ so that it won't get broken by longjmp. */
static char *config; char *config;
const char *prefix; const char *prefix;
prefix = grub_env_get ("prefix"); prefix = grub_env_get ("prefix");
@ -493,10 +511,82 @@ quit:
return 0; return 0;
} }
/* Exit from normal mode to rescue mode. */
static grub_err_t
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
if (nested_level <= grub_normal_exit_level)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
grub_normal_exit_level++;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_normal_reader_init (int nested)
{
struct grub_term_output *term;
const char *msg = _("Minimal BASH-like line editing is supported. For "
"the first word, TAB lists possible command completions. Anywhere "
"else TAB lists possible device or file completions. %s");
const char *msg_esc = _("ESC at any time exits.");
char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) +
grub_strlen(msg_esc) + 1));
grub_sprintf (msg_formatted, msg, nested ? msg_esc : "");
FOR_ACTIVE_TERM_OUTPUTS(term)
{
grub_normal_init_page (term);
grub_term_setcursor (term, 1);
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
grub_puts ("\n");
}
grub_free (msg_formatted);
return 0;
}
static grub_err_t
grub_normal_read_line_real (char **line, int cont, int nested)
{
grub_parser_t parser = grub_parser_get_current ();
char prompt[sizeof("> ") + grub_strlen (parser->name)];
if (cont)
grub_sprintf (prompt, "> ");
else
grub_sprintf (prompt, "%s> ", parser->name);
while (1)
{
*line = grub_cmdline_get (prompt);
if (*line)
break;
if (cont || nested)
{
grub_free (*line);
*line = 0;
return grub_errno;
}
}
return 0;
}
static grub_err_t
grub_normal_read_line (char **line, int cont)
{
return grub_normal_read_line_real (line, cont, 0);
}
void void
grub_cmdline_run (int nested) grub_cmdline_run (int nested)
{ {
grub_reader_t reader;
grub_err_t err = GRUB_ERR_NONE; grub_err_t err = GRUB_ERR_NONE;
err = grub_auth_check_authentication (NULL); err = grub_auth_check_authentication (NULL);
@ -508,72 +598,28 @@ grub_cmdline_run (int nested)
return; return;
} }
reader = grub_reader_get_current (); grub_normal_reader_init (nested);
reader_nested = nested;
if (reader->init)
reader->init ();
grub_reader_loop (0);
}
static grub_err_t
grub_normal_reader_init (void)
{
grub_normal_init_page ();
grub_setcursor (1);
const char *msg = _("Minimal BASH-like line editing is supported. For "
"the first word, TAB lists possible command completions. Anywhere "
"else TAB lists possible device or file completions. %s");
const char *msg_esc = _("ESC at any time exits.");
char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) +
grub_strlen(msg_esc) + 1));
grub_sprintf (msg_formatted, msg, reader_nested ? msg_esc : "");
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN);
grub_puts ("\n");
grub_free (msg_formatted);
return 0;
}
static char cmdline[GRUB_MAX_CMDLINE];
static grub_err_t
grub_normal_read_line (char **line, int cont)
{
grub_parser_t parser = grub_parser_get_current ();
char prompt[sizeof("> ") + grub_strlen (parser->name)];
grub_sprintf (prompt, "%s> ", parser->name);
while (1) while (1)
{ {
cmdline[0] = 0; char *line;
if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
if (grub_normal_exit_level)
break; break;
if ((reader_nested) || (cont)) /* Print an error, if any. */
{ grub_print_error ();
*line = 0; grub_errno = GRUB_ERR_NONE;
return grub_errno;
} grub_normal_read_line_real (&line, 0, nested);
if (! line)
break;
grub_parser_get_current ()->parse_line (line, grub_normal_read_line);
grub_free (line);
} }
*line = grub_strdup (cmdline);
return 0;
} }
static struct grub_reader grub_normal_reader =
{
.name = "normal",
.init = grub_normal_reader_init,
.read_line = grub_normal_read_line
};
static char * static char *
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
const char *val) const char *val)
@ -588,17 +634,22 @@ GRUB_MOD_INIT(normal)
if (mod) if (mod)
grub_dl_ref (mod); grub_dl_ref (mod);
grub_menu_viewer_register (&grub_normal_text_menu_viewer);
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
grub_reader_register ("normal", &grub_normal_reader); grub_menu_register_viewer_init (grub_menu_text_register_instances);
grub_reader_set_current (&grub_normal_reader); if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_register_variable_hook ("pager", 0, grub_env_write_pager); grub_register_variable_hook ("pager", 0, grub_env_write_pager);
/* Register a command "normal" for the rescue mode. */ /* Register a command "normal" for the rescue mode. */
grub_register_command_prio ("normal", grub_cmd_normal, grub_register_command ("normal", grub_cmd_normal,
0, "Enter normal mode", 0); 0, "Enter normal mode");
grub_register_command ("normal_exit", grub_cmd_normal_exit,
0, "Exit from normal mode");
/* Reload terminal colors when these variables are written to. */ /* Reload terminal colors when these variables are written to. */
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal); grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
@ -607,14 +658,11 @@ GRUB_MOD_INIT(normal)
/* Preserve hooks after context changes. */ /* Preserve hooks after context changes. */
grub_env_export ("color_normal"); grub_env_export ("color_normal");
grub_env_export ("color_highlight"); grub_env_export ("color_highlight");
grub_menu_viewer_init ();
} }
GRUB_MOD_FINI(normal) GRUB_MOD_FINI(normal)
{ {
grub_set_history (0); grub_set_history (0);
grub_reader_unregister (&grub_normal_reader);
grub_register_variable_hook ("pager", 0, 0); grub_register_variable_hook ("pager", 0, 0);
grub_fs_autoload_hook = 0; grub_fs_autoload_hook = 0;
free_handler_list (); free_handler_list ();

View file

@ -27,6 +27,30 @@
#include <grub/command.h> #include <grub/command.h>
#include <grub/parser.h> #include <grub/parser.h>
#include <grub/auth.h> #include <grub/auth.h>
#include <grub/i18n.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
struct menu_run_callback
{
struct menu_run_callback *next;
void (*hook) (int entry, grub_menu_t menu, int nested);
};
struct menu_run_callback *callbacks = NULL;
/* Wait until the user pushes any key so that the user
can see what happened. */
void
grub_wait_after_message (void)
{
grub_putchar ('\n');
grub_printf_ (N_("Press any key to continue..."));
(void) grub_getkey ();
grub_putchar ('\n');
}
/* Get a menu entry by its index in the entry list. */ /* Get a menu entry by its index in the entry list. */
grub_menu_entry_t grub_menu_entry_t
@ -181,6 +205,86 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
callback->notify_failure (callback_data); callback->notify_failure (callback_data);
} }
static struct grub_menu_viewer *viewers;
static void
menu_set_chosen_entry (int entry)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->set_chosen_entry (entry, cur->data);
}
static void
menu_print_timeout (int timeout)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->print_timeout (timeout, cur->data);
}
static void
menu_fini (void)
{
struct grub_menu_viewer *cur, *next;
for (cur = viewers; cur; cur = next)
{
next = cur->next;
cur->fini (cur->data);
grub_free (cur);
}
viewers = NULL;
}
/* FIXME: allow text menu in parallel with gfxmenu. */
grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested) = NULL;
static void
menu_init (int entry, grub_menu_t menu, int nested)
{
struct menu_run_callback *cb;
if (grub_gfxmenu_try_hook)
{
if(!grub_gfxmenu_try_hook (entry, menu, nested))
return;
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
for (cb = callbacks; cb; cb = cb->next)
cb->hook (entry, menu, nested);
}
static void
clear_timeout (void)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->clear_timeout (cur->data);
}
void
grub_menu_register_viewer (struct grub_menu_viewer *viewer)
{
viewer->next = viewers;
viewers = viewer;
}
grub_err_t
grub_menu_register_viewer_init (void (*callback) (int entry, grub_menu_t menu,
int nested))
{
struct menu_run_callback *cb;
cb = grub_malloc (sizeof (*cb));
if (!cb)
return grub_errno;
cb->hook = callback;
cb->next = callbacks;
callbacks = cb;
return GRUB_ERR_NONE;
}
/* Get the entry number from the variable NAME. */ /* Get the entry number from the variable NAME. */
static int static int
get_entry_number (grub_menu_t menu, const char *name) get_entry_number (grub_menu_t menu, const char *name)
@ -229,8 +333,279 @@ get_entry_number (grub_menu_t menu, const char *name)
return entry; return entry;
} }
int #define GRUB_MENU_PAGE_SIZE 10
grub_menu_get_default_entry_index (grub_menu_t menu)
/* Show the menu and handle menu entry selection. Returns the menu entry
index that should be executed or -1 if no entry should be executed (e.g.,
Esc pressed to exit a sub-menu or switching menu viewers).
If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
entry to be executed is a result of an automatic default selection because
of the timeout. */
static int
run_menu (grub_menu_t menu, int nested, int *auto_boot)
{ {
return get_entry_number (menu, "default"); grub_uint64_t saved_time;
int default_entry, current_entry;
int timeout;
default_entry = get_entry_number (menu, "default");
/* If DEFAULT_ENTRY is not within the menu entries, fall back to
the first entry. */
if (default_entry < 0 || default_entry >= menu->size)
default_entry = 0;
/* If timeout is 0, drawing is pointless (and ugly). */
if (grub_menu_get_timeout () == 0)
{
*auto_boot = 1;
return default_entry;
}
current_entry = default_entry;
/* Initialize the time. */
saved_time = grub_get_time_ms ();
refresh:
menu_init (current_entry, menu, nested);
timeout = grub_menu_get_timeout ();
if (timeout > 0)
menu_print_timeout (timeout);
while (1)
{
int c;
timeout = grub_menu_get_timeout ();
if (grub_normal_exit_level)
return -1;
if (timeout > 0)
{
grub_uint64_t current_time;
current_time = grub_get_time_ms ();
if (current_time - saved_time >= 1000)
{
timeout--;
grub_menu_set_timeout (timeout);
saved_time = current_time;
menu_print_timeout (timeout);
}
}
if (timeout == 0)
{
grub_env_unset ("timeout");
*auto_boot = 1;
menu_fini ();
return default_entry;
}
if (grub_checkkey () >= 0 || timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (timeout >= 0)
{
grub_env_unset ("timeout");
grub_env_unset ("fallback");
clear_timeout ();
}
switch (c)
{
case GRUB_TERM_HOME:
current_entry = 0;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_END:
current_entry = menu->size - 1;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_UP:
case '^':
if (current_entry > 0)
current_entry--;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_DOWN:
case 'v':
if (current_entry < menu->size - 1)
current_entry++;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_PPAGE:
if (current_entry < GRUB_MENU_PAGE_SIZE)
current_entry = 0;
else
current_entry -= GRUB_MENU_PAGE_SIZE;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_NPAGE:
if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size)
current_entry += GRUB_MENU_PAGE_SIZE;
else
current_entry = menu->size - 1;
menu_set_chosen_entry (current_entry);
break;
case '\n':
case '\r':
case 6:
menu_fini ();
*auto_boot = 0;
return current_entry;
case '\e':
if (nested)
{
menu_fini ();
return -1;
}
break;
case 'c':
menu_fini ();
grub_cmdline_run (1);
goto refresh;
case 'e':
menu_fini ();
{
grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry);
if (e)
grub_menu_entry_run (e);
}
goto refresh;
default:
break;
}
}
}
/* Never reach here. */
return -1;
}
/* Callback invoked immediately before a menu entry is executed. */
static void
notify_booting (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf (" ");
grub_printf_ (N_("Booting \'%s\'"), entry->title);
grub_printf ("\n\n");
}
/* Callback invoked when a default menu entry executed because of a timeout
has failed and an attempt will be made to execute the next fallback
entry, ENTRY. */
static void
notify_fallback (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf ("\n ");
grub_printf_ (N_("Falling back to \'%s\'"), entry->title);
grub_printf ("\n\n");
grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
}
/* Callback invoked when a menu entry has failed and there is no remaining
fallback entry to attempt. */
static void
notify_execution_failure (void *userdata __attribute__((unused)))
{
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_printf ("\n ");
grub_printf_ (N_("Failed to boot default entries.\n"));
grub_wait_after_message ();
}
/* Callbacks used by the text menu to provide user feedback when menu entries
are executed. */
static struct grub_menu_execute_callback execution_callback =
{
.notify_booting = notify_booting,
.notify_fallback = notify_fallback,
.notify_failure = notify_execution_failure
};
static grub_err_t
show_menu (grub_menu_t menu, int nested)
{
while (1)
{
int boot_entry;
grub_menu_entry_t e;
int auto_boot;
boot_entry = run_menu (menu, nested, &auto_boot);
if (boot_entry < 0)
break;
e = grub_menu_get_entry (menu, boot_entry);
if (! e)
continue; /* Menu is empty. */
grub_cls ();
if (auto_boot)
{
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
}
else
{
grub_errno = GRUB_ERR_NONE;
grub_menu_execute_entry (e);
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_wait_after_message ();
}
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_show_menu (grub_menu_t menu, int nested)
{
grub_err_t err1, err2;
while (1)
{
err1 = show_menu (menu, nested);
grub_print_error ();
if (grub_normal_exit_level)
break;
err2 = grub_auth_check_authentication (NULL);
if (err2)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
break;
}
return err1;
} }

File diff suppressed because it is too large Load diff

View file

@ -26,96 +26,66 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/menu_viewer.h> #include <grub/menu_viewer.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
static grub_uint8_t grub_color_menu_normal; static grub_uint8_t grub_color_menu_normal;
static grub_uint8_t grub_color_menu_highlight; static grub_uint8_t grub_color_menu_highlight;
/* Wait until the user pushes any key so that the user struct menu_viewer_data
can see what happened. */
void
grub_wait_after_message (void)
{ {
grub_putchar ('\n'); int first, offset;
grub_printf_ (N_("Press any key to continue...")); grub_menu_t menu;
(void) grub_getkey (); struct grub_term_output *term;
grub_putchar ('\n'); };
}
static void static void
print_spaces (int number_spaces) print_spaces (int number_spaces, struct grub_term_output *term)
{ {
int i; int i;
for (i = 0; i < number_spaces; i++) for (i = 0; i < number_spaces; i++)
grub_putchar (' '); grub_putcode (' ', term);
} }
void void
grub_print_ucs4 (const grub_uint32_t * str, grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position) const grub_uint32_t * last_position,
struct grub_term_output *term)
{ {
while (str < last_position) while (str < last_position)
{ {
grub_putcode (*str); grub_putcode (*str, term);
str++; str++;
} }
} }
int
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position)
{
grub_ssize_t msg_len = grub_strlen (msg);
*unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t));
if (!*unicode_msg)
{
grub_printf ("utf8_to_ucs4 ERROR1: %s", msg);
return -1;
}
msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len,
(grub_uint8_t *) msg, -1, 0);
*last_position = *unicode_msg + msg_len;
if (msg_len < 0)
{
grub_printf ("utf8_to_ucs4 ERROR2: %s", msg);
grub_free (*unicode_msg);
}
return msg_len;
}
grub_ssize_t grub_ssize_t
grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position) grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position,
struct grub_term_output *term)
{ {
grub_ssize_t width = 0; grub_ssize_t width = 0;
while (str < last_position) while (str < last_position)
{ {
width += grub_getcharwidth (*str); width += grub_term_getcharwidth (term, *str);
str++; str++;
} }
return width; return width;
} }
void void
grub_print_message_indented (const char *msg, int margin_left, int margin_right) grub_print_message_indented (const char *msg, int margin_left, int margin_right,
struct grub_term_output *term)
{ {
int line_len; int line_len;
line_len = GRUB_TERM_WIDTH - grub_getcharwidth ('m') *
(margin_left + margin_right);
grub_uint32_t *unicode_msg; grub_uint32_t *unicode_msg;
grub_uint32_t *last_position; grub_uint32_t *last_position;
int msg_len; int msg_len;
line_len = grub_term_width (term) - grub_term_getcharwidth (term, 'm') *
(margin_left + margin_right);
msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position); msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position);
if (msg_len < 0) if (msg_len < 0)
@ -132,11 +102,12 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
while (current_position < last_position) while (current_position < last_position)
{ {
if (! first_loop) if (! first_loop)
grub_putchar ('\n'); grub_putcode ('\n', term);
next_new_line = (grub_uint32_t *) last_position; next_new_line = (grub_uint32_t *) last_position;
while (grub_getstringwidth (current_position, next_new_line) > line_len while (grub_getstringwidth (current_position, next_new_line,term)
> line_len
|| (*next_new_line != ' ' && next_new_line > current_position && || (*next_new_line != ' ' && next_new_line > current_position &&
next_new_line != last_position)) next_new_line != last_position))
{ {
@ -149,8 +120,8 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
(grub_uint32_t *) last_position : next_new_line + line_len; (grub_uint32_t *) last_position : next_new_line + line_len;
} }
print_spaces (margin_left); print_spaces (margin_left, term);
grub_print_ucs4 (current_position, next_new_line); grub_print_ucs4 (current_position, next_new_line, term);
next_new_line++; next_new_line++;
current_position = next_new_line; current_position = next_new_line;
@ -161,52 +132,54 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
static void static void
draw_border (void) draw_border (struct grub_term_output *term)
{ {
unsigned i; unsigned i;
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y); grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
grub_putcode (GRUB_TERM_DISP_UL); grub_putcode (GRUB_TERM_DISP_UL, term);
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
grub_putcode (GRUB_TERM_DISP_HLINE); grub_putcode (GRUB_TERM_DISP_HLINE, term);
grub_putcode (GRUB_TERM_DISP_UR); grub_putcode (GRUB_TERM_DISP_UR, term);
for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++) for (i = 0; i < (unsigned) grub_term_num_entries (term); i++)
{ {
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1); grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
grub_putcode (GRUB_TERM_DISP_VLINE); grub_putcode (GRUB_TERM_DISP_VLINE, term);
grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1, grub_term_gotoxy (term, GRUB_TERM_MARGIN + grub_term_border_width (term)
GRUB_TERM_TOP_BORDER_Y + i + 1); - 1,
grub_putcode (GRUB_TERM_DISP_VLINE); GRUB_TERM_TOP_BORDER_Y + i + 1);
grub_putcode (GRUB_TERM_DISP_VLINE, term);
} }
grub_gotoxy (GRUB_TERM_MARGIN, grub_term_gotoxy (term, GRUB_TERM_MARGIN,
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1); GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1);
grub_putcode (GRUB_TERM_DISP_LL); grub_putcode (GRUB_TERM_DISP_LL, term);
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
grub_putcode (GRUB_TERM_DISP_HLINE); grub_putcode (GRUB_TERM_DISP_HLINE, term);
grub_putcode (GRUB_TERM_DISP_LR); grub_putcode (GRUB_TERM_DISP_LR, term);
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_MARGIN, grub_term_gotoxy (term, GRUB_TERM_MARGIN,
(GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES (GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)
+ GRUB_TERM_MARGIN + 1)); + GRUB_TERM_MARGIN + 1));
} }
static void static void
print_message (int nested, int edit) print_message (int nested, int edit, struct grub_term_output *term)
{ {
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
if (edit) if (edit)
{ {
grub_putchar ('\n'); grub_putcode ('\n', term);
grub_print_message_indented (_("Minimum Emacs-like screen editing is \ grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \
command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN); command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN,
term);
} }
else else
{ {
@ -218,23 +191,33 @@ entry is highlighted.\n");
grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP, grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP,
(grub_uint32_t) GRUB_TERM_DISP_DOWN); (grub_uint32_t) GRUB_TERM_DISP_DOWN);
grub_putchar ('\n'); grub_putchar ('\n');
grub_print_message_indented (msg_translated, STANDARD_MARGIN, STANDARD_MARGIN); grub_print_message_indented (msg_translated, STANDARD_MARGIN,
STANDARD_MARGIN, term);
grub_free (msg_translated); grub_free (msg_translated);
grub_print_message_indented (_("Press enter to boot the selected OS, \
\'e\' to edit the commands before booting or \'c\' for a command-line.\n"), STANDARD_MARGIN, STANDARD_MARGIN);
if (nested) if (nested)
{ {
grub_printf ("\n "); grub_print_message_indented
grub_printf_ (N_("ESC to return previous menu.")); (_("Press enter to boot the selected OS, "
} "\'e\' to edit the commands before booting "
"or \'c\' for a command-line. ESC to return previous menu.\n"),
STANDARD_MARGIN, STANDARD_MARGIN, term);
}
else
{
grub_print_message_indented
(_("Press enter to boot the selected OS, "
"\'e\' to edit the commands before booting "
"or \'c\' for a command-line.\n"),
STANDARD_MARGIN, STANDARD_MARGIN, term);
}
} }
} }
static void static void
print_entry (int y, int highlight, grub_menu_entry_t entry) print_entry (int y, int highlight, grub_menu_entry_t entry,
struct grub_term_output *term)
{ {
int x; int x;
const char *title; const char *title;
@ -260,461 +243,251 @@ print_entry (int y, int highlight, grub_menu_entry_t entry)
return; return;
} }
grub_getcolor (&old_color_normal, &old_color_highlight); grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
grub_setcolorstate (highlight grub_term_setcolorstate (term, highlight
? GRUB_TERM_COLOR_HIGHLIGHT ? GRUB_TERM_COLOR_HIGHLIGHT
: GRUB_TERM_COLOR_NORMAL); : GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y); grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0; for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN; x < (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN);
i++) i++)
{ {
if (i < len if (i < len
&& x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH && x <= (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN - 1)) - GRUB_TERM_MARGIN - 1))
{ {
grub_ssize_t width; grub_ssize_t width;
width = grub_getcharwidth (unicode_title[i]); width = grub_term_getcharwidth (term, unicode_title[i]);
if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH if (x + width > (int) (GRUB_TERM_LEFT_BORDER_X
- GRUB_TERM_MARGIN - 1)) + grub_term_border_width (term)
grub_putcode (GRUB_TERM_DISP_RIGHT); - GRUB_TERM_MARGIN - 1))
grub_putcode (GRUB_TERM_DISP_RIGHT, term);
else else
grub_putcode (unicode_title[i]); grub_putcode (unicode_title[i], term);
x += width; x += width;
} }
else else
{ {
grub_putchar (' '); grub_putcode (' ', term);
x++; x++;
} }
} }
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_putchar (' '); grub_putcode (' ', term);
grub_gotoxy (GRUB_TERM_CURSOR_X, y); grub_term_gotoxy (term, grub_term_cursor_x (term), y);
grub_setcolor (old_color_normal, old_color_highlight); grub_term_setcolor (term, old_color_normal, old_color_highlight);
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_free (unicode_title); grub_free (unicode_title);
} }
static void static void
print_entries (grub_menu_t menu, int first, int offset) print_entries (grub_menu_t menu, int first, int offset,
struct grub_term_output *term)
{ {
grub_menu_entry_t e; grub_menu_entry_t e;
int i; int i;
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, grub_term_gotoxy (term,
GRUB_TERM_FIRST_ENTRY_Y); GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term),
GRUB_TERM_FIRST_ENTRY_Y);
if (first) if (first)
grub_putcode (GRUB_TERM_DISP_UP); grub_putcode (GRUB_TERM_DISP_UP, term);
else else
grub_putchar (' '); grub_putcode (' ', term);
e = grub_menu_get_entry (menu, first); e = grub_menu_get_entry (menu, first);
for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++) for (i = 0; i < grub_term_num_entries (term); i++)
{ {
print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e); print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e, term);
if (e) if (e)
e = e->next; e = e->next;
} }
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES); + grub_term_border_width (term),
GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term));
if (e) if (e)
grub_putcode (GRUB_TERM_DISP_DOWN); grub_putcode (GRUB_TERM_DISP_DOWN, term);
else else
grub_putchar (' '); grub_putcode (' ', term);
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); grub_term_gotoxy (term, grub_term_cursor_x (term),
GRUB_TERM_FIRST_ENTRY_Y + offset);
} }
/* Initialize the screen. If NESTED is non-zero, assume that this menu /* Initialize the screen. If NESTED is non-zero, assume that this menu
is run from another menu or a command-line. If EDIT is non-zero, show is run from another menu or a command-line. If EDIT is non-zero, show
a message for the menu entry editor. */ a message for the menu entry editor. */
void void
grub_menu_init_page (int nested, int edit) grub_menu_init_page (int nested, int edit,
struct grub_term_output *term)
{ {
grub_uint8_t old_color_normal, old_color_highlight; grub_uint8_t old_color_normal, old_color_highlight;
grub_getcolor (&old_color_normal, &old_color_highlight); grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
/* By default, use the same colors for the menu. */ /* By default, use the same colors for the menu. */
grub_color_menu_normal = old_color_normal; grub_color_menu_normal = old_color_normal;
grub_color_menu_highlight = old_color_highlight; grub_color_menu_highlight = old_color_highlight;
/* Then give user a chance to replace them. */ /* Then give user a chance to replace them. */
grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal")); grub_parse_color_name_pair (&grub_color_menu_normal,
grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight")); grub_env_get ("menu_color_normal"));
grub_parse_color_name_pair (&grub_color_menu_highlight,
grub_env_get ("menu_color_highlight"));
grub_normal_init_page (); grub_normal_init_page (term);
grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
draw_border (); draw_border (term);
grub_setcolor (old_color_normal, old_color_highlight); grub_term_setcolor (term, old_color_normal, old_color_highlight);
print_message (nested, edit); print_message (nested, edit, term);
} }
static void static void
print_timeout (int timeout, int offset) menu_text_print_timeout (int timeout, void *dataptr)
{ {
const char *msg = const char *msg =
_("The highlighted entry will be booted automatically in %ds."); _("The highlighted entry will be booted automatically in %ds.");
struct menu_viewer_data *data = dataptr;
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); char *msg_translated;
char *msg_translated =
grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
grub_sprintf (msg_translated, msg, timeout);
grub_print_message_indented (msg_translated, 3, 0);
int posx; int posx;
posx = grub_getxy() >> 8;
print_spaces (GRUB_TERM_WIDTH - posx - 1);
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3);
grub_refresh ();
}
/* Show the menu and handle menu entry selection. Returns the menu entry msg_translated = grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
index that should be executed or -1 if no entry should be executed (e.g., if (!msg_translated)
Esc pressed to exit a sub-menu or switching menu viewers).
If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
entry to be executed is a result of an automatic default selection because
of the timeout. */
static int
run_menu (grub_menu_t menu, int nested, int *auto_boot)
{
int first, offset;
grub_uint64_t saved_time;
int default_entry;
int timeout;
first = 0;
default_entry = grub_menu_get_default_entry_index (menu);
/* If DEFAULT_ENTRY is not within the menu entries, fall back to
the first entry. */
if (default_entry < 0 || default_entry >= menu->size)
default_entry = 0;
/* If timeout is 0, drawing is pointless (and ugly). */
if (grub_menu_get_timeout () == 0)
{
*auto_boot = 1;
return default_entry;
}
offset = default_entry;
if (offset > GRUB_TERM_NUM_ENTRIES - 1)
{
first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
/* Initialize the time. */
saved_time = grub_get_time_ms ();
refresh:
grub_setcursor (0);
grub_menu_init_page (nested, 0);
print_entries (menu, first, offset);
grub_refresh ();
timeout = grub_menu_get_timeout ();
if (timeout > 0)
print_timeout (timeout, offset);
while (! grub_menu_viewer_should_return ())
{
int c;
timeout = grub_menu_get_timeout ();
if (timeout > 0)
{
grub_uint64_t current_time;
current_time = grub_get_time_ms ();
if (current_time - saved_time >= 1000)
{
timeout--;
grub_menu_set_timeout (timeout);
saved_time = current_time;
print_timeout (timeout, offset);
}
}
if (timeout == 0)
{
grub_env_unset ("timeout");
*auto_boot = 1;
return default_entry;
}
if (grub_checkkey () >= 0 || timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (timeout >= 0)
{
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
print_spaces (GRUB_TERM_WIDTH - 1);
grub_env_unset ("timeout");
grub_env_unset ("fallback");
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
}
switch (c)
{
case GRUB_TERM_HOME:
first = 0;
offset = 0;
print_entries (menu, first, offset);
break;
case GRUB_TERM_END:
offset = menu->size - 1;
if (offset > GRUB_TERM_NUM_ENTRIES - 1)
{
first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
print_entries (menu, first, offset);
break;
case GRUB_TERM_UP:
case '^':
if (offset > 0)
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
grub_menu_get_entry (menu, first + offset));
offset--;
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
grub_menu_get_entry (menu, first + offset));
}
else if (first > 0)
{
first--;
print_entries (menu, first, offset);
}
break;
case GRUB_TERM_DOWN:
case 'v':
if (menu->size > first + offset + 1)
{
if (offset < GRUB_TERM_NUM_ENTRIES - 1)
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
grub_menu_get_entry (menu, first + offset));
offset++;
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
grub_menu_get_entry (menu, first + offset));
}
else
{
first++;
print_entries (menu, first, offset);
}
}
break;
case GRUB_TERM_PPAGE:
if (first == 0)
{
offset = 0;
}
else
{
first -= GRUB_TERM_NUM_ENTRIES;
if (first < 0)
{
offset += first;
first = 0;
}
}
print_entries (menu, first, offset);
break;
case GRUB_TERM_NPAGE:
if (offset == 0)
{
offset += GRUB_TERM_NUM_ENTRIES - 1;
if (first + offset >= menu->size)
{
offset = menu->size - first - 1;
}
}
else
{
first += GRUB_TERM_NUM_ENTRIES;
if (first + offset >= menu->size)
{
first -= GRUB_TERM_NUM_ENTRIES;
offset += GRUB_TERM_NUM_ENTRIES;
if (offset > menu->size - 1 ||
offset > GRUB_TERM_NUM_ENTRIES - 1)
{
offset = menu->size - first - 1;
}
if (offset > GRUB_TERM_NUM_ENTRIES)
{
first += offset - GRUB_TERM_NUM_ENTRIES + 1;
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
}
}
print_entries (menu, first, offset);
break;
case '\n':
case '\r':
case 6:
grub_setcursor (1);
*auto_boot = 0;
return first + offset;
case '\e':
if (nested)
{
grub_setcursor (1);
return -1;
}
break;
case 'c':
grub_cmdline_run (1);
goto refresh;
case 'e':
{
grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset);
if (e)
grub_menu_entry_run (e);
}
goto refresh;
case 't':
grub_env_set ("menuviewer", "gfxmenu");
goto refresh;
default:
break;
}
grub_refresh ();
}
}
/* Exit menu without activating an item. This occurs if the user presses
* 't', switching to the graphical menu viewer. */
return -1;
}
/* Callback invoked immediately before a menu entry is executed. */
static void
notify_booting (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf (" ");
grub_printf_ (N_("Booting \'%s\'"), entry->title);
grub_printf ("\n\n");
}
/* Callback invoked when a default menu entry executed because of a timeout
has failed and an attempt will be made to execute the next fallback
entry, ENTRY. */
static void
notify_fallback (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf ("\n ");
grub_printf_ (N_("Falling back to \'%s\'"), entry->title);
grub_printf ("\n\n");
grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
}
/* Callback invoked when a menu entry has failed and there is no remaining
fallback entry to attempt. */
static void
notify_execution_failure (void *userdata __attribute__((unused)))
{
if (grub_errno != GRUB_ERR_NONE)
{ {
grub_print_error (); grub_print_error ();
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return;
} }
grub_printf ("\n ");
grub_printf_ (N_("Failed to boot default entries.\n")); grub_sprintf (msg_translated, msg, timeout);
grub_wait_after_message (); grub_print_message_indented (msg_translated, 3, 0, data->term);
posx = grub_term_getxy (data->term) >> 8;
print_spaces (grub_term_width (data->term) - posx - 1, data->term);
grub_term_gotoxy (data->term,
grub_term_cursor_x (data->term),
GRUB_TERM_FIRST_ENTRY_Y + data->offset);
grub_term_refresh (data->term);
} }
/* Callbacks used by the text menu to provide user feedback when menu entries static void
are executed. */ menu_text_set_chosen_entry (int entry, void *dataptr)
static struct grub_menu_execute_callback execution_callback =
{ {
.notify_booting = notify_booting, struct menu_viewer_data *data = dataptr;
.notify_fallback = notify_fallback, int oldoffset = data->offset;
.notify_failure = notify_execution_failure int complete_redraw = 0;
};
static grub_err_t data->offset = entry - data->first;
show_text_menu (grub_menu_t menu, int nested) if (data->offset > grub_term_num_entries (data->term) - 1)
{
while (1)
{ {
int boot_entry; data->first = entry - (grub_term_num_entries (data->term) - 1);
grub_menu_entry_t e; data->offset = grub_term_num_entries (data->term) - 1;
int auto_boot; complete_redraw = 1;
boot_entry = run_menu (menu, nested, &auto_boot);
if (boot_entry < 0)
break;
e = grub_menu_get_entry (menu, boot_entry);
if (! e)
continue; /* Menu is empty. */
grub_cls ();
grub_setcursor (1);
if (auto_boot)
{
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
}
else
{
grub_errno = GRUB_ERR_NONE;
grub_menu_execute_entry (e);
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_wait_after_message ();
}
}
} }
if (data->offset < 0)
return GRUB_ERR_NONE; {
data->offset = 0;
data->first = entry;
complete_redraw = 1;
}
if (complete_redraw)
print_entries (data->menu, data->first, data->offset, data->term);
else
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + oldoffset, 0,
grub_menu_get_entry (data->menu, data->first + oldoffset),
data->term);
print_entry (GRUB_TERM_FIRST_ENTRY_Y + data->offset, 1,
grub_menu_get_entry (data->menu, data->first + data->offset),
data->term);
}
grub_term_refresh (data->term);
} }
struct grub_menu_viewer grub_normal_text_menu_viewer = static void
menu_text_fini (void *dataptr)
{ {
.name = "text", struct menu_viewer_data *data = dataptr;
.show_menu = show_text_menu
}; grub_term_setcursor (data->term, 1);
grub_term_cls (data->term);
}
static void
menu_text_clear_timeout (void *dataptr)
{
struct menu_viewer_data *data = dataptr;
grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3);
print_spaces (grub_term_width (data->term) - 1, data->term);
grub_term_gotoxy (data->term, grub_term_cursor_x (data->term),
GRUB_TERM_FIRST_ENTRY_Y + data->offset);
grub_term_refresh (data->term);
}
void
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested)
{
struct menu_viewer_data *data;
struct grub_menu_viewer *instance;
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
instance = grub_zalloc (sizeof (*instance));
if (!instance)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
data = grub_zalloc (sizeof (*data));
if (!data)
{
grub_free (instance);
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
data->term = term;
instance->data = data;
instance->set_chosen_entry = menu_text_set_chosen_entry;
instance->print_timeout = menu_text_print_timeout;
instance->clear_timeout = menu_text_clear_timeout;
instance->fini = menu_text_fini;
data->menu = menu;
data->offset = entry;
data->first = 0;
if (data->offset > grub_term_num_entries (data->term) - 1)
{
data->first = data->offset - (grub_term_num_entries (data->term) - 1);
data->offset = grub_term_num_entries (data->term) - 1;
}
grub_term_setcursor (data->term, 0);
grub_menu_init_page (nested, 0, data->term);
print_entries (menu, data->first, data->offset, data->term);
grub_term_refresh (data->term);
grub_menu_register_viewer (instance);
}
}

View file

@ -1,112 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 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/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/menu_viewer.h>
#include <grub/menu.h>
#include <grub/auth.h>
/* The list of menu viewers. */
static grub_menu_viewer_t menu_viewer_list;
static int should_return;
static int menu_viewer_changed;
void
grub_menu_viewer_register (grub_menu_viewer_t viewer)
{
viewer->next = menu_viewer_list;
menu_viewer_list = viewer;
}
static grub_menu_viewer_t get_current_menu_viewer (void)
{
const char *selected_name = grub_env_get ("menuviewer");
/* If none selected, pick the last registered one. */
if (selected_name == 0)
return menu_viewer_list;
grub_menu_viewer_t cur;
for (cur = menu_viewer_list; cur; cur = cur->next)
{
if (grub_strcmp (cur->name, selected_name) == 0)
return cur;
}
/* Fall back to the first entry (or null). */
return menu_viewer_list;
}
grub_err_t
grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
{
grub_err_t err1, err2;
while (1)
{
grub_menu_viewer_t cur = get_current_menu_viewer ();
if (!cur)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "No menu viewer available.");
menu_viewer_changed = 0;
should_return = 0;
err1 = cur->show_menu (menu, nested);
grub_print_error ();
if (menu_viewer_changed)
continue;
err2 = grub_auth_check_authentication (NULL);
if (err2)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
break;
}
return err1;
}
int
grub_menu_viewer_should_return (void)
{
return should_return;
}
static char *
menuviewer_write_hook (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
menu_viewer_changed = 1;
should_return = 1;
return grub_strdup (val);
}
void
grub_menu_viewer_init (void)
{
grub_register_variable_hook ("menuviewer", 0, menuviewer_write_hook);
}

252
normal/term.c Normal file
View file

@ -0,0 +1,252 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2007,2008,2009 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/term.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/file.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/normal.h>
/* The amount of lines counted by the pager. */
static unsigned grub_more_lines;
/* If the more pager is active. */
static int grub_more;
static void
process_newline (void)
{
struct grub_term_output *cur;
unsigned height = -1;
FOR_ACTIVE_TERM_OUTPUTS(cur)
if (grub_term_height (cur) < height)
height = grub_term_height (cur);
grub_more_lines++;
if (grub_more && grub_more_lines >= height - 1)
{
char key;
grub_uint16_t *pos;
pos = grub_term_save_pos ();
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_printf ("--MORE--");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
key = grub_getkey ();
/* Remove the message. */
grub_term_restore_pos (pos);
grub_printf (" ");
grub_term_restore_pos (pos);
/* Scroll one lines or an entire page, depending on the key. */
if (key == '\r' || key =='\n')
grub_more_lines = height - 2;
else
grub_more_lines = 0;
}
}
void
grub_set_more (int onoff)
{
if (onoff == 1)
grub_more++;
else
grub_more--;
grub_more_lines = 0;
grub_newline_hook = process_newline;
}
void
grub_puts_terminal (const char *str, struct grub_term_output *term)
{
grub_uint32_t code;
grub_ssize_t ret;
const grub_uint8_t *ptr = (const grub_uint8_t *) str;
const grub_uint8_t *end;
end = (const grub_uint8_t *) (str + grub_strlen (str));
while (*ptr)
{
ret = grub_utf8_to_ucs4 (&code, 1, ptr, end - ptr, &ptr);
grub_putcode (code, term);
}
}
grub_uint16_t *
grub_term_save_pos (void)
{
struct grub_term_output *cur;
unsigned cnt = 0;
grub_uint16_t *ret, *ptr;
FOR_ACTIVE_TERM_OUTPUTS(cur)
cnt++;
ret = grub_malloc (cnt * sizeof (ret[0]));
if (!ret)
return NULL;
ptr = ret;
FOR_ACTIVE_TERM_OUTPUTS(cur)
*ptr++ = grub_term_getxy (cur);
return ret;
}
void
grub_term_restore_pos (grub_uint16_t *pos)
{
struct grub_term_output *cur;
grub_uint16_t *ptr = pos;
if (!pos)
return;
FOR_ACTIVE_TERM_OUTPUTS(cur)
{
grub_term_gotoxy (cur, (*ptr & 0xff00) >> 8, *ptr & 0xff);
ptr++;
}
}
static void
grub_terminal_autoload_free (void)
{
struct grub_term_autoload *cur, *next;
unsigned i;
for (i = 0; i < 2; i++)
for (cur = i ? grub_term_input_autoload : grub_term_output_autoload;
cur; cur = next)
{
next = cur->next;
grub_free (cur->name);
grub_free (cur->modname);
grub_free (cur);
}
grub_term_input_autoload = NULL;
grub_term_output_autoload = NULL;
}
/* Read the file terminal.lst for auto-loading. */
void
read_terminal_list (void)
{
const char *prefix;
char *filename;
grub_file_t file;
char *buf = NULL;
prefix = grub_env_get ("prefix");
if (!prefix)
{
grub_errno = GRUB_ERR_NONE;
return;
}
filename = grub_malloc (grub_strlen (prefix) + sizeof ("/crypto.lst"));
if (!filename)
{
grub_errno = GRUB_ERR_NONE;
return;
}
grub_sprintf (filename, "%s/terminal.lst", prefix);
file = grub_file_open (filename);
if (!file)
{
grub_errno = GRUB_ERR_NONE;
return;
}
/* Override previous terminal.lst. */
grub_terminal_autoload_free ();
for (;; grub_free (buf))
{
char *p, *name;
struct grub_term_autoload *cur;
struct grub_term_autoload **target = NULL;
buf = grub_file_getline (file);
if (! buf)
break;
switch (buf[0])
{
case 'i':
target = &grub_term_input_autoload;
break;
case 'o':
target = &grub_term_output_autoload;
break;
}
if (!target)
continue;
name = buf + 1;
p = grub_strchr (name, ':');
if (! p)
continue;
*p = '\0';
while (*++p == ' ')
;
cur = grub_malloc (sizeof (*cur));
if (!cur)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
cur->name = grub_strdup (name);
if (! name)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
continue;
}
cur->modname = grub_strdup (p);
if (! cur->modname)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
grub_free (cur->name);
continue;
}
cur->next = *target;
*target = cur;
}
grub_file_close (file);
grub_errno = GRUB_ERR_NONE;
}

View file

@ -351,8 +351,7 @@ static struct grub_term_output grub_console_term_output =
.setcolorstate = grub_console_setcolorstate, .setcolorstate = grub_console_setcolorstate,
.setcolor = grub_console_setcolor, .setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor, .getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor, .setcursor = grub_console_setcursor
.flags = 0,
}; };
void void
@ -366,8 +365,8 @@ grub_console_init (void)
return; return;
} }
grub_term_register_input ("console", &grub_console_term_input); grub_term_register_input_active ("console", &grub_console_term_input);
grub_term_register_output ("console", &grub_console_term_output); grub_term_register_output_active ("console", &grub_console_term_output);
} }
void void

View file

@ -233,7 +233,11 @@ static struct grub_term_input grub_at_keyboard_term =
GRUB_MOD_INIT(at_keyboard) GRUB_MOD_INIT(at_keyboard)
{ {
#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
grub_term_register_input_active ("at_keyboard", &grub_at_keyboard_term);
#else
grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); grub_term_register_input ("at_keyboard", &grub_at_keyboard_term);
#endif
} }
GRUB_MOD_FINI(at_keyboard) GRUB_MOD_FINI(at_keyboard)

View file

@ -65,24 +65,19 @@ static struct grub_term_output grub_console_term_output =
.setcolorstate = grub_console_setcolorstate, .setcolorstate = grub_console_setcolorstate,
.setcolor = grub_console_setcolor, .setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor, .getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor, .setcursor = grub_console_setcursor
.flags = 0,
}; };
void void
grub_console_init (void) grub_console_init (void)
{ {
grub_term_register_output ("console", &grub_console_term_output); grub_term_register_output_active ("console", &grub_console_term_output);
grub_term_register_input ("console", &grub_console_term_input); grub_term_register_input_active ("console", &grub_console_term_input);
} }
void void
grub_console_fini (void) grub_console_fini (void)
{ {
/* This is to make sure the console is restored to text mode before
we boot. */
grub_term_set_current_output (&grub_console_term_output);
grub_term_unregister_input (&grub_console_term_input); grub_term_unregister_input (&grub_console_term_input);
grub_term_unregister_output (&grub_console_term_output); grub_term_unregister_output (&grub_console_term_output);
} }

View file

@ -30,6 +30,7 @@
#define TEXT_WIDTH 80 #define TEXT_WIDTH 80
#define TEXT_HEIGHT 25 #define TEXT_HEIGHT 25
static struct grub_term_output grub_serial_term_output;
static unsigned int xpos, ypos; static unsigned int xpos, ypos;
static unsigned int keep_track = 1; static unsigned int keep_track = 1;
static unsigned int registered = 0; static unsigned int registered = 0;
@ -413,7 +414,7 @@ grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y)
else else
{ {
keep_track = 0; keep_track = 0;
grub_terminfo_gotoxy (x, y); grub_terminfo_gotoxy (x, y, &grub_serial_term_output);
keep_track = 1; keep_track = 1;
xpos = x; xpos = x;
@ -425,7 +426,7 @@ static void
grub_serial_cls (void) grub_serial_cls (void)
{ {
keep_track = 0; keep_track = 0;
grub_terminfo_cls (); grub_terminfo_cls (&grub_serial_term_output);
keep_track = 1; keep_track = 1;
xpos = ypos = 0; xpos = ypos = 0;
@ -439,10 +440,10 @@ grub_serial_setcolorstate (const grub_term_color_state state)
{ {
case GRUB_TERM_COLOR_STANDARD: case GRUB_TERM_COLOR_STANDARD:
case GRUB_TERM_COLOR_NORMAL: case GRUB_TERM_COLOR_NORMAL:
grub_terminfo_reverse_video_off (); grub_terminfo_reverse_video_off (&grub_serial_term_output);
break; break;
case GRUB_TERM_COLOR_HIGHLIGHT: case GRUB_TERM_COLOR_HIGHLIGHT:
grub_terminfo_reverse_video_on (); grub_terminfo_reverse_video_on (&grub_serial_term_output);
break; break;
default: default:
break; break;
@ -454,9 +455,9 @@ static void
grub_serial_setcursor (const int on) grub_serial_setcursor (const int on)
{ {
if (on) if (on)
grub_terminfo_cursor_on (); grub_terminfo_cursor_on (&grub_serial_term_output);
else else
grub_terminfo_cursor_off (); grub_terminfo_cursor_off (&grub_serial_term_output);
} }
static struct grub_term_input grub_serial_term_input = static struct grub_term_input grub_serial_term_input =

View file

@ -163,12 +163,16 @@ static struct grub_term_output grub_vga_text_term =
.setcolorstate = grub_console_setcolorstate, .setcolorstate = grub_console_setcolorstate,
.setcolor = grub_console_setcolor, .setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor, .getcolor = grub_console_getcolor,
.setcursor = grub_vga_text_setcursor, .setcursor = grub_vga_text_setcursor
}; };
GRUB_MOD_INIT(vga_text) GRUB_MOD_INIT(vga_text)
{ {
#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
grub_term_register_output_active ("vga_text", &grub_vga_text_term);
#else
grub_term_register_output ("vga_text", &grub_vga_text_term); grub_term_register_output ("vga_text", &grub_vga_text_term);
#endif
} }
GRUB_MOD_FINI(vga_text) GRUB_MOD_FINI(vga_text)

View file

@ -414,15 +414,14 @@ static struct grub_term_output grub_ofconsole_term_output =
.setcolor = grub_ofconsole_setcolor, .setcolor = grub_ofconsole_setcolor,
.getcolor = grub_ofconsole_getcolor, .getcolor = grub_ofconsole_getcolor,
.setcursor = grub_ofconsole_setcursor, .setcursor = grub_ofconsole_setcursor,
.refresh = grub_ofconsole_refresh, .refresh = grub_ofconsole_refresh
.flags = 0,
}; };
void void
grub_console_init (void) grub_console_init (void)
{ {
grub_term_register_input ("ofconsole", &grub_ofconsole_term_input); grub_term_register_input_active ("ofconsole", &grub_ofconsole_term_input);
grub_term_register_output ("ofconsole", &grub_ofconsole_term_output); grub_term_register_output_active ("ofconsole", &grub_ofconsole_term_output);
} }
void void

View file

@ -108,52 +108,52 @@ grub_terminfo_set_current (const char *str)
/* Wrapper for grub_putchar to write strings. */ /* Wrapper for grub_putchar to write strings. */
static void static void
putstr (const char *str) putstr (const char *str, grub_term_output_t oterm)
{ {
while (*str) while (*str)
grub_putchar (*str++); grub_putcode (*str++, oterm);
} }
/* Move the cursor to the given position starting with "0". */ /* Move the cursor to the given position starting with "0". */
void void
grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y) grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.gotoxy, y, x)); putstr (grub_terminfo_tparm (term.gotoxy, y, x), oterm);
} }
/* Clear the screen. */ /* Clear the screen. */
void void
grub_terminfo_cls (void) grub_terminfo_cls (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cls)); putstr (grub_terminfo_tparm (term.cls), oterm);
} }
/* Set reverse video mode on. */ /* Set reverse video mode on. */
void void
grub_terminfo_reverse_video_on (void) grub_terminfo_reverse_video_on (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.reverse_video_on)); putstr (grub_terminfo_tparm (term.reverse_video_on), oterm);
} }
/* Set reverse video mode off. */ /* Set reverse video mode off. */
void void
grub_terminfo_reverse_video_off (void) grub_terminfo_reverse_video_off (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.reverse_video_off)); putstr (grub_terminfo_tparm (term.reverse_video_off), oterm);
} }
/* Show cursor. */ /* Show cursor. */
void void
grub_terminfo_cursor_on (void) grub_terminfo_cursor_on (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cursor_on)); putstr (grub_terminfo_tparm (term.cursor_on), oterm);
} }
/* Hide cursor. */ /* Hide cursor. */
void void
grub_terminfo_cursor_off (void) grub_terminfo_cursor_off (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cursor_off)); putstr (grub_terminfo_tparm (term.cursor_off), oterm);
} }
/* GRUB Command. */ /* GRUB Command. */

View file

@ -367,17 +367,14 @@ static struct grub_term_output grub_ncurses_term_output =
.setcolor = grub_ncurses_setcolor, .setcolor = grub_ncurses_setcolor,
.getcolor = grub_ncurses_getcolor, .getcolor = grub_ncurses_getcolor,
.setcursor = grub_ncurses_setcursor, .setcursor = grub_ncurses_setcursor,
.refresh = grub_ncurses_refresh, .refresh = grub_ncurses_refresh
.flags = 0,
}; };
void void
grub_console_init (void) grub_console_init (void)
{ {
grub_term_register_output ("console", &grub_ncurses_term_output); grub_term_register_output_active ("console", &grub_ncurses_term_output);
grub_term_register_input ("console", &grub_ncurses_term_input); grub_term_register_input_active ("console", &grub_ncurses_term_input);
grub_term_set_current_output (&grub_ncurses_term_output);
grub_term_set_current_input (&grub_ncurses_term_input);
} }
void void

View file

@ -46,9 +46,6 @@ grub_refresh (void)
fflush (stdout); fflush (stdout);
} }
struct grub_handler_class grub_term_input_class;
struct grub_handler_class grub_term_output_class;
int int
grub_getkey (void) grub_getkey (void)
{ {

342
util/grub-mkpasswd-pbkdf2.c Normal file
View file

@ -0,0 +1,342 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1992-1999,2001,2003,2004,2005,2009 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/types.h>
#include <grub/crypto.h>
#include <grub/util/misc.h>
#include <grub/i18n.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <termios.h>
#include "progname.h"
/* Few functions to make crypto happy. */
void *
grub_memmove (void *dest, const void *src, grub_size_t n)
{
return memmove (dest, src, n);
}
void *
grub_memset (void *s, int c, grub_size_t n)
{
return memset (s, c, n);
}
int
grub_vprintf (const char *fmt, va_list args)
{
return vprintf (fmt, args);
}
int
grub_vsprintf (char *str, const char *fmt, va_list args)
{
return vsprintf (str, fmt, args);
}
void
grub_abort (void)
{
abort ();
}
static struct option options[] =
{
{"iteration_count", required_argument, 0, 'c'},
{"buflen", required_argument, 0, 'l'},
{"saltlen", required_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub-scrypt --help'' for more information.\n");
else
printf ("\
Usage: grub-scrypt [OPTIONS]\n\
\nOptions:\n\
-c number, --iteration-count=number Number of PBKDF2 iterations\n\
-l number, --buflen=number Length of generated hash\n\
-s number, --salt=number Length of salt\n\
\n\
Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
exit (status);
}
static void
hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
{
while (n--)
{
if (((*bin & 0xf0) >> 4) < 10)
*hex = ((*bin & 0xf0) >> 4) + '0';
else
*hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
hex++;
if ((*bin & 0xf) < 10)
*hex = (*bin & 0xf) + '0';
else
*hex = (*bin & 0xf) + 'A' - 10;
hex++;
bin++;
}
*hex = 0;
}
int
main (int argc, char *argv[])
{
unsigned int c = 10000, buflen = 64, saltlen = 64;
char *pass1, *pass2;
char *bufhex, *salthex;
gcry_err_code_t gcry_err;
grub_uint8_t *buf, *salt;
ssize_t nr;
FILE *in, *out;
struct termios s, t;
int tty_changed;
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
/* Check for options. */
while (1)
{
int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0);
if (c == -1)
break;
switch (c)
{
case 'c':
c = strtoul (optarg, NULL, 0);
break;
case 'l':
buflen = strtoul (optarg, NULL, 0);
break;
case 's':
saltlen = strtoul (optarg, NULL, 0);
break;
case 'h':
usage (0);
return 0;
case 'V':
printf ("%s (%s) %s\n", program_name,
PACKAGE_NAME, PACKAGE_VERSION);
return 0;
default:
usage (1);
return 1;
}
}
bufhex = malloc (buflen * 2 + 1);
if (!bufhex)
grub_util_error ("Out of memory");
buf = malloc (buflen);
if (!buf)
{
free (bufhex);
grub_util_error ("Out of memory");
}
salt = malloc (saltlen);
if (!salt)
{
free (bufhex);
free (buf);
grub_util_error ("Out of memory");
}
salthex = malloc (saltlen * 2 + 1);
if (!salthex)
{
free (salt);
free (bufhex);
free (buf);
grub_util_error ("Out of memory");
}
/* Disable echoing. Based on glibc. */
in = fopen ("/dev/tty", "w+c");
if (in == NULL)
{
in = stdin;
out = stderr;
}
else
out = in;
if (tcgetattr (fileno (in), &t) == 0)
{
/* Save the old one. */
s = t;
/* Tricky, tricky. */
t.c_lflag &= ~(ECHO|ISIG);
tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
}
else
tty_changed = 0;
printf ("Enter password: ");
pass1 = NULL;
{
grub_size_t n;
nr = getline (&pass1, &n, stdin);
}
if (nr < 0 || !pass1)
{
free (buf);
free (bufhex);
free (salthex);
free (salt);
/* Restore the original setting. */
if (tty_changed)
(void) tcsetattr (fileno (in), TCSAFLUSH, &s);
grub_util_error ("Failure to read password");
}
if (nr >= 1 && pass1[nr-1] == '\n')
pass1[nr-1] = 0;
printf ("\nReenter password: ");
pass2 = NULL;
{
grub_size_t n;
nr = getline (&pass2, &n, stdin);
}
/* Restore the original setting. */
if (tty_changed)
(void) tcsetattr (fileno (in), TCSAFLUSH, &s);
printf ("\n");
if (nr < 0 || !pass2)
{
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("Failure to read password");
}
if (nr >= 1 && pass2[nr-1] == '\n')
pass2[nr-1] = 0;
if (strcmp (pass1, pass2) != 0)
{
memset (pass1, 0, strlen (pass1));
memset (pass2, 0, strlen (pass2));
free (pass1);
free (pass2);
free (buf);
free (bufhex);
free (salthex);
free (salt);
grub_util_error ("Passwords don't match");
}
memset (pass2, 0, strlen (pass2));
free (pass2);
#if ! defined (__linux__) && ! defined (__FreeBSD__)
printf ("WARNING: your random generator isn't known to be secure\n");
#endif
{
FILE *f;
size_t rd;
f = fopen ("/dev/random", "rb");
if (!f)
{
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
fclose (f);
grub_util_error ("Couldn't retrieve random data for salt");
}
rd = fread (salt, 1, saltlen, f);
if (rd != saltlen)
{
fclose (f);
memset (pass1, 0, strlen (pass1));
free (pass1);
free (buf);
free (bufhex);
free (salthex);
free (salt);
fclose (f);
grub_util_error ("Couldn't retrieve random data for salt");
}
fclose (f);
}
gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
(grub_uint8_t *) pass1, strlen (pass1),
salt, saltlen,
c, buf, buflen);
memset (pass1, 0, strlen (pass1));
free (pass1);
if (gcry_err)
{
memset (buf, 0, buflen);
memset (bufhex, 0, 2 * buflen);
free (buf);
free (bufhex);
memset (salt, 0, saltlen);
memset (salthex, 0, 2 * saltlen);
free (salt);
free (salthex);
grub_util_error ("Cryptographic error number %d", gcry_err);
}
hexify (bufhex, buf, buflen);
hexify (salthex, salt, saltlen);
printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex);
memset (buf, 0, buflen);
memset (bufhex, 0, 2 * buflen);
free (buf);
free (bufhex);
memset (salt, 0, saltlen);
memset (salthex, 0, 2 * saltlen);
free (salt);
free (salthex);
return 0;
}

View file

@ -61,12 +61,30 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
"_gcry_digest_spec_tiger" : 64, "_gcry_digest_spec_tiger" : 64,
"_gcry_digest_spec_whirlpool" : 64} "_gcry_digest_spec_whirlpool" : 64}
cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w")
# rijndael is the only cipher using aliases. So no need for mangling, just
# hardcode it
cryptolist.write ("RIJNDAEL: gcry_rijndael\n");
cryptolist.write ("RIJNDAEL192: gcry_rijndael\n");
cryptolist.write ("RIJNDAEL256: gcry_rijndael\n");
cryptolist.write ("AES128: gcry_rijndael\n");
cryptolist.write ("AES-128: gcry_rijndael\n");
cryptolist.write ("AES-192: gcry_rijndael\n");
cryptolist.write ("AES-256: gcry_rijndael\n");
for cipher_file in cipher_files: for cipher_file in cipher_files:
infile = os.path.join (cipher_dir_in, cipher_file) infile = os.path.join (cipher_dir_in, cipher_file)
outfile = os.path.join (cipher_dir_out, cipher_file) outfile = os.path.join (cipher_dir_out, cipher_file)
if cipher_file == "ChangeLog": if cipher_file == "ChangeLog":
continue continue
chlognew = " * %s" % cipher_file chlognew = " * %s" % cipher_file
if re.match ("(Manifest|Makefile\.am|ac\.c|cipher\.c|hash-common\.c|hmac-tests\.c|md\.c|pubkey\.c)$", cipher_file):
chlog = "%s%s: Removed\n" % (chlog, chlognew)
continue
# Autogenerated files. Not even worth mentionning in ChangeLog
if re.match ("Makefile\.in$", cipher_file):
continue
nch = False nch = False
if re.match (".*\.[ch]$", cipher_file): if re.match (".*\.[ch]$", cipher_file):
isc = re.match (".*\.c$", cipher_file) isc = re.match (".*\.c$", cipher_file)
@ -80,8 +98,21 @@ for cipher_file in cipher_files:
skip = False skip = False
skip2 = False skip2 = False
ismd = False ismd = False
iscryptostart = False
iscomma = False iscomma = False
isglue = False
skip_statement = False
if isc:
modname = cipher_file [0:len(cipher_file) - 2]
if re.match (".*-glue$", modname):
modname = modname.replace ("-glue", "")
isglue = True
modname = "gcry_%s" % modname
for line in f: for line in f:
if skip_statement:
if not re.search (";", line) is None:
skip_statement = False
continue
if skip: if skip:
if line[0] == "}": if line[0] == "}":
skip = False skip = False
@ -90,6 +121,12 @@ for cipher_file in cipher_files:
if not re.search (" *};", line) is None: if not re.search (" *};", line) is None:
skip2 = False skip2 = False
continue continue
if iscryptostart:
s = re.search (" *\"([A-Z0-9_a-z]*)\"", line)
if not s is None:
sg = s.groups()[0]
cryptolist.write (("%s: %s\n") % (sg, modname))
iscryptostart = False
if ismd: if ismd:
if not re.search (" *};", line) is None: if not re.search (" *};", line) is None:
if not mdblocksizes.has_key (mdname): if not mdblocksizes.has_key (mdname):
@ -100,10 +137,22 @@ for cipher_file in cipher_files:
fw.write (" .blocksize = %s\n" % mdblocksizes [mdname]) fw.write (" .blocksize = %s\n" % mdblocksizes [mdname])
ismd = False ismd = False
iscomma = not re.search (",$", line) is None iscomma = not re.search (",$", line) is None
# Used only for selftests.
m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line)
if not m is None:
skip = True
fname = m.groups ()[1]
chmsg = "(%s): Removed." % fname
if nch:
chlognew = "%s\n %s" % (chlognew, chmsg)
else:
chlognew = "%s %s" % (chlognew, chmsg)
nch = True
continue
if hold: if hold:
hold = False hold = False
# We're optimising for size. # We're optimising for size.
if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer)", line) is None: if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info)", line) is None:
skip = True skip = True
fname = re.match ("[a-zA-Z0-9_]*", line).group () fname = re.match ("[a-zA-Z0-9_]*", line).group ()
chmsg = "(%s): Removed." % fname chmsg = "(%s): Removed." % fname
@ -127,16 +176,20 @@ for cipher_file in cipher_files:
continue continue
m = re.match ("gcry_cipher_spec_t", line) m = re.match ("gcry_cipher_spec_t", line)
if isc and not m is None: if isc and not m is None:
assert (not iscryptostart)
ciphername = line [len ("gcry_cipher_spec_t"):].strip () ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group () ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
ciphernames.append (ciphername) ciphernames.append (ciphername)
iscryptostart = True
m = re.match ("gcry_md_spec_t", line) m = re.match ("gcry_md_spec_t", line)
if isc and not m is None: if isc and not m is None:
assert (not ismd) assert (not ismd)
assert (not iscryptostart)
mdname = line [len ("gcry_md_spec_t"):].strip () mdname = line [len ("gcry_md_spec_t"):].strip ()
mdname = re.match("[a-zA-Z0-9_]*",mdname).group () mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
mdnames.append (mdname) mdnames.append (mdname)
ismd = True ismd = True
iscryptostart = True
m = re.match ("static const char \*selftest.*;$", line) m = re.match ("static const char \*selftest.*;$", line)
if not m is None: if not m is None:
fname = line[len ("static const char \*"):] fname = line[len ("static const char \*"):]
@ -148,11 +201,18 @@ for cipher_file in cipher_files:
chlognew = "%s %s" % (chlognew, chmsg) chlognew = "%s %s" % (chlognew, chmsg)
nch = True nch = True
continue continue
m = re.match ("(static const char( |)\*|static gpg_err_code_t|void)$", line) m = re.match ("(static const char( |)\*|static gpg_err_code_t|void|static int|static gcry_err_code_t)$", line)
if not m is None: if not m is None:
hold = True hold = True
holdline = line holdline = line
continue continue
m = re.match ("static int tripledes_set2keys \(.*\);", line)
if not m is None:
continue
m = re.match ("static int tripledes_set2keys \(", line)
if not m is None:
skip_statement = True
continue
m = re.match ("cipher_extra_spec_t", line) m = re.match ("cipher_extra_spec_t", line)
if isc and not m is None: if isc and not m is None:
skip2 = True skip2 = True
@ -179,14 +239,11 @@ for cipher_file in cipher_files:
continue continue
fw.write (line) fw.write (line)
if len (ciphernames) > 0 or len (mdnames) > 0: if len (ciphernames) > 0 or len (mdnames) > 0:
modname = cipher_file [0:len(cipher_file) - 2] if isglue:
if re.match (".*-glue$", modname): modfiles = "lib/libgcrypt-grub/cipher/%s lib/libgcrypt-grub/cipher/%s" \
modfiles = "libgcrypt-grub/cipher/%s libgcrypt-grub/cipher/%s" \
% (cipher_file, cipher_file.replace ("-glue.c", ".c")) % (cipher_file, cipher_file.replace ("-glue.c", ".c"))
modname = modname.replace ("-glue", "")
else: else:
modfiles = "libgcrypt-grub/cipher/%s" % cipher_file modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file
modname = "gcry_%s" % modname
chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
if nch: if nch:
chlognew = "%s\n %s" % (chlognew, chmsg) chlognew = "%s\n %s" % (chlognew, chmsg)
@ -220,7 +277,7 @@ for cipher_file in cipher_files:
conf.write ("pkglib_MODULES += %s.mod\n" % modname) conf.write ("pkglib_MODULES += %s.mod\n" % modname)
conf.write ("%s_mod_SOURCES = %s\n" %\ conf.write ("%s_mod_SOURCES = %s\n" %\
(modname, modfiles)) (modname, modfiles))
conf.write ("%s_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-missing-field-initializers -Wno-error\n" % modname) conf.write ("%s_mod_CFLAGS = $(COMMON_CFLAGS) -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap\n" % modname)
conf.write ("%s_mod_LDFLAGS = $(COMMON_LDFLAGS)\n\n" % modname) conf.write ("%s_mod_LDFLAGS = $(COMMON_LDFLAGS)\n\n" % modname)
elif isc and cipher_file != "camellia.c": elif isc and cipher_file != "camellia.c":
print ("WARNING: C file isn't a module: %s" % cipher_file) print ("WARNING: C file isn't a module: %s" % cipher_file)
@ -229,26 +286,22 @@ for cipher_file in cipher_files:
if nch: if nch:
chlog = "%s%s\n" % (chlog, chlognew) chlog = "%s%s\n" % (chlog, chlognew)
continue continue
if re.match ("(Manifest|Makefile\.am)$", cipher_file):
chlog = "%s%sRemoved\n" % (chlog, chlognew)
continue
# Autogenerated files. Not even worth mentionning in ChangeLog
if re.match ("Makefile\.in$", cipher_file):
chlog = "%s%sRemoved\n" % (chlog, chlognew)
continue
chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew) chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
print ("WARNING: unknown file %s" % cipher_file) print ("WARNING: unknown file %s" % cipher_file)
cryptolist.close ()
chlog = "%s * crypto.lst: New file.\n" % chlog
outfile = os.path.join (cipher_dir_out, "types.h") outfile = os.path.join (cipher_dir_out, "types.h")
fw=open (outfile, "w") fw=open (outfile, "w")
fw.write ("#include <grub/types.h>\n") fw.write ("#include <grub/types.h>\n")
fw.write ("#include <grub/cipher_wrap.h>\n") fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * types.h: New file.\n" % chlog chlog = "%s * types.h: New file.\n" % chlog
fw.close () fw.close ()
outfile = os.path.join (cipher_dir_out, "memory.h") outfile = os.path.join (cipher_dir_out, "memory.h")
fw=open (outfile, "w") fw=open (outfile, "w")
fw.write ("#include <grub/cipher_wrap.h>\n") fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * memory.h: New file.\n" % chlog chlog = "%s * memory.h: New file.\n" % chlog
fw.close () fw.close ()
@ -256,13 +309,13 @@ fw.close ()
outfile = os.path.join (cipher_dir_out, "cipher.h") outfile = os.path.join (cipher_dir_out, "cipher.h")
fw=open (outfile, "w") fw=open (outfile, "w")
fw.write ("#include <grub/crypto.h>\n") fw.write ("#include <grub/crypto.h>\n")
fw.write ("#include <grub/cipher_wrap.h>\n") fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * cipher.h: Likewise.\n" % chlog chlog = "%s * cipher.h: Likewise.\n" % chlog
fw.close () fw.close ()
outfile = os.path.join (cipher_dir_out, "g10lib.h") outfile = os.path.join (cipher_dir_out, "g10lib.h")
fw=open (outfile, "w") fw=open (outfile, "w")
fw.write ("#include <grub/cipher_wrap.h>\n") fw.write ("#include <cipher_wrap.h>\n")
chlog = "%s * g10lib.h: Likewise.\n" % chlog chlog = "%s * g10lib.h: Likewise.\n" % chlog
fw.close () fw.close ()