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