1 /* $NetBSD: boot.c,v 1.17 2008/05/29 14:25:00 tsutsui Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
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
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
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
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
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>
74 #include <sys/exec_elf.h>
76 #include <machine/cpu.h>
78 #include <cobalt/dev/gtreg.h>
85 char *kernelnames
[] = {
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 */
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.
135 printf("rebooting...\n\n");
137 *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(LED_ADDR
) = LED_RESET
;
138 printf("WARNING: reboot failed!\n");
145 * Substitute root value with NetBSD root partition name.
148 patch_bootstring(char *bootspec
)
150 char *sp
= bootstring
;
155 DPRINTF(("patch_bootstring: %s\n", bootspec
));
157 /* get boot parameters */
158 if (devparse(bootspec
, &dev
, &unit
, &part
, (const char **)&file
) != 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
) {
167 end
= strchr(sp
, ' ');
169 /* strip off leading spaces */
170 for (--sp
; (sp
> bootstring
) && (*sp
== ' '); --sp
)
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
)) {
186 /* omit "nfsroot=" arg on wd boot */
187 if ((sp
= strstr(bootstring
, "nfsroot=")) != NULL
) {
190 end
= strchr(sp
, ' ');
192 /* strip off leading spaces */
193 for (--sp
; (sp
> bootstring
) && (*sp
== ' '); --sp
)
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
));
216 * Extract NetBSD boot specification
219 get_bsdbootname(char **dev
, char **kname
, int *howtop
)
222 int bootunit
, bootpart
;
223 char *bootstr_dev
, *bootstr_kname
;
224 char *prompt_dev
, *prompt_kname
;
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 */
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
;
251 bootstr_dev
= bootdev
;
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
;
263 if (parse_bootname(spec
, len
,
264 &bootstr_dev
, &bootstr_kname
))
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>"));
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)
290 while ((c
= *ptr
) != '\0') {
296 while ((c
= *++ptr
) && c
!= ' ')
297 BOOT_FLAG(c
, *howtop
);
300 while ((c
= *++ptr
) && c
!= ' ')
309 if (parse_bootname(spec
, len
, &prompt_dev
, &prompt_kname
))
313 DPRINTF(("prompt_dev = %s, prompt_kname = %s\n",
314 prompt_dev
? prompt_dev
: "<NULL>",
315 prompt_kname
? prompt_kname
: "<NULL>"));
323 *kname
= prompt_kname
;
325 *kname
= bootstr_kname
;
327 DPRINTF(("dev = %s, kname = %s\n",
328 *dev
? *dev
: "<NULL>",
329 *kname
? *kname
: "<NULL>"));
335 parse_bootname(char *spec
, int len
, char **dev
, char **kname
)
337 char *bootname
, *ptr
;
339 bootname
= alloc(len
+ 1);
340 if (bootname
== NULL
)
342 memcpy(bootname
, spec
, len
);
343 bootname
[len
] = '\0';
345 if ((ptr
= memchr(bootname
, ':', len
)) != NULL
) {
358 * Get the bootstring from PROM.
361 prominit(unsigned int memsize
)
364 bootstring
= (char *)(memsize
- 512);
365 bootstring
[511] = '\0';
369 * Print boot message.
372 print_banner(unsigned int memsize
)
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
);
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
);
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
];
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
;
425 /* Initialize boot info early */
429 bi_flags
.bi_flags
= 0x0;
433 cobalt_id
= read_board_id();
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
;
448 DPRINTF(("kernel: NULL\n"));
452 DPRINTF(("Kernel names: %p\n", kernelnames
));
453 for (namep
= kernelnames
, win
= 0; (*namep
!= NULL
) && !win
; namep
++) {
458 strcpy(bootpath
, dev
? dev
: DEFBOOTDEV
);
459 strcat(bootpath
, ":");
460 strcat(bootpath
, kernel
);
462 lcd_loadfile(bootpath
);
463 printf("Loading: %s", bootpath
);
465 printf(" (howto 0x%x)", howto
);
467 patch_bootstring(bootpath
);
468 win
= (loadfile(bootpath
, marks
, LOAD_ALL
) != -1);
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
);
495 (void)printf("Boot failed! Rebooting...\n");