Home | History | Annotate | Line # | Download | only in common
boot.c revision 1.1
      1  1.1  pooka /*	$NetBSD: boot.c,v 1.1 2011/01/26 01:18:54 pooka Exp $	*/
      2  1.1  pooka 
      3  1.1  pooka /*-
      4  1.1  pooka  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  1.1  pooka  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      6  1.1  pooka  * All rights reserved.
      7  1.1  pooka  *
      8  1.1  pooka  * This code was written by Alessandro Forin and Neil Pittman
      9  1.1  pooka  * at Microsoft Research and contributed to The NetBSD Foundation
     10  1.1  pooka  * by Microsoft Corporation.
     11  1.1  pooka  *
     12  1.1  pooka  * Redistribution and use in source and binary forms, with or without
     13  1.1  pooka  * modification, are permitted provided that the following conditions
     14  1.1  pooka  * are met:
     15  1.1  pooka  * 1. Redistributions of source code must retain the above copyright
     16  1.1  pooka  *    notice, this list of conditions and the following disclaimer.
     17  1.1  pooka  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.1  pooka  *    notice, this list of conditions and the following disclaimer in the
     19  1.1  pooka  *    documentation and/or other materials provided with the distribution.
     20  1.1  pooka  *
     21  1.1  pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  1.1  pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  1.1  pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  1.1  pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  1.1  pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  1.1  pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  1.1  pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  1.1  pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  1.1  pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  1.1  pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  1.1  pooka  * POSSIBILITY OF SUCH DAMAGE.
     32  1.1  pooka  */
     33  1.1  pooka 
     34  1.1  pooka #include <lib/libsa/stand.h>
     35  1.1  pooka #include <lib/libsa/loadfile.h>
     36  1.1  pooka #include <lib/libkern/libkern.h>
     37  1.1  pooka 
     38  1.1  pooka #include <sys/param.h>
     39  1.1  pooka #include <sys/exec.h>
     40  1.1  pooka #include <sys/exec_elf.h>
     41  1.1  pooka 
     42  1.1  pooka #include "common.h"
     43  1.1  pooka #include "bootinfo.h"
     44  1.1  pooka #include "start.h"
     45  1.1  pooka 
     46  1.1  pooka /*
     47  1.1  pooka  * We won't go overboard with gzip'd kernel names.  After all we can
     48  1.1  pooka  * still boot a gzip'd kernel called "netbsd.emips" - it doesn't need
     49  1.1  pooka  * the .gz suffix.
     50  1.1  pooka  */
     51  1.1  pooka char *kernelnames[] = {
     52  1.1  pooka 	"netbsd",	"netbsd.gz",
     53  1.1  pooka 	"netbsd.old",
     54  1.1  pooka 	"onetbsd",
     55  1.1  pooka 	"gennetbsd",
     56  1.1  pooka     "nfsnetbsd",
     57  1.1  pooka 	NULL
     58  1.1  pooka };
     59  1.1  pooka 
     60  1.1  pooka 
     61  1.1  pooka void main (char *);
     62  1.1  pooka char *getboot(char *, char*);
     63  1.1  pooka static int devcanon(char *);
     64  1.1  pooka 
     65  1.1  pooka #define OPT_MAX PATH_MAX /* way overkill */
     66  1.1  pooka 
     67  1.1  pooka static int loadit(char *name, u_long marks[MARK_MAX])
     68  1.1  pooka {
     69  1.1  pooka     printf("Loading: %s\n", name);
     70  1.1  pooka     memset(marks, 0, sizeof marks);
     71  1.1  pooka     return (loadfile(name, marks, LOAD_ALL));
     72  1.1  pooka }
     73  1.1  pooka 
     74  1.1  pooka /*
     75  1.1  pooka  * The locore in start.S calls us with an 8KB stack carved after _end.
     76  1.1  pooka  *
     77  1.1  pooka  */
     78  1.1  pooka void
     79  1.1  pooka main(char *stack_top)
     80  1.1  pooka {
     81  1.1  pooka 	int argc;
     82  1.1  pooka     int autoboot = 1, win;
     83  1.1  pooka 	char *name, **namep, *dev, *kernel;
     84  1.1  pooka 	char bootname[PATH_MAX], bootpath[PATH_MAX], options[OPT_MAX];
     85  1.1  pooka 	uint32_t entry;
     86  1.1  pooka 	u_long marks[MARK_MAX];
     87  1.1  pooka 	struct btinfo_symtab bi_syms;
     88  1.1  pooka 	struct btinfo_bootpath bi_bpath;
     89  1.1  pooka 
     90  1.1  pooka     /* Init all peripherals, esp USART for printf and memory */
     91  1.1  pooka     init_board();
     92  1.1  pooka 
     93  1.1  pooka     /* On account of compression, we need a fairly large heap.
     94  1.1  pooka      * To keep things simple, take one meg just below the 16 meg mark.
     95  1.1  pooka      * That allows for a large kernel, and a 16MB configuration still works.
     96  1.1  pooka      */
     97  1.1  pooka     setheap((void *)(0x81000000-(1024*1024)), (void *)0x81000000);
     98  1.1  pooka 
     99  1.1  pooka     /* On the BEE3 and the Giano simulator, we need a sec between the serial-line download complete
    100  1.1  pooka      * and switching the serial line to PuTTY as console. Get a char to pause.
    101  1.1  pooka      * This delay is also the practice on PCs so.
    102  1.1  pooka      */
    103  1.1  pooka     Delay(200000);
    104  1.1  pooka     printf("Hit any char to boot..");
    105  1.1  pooka     argc = GetChar();
    106  1.1  pooka 
    107  1.1  pooka 	/* print a banner */
    108  1.1  pooka 	printf("\n");
    109  1.1  pooka 	printf("NetBSD/emips " NETBSD_VERS " " BOOT_TYPE_NAME " Bootstrap, Revision %s\n",
    110  1.1  pooka 	    bootprog_rev);
    111  1.1  pooka 
    112  1.1  pooka 	/* initialise bootinfo structure early */
    113  1.1  pooka 	bi_init(BOOTINFO_ADDR);
    114  1.1  pooka 
    115  1.1  pooka     /* Default is to auto-boot from the first disk */
    116  1.1  pooka     dev = "0/ace(0,0)/";
    117  1.1  pooka 	kernel = kernelnames[0];
    118  1.1  pooka     options[0] = 0;
    119  1.1  pooka 
    120  1.1  pooka     win = 0;
    121  1.1  pooka     for (;!win;) {
    122  1.1  pooka         strcpy(bootpath, dev);
    123  1.1  pooka         strcat(bootpath, kernel);
    124  1.1  pooka         name = getboot(bootpath,options);
    125  1.1  pooka 
    126  1.1  pooka         if (name != NULL) {
    127  1.1  pooka             win = (loadit(name, marks) == 0);
    128  1.1  pooka         } else if (autoboot)
    129  1.1  pooka             break;
    130  1.1  pooka         autoboot = 0;
    131  1.1  pooka     }
    132  1.1  pooka 
    133  1.1  pooka     if (!win) {
    134  1.1  pooka 		for (namep = kernelnames, win = 0; *namep != NULL && !win;
    135  1.1  pooka 		    namep++) {
    136  1.1  pooka 			kernel = *namep;
    137  1.1  pooka 			strcpy(bootpath, dev);
    138  1.1  pooka 			strcat(bootpath, kernel);
    139  1.1  pooka 			win = (loadit(bootpath, marks) == 0);
    140  1.1  pooka 			if (win) {
    141  1.1  pooka 				name = bootpath;
    142  1.1  pooka 			}
    143  1.1  pooka 		}
    144  1.1  pooka 	}
    145  1.1  pooka 	if (!win)
    146  1.1  pooka 		goto fail;
    147  1.1  pooka 
    148  1.1  pooka 	strncpy(bi_bpath.bootpath, name/*kernel?*/, BTINFO_BOOTPATH_LEN);
    149  1.1  pooka 	bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
    150  1.1  pooka 
    151  1.1  pooka 	entry = marks[MARK_ENTRY];
    152  1.1  pooka 	bi_syms.nsym = marks[MARK_NSYM];
    153  1.1  pooka 	bi_syms.ssym = marks[MARK_SYM];
    154  1.1  pooka 	bi_syms.esym = marks[MARK_END];
    155  1.1  pooka 	bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
    156  1.1  pooka 
    157  1.1  pooka 	printf("Starting at 0x%x\n\n", entry);
    158  1.1  pooka     call_kernel(entry, name, options, BOOTINFO_MAGIC, bootinfo);
    159  1.1  pooka 	(void)printf("KERNEL RETURNED!\n");
    160  1.1  pooka 
    161  1.1  pooka fail:
    162  1.1  pooka 	(void)printf("Boot failed!  Halting...\n");
    163  1.1  pooka }
    164  1.1  pooka 
    165  1.1  pooka static inline int
    166  1.1  pooka parse(char *cmd, char *kname, char *optarg)
    167  1.1  pooka {
    168  1.1  pooka     char *arg = cmd;
    169  1.1  pooka     char *ep, *p;
    170  1.1  pooka     int c, i;
    171  1.1  pooka 
    172  1.1  pooka     while ((c = *arg++)) {
    173  1.1  pooka         /* skip leading blanks */
    174  1.1  pooka         if (c == ' ' || c == '\t' || c == '\n')
    175  1.1  pooka             continue;
    176  1.1  pooka         /* find separator, or eol */
    177  1.1  pooka         for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
    178  1.1  pooka         ep = p;
    179  1.1  pooka         /* trim if separator */
    180  1.1  pooka         if (*p)
    181  1.1  pooka             *p++ = 0;
    182  1.1  pooka         /* token is either "-opts" or "kernelname" */
    183  1.1  pooka         if (c == '-') {
    184  1.1  pooka             /* no overflow because whole line same length as optarg anyways */
    185  1.1  pooka             while ((c = *arg++)) {
    186  1.1  pooka                 *optarg++ = c;
    187  1.1  pooka             }
    188  1.1  pooka             *optarg = 0;
    189  1.1  pooka         } else {
    190  1.1  pooka             arg--;
    191  1.1  pooka             if ((i = ep - arg)) {
    192  1.1  pooka                 if ((size_t)i >= PATH_MAX)
    193  1.1  pooka                     return -1;
    194  1.1  pooka                 memcpy(kname, arg, i + 1);
    195  1.1  pooka             }
    196  1.1  pooka         }
    197  1.1  pooka         arg = p;
    198  1.1  pooka     }
    199  1.1  pooka     return 0;
    200  1.1  pooka }
    201  1.1  pooka 
    202  1.1  pooka /* String returned is zero-terminated and at most PATH_MAX chars */
    203  1.1  pooka static inline void
    204  1.1  pooka getstr(char *cmd, int c)
    205  1.1  pooka {
    206  1.1  pooka     char *s;
    207  1.1  pooka 
    208  1.1  pooka     s = cmd;
    209  1.1  pooka     if (c == 0)
    210  1.1  pooka         c = GetChar();
    211  1.1  pooka     for (;;) {
    212  1.1  pooka         switch (c) {
    213  1.1  pooka         case 0:
    214  1.1  pooka             break;
    215  1.1  pooka         case '\177':
    216  1.1  pooka         case '\b':
    217  1.1  pooka             if (s > cmd) {
    218  1.1  pooka                 s--;
    219  1.1  pooka                 printf("\b \b");
    220  1.1  pooka             }
    221  1.1  pooka             break;
    222  1.1  pooka         case '\n':
    223  1.1  pooka         case '\r':
    224  1.1  pooka             *s = 0;
    225  1.1  pooka             return;
    226  1.1  pooka         default:
    227  1.1  pooka             if ((s - cmd) < (PATH_MAX - 1))
    228  1.1  pooka                 *s++ = c;
    229  1.1  pooka             xputchar(c);
    230  1.1  pooka         }
    231  1.1  pooka         c = GetChar();
    232  1.1  pooka     }
    233  1.1  pooka }
    234  1.1  pooka 
    235  1.1  pooka char *getboot(char *kname, char* optarg)
    236  1.1  pooka {
    237  1.1  pooka     char c = 0;
    238  1.1  pooka     char cmd[PATH_MAX];
    239  1.1  pooka 
    240  1.1  pooka     printf("\nDefault: %s%s %s\nboot: ", (*optarg) ? "-" : "", optarg, kname);
    241  1.1  pooka     if ((c = GetChar()) == -1)
    242  1.1  pooka         return NULL;
    243  1.1  pooka 
    244  1.1  pooka     cmd[0] = 0;
    245  1.1  pooka     getstr(cmd,c);
    246  1.1  pooka     xputchar('\n');
    247  1.1  pooka     if (parse(cmd,kname,optarg))
    248  1.1  pooka         xputchar('\a');
    249  1.1  pooka     else if (devcanon(kname) == 0)
    250  1.1  pooka         return kname;
    251  1.1  pooka     return NULL;
    252  1.1  pooka }
    253  1.1  pooka 
    254  1.1  pooka /*
    255  1.1  pooka  * Make bootpath canonical, provides defaults when missing
    256  1.1  pooka  */
    257  1.1  pooka static int
    258  1.1  pooka devcanon(char *fname)
    259  1.1  pooka {
    260  1.1  pooka 	int ctlr = 0, unit = 0, part = 0;
    261  1.1  pooka 	int c, rc;
    262  1.1  pooka 	char device_name[20];
    263  1.1  pooka     char file_name[PATH_MAX];
    264  1.1  pooka 	const char *cp;
    265  1.1  pooka 	char *ncp;
    266  1.1  pooka 
    267  1.1  pooka     //printf("devcanon(%s)\n",fname);
    268  1.1  pooka 
    269  1.1  pooka 	cp = fname;
    270  1.1  pooka 	ncp = device_name;
    271  1.1  pooka 
    272  1.1  pooka     /* expect a string like '0/ace(0,0)/netbsd' e.g. ctrl/name(unit,part)/file
    273  1.1  pooka      * Defaults: ctrl=0, name='ace', unit=0, part=0, file=<none>
    274  1.1  pooka      */
    275  1.1  pooka 
    276  1.1  pooka     /* get controller number */
    277  1.1  pooka     if ((c = *cp) >= '0' && c <= '9') {
    278  1.1  pooka         ctlr = c - '0';
    279  1.1  pooka         c = *++cp;
    280  1.1  pooka         if (c != '/')
    281  1.1  pooka             return (ENXIO);
    282  1.1  pooka         c = *++cp;
    283  1.1  pooka     }
    284  1.1  pooka 
    285  1.1  pooka     /* get device name */
    286  1.1  pooka     while ((c = *cp) != '\0') {
    287  1.1  pooka         if ((c == '(') || (c == '/')) {
    288  1.1  pooka             cp++;
    289  1.1  pooka             break;
    290  1.1  pooka         }
    291  1.1  pooka         if (ncp < device_name + sizeof(device_name) - 1)
    292  1.1  pooka             *ncp++ = c;
    293  1.1  pooka         cp++;
    294  1.1  pooka     }
    295  1.1  pooka     /* set default if missing */
    296  1.1  pooka     if (ncp == device_name) {
    297  1.1  pooka         strcpy(device_name,"ace");
    298  1.1  pooka         ncp += 3;
    299  1.1  pooka     }
    300  1.1  pooka 
    301  1.1  pooka     /* get device number */
    302  1.1  pooka     if ((c = *cp) >= '0' && c <= '9') {
    303  1.1  pooka         unit = c - '0';
    304  1.1  pooka         c = *++cp;
    305  1.1  pooka     }
    306  1.1  pooka 
    307  1.1  pooka     if (c == ',') {
    308  1.1  pooka         /* get partition number */
    309  1.1  pooka         if ((c = *++cp) >= '0' && c <= '9') {
    310  1.1  pooka             part = c - '0';
    311  1.1  pooka             c = *++cp;
    312  1.1  pooka         }
    313  1.1  pooka     }
    314  1.1  pooka 
    315  1.1  pooka     if (c == ')')
    316  1.1  pooka         c = *++cp;
    317  1.1  pooka     if (c == '/')
    318  1.1  pooka         cp++;
    319  1.1  pooka 
    320  1.1  pooka 	*ncp = '\0';
    321  1.1  pooka 
    322  1.1  pooka     /* Copy kernel name before we overwrite, then do it */
    323  1.1  pooka     strcpy(file_name, (*cp) ? cp : kernelnames[0]);
    324  1.1  pooka     sprintf(fname,"%c/%s(%c,%c)/%s",
    325  1.1  pooka             ctlr + '0', device_name, unit + '0', part + '0', file_name);
    326  1.1  pooka 
    327  1.1  pooka     //printf("devcanon -> %s\n",fname);
    328  1.1  pooka 
    329  1.1  pooka 	return (0);
    330  1.1  pooka }
    331