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