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
usage(int status)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@gnu.org>.\n\
121 ",
122 default_boot_drive, default_config_file,
123 default_install_partition);
124
125 exit (status);
126 }
127
128
129 int
main(int argc,char ** argv)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