b47efe305a
Add `linux.mod' and `multiboot.mod' so linux and multiboot kernels can be loaded from normal mode. * conf/i386-pc.rmk (pkgdata_MODULES): Add `linux.mod' and `multiboot.mod'. (linux_mod_SOURCES, linux_mod_CFLAGS, multiboot_mod_SOURCES) (multiboot_mod_CFLAGS): New variables. * loader/i386/pc/linux_normal.c: New file. * loader/i386/pc/multiboot_normal.c: Likewise. * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Don't use the attribute `unused'. * fs/ext2.c (grub_ext2_iterate_dir): Fix typos in inode type. Use `fdiro' to read the mode information from instead of `diro'. * fs/fshelp.c (grub_fshelp_find_file): Set type to foundtype after looking up a symlink. * include/grub/normal.h (GRUB_COMMAND_FLAG_NO_ARG_PARSE): New macro. * normal/command.c (grub_command_execute): Don't parse the arguments when `GRUB_COMMAND_FLAG_NO_ARG_PARSE' is set in the flags of the command. * normal/menu.c (grub_menu_run): Fix typo.
332 lines
7.7 KiB
C
332 lines
7.7 KiB
C
/*
|
|
* GRUB -- GRand Unified Bootloader
|
|
* Copyright (C) 2003 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 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <grub/normal.h>
|
|
#include <grub/misc.h>
|
|
#include <grub/mm.h>
|
|
#include <grub/err.h>
|
|
#include <grub/term.h>
|
|
#include <grub/env.h>
|
|
#include <grub/dl.h>
|
|
|
|
static grub_command_t grub_command_list;
|
|
|
|
void
|
|
grub_register_command (const char *name,
|
|
grub_err_t (*func) (struct grub_arg_list *state,
|
|
int argc, char **args),
|
|
unsigned flags,
|
|
const char *summary,
|
|
const char *description,
|
|
const struct grub_arg_option *options)
|
|
{
|
|
grub_command_t cmd, *p;
|
|
|
|
cmd = (grub_command_t) grub_malloc (sizeof (*cmd));
|
|
if (! cmd)
|
|
return;
|
|
|
|
cmd->name = name;
|
|
cmd->func = func;
|
|
cmd->flags = flags;
|
|
cmd->summary = summary;
|
|
cmd->description = description;
|
|
cmd->options = options;
|
|
|
|
/* Keep the list sorted for simplicity. */
|
|
p = &grub_command_list;
|
|
while (*p)
|
|
{
|
|
if (grub_strcmp ((*p)->name, name) > 0)
|
|
break;
|
|
|
|
p = &((*p)->next);
|
|
}
|
|
|
|
cmd->next = *p;
|
|
*p = cmd;
|
|
}
|
|
|
|
void
|
|
grub_unregister_command (const char *name)
|
|
{
|
|
grub_command_t *p, q;
|
|
|
|
for (p = &grub_command_list, q = *p; q; p = &(q->next), q = q->next)
|
|
if (grub_strcmp (name, q->name) == 0)
|
|
{
|
|
*p = q->next;
|
|
grub_free (q);
|
|
break;
|
|
}
|
|
}
|
|
|
|
grub_command_t
|
|
grub_command_find (char *cmdline)
|
|
{
|
|
char *first_space;
|
|
grub_command_t cmd;
|
|
|
|
first_space = grub_strchr (cmdline, ' ');
|
|
if (first_space)
|
|
*first_space = '\0';
|
|
|
|
for (cmd = grub_command_list; cmd; cmd = cmd->next)
|
|
if (grub_strcmp (cmdline, cmd->name) == 0)
|
|
break;
|
|
|
|
if (! cmd)
|
|
grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%s'", cmdline);
|
|
|
|
if (first_space)
|
|
*first_space = ' ';
|
|
|
|
return cmd;
|
|
}
|
|
|
|
int
|
|
grub_iterate_commands (int (*iterate) (grub_command_t))
|
|
{
|
|
grub_command_t cmd;
|
|
for (cmd = grub_command_list; cmd; cmd = cmd->next)
|
|
iterate (cmd);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
grub_command_execute (char *cmdline)
|
|
{
|
|
auto grub_err_t cmdline_get (char **s);
|
|
grub_err_t cmdline_get (char **s)
|
|
{
|
|
*s = grub_malloc (GRUB_MAX_CMDLINE);
|
|
*s[0] = '\0';
|
|
return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
|
|
}
|
|
|
|
grub_command_t cmd;
|
|
grub_err_t ret = 0;
|
|
char *pager;
|
|
int num;
|
|
char **args;
|
|
struct grub_arg_list *state;
|
|
struct grub_arg_option *parser;
|
|
int maxargs = 0;
|
|
char **arglist;
|
|
int numargs;
|
|
|
|
if (grub_split_cmdline (cmdline, cmdline_get, &num, &args))
|
|
return 0;
|
|
|
|
/* In case of an assignment set the environment accordingly instead
|
|
of calling a function. */
|
|
if (num == 0 && grub_strchr (args[0], '='))
|
|
{
|
|
char *val = grub_strchr (args[0], '=');
|
|
val[0] = 0;
|
|
grub_env_set (args[0], val + 1);
|
|
val[0] = '=';
|
|
return 0;
|
|
}
|
|
|
|
cmd = grub_command_find (args[0]);
|
|
if (! cmd)
|
|
return -1;
|
|
|
|
/* Enable the pager if the environment pager is set to 1. */
|
|
pager = grub_env_get ("pager");
|
|
if (pager && (! grub_strcmp (pager, "1")))
|
|
grub_set_more (1);
|
|
|
|
parser = (struct grub_arg_option *) cmd->options;
|
|
while (parser && (parser++)->doc)
|
|
maxargs++;
|
|
|
|
state = grub_malloc (sizeof (struct grub_arg_list) * maxargs);
|
|
grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
|
|
if (! (cmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
|
|
{
|
|
if (grub_arg_parse (cmd, num, &args[1], state, &arglist, &numargs))
|
|
ret = (cmd->func) (state, numargs, arglist);
|
|
}
|
|
else
|
|
ret = (cmd->func) (state, num, &args[1]);
|
|
|
|
grub_free (state);
|
|
|
|
if (pager && (! grub_strcmp (pager, "1")))
|
|
grub_set_more (0);
|
|
|
|
grub_free (args);
|
|
return ret;
|
|
}
|
|
|
|
static grub_err_t
|
|
rescue_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc __attribute__ ((unused)),
|
|
char **args __attribute__ ((unused)))
|
|
{
|
|
grub_longjmp (grub_exit_env, 0);
|
|
|
|
/* Never reach here. */
|
|
return 0;
|
|
}
|
|
|
|
|
|
static grub_err_t
|
|
set_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc, char **args)
|
|
{
|
|
char *var;
|
|
char *val;
|
|
|
|
auto int print_env (struct grub_env_var *env);
|
|
int print_env (struct grub_env_var *env)
|
|
{
|
|
grub_printf ("%s=%s\n", env->name, env->value);
|
|
return 0;
|
|
}
|
|
|
|
if (! argc)
|
|
{
|
|
grub_env_iterate (print_env);
|
|
return 0;
|
|
}
|
|
|
|
var = args[0];
|
|
val = grub_strchr (var, '=');
|
|
if (! val)
|
|
{
|
|
grub_error (GRUB_ERR_BAD_ARGUMENT, "not an assignment");
|
|
return grub_errno;
|
|
}
|
|
|
|
val[0] = 0;
|
|
grub_env_set (var, val + 1);
|
|
val[0] = '=';
|
|
return 0;
|
|
}
|
|
|
|
static grub_err_t
|
|
unset_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc, char **args)
|
|
{
|
|
if (argc < 1)
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
|
"no environment variable specified");
|
|
|
|
grub_env_unset (args[0]);
|
|
return 0;
|
|
}
|
|
|
|
static grub_err_t
|
|
insmod_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc, char **args)
|
|
{
|
|
char *p;
|
|
grub_dl_t mod;
|
|
|
|
if (argc == 0)
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
|
|
|
p = grub_strchr (args[0], '/');
|
|
if (! p)
|
|
mod = grub_dl_load (args[0]);
|
|
else
|
|
mod = grub_dl_load_file (args[0]);
|
|
|
|
if (mod)
|
|
grub_dl_ref (mod);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static grub_err_t
|
|
rmmod_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc, char **args)
|
|
{
|
|
grub_dl_t mod;
|
|
|
|
if (argc == 0)
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
|
|
|
|
mod = grub_dl_get (args[0]);
|
|
if (! mod)
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module");
|
|
|
|
if (! grub_dl_unref (mod))
|
|
grub_dl_unload (mod);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static grub_err_t
|
|
lsmod_command (struct grub_arg_list *state __attribute__ ((unused)),
|
|
int argc __attribute__ ((unused)),
|
|
char **args __attribute__ ((unused)))
|
|
{
|
|
auto int print_module (grub_dl_t mod);
|
|
|
|
int print_module (grub_dl_t mod)
|
|
{
|
|
grub_dl_dep_t dep;
|
|
|
|
grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count);
|
|
for (dep = mod->dep; dep; dep = dep->next)
|
|
{
|
|
if (dep != mod->dep)
|
|
grub_putchar (',');
|
|
|
|
grub_printf ("%s", dep->mod->name);
|
|
}
|
|
grub_putchar ('\n');
|
|
grub_refresh ();
|
|
|
|
return 0;
|
|
}
|
|
|
|
grub_printf ("Name\tRef Count\tDependencies\n");
|
|
grub_dl_iterate (print_module);
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
grub_command_init (void)
|
|
{
|
|
/* This is a special command, because this never be called actually. */
|
|
grub_register_command ("title", 0, GRUB_COMMAND_FLAG_TITLE, 0, 0, 0);
|
|
|
|
grub_register_command ("rescue", rescue_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"rescue", "Enter into the rescue mode.", 0);
|
|
|
|
grub_register_command ("set", set_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"unset ENVVAR", "Set an environment variable.", 0);
|
|
|
|
grub_register_command ("unset", unset_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"set [ENVVAR=VALUE]", "Remove an environment variable.", 0);
|
|
|
|
grub_register_command ("insmod", insmod_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"insmod MODULE|FILE", "Insert a module.", 0);
|
|
|
|
grub_register_command ("rmmod", rmmod_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"rmmod MODULE", "Remove a module.", 0);
|
|
|
|
grub_register_command ("lsmod", lsmod_command, GRUB_COMMAND_FLAG_BOTH,
|
|
"lsmod", "Show loaded modules.", 0);
|
|
}
|