Home | History | Annotate | Line # | Download | only in dosboot
main.c revision 1.9
      1 /*	$NetBSD: main.c,v 1.9 1997/10/31 18:50:09 drochner 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 
     44 #include <libi386.h>
     45 
     46 extern void ls  __P((char *));
     47 extern int getopt __P((int, char **, const char *));
     48 
     49 #ifdef SUPPORT_LYNX
     50 extern int exec_lynx __P((const char*, int));
     51 #endif
     52 
     53 int             errno;
     54 
     55 extern	char bootprog_name[], bootprog_rev[], bootprog_date[],
     56 	bootprog_maker[];
     57 
     58 #define MAXDEVNAME 16
     59 
     60 static char    *current_fsmode;
     61 static char    *default_devname;
     62 static int      default_unit, default_partition;
     63 static char    *default_filename;
     64 
     65 void	command_help __P((char *));
     66 void	command_ls __P((char *));
     67 void	command_quit __P((char *));
     68 void	command_boot __P((char *));
     69 void	command_mode __P((char *));
     70 void	command_dev __P((char *));
     71 
     72 struct bootblk_command commands[] = {
     73 	{ "help",	command_help },
     74 	{ "?",		command_help },
     75 	{ "ls",		command_ls },
     76 	{ "quit",	command_quit },
     77 	{ "boot",	command_boot },
     78 	{ "mode",	command_mode },
     79 	{ "dev",	command_dev },
     80 	{ NULL,		NULL },
     81 };
     82 
     83 int
     84 parsebootfile(fname, fsmode, devname, unit, partition, file)
     85 	const char     *fname;
     86 	char          **fsmode; /* out */
     87 	char          **devname; /* out */
     88 	unsigned int   *unit, *partition; /* out */
     89 	const char    **file; /* out */
     90 {
     91 	const char     *col, *help;
     92 
     93 	*fsmode = current_fsmode;
     94 	*devname = default_devname;
     95 	*unit = default_unit;
     96 	*partition = default_partition;
     97 	*file = default_filename;
     98 
     99 	if (fname == NULL)
    100 		return (0);
    101 
    102 	if (strcmp(current_fsmode, "dos") && (col = strchr(fname, ':'))) {
    103 		/* no DOS, device given */
    104 		static char     savedevname[MAXDEVNAME + 1];
    105 		int             devlen;
    106 		unsigned int    u = 0, p = 0;
    107 		int             i = 0;
    108 
    109 		devlen = col - fname;
    110 		if (devlen > MAXDEVNAME)
    111 			return (EINVAL);
    112 
    113 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
    114 		if (!isvalidname(fname[i]))
    115 			return (EINVAL);
    116 		do {
    117 			savedevname[i] = fname[i];
    118 			i++;
    119 		} while (isvalidname(fname[i]));
    120 		savedevname[i] = '\0';
    121 
    122 #define isnum(c) ((c) >= '0' && (c) <= '9')
    123 		if (i < devlen) {
    124 			if (!isnum(fname[i]))
    125 				return (EUNIT);
    126 			do {
    127 				u *= 10;
    128 				u += fname[i++] - '0';
    129 			} while (isnum(fname[i]));
    130 		}
    131 
    132 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
    133 		if (i < devlen) {
    134 			if (!isvalidpart(fname[i]))
    135 				return (EPART);
    136 			p = fname[i++] - 'a';
    137 		}
    138 		if (i != devlen)
    139 			return (ENXIO);
    140 
    141 		*devname = savedevname;
    142 		*unit = u;
    143 		*partition = p;
    144 		help = col + 1;
    145 	} else
    146 		help = fname;
    147 
    148 	if (*help)
    149 		*file = help;
    150 
    151 	return (0);
    152 }
    153 
    154 char *sprint_bootsel(filename)
    155 const char *filename;
    156 {
    157 	char *fsname, *devname;
    158 	int unit, partition;
    159 	const char *file;
    160 	static char buf[80];
    161 
    162 	if (parsebootfile(filename, &fsname, &devname, &unit,
    163 			  &partition, &file) == 0) {
    164 		if (!strcmp(fsname, "dos"))
    165 			sprintf(buf, "dos:%s", file);
    166 		else if (!strcmp(fsname, "ufs"))
    167 			sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
    168 		else goto bad;
    169 		return(buf);
    170 	}
    171 bad:
    172 	return("(invalid)");
    173 }
    174 
    175 static void
    176 bootit(filename, howto, tell)
    177 	const char     *filename;
    178 	int             howto, tell;
    179 {
    180 	if (tell) {
    181 		printf("booting %s", sprint_bootsel(filename));
    182 		if (howto)
    183 			printf(" (howto 0x%x)", howto);
    184 		printf("\n");
    185 	}
    186 #ifdef SUPPORT_LYNX
    187 	if(exec_netbsd(filename, 0, howto) < 0)
    188 		printf("boot netbsd: %s: %s\n", sprint_bootsel(filename),
    189 		       strerror(errno));
    190 	else {
    191 		printf("boot netbsd returned\n");
    192 		return;
    193 	}
    194 	if (exec_lynx(filename, 0) < 0)
    195 		printf("boot lynx: %s: %s\n", sprint_bootsel(filename),
    196 		       strerror(errno));
    197 	else
    198 		printf("boot lynx returned\n");
    199 #else
    200 	if (exec_netbsd(filename, 0, howto) < 0)
    201 		printf("boot: %s: %s\n", sprint_bootsel(filename),
    202 		       strerror(errno));
    203 	else
    204 		printf("boot returned\n");
    205 #endif
    206 }
    207 
    208 static void
    209 print_banner(void)
    210 {
    211 	int extmem = getextmem();
    212 	char *s = "";
    213 
    214 #ifdef XMS
    215 	if (getextmem1() == 0) {
    216 		if ((extmem = checkxms()) != 0)
    217 			s = "(xms) ";
    218 	}
    219 #endif
    220 
    221 	printf("\n");
    222 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
    223 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    224 	printf(">> Memory: %d/%d %sk\n", getbasemem(), extmem, s);
    225 }
    226 
    227 void
    228 usage()
    229 {
    230 	printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n");
    231 }
    232 
    233 int
    234 main(argc, argv)
    235 	int             argc;
    236 	char          **argv;
    237 {
    238 	int             ch;
    239 	int             interactive = 0;
    240 	int             howto;
    241 	extern char    *optarg;
    242 	extern int      optind;
    243 
    244 	initio(CONSDEV_PC);
    245 	gateA20();
    246 
    247 	print_banner();
    248 
    249 	current_fsmode = "dos";
    250 	default_devname = "hd";
    251 	default_unit = 0;
    252 	default_partition = 0;
    253 	default_filename = "netbsd";
    254 
    255 	while ((ch = getopt(argc, argv, "c:iu")) != -1) {
    256 		switch (ch) {
    257 		case 'c':
    258 			docommand(optarg);
    259 			return (1);
    260 			break;
    261 		case 'i':
    262 			interactive = 1;
    263 			break;
    264 		case 'u':
    265 			current_fsmode = "ufs";
    266 			break;
    267 		default:
    268 			usage();
    269 			return (1);
    270 		}
    271 	}
    272 
    273 	if (interactive) {
    274 		printf("type \"?\" or \"help\" for help.\n");
    275 		bootmenu();
    276 	}
    277 
    278 	argc -= optind;
    279 	argv += optind;
    280 
    281 	if (argc > 2) {
    282 		usage();
    283 		return (1);
    284 	}
    285 	howto = 0;
    286 	if (argc > 1 && !parseopts(argv[1], &howto))
    287 		return (1);
    288 
    289 	bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1);
    290 	return (1);
    291 }
    292 
    293 /* ARGSUSED */
    294 void
    295 command_help(arg)
    296 	char *arg;
    297 {
    298 	printf("commands are:\n"
    299 	       "boot [xdNx:][filename] [-adrs]\n"
    300 	       "     (ex. \"sd0a:netbsd.old -s\"\n"
    301 	       "ls [path]\n"
    302 	       "mode ufs|dos\n"
    303 	       "dev xd[N[x]]:\n"
    304 	       "help|?\n"
    305 	       "quit\n");
    306 }
    307 
    308 void
    309 command_ls(arg)
    310 	char *arg;
    311 {
    312 	char *help = default_filename;
    313 	if (strcmp(current_fsmode, "ufs")) {
    314 		printf("UFS only\n");
    315 		return;
    316 	}
    317 	default_filename = "/";
    318 	ls(arg);
    319 	default_filename = help;
    320 }
    321 
    322 /* ARGSUSED */
    323 void
    324 command_quit(arg)
    325 	char *arg;
    326 {
    327 	printf("Exiting... goodbye...\n");
    328 	exit(0);
    329 }
    330 
    331 void
    332 command_boot(arg)
    333 	char *arg;
    334 {
    335 	char *filename;
    336 	int howto;
    337 
    338 	if (parseboot(arg, &filename, &howto))
    339 		bootit(filename, howto, 1);
    340 }
    341 
    342 void
    343 command_mode(arg)
    344 	char *arg;
    345 {
    346 	if (!strcmp("dos", arg))
    347 		current_fsmode = "dos";
    348 	else if (!strcmp("ufs", arg))
    349 		current_fsmode = "ufs";
    350 	else
    351 		printf("invalid mode\n");
    352 }
    353 
    354 void
    355 command_dev(arg)
    356 	char *arg;
    357 {
    358 	static char savedevname[MAXDEVNAME + 1];
    359 	char *fsname, *devname;
    360 	const char *file; /* dummy */
    361 
    362 	if (!strcmp(current_fsmode, "dos")) {
    363 		printf("not available in DOS mode\n");
    364 		return;
    365 	}
    366 
    367 	if (*arg == '\0') {
    368 		printf("%s%d%c:\n", default_devname, default_unit,
    369 		       'a' + default_partition);
    370 		return;
    371 	}
    372 
    373 	if (!strchr(arg, ':') ||
    374 	    parsebootfile(arg, &fsname, &devname, &default_unit,
    375 			  &default_partition, &file)) {
    376 		command_help(NULL);
    377 		return;
    378 	}
    379 
    380 	/* put to own static storage */
    381 	strncpy(savedevname, devname, MAXDEVNAME + 1);
    382 	default_devname = savedevname;
    383 }
    384