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