Home | History | Annotate | Line # | Download | only in dosboot
main.c revision 1.14
      1  1.14    martin /*	$NetBSD: main.c,v 1.14 2000/03/13 10:51:22 martin Exp $	 */
      2   1.1     perry 
      3   1.1     perry /*
      4   1.1     perry  * Copyright (c) 1996, 1997
      5   1.1     perry  * 	Matthias Drochner.  All rights reserved.
      6   1.1     perry  * Copyright (c) 1996, 1997
      7   1.1     perry  * 	Perry E. Metzger.  All rights reserved.
      8   1.1     perry  *
      9   1.1     perry  * Redistribution and use in source and binary forms, with or without
     10   1.1     perry  * modification, are permitted provided that the following conditions
     11   1.1     perry  * are met:
     12   1.1     perry  * 1. Redistributions of source code must retain the above copyright
     13   1.1     perry  *    notice, this list of conditions and the following disclaimer.
     14   1.1     perry  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1     perry  *    notice, this list of conditions and the following disclaimer in the
     16   1.1     perry  *    documentation and/or other materials provided with the distribution.
     17   1.1     perry  * 3. All advertising materials mentioning features or use of this software
     18   1.1     perry  *    must display the following acknowledgements:
     19   1.1     perry  *	This product includes software developed for the NetBSD Project
     20   1.1     perry  *	by Matthias Drochner.
     21   1.1     perry  *	This product includes software developed for the NetBSD Project
     22   1.1     perry  *	by Perry E. Metzger.
     23   1.1     perry  * 4. The names of the authors may not be used to endorse or promote products
     24   1.1     perry  *    derived from this software without specific prior written permission.
     25   1.1     perry  *
     26   1.1     perry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     27   1.1     perry  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     28   1.1     perry  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29   1.1     perry  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     30   1.1     perry  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     31   1.1     perry  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     32   1.1     perry  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     33   1.1     perry  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     34   1.1     perry  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     35   1.1     perry  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     36   1.1     perry  */
     37   1.1     perry 
     38   1.1     perry 
     39   1.1     perry #include <sys/reboot.h>
     40   1.1     perry 
     41   1.1     perry #include <lib/libkern/libkern.h>
     42   1.1     perry #include <lib/libsa/stand.h>
     43  1.12  drochner #include <lib/libsa/ufs.h>
     44   1.1     perry 
     45   1.1     perry #include <libi386.h>
     46   1.1     perry 
     47   1.7  drochner #ifdef SUPPORT_LYNX
     48   1.7  drochner extern int exec_lynx __P((const char*, int));
     49   1.7  drochner #endif
     50   1.7  drochner 
     51  1.12  drochner int errno;
     52   1.1     perry 
     53   1.4   thorpej extern	char bootprog_name[], bootprog_rev[], bootprog_date[],
     54   1.4   thorpej 	bootprog_maker[];
     55   1.1     perry 
     56   1.1     perry #define MAXDEVNAME 16
     57   1.1     perry 
     58   1.2   thorpej static char    *current_fsmode;
     59   1.2   thorpej static char    *default_devname;
     60   1.2   thorpej static int      default_unit, default_partition;
     61   1.2   thorpej static char    *default_filename;
     62   1.1     perry 
     63  1.12  drochner char *sprint_bootsel __P((const char *));
     64  1.12  drochner static void bootit __P((const char *, int, int));
     65  1.12  drochner void usage __P((void));
     66  1.12  drochner int main __P((int, char **));
     67  1.12  drochner 
     68   1.7  drochner void	command_help __P((char *));
     69   1.7  drochner void	command_ls __P((char *));
     70   1.7  drochner void	command_quit __P((char *));
     71   1.7  drochner void	command_boot __P((char *));
     72   1.7  drochner void	command_mode __P((char *));
     73   1.9  drochner void	command_dev __P((char *));
     74   1.7  drochner 
     75   1.7  drochner struct bootblk_command commands[] = {
     76   1.7  drochner 	{ "help",	command_help },
     77   1.7  drochner 	{ "?",		command_help },
     78   1.7  drochner 	{ "ls",		command_ls },
     79   1.7  drochner 	{ "quit",	command_quit },
     80   1.7  drochner 	{ "boot",	command_boot },
     81   1.7  drochner 	{ "mode",	command_mode },
     82   1.9  drochner 	{ "dev",	command_dev },
     83   1.7  drochner 	{ NULL,		NULL },
     84   1.7  drochner };
     85   1.7  drochner 
     86   1.1     perry int
     87   1.1     perry parsebootfile(fname, fsmode, devname, unit, partition, file)
     88   1.2   thorpej 	const char     *fname;
     89   1.7  drochner 	char          **fsmode; /* out */
     90   1.7  drochner 	char          **devname; /* out */
     91   1.7  drochner 	unsigned int   *unit, *partition; /* out */
     92   1.7  drochner 	const char    **file; /* out */
     93   1.2   thorpej {
     94   1.2   thorpej 	const char     *col, *help;
     95   1.2   thorpej 
     96   1.2   thorpej 	*fsmode = current_fsmode;
     97   1.2   thorpej 	*devname = default_devname;
     98   1.2   thorpej 	*unit = default_unit;
     99   1.2   thorpej 	*partition = default_partition;
    100   1.2   thorpej 	*file = default_filename;
    101   1.2   thorpej 
    102   1.7  drochner 	if (fname == NULL)
    103   1.2   thorpej 		return (0);
    104   1.2   thorpej 
    105   1.9  drochner 	if (strcmp(current_fsmode, "dos") && (col = strchr(fname, ':'))) {
    106   1.9  drochner 		/* no DOS, device given */
    107   1.2   thorpej 		static char     savedevname[MAXDEVNAME + 1];
    108   1.2   thorpej 		int             devlen;
    109   1.2   thorpej 		unsigned int    u = 0, p = 0;
    110   1.2   thorpej 		int             i = 0;
    111   1.2   thorpej 
    112   1.2   thorpej 		devlen = col - fname;
    113   1.2   thorpej 		if (devlen > MAXDEVNAME)
    114   1.2   thorpej 			return (EINVAL);
    115   1.1     perry 
    116   1.1     perry #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
    117   1.2   thorpej 		if (!isvalidname(fname[i]))
    118   1.2   thorpej 			return (EINVAL);
    119   1.2   thorpej 		do {
    120   1.2   thorpej 			savedevname[i] = fname[i];
    121   1.2   thorpej 			i++;
    122   1.2   thorpej 		} while (isvalidname(fname[i]));
    123   1.2   thorpej 		savedevname[i] = '\0';
    124   1.1     perry 
    125   1.1     perry #define isnum(c) ((c) >= '0' && (c) <= '9')
    126   1.2   thorpej 		if (i < devlen) {
    127   1.2   thorpej 			if (!isnum(fname[i]))
    128   1.2   thorpej 				return (EUNIT);
    129   1.2   thorpej 			do {
    130   1.2   thorpej 				u *= 10;
    131   1.2   thorpej 				u += fname[i++] - '0';
    132   1.2   thorpej 			} while (isnum(fname[i]));
    133   1.2   thorpej 		}
    134   1.7  drochner 
    135   1.1     perry #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
    136   1.2   thorpej 		if (i < devlen) {
    137   1.2   thorpej 			if (!isvalidpart(fname[i]))
    138   1.2   thorpej 				return (EPART);
    139   1.2   thorpej 			p = fname[i++] - 'a';
    140   1.2   thorpej 		}
    141   1.2   thorpej 		if (i != devlen)
    142   1.2   thorpej 			return (ENXIO);
    143   1.2   thorpej 
    144   1.2   thorpej 		*devname = savedevname;
    145   1.2   thorpej 		*unit = u;
    146   1.2   thorpej 		*partition = p;
    147   1.2   thorpej 		help = col + 1;
    148   1.2   thorpej 	} else
    149   1.2   thorpej 		help = fname;
    150   1.1     perry 
    151   1.2   thorpej 	if (*help)
    152   1.2   thorpej 		*file = help;
    153   1.1     perry 
    154   1.2   thorpej 	return (0);
    155   1.1     perry }
    156   1.1     perry 
    157  1.12  drochner char *
    158  1.12  drochner sprint_bootsel(filename)
    159  1.12  drochner 	const char *filename;
    160   1.1     perry {
    161   1.7  drochner 	char *fsname, *devname;
    162   1.7  drochner 	int unit, partition;
    163   1.7  drochner 	const char *file;
    164   1.7  drochner 	static char buf[80];
    165   1.7  drochner 
    166   1.7  drochner 	if (parsebootfile(filename, &fsname, &devname, &unit,
    167   1.7  drochner 			  &partition, &file) == 0) {
    168   1.2   thorpej 		if (!strcmp(fsname, "dos"))
    169   1.7  drochner 			sprintf(buf, "dos:%s", file);
    170   1.2   thorpej 		else if (!strcmp(fsname, "ufs"))
    171  1.12  drochner 			sprintf(buf, "%s%d%c:%s", devname, unit,
    172  1.12  drochner 				'a' + partition, file);
    173   1.7  drochner 		else goto bad;
    174  1.12  drochner 		return (buf);
    175   1.2   thorpej 	}
    176   1.7  drochner bad:
    177  1.12  drochner 	return ("(invalid)");
    178   1.1     perry }
    179   1.1     perry 
    180   1.1     perry static void
    181   1.1     perry bootit(filename, howto, tell)
    182   1.2   thorpej 	const char     *filename;
    183   1.2   thorpej 	int             howto, tell;
    184   1.1     perry {
    185   1.7  drochner 	if (tell) {
    186   1.7  drochner 		printf("booting %s", sprint_bootsel(filename));
    187   1.7  drochner 		if (howto)
    188   1.7  drochner 			printf(" (howto 0x%x)", howto);
    189   1.7  drochner 		printf("\n");
    190   1.7  drochner 	}
    191   1.7  drochner #ifdef SUPPORT_LYNX
    192   1.7  drochner 	if(exec_netbsd(filename, 0, howto) < 0)
    193   1.7  drochner 		printf("boot netbsd: %s: %s\n", sprint_bootsel(filename),
    194   1.7  drochner 		       strerror(errno));
    195   1.7  drochner 	else {
    196   1.7  drochner 		printf("boot netbsd returned\n");
    197   1.7  drochner 		return;
    198   1.7  drochner 	}
    199   1.7  drochner 	if (exec_lynx(filename, 0) < 0)
    200   1.7  drochner 		printf("boot lynx: %s: %s\n", sprint_bootsel(filename),
    201   1.7  drochner 		       strerror(errno));
    202   1.7  drochner 	else
    203   1.7  drochner 		printf("boot lynx returned\n");
    204   1.7  drochner #else
    205   1.7  drochner 	if (exec_netbsd(filename, 0, howto) < 0)
    206   1.7  drochner 		printf("boot: %s: %s\n", sprint_bootsel(filename),
    207   1.7  drochner 		       strerror(errno));
    208   1.2   thorpej 	else
    209   1.2   thorpej 		printf("boot returned\n");
    210   1.7  drochner #endif
    211   1.1     perry }
    212   1.1     perry 
    213   1.1     perry static void
    214   1.1     perry print_banner(void)
    215   1.1     perry {
    216   1.5  christos 	int extmem = getextmem();
    217   1.5  christos 	char *s = "";
    218   1.5  christos 
    219   1.5  christos #ifdef XMS
    220  1.10  drochner 	u_long xmsmem;
    221  1.10  drochner 	if (getextmem1() == 0 && (xmsmem = checkxms()) != 0) {
    222  1.10  drochner 		/*
    223  1.10  drochner 		 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
    224  1.10  drochner 		 *  getextmem() is getextmem1(). Without, the "smart"
    225  1.10  drochner 		 *  methods could fail to report all memory as well.
    226  1.10  drochner 		 * xmsmem is a few kB less than the actual size, but
    227  1.10  drochner 		 *  better than nothing.
    228  1.10  drochner 		 */
    229  1.10  drochner 		if (xmsmem > extmem)
    230  1.10  drochner 			extmem = xmsmem;
    231  1.10  drochner 		s = "(xms) ";
    232   1.5  christos 	}
    233   1.5  christos #endif
    234   1.4   thorpej 
    235   1.4   thorpej 	printf("\n");
    236   1.4   thorpej 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
    237   1.4   thorpej 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    238   1.5  christos 	printf(">> Memory: %d/%d %sk\n", getbasemem(), extmem, s);
    239   1.2   thorpej }
    240   1.2   thorpej 
    241   1.2   thorpej void
    242   1.2   thorpej usage()
    243   1.2   thorpej {
    244   1.2   thorpej 	printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n");
    245   1.2   thorpej }
    246   1.2   thorpej 
    247   1.2   thorpej int
    248   1.2   thorpej main(argc, argv)
    249   1.2   thorpej 	int             argc;
    250   1.2   thorpej 	char          **argv;
    251   1.2   thorpej {
    252   1.2   thorpej 	int             ch;
    253   1.2   thorpej 	int             interactive = 0;
    254   1.2   thorpej 	int             howto;
    255   1.2   thorpej 	extern char    *optarg;
    256   1.2   thorpej 	extern int      optind;
    257   1.2   thorpej 
    258  1.14    martin #ifdef	SUPPORT_SERIAL
    259  1.14    martin 	initio(SUPPORT_SERIAL);
    260  1.14    martin #else
    261   1.7  drochner 	initio(CONSDEV_PC);
    262  1.14    martin #endif
    263   1.2   thorpej 	gateA20();
    264   1.2   thorpej 
    265   1.2   thorpej 	print_banner();
    266   1.2   thorpej 
    267   1.2   thorpej 	current_fsmode = "dos";
    268   1.2   thorpej 	default_devname = "hd";
    269   1.2   thorpej 	default_unit = 0;
    270   1.2   thorpej 	default_partition = 0;
    271   1.2   thorpej 	default_filename = "netbsd";
    272   1.2   thorpej 
    273   1.2   thorpej 	while ((ch = getopt(argc, argv, "c:iu")) != -1) {
    274   1.2   thorpej 		switch (ch) {
    275   1.2   thorpej 		case 'c':
    276   1.2   thorpej 			docommand(optarg);
    277   1.2   thorpej 			return (1);
    278   1.2   thorpej 			break;
    279   1.2   thorpej 		case 'i':
    280   1.2   thorpej 			interactive = 1;
    281   1.2   thorpej 			break;
    282   1.2   thorpej 		case 'u':
    283   1.2   thorpej 			current_fsmode = "ufs";
    284   1.2   thorpej 			break;
    285   1.2   thorpej 		default:
    286   1.2   thorpej 			usage();
    287   1.2   thorpej 			return (1);
    288   1.2   thorpej 		}
    289   1.2   thorpej 	}
    290   1.2   thorpej 
    291   1.7  drochner 	if (interactive) {
    292   1.8  drochner 		printf("type \"?\" or \"help\" for help.\n");
    293   1.2   thorpej 		bootmenu();
    294   1.7  drochner 	}
    295   1.2   thorpej 
    296   1.2   thorpej 	argc -= optind;
    297   1.2   thorpej 	argv += optind;
    298   1.2   thorpej 
    299   1.2   thorpej 	if (argc > 2) {
    300   1.2   thorpej 		usage();
    301   1.2   thorpej 		return (1);
    302   1.2   thorpej 	}
    303   1.2   thorpej 	howto = 0;
    304   1.2   thorpej 	if (argc > 1 && !parseopts(argv[1], &howto))
    305   1.2   thorpej 		return (1);
    306   1.1     perry 
    307   1.2   thorpej 	bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1);
    308   1.2   thorpej 	return (1);
    309   1.7  drochner }
    310   1.7  drochner 
    311   1.7  drochner /* ARGSUSED */
    312   1.7  drochner void
    313   1.7  drochner command_help(arg)
    314   1.7  drochner 	char *arg;
    315   1.7  drochner {
    316   1.7  drochner 	printf("commands are:\n"
    317   1.7  drochner 	       "boot [xdNx:][filename] [-adrs]\n"
    318   1.7  drochner 	       "     (ex. \"sd0a:netbsd.old -s\"\n"
    319   1.7  drochner 	       "ls [path]\n"
    320   1.7  drochner 	       "mode ufs|dos\n"
    321   1.9  drochner 	       "dev xd[N[x]]:\n"
    322   1.7  drochner 	       "help|?\n"
    323   1.7  drochner 	       "quit\n");
    324   1.7  drochner }
    325   1.7  drochner 
    326   1.7  drochner void
    327   1.7  drochner command_ls(arg)
    328   1.7  drochner 	char *arg;
    329   1.7  drochner {
    330   1.7  drochner 	char *help = default_filename;
    331   1.7  drochner 	if (strcmp(current_fsmode, "ufs")) {
    332   1.7  drochner 		printf("UFS only\n");
    333   1.7  drochner 		return;
    334   1.7  drochner 	}
    335   1.7  drochner 	default_filename = "/";
    336  1.12  drochner 	ufs_ls(arg);
    337   1.7  drochner 	default_filename = help;
    338   1.7  drochner }
    339   1.7  drochner 
    340   1.7  drochner /* ARGSUSED */
    341   1.7  drochner void
    342   1.7  drochner command_quit(arg)
    343   1.7  drochner 	char *arg;
    344   1.7  drochner {
    345   1.7  drochner 	printf("Exiting... goodbye...\n");
    346  1.12  drochner 	exit(0);
    347   1.7  drochner }
    348   1.7  drochner 
    349   1.7  drochner void
    350   1.7  drochner command_boot(arg)
    351   1.7  drochner 	char *arg;
    352   1.7  drochner {
    353   1.7  drochner 	char *filename;
    354   1.7  drochner 	int howto;
    355   1.7  drochner 
    356   1.7  drochner 	if (parseboot(arg, &filename, &howto))
    357   1.7  drochner 		bootit(filename, howto, 1);
    358   1.7  drochner }
    359   1.7  drochner 
    360   1.7  drochner void
    361   1.7  drochner command_mode(arg)
    362   1.7  drochner 	char *arg;
    363   1.7  drochner {
    364   1.7  drochner 	if (!strcmp("dos", arg))
    365   1.7  drochner 		current_fsmode = "dos";
    366   1.7  drochner 	else if (!strcmp("ufs", arg))
    367   1.7  drochner 		current_fsmode = "ufs";
    368   1.7  drochner 	else
    369   1.7  drochner 		printf("invalid mode\n");
    370   1.9  drochner }
    371   1.9  drochner 
    372   1.9  drochner void
    373   1.9  drochner command_dev(arg)
    374   1.9  drochner 	char *arg;
    375   1.9  drochner {
    376   1.9  drochner 	static char savedevname[MAXDEVNAME + 1];
    377   1.9  drochner 	char *fsname, *devname;
    378   1.9  drochner 	const char *file; /* dummy */
    379   1.9  drochner 
    380   1.9  drochner 	if (!strcmp(current_fsmode, "dos")) {
    381   1.9  drochner 		printf("not available in DOS mode\n");
    382   1.9  drochner 		return;
    383   1.9  drochner 	}
    384   1.9  drochner 
    385   1.9  drochner 	if (*arg == '\0') {
    386   1.9  drochner 		printf("%s%d%c:\n", default_devname, default_unit,
    387   1.9  drochner 		       'a' + default_partition);
    388   1.9  drochner 		return;
    389   1.9  drochner 	}
    390   1.9  drochner 
    391   1.9  drochner 	if (!strchr(arg, ':') ||
    392   1.9  drochner 	    parsebootfile(arg, &fsname, &devname, &default_unit,
    393   1.9  drochner 			  &default_partition, &file)) {
    394   1.9  drochner 		command_help(NULL);
    395   1.9  drochner 		return;
    396   1.9  drochner 	}
    397   1.9  drochner 
    398   1.9  drochner 	/* put to own static storage */
    399   1.9  drochner 	strncpy(savedevname, devname, MAXDEVNAME + 1);
    400   1.9  drochner 	default_devname = savedevname;
    401   1.1     perry }
    402