Home | History | Annotate | Line # | Download | only in boot
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