boot.c revision 1.3 1 /* $NetBSD: boot.c,v 1.3 1998/08/29 06:40:43 mrg 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