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