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