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