Home | History | Annotate | Line # | Download | only in boot
boot.c revision 1.2
      1 /*	$NetBSD: boot.c,v 1.2 2003/08/07 16:27:17 agc Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jonathan Stone, Michael Hitch, Simon Burge and Wayne Knowles.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Copyright (c) 1992, 1993
     41  *	The Regents of the University of California.  All rights reserved.
     42  *
     43  * This code is derived from software contributed to Berkeley by
     44  * Ralph Campbell.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. Neither the name of the University nor the names of its contributors
     55  *    may be used to endorse or promote products derived from this software
     56  *    without specific prior written permission.
     57  *
     58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     68  * SUCH DAMAGE.
     69  *
     70  *	@(#)boot.c	8.1 (Berkeley) 6/10/93
     71  */
     72 
     73 #include <machine/cpu.h>
     74 #include <machine/leds.h>
     75 #include <machine/vmparam.h>
     76 
     77 #include <lib/libsa/stand.h>
     78 #include <lib/libsa/loadfile.h>
     79 #include <lib/libkern/libkern.h>
     80 
     81 #include <sys/param.h>
     82 #include <sys/exec.h>
     83 #include <sys/exec_elf.h>
     84 
     85 #include "boot.h"
     86 #include "cons.h"
     87 #include "common.h"
     88 
     89 char *kernelnames[] = {
     90 	"netbsd",
     91 	"netbsd.gz",
     92 	"onetbsd",
     93 	"onetbsd.gz",
     94 	"netbsd.bak",
     95 	"netbsd.bak.gz",
     96 	"netbsd.old",
     97 	"netbsd.old.gz",
     98 	"netbsd.cobalt",
     99 	"netbsd.cobalt.gz",
    100 	"netbsd.elf",
    101 	"netbsd.elf.gz",
    102 	NULL
    103 };
    104 
    105 extern long end;
    106 static char *bootstring;
    107 
    108 static int patch_bootstring	(char *bootspec);
    109 static int get_bsdbootname	(char **dev, char **name, char **kname);
    110 static int prominit		(unsigned int memsize);
    111 static int print_banner		(unsigned int memsize);
    112 
    113 void start(void);
    114 int cpu_reboot(void);
    115 int main(unsigned int memsize);
    116 
    117 /*
    118  * Perform CPU reboot.
    119  */
    120 int
    121 cpu_reboot()
    122 {
    123 	printf("rebooting...\n\n");
    124 
    125 	*(volatile char *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
    126 	printf("WARNING: reboot failed!\n");
    127 
    128 	for (;;);
    129 }
    130 
    131 /*
    132  * Substitute root value with NetBSD root partition name.
    133  */
    134 int
    135 patch_bootstring(bootspec)
    136 	char *bootspec;
    137 {
    138 	char *sp = bootstring;
    139 	u_int8_t unit, part;
    140 	int dev, error;
    141 	char *file;
    142 
    143 	DPRINTF(("patch_bootstring: %s\n", bootspec));
    144 
    145 	/* get boot parameters */
    146 	if (devparse(bootspec, &dev, &unit, &part, (const char **)&file) != 0)
    147 		unit = part = 0;
    148 
    149 	DPRINTF(("patch_bootstring: %d, %d\n", unit, part));
    150 
    151 	/* take out the 'root=xxx' parameter */
    152 	if ( (sp = strstr(bootstring, "root=")) != NULL) {
    153 		const char *end;
    154 
    155 		end = strchr(sp, ' ');
    156 
    157 		/* strip off leading spaces */
    158 		for (--sp; (sp > bootstring) && (*sp == ' '); --sp)
    159 			;
    160 
    161 		if (end != NULL)
    162 			strcpy(++sp, end);
    163 		else
    164 			*++sp = '\0';
    165 	}
    166 
    167 	DPRINTF(("patch_bootstring: [%s]\n", bootstring));
    168 
    169 #define DEVNAMESIZE	(MAXDEVNAME + sizeof(" root=/dev/hd") + sizeof("0a"))
    170 	/* bsd notation -> linux notation (wd0a -> hda1) */
    171 	if (strlen(bootstring) <= (511 - DEVNAMESIZE)) {
    172 		int len;
    173 
    174 		strcat(bootstring, " root=/dev/hd");
    175 
    176 		len = strlen(bootstring);
    177 		bootstring[len++] = unit + 'a';
    178 		bootstring[len++] = part + '1';
    179 		bootstring[len++] = '\0';
    180 	}
    181 
    182 	DPRINTF(("patch_bootstring: -> %s\n", bootstring));
    183 	return (0);
    184 }
    185 
    186 /*
    187  * Extract NetBSD boot specification
    188  */
    189 int
    190 get_bsdbootname(dev, name, kname)
    191 	char **dev;
    192 	char **name;
    193 	char **kname;
    194 {
    195 	char *spec;
    196 
    197 	*dev = NULL;
    198 	*name = NULL;
    199 	*kname = NULL;
    200 
    201 	if ( (spec = strstr(bootstring, "nbsd=")) != NULL) {
    202 		int len;
    203 		char *ptr = strchr(spec, ' ');
    204 
    205 		spec += 5; 	/* skip 'nbsd=' */
    206 		len = (ptr == NULL) ? strlen(spec) : ptr - spec;
    207 
    208 		if (len > 0) {
    209 			char *devname = alloc(len + 1);
    210 			if (devname != NULL) {
    211 				memcpy(devname, spec, len);
    212 				devname[len] = '\0';
    213 
    214 				if ( (ptr = memchr(devname,':',len)) != NULL) {
    215 					/* wdXX:kernel */
    216 					*ptr = '\0';
    217 					*dev = devname;
    218 
    219 					if (*++ptr)
    220 						*kname = ptr;
    221 
    222 					devname = alloc(len + 1);
    223 					if (devname != NULL) {
    224 						memcpy(devname, spec, len);
    225 						devname[len] = '\0';
    226 					}
    227 				}
    228 
    229 				*name = devname;
    230 				return (0);
    231 			}
    232 		}
    233 	}
    234 
    235 	return (1);
    236 }
    237 
    238 /*
    239  * Get the bootstring from PROM.
    240  */
    241 int
    242 prominit(memsize)
    243 	unsigned int memsize;
    244 {
    245 	bootstring = (char *)(memsize - 512);
    246 	bootstring[511] = '\0';
    247 }
    248 
    249 /*
    250  * Print boot message.
    251  */
    252 int
    253 print_banner(memsize)
    254 	unsigned int memsize;
    255 {
    256 	printf("\n");
    257 	printf(">> %s " NETBSD_VERS " Bootloader, Revision %s [@%p]\n",
    258 			bootprog_name, bootprog_rev,
    259 			(unsigned long)&start & ~PAGE_MASK);
    260 	printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
    261 	printf(">> Memory:\t\t%u k\n", (memsize - MIPS_KSEG0_START) / 1024);
    262 	printf(">> PROM boot string:\t%s\n", bootstring);
    263 }
    264 
    265 /*
    266  * Entry point.
    267  * Parse PROM boot string, load the kernel and jump into it
    268  */
    269 int
    270 main(memsize)
    271 	unsigned int memsize;
    272 {
    273 	char *name, **namep, *dev, *kernel, *spec;
    274 	char bootpath[PATH_MAX];
    275 	int win;
    276 	u_long marks[MARK_MAX];
    277 	void (*entry) __P((unsigned int));
    278 
    279 	int addr, speed;
    280 
    281 	prominit(memsize);
    282 	cninit(&addr, &speed);
    283 
    284 	print_banner(memsize);
    285 
    286 	memset(marks, 0, sizeof marks);
    287 	get_bsdbootname(&dev, &name, &kernel);
    288 
    289 	if (kernel != NULL) {
    290 		DPRINTF(("kernel: %s\n", kernel));
    291 		patch_bootstring(name);
    292 		win = (loadfile(name, marks, LOAD_KERNEL) == 0);
    293 	} else {
    294 		win = 0;
    295 		DPRINTF(("kernel: NULL\n"));
    296 		for (namep = kernelnames, win = 0;
    297 				(*namep != NULL) && !win;
    298 				namep++) {
    299 			kernel = *namep;
    300 
    301 			bootpath[0] = '\0';
    302 
    303 			strcpy(bootpath, (dev != NULL) ? dev : "wd0a");
    304 			strcat(bootpath, ":");
    305 			strcat(bootpath, kernel);
    306 
    307 			printf("Loading: %s\n", bootpath);
    308 			patch_bootstring(bootpath);
    309 			win = (loadfile(bootpath, marks, LOAD_ALL) != -1);
    310 		}
    311 	}
    312 
    313 	if (win) {
    314 		entry = (void *) marks[MARK_ENTRY];
    315 
    316 		printf("Starting at 0x%x\n\n", (u_int)entry);
    317 		(*entry)(memsize);
    318 	}
    319 
    320 	(void)printf("Boot failed! Rebooting...\n");
    321 	return (0);
    322 }
    323