Home | History | Annotate | Download | only in grub
      1 /* main.c - experimental GRUB stage2 that runs under Unix */
      2 /*
      3  *  GRUB  --  GRand Unified Bootloader
      4  *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
      5  *
      6  *  This program is free software; you can redistribute it and/or modify
      7  *  it under the terms of the GNU General Public License as published by
      8  *  the Free Software Foundation; either version 2 of the License, or
      9  *  (at your option) any later version.
     10  *
     11  *  This program is distributed in the hope that it will be useful,
     12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  *  GNU General Public License for more details.
     15  *
     16  *  You should have received a copy of the GNU General Public License
     17  *  along with this program; if not, write to the Free Software
     18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     19  */
     20 
     21 /* Simulator entry point. */
     22 int grub_stage2 (void);
     23 
     24 #include <stdio.h>
     25 #include <getopt.h>
     26 #include <unistd.h>
     27 #include <string.h>
     28 #include <stdlib.h>
     29 #include <limits.h>
     30 #include <setjmp.h>
     31 
     32 #define WITHOUT_LIBC_STUBS 1
     33 #include <shared.h>
     34 #include <term.h>
     35 
     36 char *program_name = 0;
     37 int use_config_file = 1;
     38 int use_preset_menu = 0;
     39 #ifdef HAVE_LIBCURSES
     40 int use_curses = 1;
     41 #else
     42 int use_curses = 0;
     43 #endif
     44 int verbose = 0;
     45 int read_only = 0;
     46 int floppy_disks = 1;
     47 char *device_map_file = 0;
     48 static int default_boot_drive;
     49 static int default_install_partition;
     50 static char *default_config_file;
     51 
     52 #define OPT_HELP		-2
     53 #define OPT_VERSION		-3
     54 #define OPT_HOLD		-4
     55 #define OPT_CONFIG_FILE		-5
     56 #define OPT_INSTALL_PARTITION	-6
     57 #define OPT_BOOT_DRIVE		-7
     58 #define OPT_NO_CONFIG_FILE	-8
     59 #define OPT_NO_CURSES		-9
     60 #define OPT_BATCH		-10
     61 #define OPT_VERBOSE		-11
     62 #define OPT_READ_ONLY		-12
     63 #define OPT_PROBE_SECOND_FLOPPY	-13
     64 #define OPT_NO_FLOPPY		-14
     65 #define OPT_DEVICE_MAP		-15
     66 #define OPT_PRESET_MENU		-16
     67 #define OPT_NO_PAGER		-17
     68 #define OPTSTRING ""
     69 
     70 static struct option longopts[] =
     71 {
     72   {"batch", no_argument, 0, OPT_BATCH},
     73   {"boot-drive", required_argument, 0, OPT_BOOT_DRIVE},
     74   {"config-file", required_argument, 0, OPT_CONFIG_FILE},
     75   {"device-map", required_argument, 0, OPT_DEVICE_MAP},
     76   {"help", no_argument, 0, OPT_HELP},
     77   {"hold", optional_argument, 0, OPT_HOLD},
     78   {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION},
     79   {"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE},
     80   {"no-curses", no_argument, 0, OPT_NO_CURSES},
     81   {"no-floppy", no_argument, 0, OPT_NO_FLOPPY},
     82   {"no-pager", no_argument, 0, OPT_NO_PAGER},
     83   {"preset-menu", no_argument, 0, OPT_PRESET_MENU},
     84   {"probe-second-floppy", no_argument, 0, OPT_PROBE_SECOND_FLOPPY},
     85   {"read-only", no_argument, 0, OPT_READ_ONLY},
     86   {"verbose", no_argument, 0, OPT_VERBOSE},
     87   {"version", no_argument, 0, OPT_VERSION},
     88   {0},
     89 };
     90 
     91 
     92 static void
     93 usage (int status)
     94 {
     95   if (status)
     96     fprintf (stderr, "Try ``grub --help'' for more information.\n");
     97   else
     98     printf ("\
     99 Usage: grub [OPTION]...\n\
    100 \n\
    101 Enter the GRand Unified Bootloader command shell.\n\
    102 \n\
    103     --batch                  turn on batch mode for non-interactive use\n\
    104     --boot-drive=DRIVE       specify stage2 boot_drive [default=0x%x]\n\
    105     --config-file=FILE       specify stage2 config_file [default=%s]\n\
    106     --device-map=FILE        use the device map file FILE\n\
    107     --help                   display this message and exit\n\
    108     --hold                   wait until a debugger will attach\n\
    109     --install-partition=PAR  specify stage2 install_partition [default=0x%x]\n\
    110     --no-config-file         do not use the config file\n\
    111     --no-curses              do not use curses\n\
    112     --no-floppy              do not probe any floppy drive\n\
    113     --no-pager               do not use internal pager\n\
    114     --preset-menu            use the preset menu\n\
    115     --probe-second-floppy    probe the second floppy drive\n\
    116     --read-only              do not write anything to devices\n\
    117     --verbose                print verbose messages\n\
    118     --version                print version information and exit\n\
    119 \n\
    120 Report bugs to <bug-grub (at) gnu.org>.\n\
    121 ",
    122 	    default_boot_drive, default_config_file,
    123 	    default_install_partition);
    124 
    125   exit (status);
    126 }
    127 
    128 
    129 int
    130 main (int argc, char **argv)
    131 {
    132   int c;
    133   int hold = 0;
    134 
    135   /* First of all, call sync so that all in-core data is scheduled to be
    136      actually written to disks. This is very important because GRUB does
    137      not use ordinary stdio interface but raw devices.  */
    138   sync ();
    139 
    140   program_name = argv[0];
    141   default_boot_drive = boot_drive;
    142   default_install_partition = install_partition;
    143   if (config_file)
    144     default_config_file = config_file;
    145   else
    146     default_config_file = "NONE";
    147 
    148   /* Parse command-line options. */
    149   do
    150     {
    151       c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
    152       switch (c)
    153 	{
    154 	case EOF:
    155 	  /* Fall through the bottom of the loop. */
    156 	  break;
    157 
    158 	case OPT_HELP:
    159 	  usage (0);
    160 	  break;
    161 
    162 	case OPT_VERSION:
    163 	  printf ("grub (GNU GRUB " VERSION ")\n");
    164 	  exit (0);
    165 	  break;
    166 
    167 	case OPT_HOLD:
    168 	  if (! optarg)
    169 	    hold = -1;
    170 	  else
    171 	    hold = atoi (optarg);
    172 	  break;
    173 
    174 	case OPT_CONFIG_FILE:
    175 	  strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
    176 	  config_file[127] = '\0';
    177 	  break;
    178 
    179 	case OPT_INSTALL_PARTITION:
    180 	  install_partition = strtoul (optarg, 0, 0);
    181 	  if (install_partition == ULONG_MAX)
    182 	    {
    183 	      perror ("strtoul");
    184 	      exit (1);
    185 	    }
    186 	  break;
    187 
    188 	case OPT_BOOT_DRIVE:
    189 	  boot_drive = strtoul (optarg, 0, 0);
    190 	  if (boot_drive == ULONG_MAX)
    191 	    {
    192 	      perror ("strtoul");
    193 	      exit (1);
    194 	    }
    195 	  break;
    196 
    197 	case OPT_NO_CONFIG_FILE:
    198 	  use_config_file = 0;
    199 	  break;
    200 
    201 	case OPT_NO_CURSES:
    202 	  use_curses = 0;
    203 	  break;
    204 
    205 	case OPT_NO_PAGER:
    206 	  use_pager = 0;
    207 	  break;
    208 
    209 	case OPT_BATCH:
    210 	  /* This is the same as "--no-config-file --no-curses --no-pager".  */
    211 	  use_config_file = 0;
    212 	  use_curses = 0;
    213 	  use_pager = 0;
    214 	  break;
    215 
    216 	case OPT_READ_ONLY:
    217 	  read_only = 1;
    218 	  break;
    219 
    220 	case OPT_VERBOSE:
    221 	  verbose = 1;
    222 	  break;
    223 
    224 	case OPT_NO_FLOPPY:
    225 	  floppy_disks = 0;
    226 	  break;
    227 
    228 	case OPT_PROBE_SECOND_FLOPPY:
    229 	  floppy_disks = 2;
    230 	  break;
    231 
    232 	case OPT_DEVICE_MAP:
    233 	  device_map_file = strdup (optarg);
    234 	  break;
    235 
    236 	case OPT_PRESET_MENU:
    237 	  use_preset_menu = 1;
    238 	  break;
    239 
    240 	default:
    241 	  usage (1);
    242 	}
    243     }
    244   while (c != EOF);
    245 
    246   /* Wait until the HOLD variable is cleared by an attached debugger. */
    247   if (hold && verbose)
    248     printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
    249 	    program_name, (int) getpid ());
    250   while (hold)
    251     {
    252       if (hold > 0)
    253 	hold--;
    254 
    255       sleep (1);
    256     }
    257 
    258   /* If we don't have curses (!HAVE_LIBCURSES or --no-curses or
    259      --batch) put terminal to dumb for better handling of line i/o */
    260   if (! use_curses)
    261     current_term->flags = TERM_NO_EDIT | TERM_DUMB;
    262 
    263   /* Transfer control to the stage2 simulator. */
    264   exit (grub_stage2 ());
    265 }
    266