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