Home | History | Annotate | Line # | Download | only in boot
boot.c revision 1.6.2.3
      1  1.6.2.3     joerg /*	$NetBSD: boot.c,v 1.6.2.3 2007/10/31 23:13:56 joerg 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.3     joerg #include <lib/libsa/dev_net.h>
     79  1.6.2.2  jmcneill #include <lib/libkern/libkern.h>
     80  1.6.2.2  jmcneill 
     81  1.6.2.2  jmcneill #include <sys/param.h>
     82  1.6.2.2  jmcneill #include <sys/boot_flag.h>
     83  1.6.2.2  jmcneill #include <sys/exec.h>
     84  1.6.2.2  jmcneill #include <sys/exec_elf.h>
     85  1.6.2.2  jmcneill 
     86  1.6.2.2  jmcneill #include "boot.h"
     87  1.6.2.2  jmcneill #include "cons.h"
     88  1.6.2.2  jmcneill #include "common.h"
     89  1.6.2.2  jmcneill #include "bootinfo.h"
     90  1.6.2.2  jmcneill 
     91  1.6.2.2  jmcneill char *kernelnames[] = {
     92  1.6.2.2  jmcneill 	"netbsd",
     93  1.6.2.2  jmcneill 	"netbsd.gz",
     94  1.6.2.2  jmcneill 	"onetbsd",
     95  1.6.2.2  jmcneill 	"onetbsd.gz",
     96  1.6.2.2  jmcneill 	"netbsd.bak",
     97  1.6.2.2  jmcneill 	"netbsd.bak.gz",
     98  1.6.2.2  jmcneill 	"netbsd.old",
     99  1.6.2.2  jmcneill 	"netbsd.old.gz",
    100  1.6.2.2  jmcneill 	"netbsd.cobalt",
    101  1.6.2.2  jmcneill 	"netbsd.cobalt.gz",
    102  1.6.2.2  jmcneill 	"netbsd.elf",
    103  1.6.2.2  jmcneill 	"netbsd.elf.gz",
    104  1.6.2.2  jmcneill 	NULL
    105  1.6.2.2  jmcneill };
    106  1.6.2.2  jmcneill 
    107  1.6.2.2  jmcneill extern u_long end;		/* Boot loader code end address */
    108  1.6.2.2  jmcneill void start(void);
    109  1.6.2.2  jmcneill 
    110  1.6.2.2  jmcneill static char *bootstring;
    111  1.6.2.2  jmcneill 
    112  1.6.2.3     joerg static int patch_bootstring(char *bootspec);
    113  1.6.2.2  jmcneill static int get_bsdbootname(char **, char **, int *);
    114  1.6.2.2  jmcneill static int parse_bootname(char *, int, char **, char **);
    115  1.6.2.3     joerg static void prominit(unsigned int memsize);
    116  1.6.2.3     joerg static void print_banner(unsigned int memsize);
    117  1.6.2.2  jmcneill 
    118  1.6.2.3     joerg void cpu_reboot(void);
    119  1.6.2.2  jmcneill 
    120  1.6.2.2  jmcneill int main(unsigned int memsize);
    121  1.6.2.2  jmcneill 
    122  1.6.2.2  jmcneill /*
    123  1.6.2.2  jmcneill  * Perform CPU reboot.
    124  1.6.2.2  jmcneill  */
    125  1.6.2.3     joerg void
    126  1.6.2.2  jmcneill cpu_reboot(void)
    127  1.6.2.2  jmcneill {
    128  1.6.2.3     joerg 
    129  1.6.2.2  jmcneill 	printf("rebooting...\n\n");
    130  1.6.2.2  jmcneill 
    131  1.6.2.2  jmcneill 	*(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
    132  1.6.2.2  jmcneill 	printf("WARNING: reboot failed!\n");
    133  1.6.2.2  jmcneill 
    134  1.6.2.2  jmcneill 	for (;;)
    135  1.6.2.2  jmcneill 		;
    136  1.6.2.2  jmcneill }
    137  1.6.2.2  jmcneill 
    138  1.6.2.2  jmcneill /*
    139  1.6.2.2  jmcneill  * Substitute root value with NetBSD root partition name.
    140  1.6.2.2  jmcneill  */
    141  1.6.2.2  jmcneill int
    142  1.6.2.2  jmcneill patch_bootstring(char *bootspec)
    143  1.6.2.2  jmcneill {
    144  1.6.2.2  jmcneill 	char *sp = bootstring;
    145  1.6.2.2  jmcneill 	uint8_t unit, part;
    146  1.6.2.3     joerg 	int dev;
    147  1.6.2.2  jmcneill 	char *file;
    148  1.6.2.2  jmcneill 
    149  1.6.2.2  jmcneill 	DPRINTF(("patch_bootstring: %s\n", bootspec));
    150  1.6.2.2  jmcneill 
    151  1.6.2.2  jmcneill 	/* get boot parameters */
    152  1.6.2.2  jmcneill 	if (devparse(bootspec, &dev, &unit, &part, (const char **)&file) != 0)
    153  1.6.2.2  jmcneill 		unit = part = 0;
    154  1.6.2.2  jmcneill 
    155  1.6.2.3     joerg 	DPRINTF(("patch_bootstring: unit = %d, part = %d\n", unit, part));
    156  1.6.2.2  jmcneill 
    157  1.6.2.2  jmcneill 	/* take out the 'root=xxx' parameter */
    158  1.6.2.2  jmcneill 	if ((sp = strstr(bootstring, "root=")) != NULL) {
    159  1.6.2.2  jmcneill 		const char *end;
    160  1.6.2.2  jmcneill 
    161  1.6.2.2  jmcneill 		end = strchr(sp, ' ');
    162  1.6.2.2  jmcneill 
    163  1.6.2.2  jmcneill 		/* strip off leading spaces */
    164  1.6.2.2  jmcneill 		for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
    165  1.6.2.2  jmcneill 			;
    166  1.6.2.2  jmcneill 
    167  1.6.2.2  jmcneill 		if (end != NULL)
    168  1.6.2.2  jmcneill 			strcpy(++sp, end);
    169  1.6.2.2  jmcneill 		else
    170  1.6.2.2  jmcneill 			*++sp = '\0';
    171  1.6.2.2  jmcneill 	}
    172  1.6.2.2  jmcneill 
    173  1.6.2.2  jmcneill 	DPRINTF(("patch_bootstring: [%s]\n", bootstring));
    174  1.6.2.2  jmcneill 
    175  1.6.2.2  jmcneill #define DEVNAMESIZE	(MAXDEVNAME + sizeof(" root=/dev/hd") + sizeof("0a"))
    176  1.6.2.3     joerg 	if (strcmp(devsw[dev].dv_name, "wd") == 0 &&
    177  1.6.2.3     joerg 	    strlen(bootstring) <= (511 - DEVNAMESIZE)) {
    178  1.6.2.2  jmcneill 		int len;
    179  1.6.2.2  jmcneill 
    180  1.6.2.3     joerg 		/* omit "nfsroot=" arg on wd boot */
    181  1.6.2.3     joerg 		if ((sp = strstr(bootstring, "nfsroot=")) != NULL) {
    182  1.6.2.3     joerg 			const char *end;
    183  1.6.2.3     joerg 
    184  1.6.2.3     joerg 			end = strchr(sp, ' ');
    185  1.6.2.3     joerg 
    186  1.6.2.3     joerg 			/* strip off leading spaces */
    187  1.6.2.3     joerg 			for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
    188  1.6.2.3     joerg 				;
    189  1.6.2.3     joerg 
    190  1.6.2.3     joerg 			if (end != NULL)
    191  1.6.2.3     joerg 				strcpy(++sp, end);
    192  1.6.2.3     joerg 			else
    193  1.6.2.3     joerg 				*++sp = '\0';
    194  1.6.2.3     joerg 		}
    195  1.6.2.3     joerg 
    196  1.6.2.3     joerg 		/* bsd notation -> linux notation (wd0a -> hda1) */
    197  1.6.2.2  jmcneill 		strcat(bootstring, " root=/dev/hd");
    198  1.6.2.2  jmcneill 
    199  1.6.2.2  jmcneill 		len = strlen(bootstring);
    200  1.6.2.2  jmcneill 		bootstring[len++] = unit + 'a';
    201  1.6.2.2  jmcneill 		bootstring[len++] = part + '1';
    202  1.6.2.2  jmcneill 		bootstring[len++] = '\0';
    203  1.6.2.2  jmcneill 	}
    204  1.6.2.2  jmcneill 
    205  1.6.2.2  jmcneill 	DPRINTF(("patch_bootstring: -> %s\n", bootstring));
    206  1.6.2.2  jmcneill 	return 0;
    207  1.6.2.2  jmcneill }
    208  1.6.2.2  jmcneill 
    209  1.6.2.2  jmcneill /*
    210  1.6.2.2  jmcneill  * Extract NetBSD boot specification
    211  1.6.2.2  jmcneill  */
    212  1.6.2.2  jmcneill static int
    213  1.6.2.2  jmcneill get_bsdbootname(char **dev, char **kname, int *howtop)
    214  1.6.2.2  jmcneill {
    215  1.6.2.3     joerg 	int len;
    216  1.6.2.2  jmcneill 	int bootunit, bootpart;
    217  1.6.2.2  jmcneill 	char *bootstr_dev, *bootstr_kname;
    218  1.6.2.2  jmcneill 	char *prompt_dev, *prompt_kname;
    219  1.6.2.2  jmcneill 	char *ptr, *spec;
    220  1.6.2.2  jmcneill 	char c, namebuf[PATH_MAX];
    221  1.6.2.2  jmcneill 	static char bootdev[] = "wd0a";
    222  1.6.2.3     joerg 	static char nfsbootdev[] = "nfs";
    223  1.6.2.2  jmcneill 
    224  1.6.2.2  jmcneill 	bootstr_dev = prompt_dev = NULL;
    225  1.6.2.2  jmcneill 	bootstr_kname = prompt_kname = NULL;
    226  1.6.2.2  jmcneill 
    227  1.6.2.2  jmcneill 	/* first, get root device specified by the firmware */
    228  1.6.2.2  jmcneill 	spec = bootstring;
    229  1.6.2.3     joerg 
    230  1.6.2.2  jmcneill 	/* assume the last one is valid */
    231  1.6.2.2  jmcneill 	while ((spec = strstr(spec, "root=")) != NULL) {
    232  1.6.2.2  jmcneill 		spec += 5;	/* skip 'root=' */
    233  1.6.2.2  jmcneill 		ptr = strchr(spec, ' ');
    234  1.6.2.2  jmcneill 		len = (ptr == NULL) ? strlen(spec) : ptr - spec;
    235  1.6.2.2  jmcneill 		/* decode unit and part from "/dev/hd[ab][1-4]" strings */
    236  1.6.2.2  jmcneill 		if (len == 9 && memcmp("/dev/hd", spec, 7) == 0) {
    237  1.6.2.2  jmcneill 			bootunit = spec[7] - 'a';
    238  1.6.2.2  jmcneill 			bootpart = spec[8] - '1';
    239  1.6.2.2  jmcneill 			if (bootunit >= 0 && bootunit < 2 &&
    240  1.6.2.2  jmcneill 			    bootpart >= 0 && bootpart < 4) {
    241  1.6.2.2  jmcneill 				bootdev[sizeof(bootdev) - 3] = '0' + bootunit;
    242  1.6.2.2  jmcneill #if 0				/* bootpart is fdisk partition of Linux root */
    243  1.6.2.2  jmcneill 				bootdev[sizeof(bootdev) - 2] = 'a' + bootpart;
    244  1.6.2.2  jmcneill #endif
    245  1.6.2.2  jmcneill 				bootstr_dev = bootdev;
    246  1.6.2.2  jmcneill 			}
    247  1.6.2.2  jmcneill 		}
    248  1.6.2.2  jmcneill 		spec += len;
    249  1.6.2.2  jmcneill 	}
    250  1.6.2.2  jmcneill 
    251  1.6.2.2  jmcneill 	/* second, get bootname from bootstrings */
    252  1.6.2.2  jmcneill 	if ((spec = strstr(bootstring, "nbsd=")) != NULL) {
    253  1.6.2.2  jmcneill 		ptr = strchr(spec, ' ');
    254  1.6.2.2  jmcneill 		spec += 5; 	/* skip 'nbsd=' */
    255  1.6.2.2  jmcneill 		len = (ptr == NULL) ? strlen(spec) : ptr - spec;
    256  1.6.2.2  jmcneill 		if (len > 0) {
    257  1.6.2.2  jmcneill 			if (parse_bootname(spec, len,
    258  1.6.2.2  jmcneill 			    &bootstr_dev, &bootstr_kname))
    259  1.6.2.2  jmcneill 				return 1;
    260  1.6.2.2  jmcneill 		}
    261  1.6.2.2  jmcneill 	}
    262  1.6.2.2  jmcneill 
    263  1.6.2.3     joerg 	/* third, check if netboot */
    264  1.6.2.3     joerg 	if (strstr(bootstring, "nfsroot=") != NULL) {
    265  1.6.2.3     joerg 		bootstr_dev = nfsbootdev;
    266  1.6.2.3     joerg 	}
    267  1.6.2.3     joerg 
    268  1.6.2.2  jmcneill 	DPRINTF(("bootstr_dev = %s, bootstr_kname = %s\n",
    269  1.6.2.2  jmcneill 	    bootstr_dev ? bootstr_dev : "<NULL>",
    270  1.6.2.2  jmcneill 	    bootstr_kname ? bootstr_kname : "<NULL>"));
    271  1.6.2.2  jmcneill 
    272  1.6.2.2  jmcneill 	spec = NULL;
    273  1.6.2.2  jmcneill 	len = 0;
    274  1.6.2.2  jmcneill 
    275  1.6.2.2  jmcneill 	memset(namebuf, 0, sizeof namebuf);
    276  1.6.2.2  jmcneill 	printf("Boot [%s:%s]: ",
    277  1.6.2.2  jmcneill 	    bootstr_dev ? bootstr_dev : DEFBOOTDEV,
    278  1.6.2.2  jmcneill 	    bootstr_kname ? bootstr_kname : DEFKERNELNAME);
    279  1.6.2.2  jmcneill 
    280  1.6.2.2  jmcneill 	if (tgets(namebuf) == -1)
    281  1.6.2.2  jmcneill 		printf("\n");
    282  1.6.2.2  jmcneill 
    283  1.6.2.2  jmcneill 	ptr = namebuf;
    284  1.6.2.2  jmcneill 	while ((c = *ptr) != '\0') {
    285  1.6.2.2  jmcneill 		while (c == ' ')
    286  1.6.2.2  jmcneill 			c = *++ptr;
    287  1.6.2.2  jmcneill 		if (c == '\0')
    288  1.6.2.2  jmcneill 			break;
    289  1.6.2.2  jmcneill 		if (c == '-') {
    290  1.6.2.2  jmcneill 			while ((c = *++ptr) && c != ' ')
    291  1.6.2.2  jmcneill 				BOOT_FLAG(c, *howtop);
    292  1.6.2.2  jmcneill 		} else {
    293  1.6.2.2  jmcneill 			spec = ptr;
    294  1.6.2.2  jmcneill 			while ((c = *++ptr) && c != ' ')
    295  1.6.2.2  jmcneill 				;
    296  1.6.2.2  jmcneill 			if (c)
    297  1.6.2.2  jmcneill 				*ptr++ = '\0';
    298  1.6.2.2  jmcneill 			len = strlen(spec);
    299  1.6.2.2  jmcneill 		}
    300  1.6.2.2  jmcneill 	}
    301  1.6.2.2  jmcneill 
    302  1.6.2.2  jmcneill 	if (len > 0) {
    303  1.6.2.2  jmcneill 		if (parse_bootname(spec, len, &prompt_dev, &prompt_kname))
    304  1.6.2.2  jmcneill 			return 1;
    305  1.6.2.2  jmcneill 	}
    306  1.6.2.2  jmcneill 
    307  1.6.2.2  jmcneill 	DPRINTF(("prompt_dev = %s, prompt_kname = %s\n",
    308  1.6.2.2  jmcneill 	    prompt_dev ? prompt_dev : "<NULL>",
    309  1.6.2.2  jmcneill 	    prompt_kname ? prompt_kname : "<NULL>"));
    310  1.6.2.2  jmcneill 
    311  1.6.2.2  jmcneill 	if (prompt_dev)
    312  1.6.2.2  jmcneill 		*dev = prompt_dev;
    313  1.6.2.2  jmcneill 	else
    314  1.6.2.2  jmcneill 		*dev = bootstr_dev;
    315  1.6.2.2  jmcneill 
    316  1.6.2.2  jmcneill 	if (prompt_kname)
    317  1.6.2.2  jmcneill 		*kname = prompt_kname;
    318  1.6.2.2  jmcneill 	else
    319  1.6.2.2  jmcneill 		*kname = bootstr_kname;
    320  1.6.2.2  jmcneill 
    321  1.6.2.2  jmcneill 	DPRINTF(("dev = %s, kname = %s\n",
    322  1.6.2.2  jmcneill 	    *dev ? *dev : "<NULL>",
    323  1.6.2.2  jmcneill 	    *kname ? *kname : "<NULL>"));
    324  1.6.2.2  jmcneill 
    325  1.6.2.2  jmcneill 	return 0;
    326  1.6.2.2  jmcneill }
    327  1.6.2.2  jmcneill 
    328  1.6.2.2  jmcneill static int
    329  1.6.2.2  jmcneill parse_bootname(char *spec, int len, char **dev, char **kname)
    330  1.6.2.2  jmcneill {
    331  1.6.2.2  jmcneill 	char *bootname, *ptr;
    332  1.6.2.2  jmcneill 
    333  1.6.2.2  jmcneill 	bootname = alloc(len + 1);
    334  1.6.2.2  jmcneill 	if (bootname == NULL)
    335  1.6.2.2  jmcneill 		return 1;
    336  1.6.2.2  jmcneill 	memcpy(bootname, spec, len);
    337  1.6.2.2  jmcneill 	bootname[len] = '\0';
    338  1.6.2.2  jmcneill 
    339  1.6.2.2  jmcneill 	if ((ptr = memchr(bootname, ':', len)) != NULL) {
    340  1.6.2.2  jmcneill 		/* "wdXX:kernel" */
    341  1.6.2.2  jmcneill 		*ptr = '\0';
    342  1.6.2.2  jmcneill 		*dev = bootname;
    343  1.6.2.2  jmcneill 		if (*++ptr)
    344  1.6.2.2  jmcneill 			*kname = ptr;
    345  1.6.2.2  jmcneill 	} else
    346  1.6.2.2  jmcneill 		/* "kernel" */
    347  1.6.2.2  jmcneill 		*kname = bootname;
    348  1.6.2.2  jmcneill 	return 0;
    349  1.6.2.2  jmcneill }
    350  1.6.2.2  jmcneill 
    351  1.6.2.2  jmcneill /*
    352  1.6.2.2  jmcneill  * Get the bootstring from PROM.
    353  1.6.2.2  jmcneill  */
    354  1.6.2.3     joerg void
    355  1.6.2.2  jmcneill prominit(unsigned int memsize)
    356  1.6.2.2  jmcneill {
    357  1.6.2.2  jmcneill 
    358  1.6.2.2  jmcneill 	bootstring = (char *)(memsize - 512);
    359  1.6.2.2  jmcneill 	bootstring[511] = '\0';
    360  1.6.2.2  jmcneill }
    361  1.6.2.2  jmcneill 
    362  1.6.2.2  jmcneill /*
    363  1.6.2.2  jmcneill  * Print boot message.
    364  1.6.2.2  jmcneill  */
    365  1.6.2.3     joerg void
    366  1.6.2.2  jmcneill print_banner(unsigned int memsize)
    367  1.6.2.2  jmcneill {
    368  1.6.2.2  jmcneill 
    369  1.6.2.2  jmcneill 	printf("\n");
    370  1.6.2.2  jmcneill 	printf(">> %s " NETBSD_VERS " Bootloader, Revision %s [@%p]\n",
    371  1.6.2.2  jmcneill 			bootprog_name, bootprog_rev, (void*)&start);
    372  1.6.2.2  jmcneill 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    373  1.6.2.2  jmcneill 	printf(">> Memory:\t\t%u k\n", (memsize - MIPS_KSEG0_START) / 1024);
    374  1.6.2.2  jmcneill 	printf(">> PROM boot string:\t%s\n", bootstring);
    375  1.6.2.2  jmcneill }
    376  1.6.2.2  jmcneill 
    377  1.6.2.2  jmcneill /*
    378  1.6.2.2  jmcneill  * Entry point.
    379  1.6.2.2  jmcneill  * Parse PROM boot string, load the kernel and jump into it
    380  1.6.2.2  jmcneill  */
    381  1.6.2.2  jmcneill int
    382  1.6.2.2  jmcneill main(unsigned int memsize)
    383  1.6.2.2  jmcneill {
    384  1.6.2.2  jmcneill 	char **namep, *dev, *kernel, *bi_addr;
    385  1.6.2.2  jmcneill 	char bootpath[PATH_MAX];
    386  1.6.2.2  jmcneill 	int win;
    387  1.6.2.2  jmcneill 	u_long marks[MARK_MAX];
    388  1.6.2.2  jmcneill 	void (*entry)(unsigned int, u_int, char *);
    389  1.6.2.2  jmcneill 
    390  1.6.2.2  jmcneill 	struct btinfo_flags bi_flags;
    391  1.6.2.2  jmcneill 	struct btinfo_symtab bi_syms;
    392  1.6.2.2  jmcneill 	struct btinfo_bootpath bi_bpath;
    393  1.6.2.2  jmcneill 	struct btinfo_howto bi_howto;
    394  1.6.2.2  jmcneill 	int addr, speed, howto;
    395  1.6.2.2  jmcneill 
    396  1.6.2.3     joerg 	try_bootp = 1;
    397  1.6.2.3     joerg 
    398  1.6.2.2  jmcneill 	/* Initialize boot info early */
    399  1.6.2.2  jmcneill 	howto = 0x0;
    400  1.6.2.2  jmcneill 	bi_flags.bi_flags = 0x0;
    401  1.6.2.2  jmcneill 	bi_addr = bi_init();
    402  1.6.2.2  jmcneill 
    403  1.6.2.2  jmcneill 	prominit(memsize);
    404  1.6.2.2  jmcneill 	if (cninit(&addr, &speed) != NULL)
    405  1.6.2.2  jmcneill 		bi_flags.bi_flags |= BI_SERIAL_CONSOLE;
    406  1.6.2.2  jmcneill 
    407  1.6.2.2  jmcneill 	print_banner(memsize);
    408  1.6.2.2  jmcneill 
    409  1.6.2.2  jmcneill 	memset(marks, 0, sizeof marks);
    410  1.6.2.2  jmcneill 	get_bsdbootname(&dev, &kernel, &howto);
    411  1.6.2.2  jmcneill 
    412  1.6.2.2  jmcneill 	if (kernel != NULL) {
    413  1.6.2.2  jmcneill 		DPRINTF(("kernel: %s\n", kernel));
    414  1.6.2.2  jmcneill 		kernelnames[0] = kernel;
    415  1.6.2.2  jmcneill 		kernelnames[1] = NULL;
    416  1.6.2.2  jmcneill 	} else {
    417  1.6.2.2  jmcneill 		DPRINTF(("kernel: NULL\n"));
    418  1.6.2.2  jmcneill 	}
    419  1.6.2.2  jmcneill 
    420  1.6.2.2  jmcneill 	win = 0;
    421  1.6.2.2  jmcneill 	DPRINTF(("Kernel names: %p\n", kernelnames));
    422  1.6.2.2  jmcneill 	for (namep = kernelnames, win = 0; (*namep != NULL) && !win; namep++) {
    423  1.6.2.2  jmcneill 		kernel = *namep;
    424  1.6.2.2  jmcneill 
    425  1.6.2.2  jmcneill 		bootpath[0] = '\0';
    426  1.6.2.2  jmcneill 
    427  1.6.2.2  jmcneill 		strcpy(bootpath, dev ? dev : DEFBOOTDEV);
    428  1.6.2.2  jmcneill 		strcat(bootpath, ":");
    429  1.6.2.2  jmcneill 		strcat(bootpath, kernel);
    430  1.6.2.2  jmcneill 
    431  1.6.2.2  jmcneill 		printf("Loading: %s", bootpath);
    432  1.6.2.2  jmcneill 		if (howto)
    433  1.6.2.2  jmcneill 			printf(" (howto 0x%x)", howto);
    434  1.6.2.2  jmcneill 		printf("\n");
    435  1.6.2.2  jmcneill 		patch_bootstring(bootpath);
    436  1.6.2.2  jmcneill 		win = (loadfile(bootpath, marks, LOAD_ALL) != -1);
    437  1.6.2.2  jmcneill 	}
    438  1.6.2.2  jmcneill 
    439  1.6.2.2  jmcneill 	if (win) {
    440  1.6.2.2  jmcneill 		strncpy(bi_bpath.bootpath, kernel, BTINFO_BOOTPATH_LEN);
    441  1.6.2.2  jmcneill 		bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath));
    442  1.6.2.2  jmcneill 
    443  1.6.2.2  jmcneill 		entry = (void *)marks[MARK_ENTRY];
    444  1.6.2.2  jmcneill 		bi_syms.nsym = marks[MARK_NSYM];
    445  1.6.2.2  jmcneill 		bi_syms.ssym = marks[MARK_SYM];
    446  1.6.2.2  jmcneill 		bi_syms.esym = marks[MARK_END];
    447  1.6.2.2  jmcneill 		bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms));
    448  1.6.2.2  jmcneill 
    449  1.6.2.2  jmcneill 		bi_add(&bi_flags, BTINFO_FLAGS, sizeof(bi_flags));
    450  1.6.2.2  jmcneill 
    451  1.6.2.2  jmcneill 		bi_howto.bi_howto = howto;
    452  1.6.2.2  jmcneill 		bi_add(&bi_howto, BTINFO_HOWTO, sizeof(bi_howto));
    453  1.6.2.2  jmcneill 
    454  1.6.2.2  jmcneill 		entry = (void *)marks[MARK_ENTRY];
    455  1.6.2.2  jmcneill 
    456  1.6.2.2  jmcneill 		DPRINTF(("Bootinfo @ 0x%x\n", bi_addr));
    457  1.6.2.2  jmcneill 		printf("Starting at 0x%x\n\n", (u_int)entry);
    458  1.6.2.2  jmcneill 		(*entry)(memsize, BOOTINFO_MAGIC, bi_addr);
    459  1.6.2.2  jmcneill 	}
    460  1.6.2.2  jmcneill 
    461  1.6.2.2  jmcneill 	(void)printf("Boot failed! Rebooting...\n");
    462  1.6.2.2  jmcneill 	return 0;
    463  1.6.2.2  jmcneill }
    464