17c478bd9Sstevel@tonic-gate /* main.c - experimental GRUB stage2 that runs under Unix */
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate * GRUB -- GRand Unified Bootloader
47c478bd9Sstevel@tonic-gate * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
57c478bd9Sstevel@tonic-gate *
67c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or modify
77c478bd9Sstevel@tonic-gate * it under the terms of the GNU General Public License as published by
87c478bd9Sstevel@tonic-gate * the Free Software Foundation; either version 2 of the License, or
97c478bd9Sstevel@tonic-gate * (at your option) any later version.
107c478bd9Sstevel@tonic-gate *
117c478bd9Sstevel@tonic-gate * This program is distributed in the hope that it will be useful,
127c478bd9Sstevel@tonic-gate * but WITHOUT ANY WARRANTY; without even the implied warranty of
137c478bd9Sstevel@tonic-gate * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
147c478bd9Sstevel@tonic-gate * GNU General Public License for more details.
157c478bd9Sstevel@tonic-gate *
167c478bd9Sstevel@tonic-gate * You should have received a copy of the GNU General Public License
177c478bd9Sstevel@tonic-gate * along with this program; if not, write to the Free Software
187c478bd9Sstevel@tonic-gate * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
197c478bd9Sstevel@tonic-gate */
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate /* Simulator entry point. */
227c478bd9Sstevel@tonic-gate int grub_stage2 (void);
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate #include <stdio.h>
257c478bd9Sstevel@tonic-gate #include <getopt.h>
267c478bd9Sstevel@tonic-gate #include <unistd.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <limits.h>
307c478bd9Sstevel@tonic-gate #include <setjmp.h>
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #define WITHOUT_LIBC_STUBS 1
337c478bd9Sstevel@tonic-gate #include <shared.h>
347c478bd9Sstevel@tonic-gate #include <term.h>
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate char *program_name = 0;
377c478bd9Sstevel@tonic-gate int use_config_file = 1;
387c478bd9Sstevel@tonic-gate int use_preset_menu = 0;
397c478bd9Sstevel@tonic-gate #ifdef HAVE_LIBCURSES
407c478bd9Sstevel@tonic-gate int use_curses = 1;
417c478bd9Sstevel@tonic-gate #else
427c478bd9Sstevel@tonic-gate int use_curses = 0;
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate int verbose = 0;
457c478bd9Sstevel@tonic-gate int read_only = 0;
467c478bd9Sstevel@tonic-gate int floppy_disks = 1;
477c478bd9Sstevel@tonic-gate char *device_map_file = 0;
487c478bd9Sstevel@tonic-gate static int default_boot_drive;
497c478bd9Sstevel@tonic-gate static int default_install_partition;
507c478bd9Sstevel@tonic-gate static char *default_config_file;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #define OPT_HELP -2
537c478bd9Sstevel@tonic-gate #define OPT_VERSION -3
547c478bd9Sstevel@tonic-gate #define OPT_HOLD -4
557c478bd9Sstevel@tonic-gate #define OPT_CONFIG_FILE -5
567c478bd9Sstevel@tonic-gate #define OPT_INSTALL_PARTITION -6
577c478bd9Sstevel@tonic-gate #define OPT_BOOT_DRIVE -7
587c478bd9Sstevel@tonic-gate #define OPT_NO_CONFIG_FILE -8
597c478bd9Sstevel@tonic-gate #define OPT_NO_CURSES -9
607c478bd9Sstevel@tonic-gate #define OPT_BATCH -10
617c478bd9Sstevel@tonic-gate #define OPT_VERBOSE -11
627c478bd9Sstevel@tonic-gate #define OPT_READ_ONLY -12
637c478bd9Sstevel@tonic-gate #define OPT_PROBE_SECOND_FLOPPY -13
647c478bd9Sstevel@tonic-gate #define OPT_NO_FLOPPY -14
657c478bd9Sstevel@tonic-gate #define OPT_DEVICE_MAP -15
667c478bd9Sstevel@tonic-gate #define OPT_PRESET_MENU -16
677c478bd9Sstevel@tonic-gate #define OPT_NO_PAGER -17
687c478bd9Sstevel@tonic-gate #define OPTSTRING ""
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate static struct option longopts[] =
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate {"batch", no_argument, 0, OPT_BATCH},
737c478bd9Sstevel@tonic-gate {"boot-drive", required_argument, 0, OPT_BOOT_DRIVE},
747c478bd9Sstevel@tonic-gate {"config-file", required_argument, 0, OPT_CONFIG_FILE},
757c478bd9Sstevel@tonic-gate {"device-map", required_argument, 0, OPT_DEVICE_MAP},
767c478bd9Sstevel@tonic-gate {"help", no_argument, 0, OPT_HELP},
777c478bd9Sstevel@tonic-gate {"hold", optional_argument, 0, OPT_HOLD},
787c478bd9Sstevel@tonic-gate {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION},
797c478bd9Sstevel@tonic-gate {"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE},
807c478bd9Sstevel@tonic-gate {"no-curses", no_argument, 0, OPT_NO_CURSES},
817c478bd9Sstevel@tonic-gate {"no-floppy", no_argument, 0, OPT_NO_FLOPPY},
827c478bd9Sstevel@tonic-gate {"no-pager", no_argument, 0, OPT_NO_PAGER},
837c478bd9Sstevel@tonic-gate {"preset-menu", no_argument, 0, OPT_PRESET_MENU},
847c478bd9Sstevel@tonic-gate {"probe-second-floppy", no_argument, 0, OPT_PROBE_SECOND_FLOPPY},
857c478bd9Sstevel@tonic-gate {"read-only", no_argument, 0, OPT_READ_ONLY},
867c478bd9Sstevel@tonic-gate {"verbose", no_argument, 0, OPT_VERBOSE},
877c478bd9Sstevel@tonic-gate {"version", no_argument, 0, OPT_VERSION},
887c478bd9Sstevel@tonic-gate {0},
897c478bd9Sstevel@tonic-gate };
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static void
usage(int status)937c478bd9Sstevel@tonic-gate usage (int status)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate if (status)
967c478bd9Sstevel@tonic-gate fprintf (stderr, "Try ``grub --help'' for more information.\n");
977c478bd9Sstevel@tonic-gate else
987c478bd9Sstevel@tonic-gate printf ("\
997c478bd9Sstevel@tonic-gate Usage: grub [OPTION]...\n\
1007c478bd9Sstevel@tonic-gate \n\
1017c478bd9Sstevel@tonic-gate Enter the GRand Unified Bootloader command shell.\n\
1027c478bd9Sstevel@tonic-gate \n\
1037c478bd9Sstevel@tonic-gate --batch turn on batch mode for non-interactive use\n\
1047c478bd9Sstevel@tonic-gate --boot-drive=DRIVE specify stage2 boot_drive [default=0x%x]\n\
1057c478bd9Sstevel@tonic-gate --config-file=FILE specify stage2 config_file [default=%s]\n\
1067c478bd9Sstevel@tonic-gate --device-map=FILE use the device map file FILE\n\
1077c478bd9Sstevel@tonic-gate --help display this message and exit\n\
1087c478bd9Sstevel@tonic-gate --hold wait until a debugger will attach\n\
1097c478bd9Sstevel@tonic-gate --install-partition=PAR specify stage2 install_partition [default=0x%x]\n\
1107c478bd9Sstevel@tonic-gate --no-config-file do not use the config file\n\
1117c478bd9Sstevel@tonic-gate --no-curses do not use curses\n\
1127c478bd9Sstevel@tonic-gate --no-floppy do not probe any floppy drive\n\
1137c478bd9Sstevel@tonic-gate --no-pager do not use internal pager\n\
1147c478bd9Sstevel@tonic-gate --preset-menu use the preset menu\n\
1157c478bd9Sstevel@tonic-gate --probe-second-floppy probe the second floppy drive\n\
1167c478bd9Sstevel@tonic-gate --read-only do not write anything to devices\n\
1177c478bd9Sstevel@tonic-gate --verbose print verbose messages\n\
1187c478bd9Sstevel@tonic-gate --version print version information and exit\n\
1197c478bd9Sstevel@tonic-gate \n\
1207c478bd9Sstevel@tonic-gate Report bugs to <bug-grub@gnu.org>.\n\
1217c478bd9Sstevel@tonic-gate ",
1227c478bd9Sstevel@tonic-gate default_boot_drive, default_config_file,
1237c478bd9Sstevel@tonic-gate default_install_partition);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate exit (status);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)1307c478bd9Sstevel@tonic-gate main (int argc, char **argv)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate int c;
1337c478bd9Sstevel@tonic-gate int hold = 0;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate /* First of all, call sync so that all in-core data is scheduled to be
1367c478bd9Sstevel@tonic-gate actually written to disks. This is very important because GRUB does
1377c478bd9Sstevel@tonic-gate not use ordinary stdio interface but raw devices. */
1387c478bd9Sstevel@tonic-gate sync ();
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate program_name = argv[0];
1417c478bd9Sstevel@tonic-gate default_boot_drive = boot_drive;
1427c478bd9Sstevel@tonic-gate default_install_partition = install_partition;
1437c478bd9Sstevel@tonic-gate if (config_file)
1447c478bd9Sstevel@tonic-gate default_config_file = config_file;
1457c478bd9Sstevel@tonic-gate else
1467c478bd9Sstevel@tonic-gate default_config_file = "NONE";
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /* Parse command-line options. */
1497c478bd9Sstevel@tonic-gate do
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
1527c478bd9Sstevel@tonic-gate switch (c)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate case EOF:
1557c478bd9Sstevel@tonic-gate /* Fall through the bottom of the loop. */
1567c478bd9Sstevel@tonic-gate break;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate case OPT_HELP:
1597c478bd9Sstevel@tonic-gate usage (0);
1607c478bd9Sstevel@tonic-gate break;
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate case OPT_VERSION:
1637c478bd9Sstevel@tonic-gate printf ("grub (GNU GRUB " VERSION ")\n");
1647c478bd9Sstevel@tonic-gate exit (0);
1657c478bd9Sstevel@tonic-gate break;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate case OPT_HOLD:
1687c478bd9Sstevel@tonic-gate if (! optarg)
1697c478bd9Sstevel@tonic-gate hold = -1;
1707c478bd9Sstevel@tonic-gate else
1717c478bd9Sstevel@tonic-gate hold = atoi (optarg);
1727c478bd9Sstevel@tonic-gate break;
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate case OPT_CONFIG_FILE:
1757c478bd9Sstevel@tonic-gate strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
1767c478bd9Sstevel@tonic-gate config_file[127] = '\0';
1777c478bd9Sstevel@tonic-gate break;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate case OPT_INSTALL_PARTITION:
1807c478bd9Sstevel@tonic-gate install_partition = strtoul (optarg, 0, 0);
1817c478bd9Sstevel@tonic-gate if (install_partition == ULONG_MAX)
1827c478bd9Sstevel@tonic-gate {
1837c478bd9Sstevel@tonic-gate perror ("strtoul");
1847c478bd9Sstevel@tonic-gate exit (1);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate break;
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate case OPT_BOOT_DRIVE:
1897c478bd9Sstevel@tonic-gate boot_drive = strtoul (optarg, 0, 0);
1907c478bd9Sstevel@tonic-gate if (boot_drive == ULONG_MAX)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate perror ("strtoul");
1937c478bd9Sstevel@tonic-gate exit (1);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate break;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate case OPT_NO_CONFIG_FILE:
1987c478bd9Sstevel@tonic-gate use_config_file = 0;
1997c478bd9Sstevel@tonic-gate break;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate case OPT_NO_CURSES:
2027c478bd9Sstevel@tonic-gate use_curses = 0;
2037c478bd9Sstevel@tonic-gate break;
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate case OPT_NO_PAGER:
2067c478bd9Sstevel@tonic-gate use_pager = 0;
2077c478bd9Sstevel@tonic-gate break;
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate case OPT_BATCH:
2107c478bd9Sstevel@tonic-gate /* This is the same as "--no-config-file --no-curses --no-pager". */
2117c478bd9Sstevel@tonic-gate use_config_file = 0;
2127c478bd9Sstevel@tonic-gate use_curses = 0;
2137c478bd9Sstevel@tonic-gate use_pager = 0;
2147c478bd9Sstevel@tonic-gate break;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate case OPT_READ_ONLY:
2177c478bd9Sstevel@tonic-gate read_only = 1;
2187c478bd9Sstevel@tonic-gate break;
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate case OPT_VERBOSE:
2217c478bd9Sstevel@tonic-gate verbose = 1;
2227c478bd9Sstevel@tonic-gate break;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate case OPT_NO_FLOPPY:
2257c478bd9Sstevel@tonic-gate floppy_disks = 0;
2267c478bd9Sstevel@tonic-gate break;
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate case OPT_PROBE_SECOND_FLOPPY:
2297c478bd9Sstevel@tonic-gate floppy_disks = 2;
2307c478bd9Sstevel@tonic-gate break;
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate case OPT_DEVICE_MAP:
2337c478bd9Sstevel@tonic-gate device_map_file = strdup (optarg);
2347c478bd9Sstevel@tonic-gate break;
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate case OPT_PRESET_MENU:
2377c478bd9Sstevel@tonic-gate use_preset_menu = 1;
2387c478bd9Sstevel@tonic-gate break;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate default:
2417c478bd9Sstevel@tonic-gate usage (1);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate while (c != EOF);
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate /* Wait until the HOLD variable is cleared by an attached debugger. */
2477c478bd9Sstevel@tonic-gate if (hold && verbose)
2487c478bd9Sstevel@tonic-gate printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
2497c478bd9Sstevel@tonic-gate program_name, (int) getpid ());
2507c478bd9Sstevel@tonic-gate while (hold)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate if (hold > 0)
2537c478bd9Sstevel@tonic-gate hold--;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate sleep (1);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /* If we don't have curses (!HAVE_LIBCURSES or --no-curses or
2597c478bd9Sstevel@tonic-gate --batch) put terminal to dumb for better handling of line i/o */
2607c478bd9Sstevel@tonic-gate if (! use_curses)
2617c478bd9Sstevel@tonic-gate current_term->flags = TERM_NO_EDIT | TERM_DUMB;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate /* Transfer control to the stage2 simulator. */
2647c478bd9Sstevel@tonic-gate exit (grub_stage2 ());
2657c478bd9Sstevel@tonic-gate }
266