blob: dfe847e98a13d74d0af208a768608c16c89a7089 [file] [log] [blame] [raw]
/* main.c - experimental GRUB stage2 that runs under Unix */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002 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.
*/
/* Simulator entry point. */
int grub_stage2 (void);
#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <setjmp.h>
#define WITHOUT_LIBC_STUBS 1
#include <shared.h>
#include <term.h>
char *program_name = 0;
int use_config_file = 1;
int use_preset_menu = 0;
#ifdef HAVE_LIBCURSES
int use_curses = 1;
#else
int use_curses = 0;
#endif
int verbose = 0;
int read_only = 0;
int floppy_disks = 1;
char *device_map_file = 0;
static int default_boot_drive;
static int default_install_partition;
static char *default_config_file;
#define OPT_HELP -2
#define OPT_VERSION -3
#define OPT_HOLD -4
#define OPT_CONFIG_FILE -5
#define OPT_INSTALL_PARTITION -6
#define OPT_BOOT_DRIVE -7
#define OPT_NO_CONFIG_FILE -8
#define OPT_NO_CURSES -9
#define OPT_BATCH -10
#define OPT_VERBOSE -11
#define OPT_READ_ONLY -12
#define OPT_PROBE_SECOND_FLOPPY -13
#define OPT_NO_FLOPPY -14
#define OPT_DEVICE_MAP -15
#define OPT_PRESET_MENU -16
#define OPT_NO_PAGER -17
#define OPTSTRING ""
static struct option longopts[] =
{
{"batch", no_argument, 0, OPT_BATCH},
{"boot-drive", required_argument, 0, OPT_BOOT_DRIVE},
{"config-file", required_argument, 0, OPT_CONFIG_FILE},
{"device-map", required_argument, 0, OPT_DEVICE_MAP},
{"help", no_argument, 0, OPT_HELP},
{"hold", optional_argument, 0, OPT_HOLD},
{"install-partition", required_argument, 0, OPT_INSTALL_PARTITION},
{"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE},
{"no-curses", no_argument, 0, OPT_NO_CURSES},
{"no-floppy", no_argument, 0, OPT_NO_FLOPPY},
{"no-pager", no_argument, 0, OPT_NO_PAGER},
{"preset-menu", no_argument, 0, OPT_PRESET_MENU},
{"probe-second-floppy", no_argument, 0, OPT_PROBE_SECOND_FLOPPY},
{"read-only", no_argument, 0, OPT_READ_ONLY},
{"verbose", no_argument, 0, OPT_VERBOSE},
{"version", no_argument, 0, OPT_VERSION},
{0},
};
static void
usage (int status)
{
if (status)
fprintf (stderr, "Try ``grub --help'' for more information.\n");
else
printf ("\
Usage: grub [OPTION]...\n\
\n\
Enter the GRand Unified Bootloader command shell.\n\
\n\
--batch turn on batch mode for non-interactive use\n\
--boot-drive=DRIVE specify stage2 boot_drive [default=0x%x]\n\
--config-file=FILE specify stage2 config_file [default=%s]\n\
--device-map=FILE use the device map file FILE\n\
--help display this message and exit\n\
--hold wait until a debugger will attach\n\
--install-partition=PAR specify stage2 install_partition [default=0x%x]\n\
--no-config-file do not use the config file\n\
--no-curses do not use curses\n\
--no-floppy do not probe any floppy drive\n\
--no-pager do not use internal pager\n\
--preset-menu use the preset menu\n\
--probe-second-floppy probe the second floppy drive\n\
--read-only do not write anything to devices\n\
--verbose print verbose messages\n\
--version print version information and exit\n\
\n\
Report bugs to <bug-grub@gnu.org>.\n\
",
default_boot_drive, default_config_file,
default_install_partition);
exit (status);
}
int
main (int argc, char **argv)
{
int c;
int hold = 0;
/* First of all, call sync so that all in-core data is scheduled to be
actually written to disks. This is very important because GRUB does
not use ordinary stdio interface but raw devices. */
sync ();
program_name = argv[0];
default_boot_drive = boot_drive;
default_install_partition = install_partition;
if (config_file)
default_config_file = config_file;
else
default_config_file = "NONE";
/* Parse command-line options. */
do
{
c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
switch (c)
{
case EOF:
/* Fall through the bottom of the loop. */
break;
case OPT_HELP:
usage (0);
break;
case OPT_VERSION:
printf ("grub (GNU GRUB " VERSION ")\n");
exit (0);
break;
case OPT_HOLD:
if (! optarg)
hold = -1;
else
hold = atoi (optarg);
break;
case OPT_CONFIG_FILE:
strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
config_file[127] = '\0';
break;
case OPT_INSTALL_PARTITION:
install_partition = strtoul (optarg, 0, 0);
if (install_partition == ULONG_MAX)
{
perror ("strtoul");
exit (1);
}
break;
case OPT_BOOT_DRIVE:
boot_drive = strtoul (optarg, 0, 0);
if (boot_drive == ULONG_MAX)
{
perror ("strtoul");
exit (1);
}
break;
case OPT_NO_CONFIG_FILE:
use_config_file = 0;
break;
case OPT_NO_CURSES:
use_curses = 0;
break;
case OPT_NO_PAGER:
use_pager = 0;
break;
case OPT_BATCH:
/* This is the same as "--no-config-file --no-curses --no-pager". */
use_config_file = 0;
use_curses = 0;
use_pager = 0;
break;
case OPT_READ_ONLY:
read_only = 1;
break;
case OPT_VERBOSE:
verbose = 1;
break;
case OPT_NO_FLOPPY:
floppy_disks = 0;
break;
case OPT_PROBE_SECOND_FLOPPY:
floppy_disks = 2;
break;
case OPT_DEVICE_MAP:
device_map_file = strdup (optarg);
break;
case OPT_PRESET_MENU:
use_preset_menu = 1;
break;
default:
usage (1);
}
}
while (c != EOF);
/* Wait until the HOLD variable is cleared by an attached debugger. */
if (hold && verbose)
printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
program_name, (int) getpid ());
while (hold)
{
if (hold > 0)
hold--;
sleep (1);
}
/* If we don't have curses (!HAVE_LIBCURSES or --no-curses or
--batch) put terminal to dumb for better handling of line i/o */
if (! use_curses)
current_term->flags = TERM_NO_EDIT | TERM_DUMB;
/* Transfer control to the stage2 simulator. */
exit (grub_stage2 ());
}