boot.c revision 1.6.2.3 1 1.6.2.3 joerg /* $NetBSD: boot.c,v 1.6.2.3 2007/10/31 23:13:56 joerg Exp $ */
2 1.6.2.2 jmcneill
3 1.6.2.2 jmcneill /*-
4 1.6.2.2 jmcneill * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 1.6.2.2 jmcneill * All rights reserved.
6 1.6.2.2 jmcneill *
7 1.6.2.2 jmcneill * This code is derived from software contributed to The NetBSD Foundation
8 1.6.2.2 jmcneill * by Jonathan Stone, Michael Hitch, Simon Burge and Wayne Knowles.
9 1.6.2.2 jmcneill *
10 1.6.2.2 jmcneill * Redistribution and use in source and binary forms, with or without
11 1.6.2.2 jmcneill * modification, are permitted provided that the following conditions
12 1.6.2.2 jmcneill * are met:
13 1.6.2.2 jmcneill * 1. Redistributions of source code must retain the above copyright
14 1.6.2.2 jmcneill * notice, this list of conditions and the following disclaimer.
15 1.6.2.2 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
16 1.6.2.2 jmcneill * notice, this list of conditions and the following disclaimer in the
17 1.6.2.2 jmcneill * documentation and/or other materials provided with the distribution.
18 1.6.2.2 jmcneill * 3. All advertising materials mentioning features or use of this software
19 1.6.2.2 jmcneill * must display the following acknowledgement:
20 1.6.2.2 jmcneill * This product includes software developed by the NetBSD
21 1.6.2.2 jmcneill * Foundation, Inc. and its contributors.
22 1.6.2.2 jmcneill * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.6.2.2 jmcneill * contributors may be used to endorse or promote products derived
24 1.6.2.2 jmcneill * from this software without specific prior written permission.
25 1.6.2.2 jmcneill *
26 1.6.2.2 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.6.2.2 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.6.2.2 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.6.2.2 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.6.2.2 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.6.2.2 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.6.2.2 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.6.2.2 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.6.2.2 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.6.2.2 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.6.2.2 jmcneill * POSSIBILITY OF SUCH DAMAGE.
37 1.6.2.2 jmcneill */
38 1.6.2.2 jmcneill
39 1.6.2.2 jmcneill /*
40 1.6.2.2 jmcneill * Copyright (c) 1992, 1993
41 1.6.2.2 jmcneill * The Regents of the University of California. All rights reserved.
42 1.6.2.2 jmcneill *
43 1.6.2.2 jmcneill * This code is derived from software contributed to Berkeley by
44 1.6.2.2 jmcneill * Ralph Campbell.
45 1.6.2.2 jmcneill *
46 1.6.2.2 jmcneill * Redistribution and use in source and binary forms, with or without
47 1.6.2.2 jmcneill * modification, are permitted provided that the following conditions
48 1.6.2.2 jmcneill * are met:
49 1.6.2.2 jmcneill * 1. Redistributions of source code must retain the above copyright
50 1.6.2.2 jmcneill * notice, this list of conditions and the following disclaimer.
51 1.6.2.2 jmcneill * 2. Redistributions in binary form must reproduce the above copyright
52 1.6.2.2 jmcneill * notice, this list of conditions and the following disclaimer in the
53 1.6.2.2 jmcneill * documentation and/or other materials provided with the distribution.
54 1.6.2.2 jmcneill * 3. Neither the name of the University nor the names of its contributors
55 1.6.2.2 jmcneill * may be used to endorse or promote products derived from this software
56 1.6.2.2 jmcneill * without specific prior written permission.
57 1.6.2.2 jmcneill *
58 1.6.2.2 jmcneill * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.6.2.2 jmcneill * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.6.2.2 jmcneill * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.6.2.2 jmcneill * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.6.2.2 jmcneill * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.6.2.2 jmcneill * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.6.2.2 jmcneill * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.6.2.2 jmcneill * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.6.2.2 jmcneill * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.6.2.2 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.6.2.2 jmcneill * SUCH DAMAGE.
69 1.6.2.2 jmcneill *
70 1.6.2.2 jmcneill * @(#)boot.c 8.1 (Berkeley) 6/10/93
71 1.6.2.2 jmcneill */
72 1.6.2.2 jmcneill
73 1.6.2.2 jmcneill #include <machine/cpu.h>
74 1.6.2.2 jmcneill #include <machine/leds.h>
75 1.6.2.2 jmcneill
76 1.6.2.2 jmcneill #include <lib/libsa/stand.h>
77 1.6.2.2 jmcneill #include <lib/libsa/loadfile.h>
78 1.6.2.3 joerg #include <lib/libsa/dev_net.h>
79 1.6.2.2 jmcneill #include <lib/libkern/libkern.h>
80 1.6.2.2 jmcneill
81 1.6.2.2 jmcneill #include <sys/param.h>
82 1.6.2.2 jmcneill #include <sys/boot_flag.h>
83 1.6.2.2 jmcneill #include <sys/exec.h>
84 1.6.2.2 jmcneill #include <sys/exec_elf.h>
85 1.6.2.2 jmcneill
86 1.6.2.2 jmcneill #include "boot.h"
87 1.6.2.2 jmcneill #include "cons.h"
88 1.6.2.2 jmcneill #include "common.h"
89 1.6.2.2 jmcneill #include "bootinfo.h"
90 1.6.2.2 jmcneill
91 1.6.2.2 jmcneill char *kernelnames[] = {
92 1.6.2.2 jmcneill "netbsd",
93 1.6.2.2 jmcneill "netbsd.gz",
94 1.6.2.2 jmcneill "onetbsd",
95 1.6.2.2 jmcneill "onetbsd.gz",
96 1.6.2.2 jmcneill "netbsd.bak",
97 1.6.2.2 jmcneill "netbsd.bak.gz",
98 1.6.2.2 jmcneill "netbsd.old",
99 1.6.2.2 jmcneill "netbsd.old.gz",
100 1.6.2.2 jmcneill "netbsd.cobalt",
101 1.6.2.2 jmcneill "netbsd.cobalt.gz",
102 1.6.2.2 jmcneill "netbsd.elf",
103 1.6.2.2 jmcneill "netbsd.elf.gz",
104 1.6.2.2 jmcneill NULL
105 1.6.2.2 jmcneill };
106 1.6.2.2 jmcneill
107 1.6.2.2 jmcneill extern u_long end; /* Boot loader code end address */
108 1.6.2.2 jmcneill void start(void);
109 1.6.2.2 jmcneill
110 1.6.2.2 jmcneill static char *bootstring;
111 1.6.2.2 jmcneill
112 1.6.2.3 joerg static int patch_bootstring(char *bootspec);
113 1.6.2.2 jmcneill static int get_bsdbootname(char **, char **, int *);
114 1.6.2.2 jmcneill static int parse_bootname(char *, int, char **, char **);
115 1.6.2.3 joerg static void prominit(unsigned int memsize);
116 1.6.2.3 joerg static void print_banner(unsigned int memsize);
117 1.6.2.2 jmcneill
118 1.6.2.3 joerg void cpu_reboot(void);
119 1.6.2.2 jmcneill
120 1.6.2.2 jmcneill int main(unsigned int memsize);
121 1.6.2.2 jmcneill
122 1.6.2.2 jmcneill /*
123 1.6.2.2 jmcneill * Perform CPU reboot.
124 1.6.2.2 jmcneill */
125 1.6.2.3 joerg void
126 1.6.2.2 jmcneill cpu_reboot(void)
127 1.6.2.2 jmcneill {
128 1.6.2.3 joerg
129 1.6.2.2 jmcneill printf("rebooting...\n\n");
130 1.6.2.2 jmcneill
131 1.6.2.2 jmcneill *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
132 1.6.2.2 jmcneill printf("WARNING: reboot failed!\n");
133 1.6.2.2 jmcneill
134 1.6.2.2 jmcneill for (;;)
135 1.6.2.2 jmcneill ;
136 1.6.2.2 jmcneill }
137 1.6.2.2 jmcneill
138 1.6.2.2 jmcneill /*
139 1.6.2.2 jmcneill * Substitute root value with NetBSD root partition name.
140 1.6.2.2 jmcneill */
141 1.6.2.2 jmcneill int
142 1.6.2.2 jmcneill patch_bootstring(char *bootspec)
143 1.6.2.2 jmcneill {
144 1.6.2.2 jmcneill char *sp = bootstring;
145 1.6.2.2 jmcneill uint8_t unit, part;
146 1.6.2.3 joerg int dev;
147 1.6.2.2 jmcneill char *file;
148 1.6.2.2 jmcneill
149 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: %s\n", bootspec));
150 1.6.2.2 jmcneill
151 1.6.2.2 jmcneill /* get boot parameters */
152 1.6.2.2 jmcneill if (devparse(bootspec, &dev, &unit, &part, (const char **)&file) != 0)
153 1.6.2.2 jmcneill unit = part = 0;
154 1.6.2.2 jmcneill
155 1.6.2.3 joerg DPRINTF(("patch_bootstring: unit = %d, part = %d\n", unit, part));
156 1.6.2.2 jmcneill
157 1.6.2.2 jmcneill /* take out the 'root=xxx' parameter */
158 1.6.2.2 jmcneill if ((sp = strstr(bootstring, "root=")) != NULL) {
159 1.6.2.2 jmcneill const char *end;
160 1.6.2.2 jmcneill
161 1.6.2.2 jmcneill end = strchr(sp, ' ');
162 1.6.2.2 jmcneill
163 1.6.2.2 jmcneill /* strip off leading spaces */
164 1.6.2.2 jmcneill for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
165 1.6.2.2 jmcneill ;
166 1.6.2.2 jmcneill
167 1.6.2.2 jmcneill if (end != NULL)
168 1.6.2.2 jmcneill strcpy(++sp, end);
169 1.6.2.2 jmcneill else
170 1.6.2.2 jmcneill *++sp = '\0';
171 1.6.2.2 jmcneill }
172 1.6.2.2 jmcneill
173 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: [%s]\n", bootstring));
174 1.6.2.2 jmcneill
175 1.6.2.2 jmcneill #define DEVNAMESIZE (MAXDEVNAME + sizeof(" root=/dev/hd") + sizeof("0a"))
176 1.6.2.3 joerg if (strcmp(devsw[dev].dv_name, "wd") == 0 &&
177 1.6.2.3 joerg strlen(bootstring) <= (511 - DEVNAMESIZE)) {
178 1.6.2.2 jmcneill int len;
179 1.6.2.2 jmcneill
180 1.6.2.3 joerg /* omit "nfsroot=" arg on wd boot */
181 1.6.2.3 joerg if ((sp = strstr(bootstring, "nfsroot=")) != NULL) {
182 1.6.2.3 joerg const char *end;
183 1.6.2.3 joerg
184 1.6.2.3 joerg end = strchr(sp, ' ');
185 1.6.2.3 joerg
186 1.6.2.3 joerg /* strip off leading spaces */
187 1.6.2.3 joerg for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
188 1.6.2.3 joerg ;
189 1.6.2.3 joerg
190 1.6.2.3 joerg if (end != NULL)
191 1.6.2.3 joerg strcpy(++sp, end);
192 1.6.2.3 joerg else
193 1.6.2.3 joerg *++sp = '\0';
194 1.6.2.3 joerg }
195 1.6.2.3 joerg
196 1.6.2.3 joerg /* bsd notation -> linux notation (wd0a -> hda1) */
197 1.6.2.2 jmcneill strcat(bootstring, " root=/dev/hd");
198 1.6.2.2 jmcneill
199 1.6.2.2 jmcneill len = strlen(bootstring);
200 1.6.2.2 jmcneill bootstring[len++] = unit + 'a';
201 1.6.2.2 jmcneill bootstring[len++] = part + '1';
202 1.6.2.2 jmcneill bootstring[len++] = '\0';
203 1.6.2.2 jmcneill }
204 1.6.2.2 jmcneill
205 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: -> %s\n", bootstring));
206 1.6.2.2 jmcneill return 0;
207 1.6.2.2 jmcneill }
208 1.6.2.2 jmcneill
209 1.6.2.2 jmcneill /*
210 1.6.2.2 jmcneill * Extract NetBSD boot specification
211 1.6.2.2 jmcneill */
212 1.6.2.2 jmcneill static int
213 1.6.2.2 jmcneill get_bsdbootname(char **dev, char **kname, int *howtop)
214 1.6.2.2 jmcneill {
215 1.6.2.3 joerg int len;
216 1.6.2.2 jmcneill int bootunit, bootpart;
217 1.6.2.2 jmcneill char *bootstr_dev, *bootstr_kname;
218 1.6.2.2 jmcneill char *prompt_dev, *prompt_kname;
219 1.6.2.2 jmcneill char *ptr, *spec;
220 1.6.2.2 jmcneill char c, namebuf[PATH_MAX];
221 1.6.2.2 jmcneill static char bootdev[] = "wd0a";
222 1.6.2.3 joerg static char nfsbootdev[] = "nfs";
223 1.6.2.2 jmcneill
224 1.6.2.2 jmcneill bootstr_dev = prompt_dev = NULL;
225 1.6.2.2 jmcneill bootstr_kname = prompt_kname = NULL;
226 1.6.2.2 jmcneill
227 1.6.2.2 jmcneill /* first, get root device specified by the firmware */
228 1.6.2.2 jmcneill spec = bootstring;
229 1.6.2.3 joerg
230 1.6.2.2 jmcneill /* assume the last one is valid */
231 1.6.2.2 jmcneill while ((spec = strstr(spec, "root=")) != NULL) {
232 1.6.2.2 jmcneill spec += 5; /* skip 'root=' */
233 1.6.2.2 jmcneill ptr = strchr(spec, ' ');
234 1.6.2.2 jmcneill len = (ptr == NULL) ? strlen(spec) : ptr - spec;
235 1.6.2.2 jmcneill /* decode unit and part from "/dev/hd[ab][1-4]" strings */
236 1.6.2.2 jmcneill if (len == 9 && memcmp("/dev/hd", spec, 7) == 0) {
237 1.6.2.2 jmcneill bootunit = spec[7] - 'a';
238 1.6.2.2 jmcneill bootpart = spec[8] - '1';
239 1.6.2.2 jmcneill if (bootunit >= 0 && bootunit < 2 &&
240 1.6.2.2 jmcneill bootpart >= 0 && bootpart < 4) {
241 1.6.2.2 jmcneill bootdev[sizeof(bootdev) - 3] = '0' + bootunit;
242 1.6.2.2 jmcneill #if 0 /* bootpart is fdisk partition of Linux root */
243 1.6.2.2 jmcneill bootdev[sizeof(bootdev) - 2] = 'a' + bootpart;
244 1.6.2.2 jmcneill #endif
245 1.6.2.2 jmcneill bootstr_dev = bootdev;
246 1.6.2.2 jmcneill }
247 1.6.2.2 jmcneill }
248 1.6.2.2 jmcneill spec += len;
249 1.6.2.2 jmcneill }
250 1.6.2.2 jmcneill
251 1.6.2.2 jmcneill /* second, get bootname from bootstrings */
252 1.6.2.2 jmcneill if ((spec = strstr(bootstring, "nbsd=")) != NULL) {
253 1.6.2.2 jmcneill ptr = strchr(spec, ' ');
254 1.6.2.2 jmcneill spec += 5; /* skip 'nbsd=' */
255 1.6.2.2 jmcneill len = (ptr == NULL) ? strlen(spec) : ptr - spec;
256 1.6.2.2 jmcneill if (len > 0) {
257 1.6.2.2 jmcneill if (parse_bootname(spec, len,
258 1.6.2.2 jmcneill &bootstr_dev, &bootstr_kname))
259 1.6.2.2 jmcneill return 1;
260 1.6.2.2 jmcneill }
261 1.6.2.2 jmcneill }
262 1.6.2.2 jmcneill
263 1.6.2.3 joerg /* third, check if netboot */
264 1.6.2.3 joerg if (strstr(bootstring, "nfsroot=") != NULL) {
265 1.6.2.3 joerg bootstr_dev = nfsbootdev;
266 1.6.2.3 joerg }
267 1.6.2.3 joerg
268 1.6.2.2 jmcneill DPRINTF(("bootstr_dev = %s, bootstr_kname = %s\n",
269 1.6.2.2 jmcneill bootstr_dev ? bootstr_dev : "<NULL>",
270 1.6.2.2 jmcneill bootstr_kname ? bootstr_kname : "<NULL>"));
271 1.6.2.2 jmcneill
272 1.6.2.2 jmcneill spec = NULL;
273 1.6.2.2 jmcneill len = 0;
274 1.6.2.2 jmcneill
275 1.6.2.2 jmcneill memset(namebuf, 0, sizeof namebuf);
276 1.6.2.2 jmcneill printf("Boot [%s:%s]: ",
277 1.6.2.2 jmcneill bootstr_dev ? bootstr_dev : DEFBOOTDEV,
278 1.6.2.2 jmcneill bootstr_kname ? bootstr_kname : DEFKERNELNAME);
279 1.6.2.2 jmcneill
280 1.6.2.2 jmcneill if (tgets(namebuf) == -1)
281 1.6.2.2 jmcneill printf("\n");
282 1.6.2.2 jmcneill
283 1.6.2.2 jmcneill ptr = namebuf;
284 1.6.2.2 jmcneill while ((c = *ptr) != '\0') {
285 1.6.2.2 jmcneill while (c == ' ')
286 1.6.2.2 jmcneill c = *++ptr;
287 1.6.2.2 jmcneill if (c == '\0')
288 1.6.2.2 jmcneill break;
289 1.6.2.2 jmcneill if (c == '-') {
290 1.6.2.2 jmcneill while ((c = *++ptr) && c != ' ')
291 1.6.2.2 jmcneill BOOT_FLAG(c, *howtop);
292 1.6.2.2 jmcneill } else {
293 1.6.2.2 jmcneill spec = ptr;
294 1.6.2.2 jmcneill while ((c = *++ptr) && c != ' ')
295 1.6.2.2 jmcneill ;
296 1.6.2.2 jmcneill if (c)
297 1.6.2.2 jmcneill *ptr++ = '\0';
298 1.6.2.2 jmcneill len = strlen(spec);
299 1.6.2.2 jmcneill }
300 1.6.2.2 jmcneill }
301 1.6.2.2 jmcneill
302 1.6.2.2 jmcneill if (len > 0) {
303 1.6.2.2 jmcneill if (parse_bootname(spec, len, &prompt_dev, &prompt_kname))
304 1.6.2.2 jmcneill return 1;
305 1.6.2.2 jmcneill }
306 1.6.2.2 jmcneill
307 1.6.2.2 jmcneill DPRINTF(("prompt_dev = %s, prompt_kname = %s\n",
308 1.6.2.2 jmcneill prompt_dev ? prompt_dev : "<NULL>",
309 1.6.2.2 jmcneill prompt_kname ? prompt_kname : "<NULL>"));
310 1.6.2.2 jmcneill
311 1.6.2.2 jmcneill if (prompt_dev)
312 1.6.2.2 jmcneill *dev = prompt_dev;
313 1.6.2.2 jmcneill else
314 1.6.2.2 jmcneill *dev = bootstr_dev;
315 1.6.2.2 jmcneill
316 1.6.2.2 jmcneill if (prompt_kname)
317 1.6.2.2 jmcneill *kname = prompt_kname;
318 1.6.2.2 jmcneill else
319 1.6.2.2 jmcneill *kname = bootstr_kname;
320 1.6.2.2 jmcneill
321 1.6.2.2 jmcneill DPRINTF(("dev = %s, kname = %s\n",
322 1.6.2.2 jmcneill *dev ? *dev : "<NULL>",
323 1.6.2.2 jmcneill *kname ? *kname : "<NULL>"));
324 1.6.2.2 jmcneill
325 1.6.2.2 jmcneill return 0;
326 1.6.2.2 jmcneill }
327 1.6.2.2 jmcneill
328 1.6.2.2 jmcneill static int
329 1.6.2.2 jmcneill parse_bootname(char *spec, int len, char **dev, char **kname)
330 1.6.2.2 jmcneill {
331 1.6.2.2 jmcneill char *bootname, *ptr;
332 1.6.2.2 jmcneill
333 1.6.2.2 jmcneill bootname = alloc(len + 1);
334 1.6.2.2 jmcneill if (bootname == NULL)
335 1.6.2.2 jmcneill return 1;
336 1.6.2.2 jmcneill memcpy(bootname, spec, len);
337 1.6.2.2 jmcneill bootname[len] = '\0';
338 1.6.2.2 jmcneill
339 1.6.2.2 jmcneill if ((ptr = memchr(bootname, ':', len)) != NULL) {
340 1.6.2.2 jmcneill /* "wdXX:kernel" */
341 1.6.2.2 jmcneill *ptr = '\0';
342 1.6.2.2 jmcneill *dev = bootname;
343 1.6.2.2 jmcneill if (*++ptr)
344 1.6.2.2 jmcneill *kname = ptr;
345 1.6.2.2 jmcneill } else
346 1.6.2.2 jmcneill /* "kernel" */
347 1.6.2.2 jmcneill *kname = bootname;
348 1.6.2.2 jmcneill return 0;
349 1.6.2.2 jmcneill }
350 1.6.2.2 jmcneill
351 1.6.2.2 jmcneill /*
352 1.6.2.2 jmcneill * Get the bootstring from PROM.
353 1.6.2.2 jmcneill */
354 1.6.2.3 joerg void
355 1.6.2.2 jmcneill prominit(unsigned int memsize)
356 1.6.2.2 jmcneill {
357 1.6.2.2 jmcneill
358 1.6.2.2 jmcneill bootstring = (char *)(memsize - 512);
359 1.6.2.2 jmcneill bootstring[511] = '\0';
360 1.6.2.2 jmcneill }
361 1.6.2.2 jmcneill
362 1.6.2.2 jmcneill /*
363 1.6.2.2 jmcneill * Print boot message.
364 1.6.2.2 jmcneill */
365 1.6.2.3 joerg void
366 1.6.2.2 jmcneill print_banner(unsigned int memsize)
367 1.6.2.2 jmcneill {
368 1.6.2.2 jmcneill
369 1.6.2.2 jmcneill printf("\n");
370 1.6.2.2 jmcneill printf(">> %s " NETBSD_VERS " Bootloader, Revision %s [@%p]\n",
371 1.6.2.2 jmcneill bootprog_name, bootprog_rev, (void*)&start);
372 1.6.2.2 jmcneill printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
373 1.6.2.2 jmcneill printf(">> Memory:\t\t%u k\n", (memsize - MIPS_KSEG0_START) / 1024);
374 1.6.2.2 jmcneill printf(">> PROM boot string:\t%s\n", bootstring);
375 1.6.2.2 jmcneill }
376 1.6.2.2 jmcneill
377 1.6.2.2 jmcneill /*
378 1.6.2.2 jmcneill * Entry point.
379 1.6.2.2 jmcneill * Parse PROM boot string, load the kernel and jump into it
380 1.6.2.2 jmcneill */
381 1.6.2.2 jmcneill int
382 1.6.2.2 jmcneill main(unsigned int memsize)
383 1.6.2.2 jmcneill {
384 1.6.2.2 jmcneill char **namep, *dev, *kernel, *bi_addr;
385 1.6.2.2 jmcneill char bootpath[PATH_MAX];
386 1.6.2.2 jmcneill int win;
387 1.6.2.2 jmcneill u_long marks[MARK_MAX];
388 1.6.2.2 jmcneill void (*entry)(unsigned int, u_int, char *);
389 1.6.2.2 jmcneill
390 1.6.2.2 jmcneill struct btinfo_flags bi_flags;
391 1.6.2.2 jmcneill struct btinfo_symtab bi_syms;
392 1.6.2.2 jmcneill struct btinfo_bootpath bi_bpath;
393 1.6.2.2 jmcneill struct btinfo_howto bi_howto;
394 1.6.2.2 jmcneill int addr, speed, howto;
395 1.6.2.2 jmcneill
396 1.6.2.3 joerg try_bootp = 1;
397 1.6.2.3 joerg
398 1.6.2.2 jmcneill /* Initialize boot info early */
399 1.6.2.2 jmcneill howto = 0x0;
400 1.6.2.2 jmcneill bi_flags.bi_flags = 0x0;
401 1.6.2.2 jmcneill bi_addr = bi_init();
402 1.6.2.2 jmcneill
403 1.6.2.2 jmcneill prominit(memsize);
404 1.6.2.2 jmcneill if (cninit(&addr, &speed) != NULL)
405 1.6.2.2 jmcneill bi_flags.bi_flags |= BI_SERIAL_CONSOLE;
406 1.6.2.2 jmcneill
407 1.6.2.2 jmcneill print_banner(memsize);
408 1.6.2.2 jmcneill
409 1.6.2.2 jmcneill memset(marks, 0, sizeof marks);
410 1.6.2.2 jmcneill get_bsdbootname(&dev, &kernel, &howto);
411 1.6.2.2 jmcneill
412 1.6.2.2 jmcneill if (kernel != NULL) {
413 1.6.2.2 jmcneill DPRINTF(("kernel: %s\n", kernel));
414 1.6.2.2 jmcneill kernelnames[0] = kernel;
415 1.6.2.2 jmcneill kernelnames[1] = NULL;
416 1.6.2.2 jmcneill } else {
417 1.6.2.2 jmcneill DPRINTF(("kernel: NULL\n"));
418 1.6.2.2 jmcneill }
419 1.6.2.2 jmcneill
420 1.6.2.2 jmcneill win = 0;
421 1.6.2.2 jmcneill DPRINTF(("Kernel names: %p\n", kernelnames));
422 1.6.2.2 jmcneill for (namep = kernelnames, win = 0; (*namep != NULL) && !win; namep++) {
423 1.6.2.2 jmcneill kernel = *namep;
424 1.6.2.2 jmcneill
425 1.6.2.2 jmcneill bootpath[0] = '\0';
426 1.6.2.2 jmcneill
427 1.6.2.2 jmcneill strcpy(bootpath, dev ? dev : DEFBOOTDEV);
428 1.6.2.2 jmcneill strcat(bootpath, ":");
429 1.6.2.2 jmcneill strcat(bootpath, kernel);
430 1.6.2.2 jmcneill
431 1.6.2.2 jmcneill printf("Loading: %s", bootpath);
432 1.6.2.2 jmcneill if (howto)
433 1.6.2.2 jmcneill printf(" (howto 0x%x)", howto);
434 1.6.2.2 jmcneill printf("\n");
435 1.6.2.2 jmcneill patch_bootstring(bootpath);
436 1.6.2.2 jmcneill win = (loadfile(bootpath, marks, LOAD_ALL) != -1);
437 1.6.2.2 jmcneill }
438 1.6.2.2 jmcneill
439 1.6.2.2 jmcneill if (win) {
440 1.6.2.2 jmcneill strncpy(bi_bpath.bootpath, kernel, BTINFO_BOOTPATH_LEN);
441 1.6.2.2 jmcneill bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
442 1.6.2.2 jmcneill
443 1.6.2.2 jmcneill entry = (void *)marks[MARK_ENTRY];
444 1.6.2.2 jmcneill bi_syms.nsym = marks[MARK_NSYM];
445 1.6.2.2 jmcneill bi_syms.ssym = marks[MARK_SYM];
446 1.6.2.2 jmcneill bi_syms.esym = marks[MARK_END];
447 1.6.2.2 jmcneill bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
448 1.6.2.2 jmcneill
449 1.6.2.2 jmcneill bi_add(&bi_flags, BTINFO_FLAGS, sizeof(bi_flags));
450 1.6.2.2 jmcneill
451 1.6.2.2 jmcneill bi_howto.bi_howto = howto;
452 1.6.2.2 jmcneill bi_add(&bi_howto, BTINFO_HOWTO, sizeof(bi_howto));
453 1.6.2.2 jmcneill
454 1.6.2.2 jmcneill entry = (void *)marks[MARK_ENTRY];
455 1.6.2.2 jmcneill
456 1.6.2.2 jmcneill DPRINTF(("Bootinfo @ 0x%x\n", bi_addr));
457 1.6.2.2 jmcneill printf("Starting at 0x%x\n\n", (u_int)entry);
458 1.6.2.2 jmcneill (*entry)(memsize, BOOTINFO_MAGIC, bi_addr);
459 1.6.2.2 jmcneill }
460 1.6.2.2 jmcneill
461 1.6.2.2 jmcneill (void)printf("Boot failed! Rebooting...\n");
462 1.6.2.2 jmcneill return 0;
463 1.6.2.2 jmcneill }
464