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