boot.c revision 1.6.2.2 1 1.6.2.2 jmcneill /* $NetBSD: boot.c,v 1.6.2.2 2007/08/16 11:02:16 jmcneill 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.2 jmcneill #include <lib/libkern/libkern.h>
79 1.6.2.2 jmcneill
80 1.6.2.2 jmcneill #include <sys/param.h>
81 1.6.2.2 jmcneill #include <sys/boot_flag.h>
82 1.6.2.2 jmcneill #include <sys/exec.h>
83 1.6.2.2 jmcneill #include <sys/exec_elf.h>
84 1.6.2.2 jmcneill
85 1.6.2.2 jmcneill #include "boot.h"
86 1.6.2.2 jmcneill #include "cons.h"
87 1.6.2.2 jmcneill #include "common.h"
88 1.6.2.2 jmcneill #include "bootinfo.h"
89 1.6.2.2 jmcneill
90 1.6.2.2 jmcneill char *kernelnames[] = {
91 1.6.2.2 jmcneill "netbsd",
92 1.6.2.2 jmcneill "netbsd.gz",
93 1.6.2.2 jmcneill "onetbsd",
94 1.6.2.2 jmcneill "onetbsd.gz",
95 1.6.2.2 jmcneill "netbsd.bak",
96 1.6.2.2 jmcneill "netbsd.bak.gz",
97 1.6.2.2 jmcneill "netbsd.old",
98 1.6.2.2 jmcneill "netbsd.old.gz",
99 1.6.2.2 jmcneill "netbsd.cobalt",
100 1.6.2.2 jmcneill "netbsd.cobalt.gz",
101 1.6.2.2 jmcneill "netbsd.elf",
102 1.6.2.2 jmcneill "netbsd.elf.gz",
103 1.6.2.2 jmcneill NULL
104 1.6.2.2 jmcneill };
105 1.6.2.2 jmcneill
106 1.6.2.2 jmcneill extern u_long end; /* Boot loader code end address */
107 1.6.2.2 jmcneill void start(void);
108 1.6.2.2 jmcneill
109 1.6.2.2 jmcneill static char *bootstring;
110 1.6.2.2 jmcneill
111 1.6.2.2 jmcneill static int patch_bootstring (char *bootspec);
112 1.6.2.2 jmcneill static int get_bsdbootname(char **, char **, int *);
113 1.6.2.2 jmcneill static int parse_bootname(char *, int, char **, char **);
114 1.6.2.2 jmcneill static int prominit (unsigned int memsize);
115 1.6.2.2 jmcneill static int print_banner (unsigned int memsize);
116 1.6.2.2 jmcneill
117 1.6.2.2 jmcneill int cpu_reboot(void);
118 1.6.2.2 jmcneill
119 1.6.2.2 jmcneill int main(unsigned int memsize);
120 1.6.2.2 jmcneill
121 1.6.2.2 jmcneill /*
122 1.6.2.2 jmcneill * Perform CPU reboot.
123 1.6.2.2 jmcneill */
124 1.6.2.2 jmcneill int
125 1.6.2.2 jmcneill cpu_reboot(void)
126 1.6.2.2 jmcneill {
127 1.6.2.2 jmcneill printf("rebooting...\n\n");
128 1.6.2.2 jmcneill
129 1.6.2.2 jmcneill *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
130 1.6.2.2 jmcneill printf("WARNING: reboot failed!\n");
131 1.6.2.2 jmcneill
132 1.6.2.2 jmcneill for (;;)
133 1.6.2.2 jmcneill ;
134 1.6.2.2 jmcneill }
135 1.6.2.2 jmcneill
136 1.6.2.2 jmcneill /*
137 1.6.2.2 jmcneill * Substitute root value with NetBSD root partition name.
138 1.6.2.2 jmcneill */
139 1.6.2.2 jmcneill int
140 1.6.2.2 jmcneill patch_bootstring(char *bootspec)
141 1.6.2.2 jmcneill {
142 1.6.2.2 jmcneill char *sp = bootstring;
143 1.6.2.2 jmcneill uint8_t unit, part;
144 1.6.2.2 jmcneill int dev, error;
145 1.6.2.2 jmcneill char *file;
146 1.6.2.2 jmcneill
147 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: %s\n", bootspec));
148 1.6.2.2 jmcneill
149 1.6.2.2 jmcneill /* get boot parameters */
150 1.6.2.2 jmcneill if (devparse(bootspec, &dev, &unit, &part, (const char **)&file) != 0)
151 1.6.2.2 jmcneill unit = part = 0;
152 1.6.2.2 jmcneill
153 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: %d, %d\n", unit, part));
154 1.6.2.2 jmcneill
155 1.6.2.2 jmcneill /* take out the 'root=xxx' parameter */
156 1.6.2.2 jmcneill if ((sp = strstr(bootstring, "root=")) != NULL) {
157 1.6.2.2 jmcneill const char *end;
158 1.6.2.2 jmcneill
159 1.6.2.2 jmcneill end = strchr(sp, ' ');
160 1.6.2.2 jmcneill
161 1.6.2.2 jmcneill /* strip off leading spaces */
162 1.6.2.2 jmcneill for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
163 1.6.2.2 jmcneill ;
164 1.6.2.2 jmcneill
165 1.6.2.2 jmcneill if (end != NULL)
166 1.6.2.2 jmcneill strcpy(++sp, end);
167 1.6.2.2 jmcneill else
168 1.6.2.2 jmcneill *++sp = '\0';
169 1.6.2.2 jmcneill }
170 1.6.2.2 jmcneill
171 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: [%s]\n", bootstring));
172 1.6.2.2 jmcneill
173 1.6.2.2 jmcneill #define DEVNAMESIZE (MAXDEVNAME + sizeof(" root=/dev/hd") + sizeof("0a"))
174 1.6.2.2 jmcneill /* bsd notation -> linux notation (wd0a -> hda1) */
175 1.6.2.2 jmcneill if (strlen(bootstring) <= (511 - DEVNAMESIZE)) {
176 1.6.2.2 jmcneill int len;
177 1.6.2.2 jmcneill
178 1.6.2.2 jmcneill strcat(bootstring, " root=/dev/hd");
179 1.6.2.2 jmcneill
180 1.6.2.2 jmcneill len = strlen(bootstring);
181 1.6.2.2 jmcneill bootstring[len++] = unit + 'a';
182 1.6.2.2 jmcneill bootstring[len++] = part + '1';
183 1.6.2.2 jmcneill bootstring[len++] = '\0';
184 1.6.2.2 jmcneill }
185 1.6.2.2 jmcneill
186 1.6.2.2 jmcneill DPRINTF(("patch_bootstring: -> %s\n", bootstring));
187 1.6.2.2 jmcneill return 0;
188 1.6.2.2 jmcneill }
189 1.6.2.2 jmcneill
190 1.6.2.2 jmcneill /*
191 1.6.2.2 jmcneill * Extract NetBSD boot specification
192 1.6.2.2 jmcneill */
193 1.6.2.2 jmcneill static int
194 1.6.2.2 jmcneill get_bsdbootname(char **dev, char **kname, int *howtop)
195 1.6.2.2 jmcneill {
196 1.6.2.2 jmcneill int len, error;
197 1.6.2.2 jmcneill int bootunit, bootpart;
198 1.6.2.2 jmcneill char *bootstr_dev, *bootstr_kname;
199 1.6.2.2 jmcneill char *prompt_dev, *prompt_kname;
200 1.6.2.2 jmcneill char *ptr, *spec;
201 1.6.2.2 jmcneill char c, namebuf[PATH_MAX];
202 1.6.2.2 jmcneill static char bootdev[] = "wd0a";
203 1.6.2.2 jmcneill
204 1.6.2.2 jmcneill bootstr_dev = prompt_dev = NULL;
205 1.6.2.2 jmcneill bootstr_kname = prompt_kname = NULL;
206 1.6.2.2 jmcneill
207 1.6.2.2 jmcneill /* first, get root device specified by the firmware */
208 1.6.2.2 jmcneill spec = bootstring;
209 1.6.2.2 jmcneill /* assume the last one is valid */
210 1.6.2.2 jmcneill while ((spec = strstr(spec, "root=")) != NULL) {
211 1.6.2.2 jmcneill spec += 5; /* skip 'root=' */
212 1.6.2.2 jmcneill ptr = strchr(spec, ' ');
213 1.6.2.2 jmcneill len = (ptr == NULL) ? strlen(spec) : ptr - spec;
214 1.6.2.2 jmcneill /* decode unit and part from "/dev/hd[ab][1-4]" strings */
215 1.6.2.2 jmcneill if (len == 9 && memcmp("/dev/hd", spec, 7) == 0) {
216 1.6.2.2 jmcneill bootunit = spec[7] - 'a';
217 1.6.2.2 jmcneill bootpart = spec[8] - '1';
218 1.6.2.2 jmcneill if (bootunit >= 0 && bootunit < 2 &&
219 1.6.2.2 jmcneill bootpart >= 0 && bootpart < 4) {
220 1.6.2.2 jmcneill bootdev[sizeof(bootdev) - 3] = '0' + bootunit;
221 1.6.2.2 jmcneill #if 0 /* bootpart is fdisk partition of Linux root */
222 1.6.2.2 jmcneill bootdev[sizeof(bootdev) - 2] = 'a' + bootpart;
223 1.6.2.2 jmcneill #endif
224 1.6.2.2 jmcneill bootstr_dev = bootdev;
225 1.6.2.2 jmcneill }
226 1.6.2.2 jmcneill }
227 1.6.2.2 jmcneill spec += len;
228 1.6.2.2 jmcneill }
229 1.6.2.2 jmcneill
230 1.6.2.2 jmcneill /* second, get bootname from bootstrings */
231 1.6.2.2 jmcneill if ((spec = strstr(bootstring, "nbsd=")) != NULL) {
232 1.6.2.2 jmcneill ptr = strchr(spec, ' ');
233 1.6.2.2 jmcneill spec += 5; /* skip 'nbsd=' */
234 1.6.2.2 jmcneill len = (ptr == NULL) ? strlen(spec) : ptr - spec;
235 1.6.2.2 jmcneill if (len > 0) {
236 1.6.2.2 jmcneill if (parse_bootname(spec, len,
237 1.6.2.2 jmcneill &bootstr_dev, &bootstr_kname))
238 1.6.2.2 jmcneill return 1;
239 1.6.2.2 jmcneill }
240 1.6.2.2 jmcneill }
241 1.6.2.2 jmcneill
242 1.6.2.2 jmcneill DPRINTF(("bootstr_dev = %s, bootstr_kname = %s\n",
243 1.6.2.2 jmcneill bootstr_dev ? bootstr_dev : "<NULL>",
244 1.6.2.2 jmcneill bootstr_kname ? bootstr_kname : "<NULL>"));
245 1.6.2.2 jmcneill
246 1.6.2.2 jmcneill spec = NULL;
247 1.6.2.2 jmcneill len = 0;
248 1.6.2.2 jmcneill
249 1.6.2.2 jmcneill memset(namebuf, 0, sizeof namebuf);
250 1.6.2.2 jmcneill printf("Boot [%s:%s]: ",
251 1.6.2.2 jmcneill bootstr_dev ? bootstr_dev : DEFBOOTDEV,
252 1.6.2.2 jmcneill bootstr_kname ? bootstr_kname : DEFKERNELNAME);
253 1.6.2.2 jmcneill
254 1.6.2.2 jmcneill if (tgets(namebuf) == -1)
255 1.6.2.2 jmcneill printf("\n");
256 1.6.2.2 jmcneill
257 1.6.2.2 jmcneill ptr = namebuf;
258 1.6.2.2 jmcneill while ((c = *ptr) != '\0') {
259 1.6.2.2 jmcneill while (c == ' ')
260 1.6.2.2 jmcneill c = *++ptr;
261 1.6.2.2 jmcneill if (c == '\0')
262 1.6.2.2 jmcneill break;
263 1.6.2.2 jmcneill if (c == '-') {
264 1.6.2.2 jmcneill while ((c = *++ptr) && c != ' ')
265 1.6.2.2 jmcneill BOOT_FLAG(c, *howtop);
266 1.6.2.2 jmcneill } else {
267 1.6.2.2 jmcneill spec = ptr;
268 1.6.2.2 jmcneill while ((c = *++ptr) && c != ' ')
269 1.6.2.2 jmcneill ;
270 1.6.2.2 jmcneill if (c)
271 1.6.2.2 jmcneill *ptr++ = '\0';
272 1.6.2.2 jmcneill len = strlen(spec);
273 1.6.2.2 jmcneill }
274 1.6.2.2 jmcneill }
275 1.6.2.2 jmcneill
276 1.6.2.2 jmcneill if (len > 0) {
277 1.6.2.2 jmcneill if (parse_bootname(spec, len, &prompt_dev, &prompt_kname))
278 1.6.2.2 jmcneill return 1;
279 1.6.2.2 jmcneill }
280 1.6.2.2 jmcneill
281 1.6.2.2 jmcneill DPRINTF(("prompt_dev = %s, prompt_kname = %s\n",
282 1.6.2.2 jmcneill prompt_dev ? prompt_dev : "<NULL>",
283 1.6.2.2 jmcneill prompt_kname ? prompt_kname : "<NULL>"));
284 1.6.2.2 jmcneill
285 1.6.2.2 jmcneill if (prompt_dev)
286 1.6.2.2 jmcneill *dev = prompt_dev;
287 1.6.2.2 jmcneill else
288 1.6.2.2 jmcneill *dev = bootstr_dev;
289 1.6.2.2 jmcneill
290 1.6.2.2 jmcneill if (prompt_kname)
291 1.6.2.2 jmcneill *kname = prompt_kname;
292 1.6.2.2 jmcneill else
293 1.6.2.2 jmcneill *kname = bootstr_kname;
294 1.6.2.2 jmcneill
295 1.6.2.2 jmcneill DPRINTF(("dev = %s, kname = %s\n",
296 1.6.2.2 jmcneill *dev ? *dev : "<NULL>",
297 1.6.2.2 jmcneill *kname ? *kname : "<NULL>"));
298 1.6.2.2 jmcneill
299 1.6.2.2 jmcneill return 0;
300 1.6.2.2 jmcneill }
301 1.6.2.2 jmcneill
302 1.6.2.2 jmcneill static int
303 1.6.2.2 jmcneill parse_bootname(char *spec, int len, char **dev, char **kname)
304 1.6.2.2 jmcneill {
305 1.6.2.2 jmcneill char *bootname, *ptr;
306 1.6.2.2 jmcneill
307 1.6.2.2 jmcneill bootname = alloc(len + 1);
308 1.6.2.2 jmcneill if (bootname == NULL)
309 1.6.2.2 jmcneill return 1;
310 1.6.2.2 jmcneill memcpy(bootname, spec, len);
311 1.6.2.2 jmcneill bootname[len] = '\0';
312 1.6.2.2 jmcneill
313 1.6.2.2 jmcneill if ((ptr = memchr(bootname, ':', len)) != NULL) {
314 1.6.2.2 jmcneill /* "wdXX:kernel" */
315 1.6.2.2 jmcneill *ptr = '\0';
316 1.6.2.2 jmcneill *dev = bootname;
317 1.6.2.2 jmcneill if (*++ptr)
318 1.6.2.2 jmcneill *kname = ptr;
319 1.6.2.2 jmcneill } else
320 1.6.2.2 jmcneill /* "kernel" */
321 1.6.2.2 jmcneill *kname = bootname;
322 1.6.2.2 jmcneill return 0;
323 1.6.2.2 jmcneill }
324 1.6.2.2 jmcneill
325 1.6.2.2 jmcneill /*
326 1.6.2.2 jmcneill * Get the bootstring from PROM.
327 1.6.2.2 jmcneill */
328 1.6.2.2 jmcneill int
329 1.6.2.2 jmcneill prominit(unsigned int memsize)
330 1.6.2.2 jmcneill {
331 1.6.2.2 jmcneill
332 1.6.2.2 jmcneill bootstring = (char *)(memsize - 512);
333 1.6.2.2 jmcneill bootstring[511] = '\0';
334 1.6.2.2 jmcneill }
335 1.6.2.2 jmcneill
336 1.6.2.2 jmcneill /*
337 1.6.2.2 jmcneill * Print boot message.
338 1.6.2.2 jmcneill */
339 1.6.2.2 jmcneill int
340 1.6.2.2 jmcneill print_banner(unsigned int memsize)
341 1.6.2.2 jmcneill {
342 1.6.2.2 jmcneill
343 1.6.2.2 jmcneill printf("\n");
344 1.6.2.2 jmcneill printf(">> %s " NETBSD_VERS " Bootloader, Revision %s [@%p]\n",
345 1.6.2.2 jmcneill bootprog_name, bootprog_rev, (void*)&start);
346 1.6.2.2 jmcneill printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
347 1.6.2.2 jmcneill printf(">> Memory:\t\t%u k\n", (memsize - MIPS_KSEG0_START) / 1024);
348 1.6.2.2 jmcneill printf(">> PROM boot string:\t%s\n", bootstring);
349 1.6.2.2 jmcneill }
350 1.6.2.2 jmcneill
351 1.6.2.2 jmcneill /*
352 1.6.2.2 jmcneill * Entry point.
353 1.6.2.2 jmcneill * Parse PROM boot string, load the kernel and jump into it
354 1.6.2.2 jmcneill */
355 1.6.2.2 jmcneill int
356 1.6.2.2 jmcneill main(unsigned int memsize)
357 1.6.2.2 jmcneill {
358 1.6.2.2 jmcneill char **namep, *dev, *kernel, *bi_addr;
359 1.6.2.2 jmcneill char bootpath[PATH_MAX];
360 1.6.2.2 jmcneill int win;
361 1.6.2.2 jmcneill u_long marks[MARK_MAX];
362 1.6.2.2 jmcneill void (*entry)(unsigned int, u_int, char *);
363 1.6.2.2 jmcneill
364 1.6.2.2 jmcneill struct btinfo_flags bi_flags;
365 1.6.2.2 jmcneill struct btinfo_symtab bi_syms;
366 1.6.2.2 jmcneill struct btinfo_bootpath bi_bpath;
367 1.6.2.2 jmcneill struct btinfo_howto bi_howto;
368 1.6.2.2 jmcneill
369 1.6.2.2 jmcneill int addr, speed, howto;
370 1.6.2.2 jmcneill
371 1.6.2.2 jmcneill /* Initialize boot info early */
372 1.6.2.2 jmcneill howto = 0x0;
373 1.6.2.2 jmcneill bi_flags.bi_flags = 0x0;
374 1.6.2.2 jmcneill bi_addr = bi_init();
375 1.6.2.2 jmcneill
376 1.6.2.2 jmcneill prominit(memsize);
377 1.6.2.2 jmcneill if (cninit(&addr, &speed) != NULL)
378 1.6.2.2 jmcneill bi_flags.bi_flags |= BI_SERIAL_CONSOLE;
379 1.6.2.2 jmcneill
380 1.6.2.2 jmcneill print_banner(memsize);
381 1.6.2.2 jmcneill
382 1.6.2.2 jmcneill memset(marks, 0, sizeof marks);
383 1.6.2.2 jmcneill get_bsdbootname(&dev, &kernel, &howto);
384 1.6.2.2 jmcneill
385 1.6.2.2 jmcneill if (kernel != NULL) {
386 1.6.2.2 jmcneill DPRINTF(("kernel: %s\n", kernel));
387 1.6.2.2 jmcneill kernelnames[0] = kernel;
388 1.6.2.2 jmcneill kernelnames[1] = NULL;
389 1.6.2.2 jmcneill } else {
390 1.6.2.2 jmcneill DPRINTF(("kernel: NULL\n"));
391 1.6.2.2 jmcneill }
392 1.6.2.2 jmcneill
393 1.6.2.2 jmcneill win = 0;
394 1.6.2.2 jmcneill DPRINTF(("Kernel names: %p\n", kernelnames));
395 1.6.2.2 jmcneill for (namep = kernelnames, win = 0; (*namep != NULL) && !win; namep++) {
396 1.6.2.2 jmcneill kernel = *namep;
397 1.6.2.2 jmcneill
398 1.6.2.2 jmcneill bootpath[0] = '\0';
399 1.6.2.2 jmcneill
400 1.6.2.2 jmcneill strcpy(bootpath, dev ? dev : DEFBOOTDEV);
401 1.6.2.2 jmcneill strcat(bootpath, ":");
402 1.6.2.2 jmcneill strcat(bootpath, kernel);
403 1.6.2.2 jmcneill
404 1.6.2.2 jmcneill printf("Loading: %s", bootpath);
405 1.6.2.2 jmcneill if (howto)
406 1.6.2.2 jmcneill printf(" (howto 0x%x)", howto);
407 1.6.2.2 jmcneill printf("\n");
408 1.6.2.2 jmcneill patch_bootstring(bootpath);
409 1.6.2.2 jmcneill win = (loadfile(bootpath, marks, LOAD_ALL) != -1);
410 1.6.2.2 jmcneill }
411 1.6.2.2 jmcneill
412 1.6.2.2 jmcneill if (win) {
413 1.6.2.2 jmcneill strncpy(bi_bpath.bootpath, kernel, BTINFO_BOOTPATH_LEN);
414 1.6.2.2 jmcneill bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
415 1.6.2.2 jmcneill
416 1.6.2.2 jmcneill entry = (void *)marks[MARK_ENTRY];
417 1.6.2.2 jmcneill bi_syms.nsym = marks[MARK_NSYM];
418 1.6.2.2 jmcneill bi_syms.ssym = marks[MARK_SYM];
419 1.6.2.2 jmcneill bi_syms.esym = marks[MARK_END];
420 1.6.2.2 jmcneill bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
421 1.6.2.2 jmcneill
422 1.6.2.2 jmcneill bi_add(&bi_flags, BTINFO_FLAGS, sizeof(bi_flags));
423 1.6.2.2 jmcneill
424 1.6.2.2 jmcneill bi_howto.bi_howto = howto;
425 1.6.2.2 jmcneill bi_add(&bi_howto, BTINFO_HOWTO, sizeof(bi_howto));
426 1.6.2.2 jmcneill
427 1.6.2.2 jmcneill entry = (void *)marks[MARK_ENTRY];
428 1.6.2.2 jmcneill
429 1.6.2.2 jmcneill DPRINTF(("Bootinfo @ 0x%x\n", bi_addr));
430 1.6.2.2 jmcneill printf("Starting at 0x%x\n\n", (u_int)entry);
431 1.6.2.2 jmcneill (*entry)(memsize, BOOTINFO_MAGIC, bi_addr);
432 1.6.2.2 jmcneill }
433 1.6.2.2 jmcneill
434 1.6.2.2 jmcneill (void)printf("Boot failed! Rebooting...\n");
435 1.6.2.2 jmcneill return 0;
436 1.6.2.2 jmcneill }
437