Home | History | Annotate | Line # | Download | only in dosboot
main.c revision 1.1
      1 /*	$NetBSD: main.c,v 1.1 1997/03/14 02:40:35 perry 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 
     40 #include <sys/reboot.h>
     41 
     42 #include <lib/libkern/libkern.h>
     43 #include <lib/libsa/stand.h>
     44 
     45 #include <libi386.h>
     46 
     47 extern char *strerror __P((int)); /* XXX missing in stand.h */
     48 
     49 extern void ls __P((char*));
     50 extern int getopt __P((int, char**, const char*));
     51 
     52 int errno;
     53 static char *consdev;
     54 
     55 extern char version[];
     56 
     57 #define MAXDEVNAME 16
     58 
     59 static char *current_fsmode;
     60 static char *default_devname;
     61 static int default_unit, default_partition;
     62 static char *default_filename;
     63 
     64 int
     65 parsebootfile(fname, fsmode, devname, unit, partition, file)
     66 const char *fname;
     67 char **fsmode;
     68 char **devname; /* out */
     69 unsigned int *unit, *partition; /* out */
     70 const char **file; /* out */
     71 {
     72     const char *col, *help;
     73 
     74     *fsmode = current_fsmode;
     75     *devname = default_devname;
     76     *unit = default_unit;
     77     *partition = default_partition;
     78     *file = default_filename;
     79 
     80     if(!fname) return(0);
     81 
     82     if((col = strchr(fname, ':'))) { /* device given */
     83 	static char savedevname[MAXDEVNAME+1];
     84 	int devlen;
     85 	unsigned int u = 0, p = 0;
     86 	int i = 0;
     87 
     88 	devlen = col - fname;
     89 	if(devlen > MAXDEVNAME)
     90 	    return(EINVAL);
     91 
     92 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
     93 	if(!isvalidname(fname[i]))
     94 	    return(EINVAL);
     95 	do {
     96 	    savedevname[i] = fname[i];
     97 	    i++;
     98 	} while(isvalidname(fname[i]));
     99 	savedevname[i] = '\0';
    100 
    101 #define isnum(c) ((c) >= '0' && (c) <= '9')
    102 	if(i < devlen) {
    103 	    if(!isnum(fname[i]))
    104 		return(EUNIT);
    105 	    do {
    106 		u *= 10;
    107 		u += fname[i++] - '0';
    108 	    } while(isnum(fname[i]));
    109 	}
    110 
    111 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
    112 	if(i < devlen) {
    113 	    if(!isvalidpart(fname[i]))
    114 		return(EPART);
    115 	    p = fname[i++] - 'a';
    116 	}
    117 
    118 	if(i != devlen)
    119 	    return(ENXIO);
    120 
    121 	*devname = savedevname;
    122 	*unit = u;
    123 	*partition = p;
    124 	help = col + 1;
    125     } else
    126 	help = fname;
    127 
    128     if(*help) *file = help;
    129 
    130     return(0);
    131 }
    132 
    133 static void
    134 print_bootsel(filename)
    135 char *filename;
    136 {
    137     char *fsname;
    138     char *devname;
    139     int unit, partition;
    140     const char *file;
    141 
    142     if(!parsebootfile(filename, &fsname, &devname, &unit, &partition, &file)) {
    143 	if(!strcmp(fsname, "dos"))
    144 		printf("booting %s\n", file);
    145 	else if(!strcmp(fsname, "ufs"))
    146 		printf("booting %s%d%c:%s\n", devname, unit,
    147 		       'a' + partition, file);
    148     }
    149 }
    150 
    151 static void
    152 bootit(filename, howto, tell)
    153 const char *filename;
    154 int howto, tell;
    155 {
    156     if(tell)
    157 	print_bootsel(filename);
    158 
    159     if(exec_netbsd(filename, 0, howto, 0, consdev) < 0)
    160 	printf("boot: %s\n", strerror(errno));
    161     else
    162 	printf("boot returned\n");
    163 }
    164 
    165 static void helpme()
    166 {
    167   printf("commands are:\n"
    168 	 "boot [xdNx:][filename] [-adrs]\n"
    169 	 "     (ex. \"sd0a:netbsd.old -s\"\n"
    170 	 "ls [path]\n"
    171 	 "mode ufs|dos\n"
    172 	 "help|?\n"
    173 	 "quit\n");
    174 }
    175 
    176 /*
    177  * chops the head from the arguments and returns the arguments if any,
    178  * or possibly an empty string.
    179  */
    180 static char *
    181 gettrailer(arg)
    182 char *arg;
    183 {
    184   char *options;
    185 
    186   if ((options = strchr(arg, ' ')) == NULL)
    187     options = "";
    188   else
    189     *options++ = '\0';
    190   /* trim leading blanks */
    191   while (*options && *options == ' ')
    192       options++;
    193 
    194   return(options);
    195 }
    196 
    197 static int
    198 parseopts(opts, howto)
    199 char *opts;
    200 int *howto;
    201 {
    202   int tmpopt = 0;
    203 
    204   opts++; /* skip - */
    205   while (*opts && *opts != ' ') {
    206     tmpopt |= netbsd_opt(*opts);
    207     if(tmpopt == -1) {
    208       printf("-%c: unknown flag\n", *opts);
    209       helpme();
    210       return(0);
    211     }
    212     opts++;
    213   }
    214   *howto = tmpopt;
    215   return(1);
    216 }
    217 
    218 static int
    219 parseboot(arg, filename, howto)
    220 char *arg;
    221 char **filename;
    222 int *howto;
    223 {
    224   char *opts = NULL;
    225 
    226   *filename = 0;
    227   *howto = 0;
    228 
    229   /* if there were no arguments */
    230   if (!*arg)
    231     return(1);
    232 
    233   /* format is... */
    234   /*[[xxNx:]filename] [-adrs]*/
    235 
    236   /* check for just args */
    237   if (arg[0] == '-'){
    238     opts = arg;
    239   } else { /* at least a file name */
    240     *filename = arg;
    241 
    242     opts = gettrailer(arg);
    243     if (!*opts)
    244       opts = NULL;
    245     else if (*opts != '-') {
    246       printf("invalid arguments\n");
    247       helpme();
    248       return(0);
    249     }
    250   }
    251   /* at this point, we have dealt with filenames. */
    252 
    253   /* now, deal with options */
    254   if (opts) {
    255     if (!parseopts(opts, howto))
    256       return(0);
    257   }
    258 
    259   return(1);
    260 }
    261 
    262 static void
    263 parsemode(arg, mode)
    264 char *arg;
    265 char **mode;
    266 {
    267     if(!strcmp("dos", arg))
    268 	*mode = "dos";
    269     else if(!strcmp("ufs", arg))
    270 	*mode = "ufs";
    271     else
    272 	printf("invalid mode\n");
    273 }
    274 
    275 static void
    276 docommand(arg)
    277 char *arg;
    278 {
    279   char *options;
    280 
    281   options = gettrailer(arg);
    282 
    283   if ((strcmp("help", arg) == 0) ||
    284       (strcmp("?", arg) == 0)) {
    285     helpme();
    286     return;
    287   }
    288   if (strcmp("ls", arg) == 0){
    289       char *help = default_filename;
    290       if(strcmp(current_fsmode, "ufs")) {
    291 	  printf("UFS only\n");
    292 	  return;
    293       }
    294       default_filename = "/";
    295       ls(options);
    296       default_filename = help;
    297       return;
    298   }
    299   if (strcmp("quit", arg) == 0){
    300     printf("Exiting... goodbye...\n");
    301     exit(0);
    302   }
    303   if (strcmp("boot", arg) == 0){
    304       char *filename;
    305       int howto;
    306       if(parseboot(options, &filename, &howto))
    307 	  bootit(filename, howto, 1);
    308       return;
    309   }
    310   if (strcmp("mode", arg) == 0){
    311       parsemode(options, &current_fsmode);
    312       return;
    313   }
    314   printf("unknown command\n");
    315   helpme();
    316 }
    317 
    318 void bootmenu()
    319 {
    320   printf("\ntype \"?\" or \"help\" for help.\n");
    321   for(;;) {
    322     char input[80];
    323 
    324     input[0] = '\0';
    325     printf("> ");
    326     gets(input);
    327 
    328     docommand(input);
    329   }
    330 }
    331 
    332 static void
    333 print_banner(void)
    334 {
    335   printf("\n"
    336 	 ">> NetBSD BOOT: %d/%d k [%s]\n",
    337 	 getbasemem(),
    338 	 getextmem(),
    339 	 version);
    340 }
    341 
    342 void usage()
    343 {
    344   printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n");
    345 }
    346 
    347 int main(argc, argv)
    348 int argc;
    349 char **argv;
    350 {
    351   int ch;
    352   int interactive = 0;
    353   int howto;
    354   extern char *optarg;
    355   extern int optind;
    356 
    357   consdev = initio(CONSDEV_PC);
    358   gateA20();
    359 
    360   print_banner();
    361 
    362   current_fsmode = "dos";
    363   default_devname = "hd";
    364   default_unit = 0;
    365   default_partition = 0;
    366   default_filename = "netbsd";
    367 
    368   while((ch = getopt(argc, argv, "c:iu")) != -1) {
    369     switch(ch) {
    370       case 'c':
    371 	docommand(optarg);
    372 	return(1);
    373 	break;
    374       case 'i':
    375 	interactive = 1;
    376 	break;
    377     case 'u':
    378 	current_fsmode = "ufs";
    379 	break;
    380       default:
    381 	usage();
    382 	return(1);
    383     }
    384   }
    385 
    386   if(interactive)
    387       bootmenu();
    388 
    389   argc -= optind;
    390   argv += optind;
    391 
    392   if(argc > 2) {
    393       usage();
    394       return(1);
    395   }
    396 
    397   howto = 0;
    398   if(argc > 1 && !parseopts(argv[1], &howto))
    399       return(1);
    400 
    401   bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1);
    402   return(1);
    403 }
    404