boot.c revision 1.14 1 /* $NetBSD: boot.c,v 1.14 2003/02/25 08:09:30 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 <sys/boot_flag.h>
41 #include <sys/exec.h>
42
43 #include <lib/libsa/stand.h>
44 #include <lib/libsa/loadfile.h>
45
46 #include <machine/promlib.h>
47 #include <sparc/stand/common/promdev.h>
48
49 #include "bootinfo.h"
50
51 extern void prom_patch __P((void)); /* prompatch.c */
52
53 static int bootoptions __P((char *));
54
55 int boothowto;
56 int debug;
57 int netif_debug;
58
59 char fbuf[80], dbuf[128];
60 u_long maxkernsize;
61
62 extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[];
63
64 int main __P((void));
65 typedef void (*entry_t)__P((caddr_t, int, int, int, long, long));
66
67 /*
68 * Boot device is derived from ROM provided information, or if there is none,
69 * this list is used in sequence, to find a kernel.
70 */
71 char *kernels[] = {
72 "netbsd",
73 "netbsd.gz",
74 "netbsd.old",
75 "netbsd.old.gz",
76 "onetbsd",
77 "onetbsd.gz",
78 "vmunix",
79 #ifdef notyet
80 "netbsd.pl",
81 "netbsd.pl.gz",
82 "netbsd.el",
83 "netbsd.el.gz",
84 #endif
85 NULL
86 };
87
88 int
89 bootoptions(ap)
90 char *ap;
91 {
92 int v = 0;
93 if (ap == NULL || *ap++ != '-')
94 return (0);
95
96 while (*ap != '\0' && *ap != ' ' && *ap != '\t' && *ap != '\n') {
97 BOOT_FLAG(*ap, v);
98 ap++;
99 }
100
101 if ((v & RB_KDB) != 0)
102 debug = 1;
103
104 return (v);
105 }
106
107 static int
108 loadk(char *kernel, u_long *marks)
109 {
110 int fd, error;
111 u_long size;
112
113 if ((fd = open(kernel, 0)) < 0)
114 return (errno ? errno : ENOENT);
115
116 marks[MARK_START] = 0;
117 if ((error = fdloadfile(fd, marks, COUNT_KERNEL)) != 0)
118 goto out;
119
120 size = marks[MARK_END] - marks[MARK_START];
121 if (size > maxkernsize) {
122 printf("kernel too large: %lu"
123 " (maximum kernel size is %lu)\n",
124 marks[MARK_END] - marks[MARK_START],
125 maxkernsize);
126 error = EFBIG;
127 goto out;
128 }
129
130 marks[MARK_START] = 0;
131 error = fdloadfile(fd, marks, LOAD_KERNEL);
132 out:
133 close(fd);
134 return (error);
135 }
136
137 int
138 main()
139 {
140 int error, i;
141 char *kernel;
142 u_long marks[MARK_MAX], bootinfo;
143 struct btinfo_symtab bi_sym;
144 void *arg;
145
146 #ifdef HEAP_VARIABLE
147 {
148 extern char end[];
149 setheap((void *)ALIGN(end), (void *)0xffffffff);
150 }
151 #endif
152 {
153 /*
154 * Find maximum the kernel size that we can handle.
155 * Our stack grows down from label `start'; assume
156 * we need no more that 16K of stack space.
157 */
158 extern char start[]; /* top of stack (see srt0.S) */
159 maxkernsize = (u_long)start - (16*1024) - PROM_LOADADDR;
160
161 }
162 prom_init();
163
164 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
165 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
166
167 /* massage machine prom */
168 prom_patch();
169
170 /*
171 * get default kernel.
172 */
173 prom_bootdevice = prom_getbootpath();
174 kernel = prom_getbootfile();
175 boothowto = bootoptions(prom_getbootargs());
176
177 if (kernel != NULL && *kernel != '\0') {
178 i = -1; /* not using the kernels */
179 } else {
180 i = 0;
181 kernel = kernels[i];
182 }
183
184 for (;;) {
185 /*
186 * ask for a kernel first ..
187 */
188 if (boothowto & RB_ASKNAME) {
189 printf("device[%s] (\"halt\" to halt): ",
190 prom_bootdevice);
191 gets(dbuf);
192 if (strcmp(dbuf, "halt") == 0)
193 _rtt();
194 if (dbuf[0])
195 prom_bootdevice = dbuf;
196 printf("boot (press RETURN to try default list): ");
197 gets(fbuf);
198 if (fbuf[0])
199 kernel = fbuf;
200 else {
201 boothowto &= ~RB_ASKNAME;
202 i = 0;
203 kernel = kernels[i];
204 }
205 }
206
207 printf("Booting %s\n", kernel);
208 if ((error = loadk(kernel, marks)) == 0)
209 break;
210
211 if (error != ENOENT) {
212 printf("Cannot load %s: error=%d\n", kernel, error);
213 boothowto |= RB_ASKNAME;
214 }
215
216 /*
217 * if we have are not in askname mode, and we aren't using the
218 * prom bootfile, try the next one (if it exits). otherwise,
219 * go into askname mode.
220 */
221 if ((boothowto & RB_ASKNAME) == 0 &&
222 i != -1 && kernels[++i]) {
223 kernel = kernels[i];
224 printf(": trying %s...\n", kernel);
225 } else {
226 printf("\n");
227 boothowto |= RB_ASKNAME;
228 }
229 }
230
231 marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) &
232 (-sizeof(int));
233 arg = (prom_version() == PROM_OLDMON) ? (caddr_t)PROM_LOADADDR : romp;
234
235 /* Should work with both a.out and ELF, but somehow ELF is busted */
236 bootinfo = bi_init(marks[MARK_END]);
237
238 bi_sym.nsym = marks[MARK_NSYM];
239 bi_sym.ssym = marks[MARK_SYM];
240 bi_sym.esym = marks[MARK_END];
241 bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym));
242
243 /*
244 * Add kernel path to bootinfo
245 */
246 i = sizeof(struct btinfo_common) + strlen(kernel) + 1;
247 /* Impose limit (somewhat arbitrary) */
248 if (i < BOOTINFO_SIZE / 2) {
249 union {
250 struct btinfo_kernelfile bi_file;
251 char x[i];
252 } U;
253 strcpy(U.bi_file.name, kernel);
254 bi_add(&U.bi_file, BTINFO_KERNELFILE, i);
255 }
256
257 (*(entry_t)marks[MARK_ENTRY])(arg, 0, 0, 0, bootinfo, DDB_MAGIC2);
258 _rtt();
259 }
260