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