Home | History | Annotate | Line # | Download | only in boot
boot.c revision 1.2.2.1
      1 /*	$NetBSD: boot.c,v 1.2.2.1 1999/01/19 07:46:15 cgd Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1982, 1986, 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  * 	@(#)boot.c	8.1 (Berkeley) 6/10/93
     36  */
     37 
     38 #include <sys/param.h>
     39 #include <sys/reboot.h>
     40 #include <a.out.h>
     41 
     42 #include <lib/libsa/stand.h>
     43 
     44 #include <sparc/stand/common/promdev.h>
     45 
     46 static void copyunix __P((int, char *));
     47 static void promsyms __P((int, struct exec *));
     48 int debug;
     49 int netif_debug;
     50 
     51 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
     52 unsigned long		esym;
     53 char			*strtab;
     54 int			strtablen;
     55 char			fbuf[80], dbuf[128];
     56 
     57 typedef void (*entry_t)__P((caddr_t, int, int, int, long, long));
     58 
     59 void	loadfile __P((int, caddr_t));
     60 
     61 /*
     62  * Boot device is derived from ROM provided information, or if there is none,
     63  * this list is used in sequence, to find a kernel.
     64  */
     65 char *kernels[] = {
     66 	"netbsd",
     67 	"netbsd.gz",
     68 	"netbsd.old",
     69 	"netbsd.old.gz",
     70 	"onetbsd",
     71 	"onetbsd.gz",
     72 	"vmunix",
     73 #ifdef notyet
     74 	"netbsd.pl",
     75 	"netbsd.pl.gz",
     76 	"netbsd.el",
     77 	"netbsd.el.gz",
     78 #endif
     79 	NULL
     80 };
     81 
     82 main()
     83 {
     84 	int	io, i;
     85 	char	*kernel;
     86 
     87 	prom_init();
     88 
     89 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
     90 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
     91 
     92 	/*
     93 	 * get default kernel.
     94 	 */
     95 	if (prom_bootfile && *prom_bootfile) {
     96 		i = -1;	/* not using the kernels */
     97 		kernel = prom_bootfile;
     98 	} else {
     99 		i = 0;
    100 		kernel = kernels[i];
    101 	}
    102 
    103 	for (;;) {
    104 		/*
    105 		 * ask for a kernel first ..
    106 		 */
    107 		if (prom_boothow & RB_ASKNAME) {
    108 			printf("device[%s] (\"halt\" to halt): ",
    109 			   prom_bootdevice);
    110 			gets(dbuf);
    111 			if (strcmp(dbuf, "halt") == 0)
    112 				_rtt();
    113 			if (dbuf[0])
    114 				prom_bootdevice = dbuf;
    115 			printf("boot (press RETURN to try default list): ");
    116 			gets(fbuf);
    117 			if (fbuf[0])
    118 				kernel = fbuf;
    119 			else {
    120 				prom_boothow &= ~RB_ASKNAME;
    121 				i = 0;
    122 				kernel = kernels[i];
    123 			}
    124 		}
    125 
    126 		if ((io = open(kernel, 0)) >= 0)
    127 			break;
    128 		printf("open: %s: %s", kernel, strerror(errno));
    129 
    130 		/*
    131 		 * if we have are not in askname mode, and we aren't using the
    132 		 * prom bootfile, try the next one (if it exits).  otherwise,
    133 		 * go into askname mode.
    134 		 */
    135 		if ((prom_boothow & RB_ASKNAME) == 0 &&
    136 		    i != -1 && kernels[++i]) {
    137 			kernel = kernels[i];
    138 			printf(": trying %s...\n", kernel);
    139 		} else {
    140 			printf("\n");
    141 			prom_boothow |= RB_ASKNAME;
    142 		}
    143 	}
    144 
    145 	/*
    146 	 * XXX
    147 	 * make loadfile() return a value, so that if the load of the kernel
    148 	 * fails, we can jump back and try another kernel in the list.
    149 	 */
    150 	printf("Booting %s @ 0x%x\n", kernel, LOADADDR);
    151 	loadfile(io, LOADADDR);
    152 
    153 	_rtt();
    154 }
    155 
    156 void
    157 loadfile(io, addr)
    158 	register int	io;
    159 	register caddr_t addr;
    160 {
    161 	register entry_t entry = (entry_t)LOADADDR;
    162 	struct exec x;
    163 	int i;
    164 
    165 	i = read(io, (char *)&x, sizeof(x));
    166 	if (i != sizeof(x) ||
    167 	    N_BADMAG(x)) {
    168 		printf("Bad format\n");
    169 		return;
    170 	}
    171 	printf("%d", x.a_text);
    172 	if (N_GETMAGIC(x) == ZMAGIC) {
    173 		entry = (entry_t)(addr+sizeof(struct exec));
    174 		addr += sizeof(struct exec);
    175 	}
    176 	if (read(io, (char *)addr, x.a_text) != x.a_text)
    177 		goto shread;
    178 	addr += x.a_text;
    179 	if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC)
    180 		while ((int)addr & __LDPGSZ)
    181 			*addr++ = 0;
    182 	printf("+%d", x.a_data);
    183 	if (read(io, addr, x.a_data) != x.a_data)
    184 		goto shread;
    185 	addr += x.a_data;
    186 	printf("+%d", x.a_bss);
    187 	for (i = 0; i < x.a_bss; i++)
    188 		*addr++ = 0;
    189 	if (x.a_syms != 0) {
    190 		bcopy(&x.a_syms, addr, sizeof(x.a_syms));
    191 		addr += sizeof(x.a_syms);
    192 		printf("+[%d", x.a_syms);
    193 		if (read(io, addr, x.a_syms) != x.a_syms)
    194 			goto shread;
    195 		addr += x.a_syms;
    196 
    197 		if (read(io, &strtablen, sizeof(int)) != sizeof(int))
    198 			goto shread;
    199 
    200 		bcopy(&strtablen, addr, sizeof(int));
    201 		if (i = strtablen) {
    202 			i -= sizeof(int);
    203 			addr += sizeof(int);
    204 			if (read(io, addr, i) != i)
    205 			    goto shread;
    206 			addr += i;
    207 		}
    208 		printf("+%d]", i);
    209 		esym = ((u_int)x.a_entry - (u_int)LOADADDR) +
    210 			(((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1));
    211 #if 0
    212 		/*
    213 		 * The FORTH word `loadsyms' is mentioned in the
    214 		 * "Openboot command reference" book, but it seems it has
    215 		 * not been implemented on at least one machine..
    216 		 */
    217 		promsyms(io, &x);
    218 #endif
    219 	}
    220 	printf("=0x%x\n", addr);
    221 	close(io);
    222 
    223 	/* Note: args 2-4 not used due to conflicts with SunOS loaders */
    224 	(*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec,
    225 		 0, 0, 0, esym, DDB_MAGIC1);
    226 	return;
    227 
    228 shread:
    229 	printf("boot: short read\n");
    230 	return;
    231 }
    232 
    233 #if 0
    234 struct syms {
    235 	u_int32_t	value;
    236 	u_int32_t	index;
    237 };
    238 
    239 static void
    240 sort(syms, n)
    241 	struct syms *syms;
    242 	int n;
    243 {
    244 	register struct syms *sj;
    245 	register int i, j, k;
    246 	register u_int32_t value, index;
    247 
    248 	/* Insertion sort.  This is O(n^2), but so what? */
    249 	for (i = 1; i < n; i++) {
    250 		/* save i'th entry */
    251 		value = syms[i].value;
    252 		index = syms[i].index;
    253 		/* find j such that i'th entry goes before j'th */
    254 		for (j = 0, sj = syms; j < i; j++, sj++)
    255 			if (value < sj->value)
    256 				break;
    257 		/* slide up any additional entries */
    258 		for (k = 0; k < (i - j); k++) {
    259 			sj[k+1].value = sj[k].value;
    260 			sj[k+1].index = sj[k].index;
    261 		}
    262 		sj->value = value;
    263 		sj->index = index;
    264 	}
    265 }
    266 
    267 void
    268 promsyms(fd, hp)
    269 	int fd;
    270 	struct exec *hp;
    271 {
    272 	int i, n, strtablen;
    273 	char *str, *p, *cp, buf[128];
    274 	struct syms *syms;
    275 
    276 	lseek(fd, sizeof(*hp)+hp->a_text+hp->a_data, SEEK_SET);
    277 	n = hp->a_syms/sizeof(struct nlist);
    278 	if (n == 0)
    279 		return;
    280 	syms = (struct syms *)alloc(n * sizeof(struct syms));
    281 
    282 	printf("+[%x+", hp->a_syms);
    283 	for (i = 0; i < n; i++) {
    284 		struct nlist nlist;
    285 
    286 		if (read(fd, &nlist, sizeof(nlist)) != sizeof(nlist)) {
    287 			printf("promsyms: read failed\n");
    288 			return;
    289 		}
    290 		syms[i].value = nlist.n_value;
    291 		syms[i].index = nlist.n_un.n_strx - sizeof(strtablen);
    292 	}
    293 
    294 	sort(syms, n);
    295 
    296 	if (read(fd, &strtablen, sizeof(strtablen)) != sizeof(strtablen)) {
    297 		printf("promsym: read failed (strtablen)\n");
    298 		return;
    299 	}
    300 	if (strtablen < sizeof(strtablen)) {
    301 		printf("promsym: string table corrupted\n");
    302 		return;
    303 	}
    304 	strtablen -= sizeof(strtablen);
    305 	str = (char *)alloc(strtablen);
    306 
    307 	printf("%x]", strtablen);
    308 	if (read(fd, str, strtablen) != strtablen) {
    309 		printf("promsym: read failed (strtab)\n");
    310 		return;
    311 	}
    312 
    313 	sprintf(buf, "%x %d %x loadsyms", syms, n, str);
    314 	(promvec->pv_fortheval.v2_eval)(buf);
    315 }
    316 #endif
    317