xref: /netbsd-src/sys/arch/sparc/stand/boot/boot.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: boot.c,v 1.2 1997/09/14 19:27:21 pk 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 /*
52  * Boot device is derived from ROM provided information.
53  */
54 #define	DEFAULT_KERNEL	"netbsd"
55 
56 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
57 unsigned long		esym;
58 char			*strtab;
59 int			strtablen;
60 char			fbuf[80], dbuf[128];
61 
62 typedef void (*entry_t)__P((caddr_t, int, int, int, long, long));
63 
64 void	loadfile __P((int, caddr_t));
65 
66 main()
67 {
68 	int	io;
69 	char	*file;
70 
71 	prom_init();
72 
73 	printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
74 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
75 
76 	file = prom_bootfile;
77 	if (file == 0 || *file == 0)
78 		file = DEFAULT_KERNEL;
79 
80 	for (;;) {
81 		if (prom_boothow & RB_ASKNAME) {
82 			printf("device[%s]: ", prom_bootdevice);
83 			gets(dbuf);
84 			if (dbuf[0])
85 				prom_bootdevice = dbuf;
86 			printf("boot: ");
87 			gets(fbuf);
88 			if (fbuf[0])
89 				file = fbuf;
90 		}
91 		if ((io = open(file, 0)) >= 0)
92 			break;
93 		printf("open: %s: %s\n", file, strerror(errno));
94 		prom_boothow |= RB_ASKNAME;
95 	}
96 
97 	printf("Booting %s @ 0x%x\n", file, LOADADDR);
98 	loadfile(io, LOADADDR);
99 
100 	_rtt();
101 }
102 
103 void
104 loadfile(io, addr)
105 	register int	io;
106 	register caddr_t addr;
107 {
108 	register entry_t entry = (entry_t)LOADADDR;
109 	struct exec x;
110 	int i;
111 
112 	i = read(io, (char *)&x, sizeof(x));
113 	if (i != sizeof(x) ||
114 	    N_BADMAG(x)) {
115 		printf("Bad format\n");
116 		return;
117 	}
118 	printf("%d", x.a_text);
119 	if (N_GETMAGIC(x) == ZMAGIC) {
120 		entry = (entry_t)(addr+sizeof(struct exec));
121 		addr += sizeof(struct exec);
122 	}
123 	if (read(io, (char *)addr, x.a_text) != x.a_text)
124 		goto shread;
125 	addr += x.a_text;
126 	if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC)
127 		while ((int)addr & __LDPGSZ)
128 			*addr++ = 0;
129 	printf("+%d", x.a_data);
130 	if (read(io, addr, x.a_data) != x.a_data)
131 		goto shread;
132 	addr += x.a_data;
133 	printf("+%d", x.a_bss);
134 	for (i = 0; i < x.a_bss; i++)
135 		*addr++ = 0;
136 	if (x.a_syms != 0) {
137 		bcopy(&x.a_syms, addr, sizeof(x.a_syms));
138 		addr += sizeof(x.a_syms);
139 		printf("+[%d", x.a_syms);
140 		if (read(io, addr, x.a_syms) != x.a_syms)
141 			goto shread;
142 		addr += x.a_syms;
143 
144 		if (read(io, &strtablen, sizeof(int)) != sizeof(int))
145 			goto shread;
146 
147 		bcopy(&strtablen, addr, sizeof(int));
148 		if (i = strtablen) {
149 			i -= sizeof(int);
150 			addr += sizeof(int);
151 			if (read(io, addr, i) != i)
152 			    goto shread;
153 			addr += i;
154 		}
155 		printf("+%d]", i);
156 		esym = ((u_int)x.a_entry - (u_int)LOADADDR) +
157 			(((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1));
158 #if 0
159 		/*
160 		 * The FORTH word `loadsyms' is mentioned in the
161 		 * "Openboot command reference" book, but it seems it has
162 		 * not been implemented on at least one machine..
163 		 */
164 		promsyms(io, &x);
165 #endif
166 	}
167 	printf("=0x%x\n", addr);
168 	close(io);
169 
170 	/* Note: args 2-4 not used due to conflicts with SunOS loaders */
171 	(*entry)(cputyp == CPU_SUN4 ? LOADADDR : (caddr_t)promvec,
172 		 0, 0, 0, esym, DDB_MAGIC1);
173 	return;
174 
175 shread:
176 	printf("boot: short read\n");
177 	return;
178 }
179 
180 #if 0
181 struct syms {
182 	u_int32_t	value;
183 	u_int32_t	index;
184 };
185 
186 static void
187 sort(syms, n)
188 	struct syms *syms;
189 	int n;
190 {
191 	register struct syms *sj;
192 	register int i, j, k;
193 	register u_int32_t value, index;
194 
195 	/* Insertion sort.  This is O(n^2), but so what? */
196 	for (i = 1; i < n; i++) {
197 		/* save i'th entry */
198 		value = syms[i].value;
199 		index = syms[i].index;
200 		/* find j such that i'th entry goes before j'th */
201 		for (j = 0, sj = syms; j < i; j++, sj++)
202 			if (value < sj->value)
203 				break;
204 		/* slide up any additional entries */
205 		for (k = 0; k < (i - j); k++) {
206 			sj[k+1].value = sj[k].value;
207 			sj[k+1].index = sj[k].index;
208 		}
209 		sj->value = value;
210 		sj->index = index;
211 	}
212 }
213 
214 void
215 promsyms(fd, hp)
216 	int fd;
217 	struct exec *hp;
218 {
219 	int i, n, strtablen;
220 	char *str, *p, *cp, buf[128];
221 	struct syms *syms;
222 
223 	lseek(fd, sizeof(*hp)+hp->a_text+hp->a_data, SEEK_SET);
224 	n = hp->a_syms/sizeof(struct nlist);
225 	if (n == 0)
226 		return;
227 	syms = (struct syms *)alloc(n * sizeof(struct syms));
228 
229 	printf("+[%x+", hp->a_syms);
230 	for (i = 0; i < n; i++) {
231 		struct nlist nlist;
232 
233 		if (read(fd, &nlist, sizeof(nlist)) != sizeof(nlist)) {
234 			printf("promsyms: read failed\n");
235 			return;
236 		}
237 		syms[i].value = nlist.n_value;
238 		syms[i].index = nlist.n_un.n_strx - sizeof(strtablen);
239 	}
240 
241 	sort(syms, n);
242 
243 	if (read(fd, &strtablen, sizeof(strtablen)) != sizeof(strtablen)) {
244 		printf("promsym: read failed (strtablen)\n");
245 		return;
246 	}
247 	if (strtablen < sizeof(strtablen)) {
248 		printf("promsym: string table corrupted\n");
249 		return;
250 	}
251 	strtablen -= sizeof(strtablen);
252 	str = (char *)alloc(strtablen);
253 
254 	printf("%x]", strtablen);
255 	if (read(fd, str, strtablen) != strtablen) {
256 		printf("promsym: read failed (strtab)\n");
257 		return;
258 	}
259 
260 	sprintf(buf, "%x %d %x loadsyms", syms, n, str);
261 	(promvec->pv_fortheval.v2_eval)(buf);
262 }
263 #endif
264