xref: /netbsd-src/sys/arch/sparc/stand/ofwboot/boot.c (revision be9f90e87153cd472561b72aa3f03674c0ffcb65)
1*be9f90e8Smartin /*	$NetBSD: boot.c,v 1.35 2017/09/15 13:25:34 martin Exp $	*/
297aa1417Scdi 
3e144281cSmrg /*
4e144281cSmrg  * Copyright (c) 1997, 1999 Eduardo E. Horvath.  All rights reserved.
5e144281cSmrg  * Copyright (c) 1997 Jason R. Thorpe.  All rights reserved.
6e144281cSmrg  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7e144281cSmrg  * Copyright (C) 1995, 1996 TooLs GmbH.
8e144281cSmrg  * All rights reserved.
9e144281cSmrg  *
10e144281cSmrg  * ELF support derived from NetBSD/alpha's boot loader, written
11e144281cSmrg  * by Christopher G. Demetriou.
12e144281cSmrg  *
13e144281cSmrg  * Redistribution and use in source and binary forms, with or without
14e144281cSmrg  * modification, are permitted provided that the following conditions
15e144281cSmrg  * are met:
16e144281cSmrg  * 1. Redistributions of source code must retain the above copyright
17e144281cSmrg  *    notice, this list of conditions and the following disclaimer.
18e144281cSmrg  * 2. Redistributions in binary form must reproduce the above copyright
19e144281cSmrg  *    notice, this list of conditions and the following disclaimer in the
20e144281cSmrg  *    documentation and/or other materials provided with the distribution.
21e144281cSmrg  * 3. All advertising materials mentioning features or use of this software
22e144281cSmrg  *    must display the following acknowledgement:
23e144281cSmrg  *	This product includes software developed by TooLs GmbH.
24e144281cSmrg  * 4. The name of TooLs GmbH may not be used to endorse or promote products
25e144281cSmrg  *    derived from this software without specific prior written permission.
26e144281cSmrg  *
27e144281cSmrg  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
28e144281cSmrg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29e144281cSmrg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30e144281cSmrg  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31e144281cSmrg  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32e144281cSmrg  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
33e144281cSmrg  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34e144281cSmrg  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35e144281cSmrg  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36e144281cSmrg  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37e144281cSmrg  */
38e144281cSmrg 
39e144281cSmrg /*
40e144281cSmrg  * First try for the boot code
41e144281cSmrg  *
42e144281cSmrg  * Input syntax is:
43e144281cSmrg  *	[promdev[{:|,}partition]]/[filename] [flags]
44e144281cSmrg  */
45e144281cSmrg 
46e144281cSmrg #include <lib/libsa/stand.h>
47e9c95bf5Srtr #include <lib/libsa/bootcfg.h>
4897aa1417Scdi #include <lib/libsa/loadfile.h>
49e144281cSmrg #include <lib/libkern/libkern.h>
50e144281cSmrg 
51e144281cSmrg #include <sys/param.h>
52e144281cSmrg #include <sys/reboot.h>
53e144281cSmrg #include <sys/disklabel.h>
5449c105ffSjdolecek #include <sys/boot_flag.h>
55e144281cSmrg 
56e144281cSmrg #include <machine/cpu.h>
5797aa1417Scdi #include <machine/promlib.h>
5897aa1417Scdi #include <machine/bootinfo.h>
597709732cSchristos #include <sparc/stand/common/isfloppy.h>
60e144281cSmrg 
6197aa1417Scdi #include "boot.h"
62e144281cSmrg #include "ofdev.h"
63e144281cSmrg #include "openfirm.h"
64e144281cSmrg 
6597aa1417Scdi 
6697aa1417Scdi #define COMPAT_BOOT(marks)	(marks[MARK_START] == marks[MARK_ENTRY])
6797aa1417Scdi 
6897aa1417Scdi 
6997aa1417Scdi typedef void (*entry_t)(long o0, long bootargs, long bootsize, long o3,
7097aa1417Scdi                         long ofw);
71e144281cSmrg 
72e144281cSmrg /*
73e144281cSmrg  * Boot device is derived from ROM provided information, or if there is none,
74e144281cSmrg  * this list is used in sequence, to find a kernel.
75e144281cSmrg  */
7697aa1417Scdi const char *kernelnames[] = {
77e144281cSmrg 	"netbsd",
78e144281cSmrg 	"netbsd.gz",
79e144281cSmrg 	"netbsd.old",
80e144281cSmrg 	"netbsd.old.gz",
81e144281cSmrg 	"onetbsd",
82e144281cSmrg 	"onetbsd.gz",
83e144281cSmrg 	"vmunix ",
84e144281cSmrg #ifdef notyet
85e144281cSmrg 	"netbsd.pl ",
86e144281cSmrg 	"netbsd.pl.gz ",
87e144281cSmrg 	"netbsd.el ",
88e144281cSmrg 	"netbsd.el.gz ",
89e144281cSmrg #endif
90e144281cSmrg 	NULL
91e144281cSmrg };
92e144281cSmrg 
9397aa1417Scdi char bootdev[PROM_MAX_PATH];
949df63719Smartin bool root_fs_quickseekable = true;	/* unset for tftp boots */
959df63719Smartin static bool bootinfo_pass_bootdev = false;
96e144281cSmrg 
9797aa1417Scdi int debug  = 0;
9897aa1417Scdi int compatmode = 0;
9930cac520Smrg extern char twiddle_toggle;
100e144281cSmrg 
101e144281cSmrg #if 0
102e144281cSmrg static void
1034c3c91e6Suwe prom2boot(char *dev)
104e144281cSmrg {
105e144281cSmrg 	char *cp, *lp = 0;
106e144281cSmrg 	int handle;
107e144281cSmrg 	char devtype[16];
108e144281cSmrg 
109e144281cSmrg 	for (cp = dev; *cp; cp++)
110e144281cSmrg 		if (*cp == ':')
111e144281cSmrg 			lp = cp;
112e144281cSmrg 	if (!lp)
113e144281cSmrg 		lp = cp;
114e144281cSmrg 	*lp = 0;
115e144281cSmrg }
116e144281cSmrg #endif
117e144281cSmrg 
11897aa1417Scdi static int
bootoptions(const char * ap,char * loaddev,char * kernel,char * options)119e3218c43Smartin bootoptions(const char *ap, char *loaddev, char *kernel, char *options)
120e144281cSmrg {
12197aa1417Scdi 	int v = 0;
122e3218c43Smartin 	const char *start1 = NULL, *end1 = NULL, *start2 = NULL, *end2 = NULL;
123e3218c43Smartin 	const char *path;
1246997cea0Smartin 	char partition, *pp;
125e144281cSmrg 
12697aa1417Scdi 	*kernel  = '\0';
12797aa1417Scdi 	*options = '\0';
128e144281cSmrg 
12997aa1417Scdi 	if (ap == NULL) {
13097aa1417Scdi 		return (0);
131e144281cSmrg 	}
132e144281cSmrg 
13397aa1417Scdi 	while (*ap == ' ') {
13497aa1417Scdi 		ap++;
13597aa1417Scdi 	}
13697aa1417Scdi 
13797aa1417Scdi 	if (*ap != '-') {
138e3218c43Smartin 		start1 = ap;
13997aa1417Scdi 		while (*ap != '\0' && *ap != ' ') {
14097aa1417Scdi 			ap++;
14197aa1417Scdi 		}
142e3218c43Smartin 		end1 = ap;
14397aa1417Scdi 
144cc645bf7Smartin 		while (*ap == ' ') {
14597aa1417Scdi 			ap++;
14697aa1417Scdi 		}
147e3218c43Smartin 
148e3218c43Smartin 		if (*ap != '-') {
149e3218c43Smartin 			start2 = ap;
150e3218c43Smartin 			while (*ap != '\0' && *ap != ' ') {
151e3218c43Smartin 				ap++;
152e3218c43Smartin 			}
153e3218c43Smartin 			end2 = ap;
154e3218c43Smartin 			while (*ap != '\0' && *ap == ' ') {
155e3218c43Smartin 				ap++;
156e3218c43Smartin 			}
157e3218c43Smartin 		}
158e3218c43Smartin 	}
159e3218c43Smartin 	if (end2 == start2) {
160e3218c43Smartin 		start2 = end2 = NULL;
161e3218c43Smartin 	}
162e3218c43Smartin 	if (end1 == start1) {
163e3218c43Smartin 		start1 = end1 = NULL;
164e3218c43Smartin 	}
165e3218c43Smartin 
166e3218c43Smartin 	if (start1 == NULL) {
167e3218c43Smartin 		/* only options */
168e3218c43Smartin 	} else if (start2 == NULL) {
169e3218c43Smartin 		memcpy(kernel, start1, (end1 - start1));
170e3218c43Smartin 		kernel[end1 - start1] = '\0';
171e3218c43Smartin 		path = filename(kernel, &partition);
1724355df58Smartin 		if (path == NULL) {
1734355df58Smartin 			strcpy(loaddev, kernel);
1744355df58Smartin 			kernel[0] = '\0';
1754355df58Smartin 		} else if (path != kernel) {
176e3218c43Smartin 			/* copy device part */
177e3218c43Smartin 			memcpy(loaddev, kernel, path-kernel);
178e3218c43Smartin 			loaddev[path-kernel] = '\0';
1796997cea0Smartin 			if (partition) {
1806997cea0Smartin 				pp = loaddev + strlen(loaddev);
1816997cea0Smartin 				pp[0] = ':';
1826997cea0Smartin 				pp[1] = partition;
1836997cea0Smartin 				pp[2] = '\0';
1846997cea0Smartin 			}
185e3218c43Smartin 			/* and kernel path */
186e3218c43Smartin 			strcpy(kernel, path);
187e3218c43Smartin 		}
188e3218c43Smartin 	} else {
189e3218c43Smartin 		memcpy(loaddev, start1, (end1-start1));
190e3218c43Smartin 		loaddev[end1-start1] = '\0';
191e3218c43Smartin 		memcpy(kernel, start2, (end2 - start2));
192e3218c43Smartin 		kernel[end2 - start2] = '\0';
19397aa1417Scdi 	}
19497aa1417Scdi 
19530cac520Smrg 	twiddle_toggle = 1;
19697aa1417Scdi 	strcpy(options, ap);
19797aa1417Scdi 	while (*ap != '\0' && *ap != ' ' && *ap != '\t' && *ap != '\n') {
19897aa1417Scdi 		BOOT_FLAG(*ap, v);
19997aa1417Scdi 		switch(*ap++) {
200e144281cSmrg 		case 'D':
201e144281cSmrg 			debug = 2;
202e144281cSmrg 			break;
20397aa1417Scdi 		case 'C':
20497aa1417Scdi 			compatmode = 1;
20597aa1417Scdi 			break;
20630cac520Smrg 		case 'T':
20730cac520Smrg 			twiddle_toggle = 1 - twiddle_toggle;
20830cac520Smrg 			break;
20949c105ffSjdolecek 		default:
210e144281cSmrg 			break;
211e144281cSmrg 		}
212e144281cSmrg 	}
21397aa1417Scdi 
21497aa1417Scdi 	if (((v & RB_KDB) != 0) && (debug == 0)) {
21597aa1417Scdi 		debug = 1;
216e144281cSmrg 	}
217e144281cSmrg 
218e3218c43Smartin 	DPRINTF(("bootoptions: device='%s', kernel='%s', options='%s'\n",
219e3218c43Smartin 	    loaddev, kernel, options));
22097aa1417Scdi 	return (v);
22197aa1417Scdi }
222e144281cSmrg 
22397aa1417Scdi /*
22497aa1417Scdi  * The older (those relying on ofwboot v1.8 and earlier) kernels can't handle
22597aa1417Scdi  * ksyms information unless it resides in a dedicated memory allocated from
22697aa1417Scdi  * PROM and aligned on NBPG boundary. This is because the kernels calculate
22797aa1417Scdi  * their ends on their own, they use address of 'end[]' reference which follows
22897aa1417Scdi  * text segment. Ok, allocate some memory from PROM and copy symbol information
22997aa1417Scdi  * over there.
23097aa1417Scdi  */
231e144281cSmrg static void
ksyms_copyout(void ** ssym,void ** esym)23297aa1417Scdi ksyms_copyout(void **ssym, void **esym)
23397aa1417Scdi {
234c95f237aStsutsui 	uint8_t *addr;
235c95f237aStsutsui 	int kssize = (int)(long)((char *)*esym - (char *)*ssym + 1);
23697aa1417Scdi 
23797aa1417Scdi 	DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p, kssize = %d\n",
23897aa1417Scdi 				*ssym, *esym, kssize));
23997aa1417Scdi 
24097aa1417Scdi 	if ( (addr = OF_claim(0, kssize, NBPG)) == (void *)-1) {
24197aa1417Scdi 		panic("ksyms_copyout(): no space for symbol table");
24297aa1417Scdi 	}
24397aa1417Scdi 
24497aa1417Scdi 	memcpy(addr, *ssym, kssize);
24597aa1417Scdi 	*ssym = addr;
24697aa1417Scdi 	*esym = addr + kssize - 1;
24797aa1417Scdi 
24897aa1417Scdi 	DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p\n", *ssym, *esym));
24997aa1417Scdi }
25097aa1417Scdi 
25197aa1417Scdi /*
25297aa1417Scdi  * Prepare boot information and jump directly to the kernel.
25397aa1417Scdi  */
25497aa1417Scdi static void
jump_to_kernel(u_long * marks,char * kernel,char * args,void * ofw,int boothowto)255a47afdb7Smartin jump_to_kernel(u_long *marks, char *kernel, char *args, void *ofw,
256a47afdb7Smartin 	int boothowto)
257e144281cSmrg {
258e144281cSmrg 	int l, machine_tag;
25997aa1417Scdi 	long newargs[4];
26097aa1417Scdi 	void *ssym, *esym;
26197aa1417Scdi 	vaddr_t bootinfo;
26297aa1417Scdi 	struct btinfo_symtab bi_sym;
26397aa1417Scdi 	struct btinfo_kernend bi_kend;
264a47afdb7Smartin 	struct btinfo_boothowto bi_howto;
26597aa1417Scdi 	char *cp;
26697aa1417Scdi 	char bootline[PROM_MAX_PATH * 2];
267e144281cSmrg 
26897aa1417Scdi 	/* Compose kernel boot line. */
26997aa1417Scdi 	strncpy(bootline, kernel, sizeof(bootline));
27097aa1417Scdi 	cp = bootline + strlen(bootline);
27197aa1417Scdi 	if (*args) {
27297aa1417Scdi 		*cp++ = ' ';
27397aa1417Scdi 		strncpy(bootline, args, sizeof(bootline) - (cp - bootline));
27497aa1417Scdi 	}
27597aa1417Scdi 	*cp = 0; args = bootline;
27697aa1417Scdi 
27797aa1417Scdi 	/* Record symbol information in the bootinfo. */
27897aa1417Scdi 	bootinfo = bi_init(marks[MARK_END]);
27997aa1417Scdi 	bi_sym.nsym = marks[MARK_NSYM];
28097aa1417Scdi 	bi_sym.ssym = marks[MARK_SYM];
28197aa1417Scdi 	bi_sym.esym = marks[MARK_END];
28297aa1417Scdi 	bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym));
28397aa1417Scdi 	bi_kend.addr= bootinfo + BOOTINFO_SIZE;
28497aa1417Scdi 	bi_add(&bi_kend, BTINFO_KERNEND, sizeof(bi_kend));
285a47afdb7Smartin 	bi_howto.boothowto = boothowto;
286a47afdb7Smartin 	bi_add(&bi_howto, BTINFO_BOOTHOWTO, sizeof(bi_howto));
287*be9f90e8Smartin 	if (bootinfo_pass_bootunit)
288*be9f90e8Smartin 		bi_add(&bi_unit, BTINFO_BOOTDEV_UNIT,
289*be9f90e8Smartin 		    sizeof(bi_unit));
2909df63719Smartin 	if (bootinfo_pass_bootdev) {
2919df63719Smartin 		struct {
2929df63719Smartin 			struct btinfo_common common;
2939df63719Smartin 			char name[256];
2949df63719Smartin 		} info;
2959df63719Smartin 
2969df63719Smartin 		strcpy(info.name, bootdev);
2979df63719Smartin 		bi_add(&info, BTINFO_BOOTDEV, strlen(bootdev)
2989df63719Smartin 			+sizeof(struct btinfo_bootdev));
2999df63719Smartin 	}
3009df63719Smartin 
3013ab04256Smartin 	sparc64_finalize_tlb(marks[MARK_DATA]);
30297aa1417Scdi 	sparc64_bi_add();
30397aa1417Scdi 
30497aa1417Scdi 	ssym  = (void*)(long)marks[MARK_SYM];
30597aa1417Scdi 	esym  = (void*)(long)marks[MARK_END];
30697aa1417Scdi 
30797aa1417Scdi 	DPRINTF(("jump_to_kernel(): ssym = %p, esym = %p\n", ssym, esym));
30897aa1417Scdi 
30997aa1417Scdi 	/* Adjust ksyms pointers, if needed. */
31097aa1417Scdi 	if (COMPAT_BOOT(marks) || compatmode) {
31197aa1417Scdi 		ksyms_copyout(&ssym, &esym);
31297aa1417Scdi 	}
313e144281cSmrg 
314e144281cSmrg 	freeall();
315e144281cSmrg 	/*
316e144281cSmrg 	 * When we come in args consists of a pointer to the boot
317e144281cSmrg 	 * string.  We need to fix it so it takes into account
318e144281cSmrg 	 * other params such as romp.
319e144281cSmrg 	 */
320e144281cSmrg 
321e144281cSmrg 	/*
322e144281cSmrg 	 * Stash pointer to end of symbol table after the argument
323e144281cSmrg 	 * strings.
324e144281cSmrg 	 */
325e144281cSmrg 	l = strlen(args) + 1;
326e2cb8590Scegger 	memcpy(args + l, &esym, sizeof(esym));
327e144281cSmrg 	l += sizeof(esym);
328e144281cSmrg 
329e144281cSmrg 	/*
330e144281cSmrg 	 * Tell the kernel we're an OpenFirmware system.
331e144281cSmrg 	 */
332e144281cSmrg 	machine_tag = SPARC_MACHINE_OPENFIRMWARE;
333e2cb8590Scegger 	memcpy(args + l, &machine_tag, sizeof(machine_tag));
334e144281cSmrg 	l += sizeof(machine_tag);
335e144281cSmrg 
336e144281cSmrg 	/*
337e144281cSmrg 	 * Since we don't need the boot string (we can get it from /chosen)
338e144281cSmrg 	 * we won't pass it in.  Just pass in esym and magic #
339e144281cSmrg 	 */
340e144281cSmrg 	newargs[0] = SPARC_MACHINE_OPENFIRMWARE;
341e144281cSmrg 	newargs[1] = (long)esym;
342e144281cSmrg 	newargs[2] = (long)ssym;
34397aa1417Scdi 	newargs[3] = (long)(void*)bootinfo;
344e144281cSmrg 	args = (char *)newargs;
345e144281cSmrg 	l = sizeof(newargs);
346e144281cSmrg 
347e144281cSmrg 	/* if -D is set then pause in the PROM. */
34897aa1417Scdi 	if (debug > 1) callrom();
349e144281cSmrg 
350e144281cSmrg 	/*
35197aa1417Scdi 	 * Jump directly to the kernel. Solaris kernel and Sun PROM
35297aa1417Scdi 	 * flash updates expect ROMP vector in %o0, so we do. Format
35397aa1417Scdi 	 * of other parameters and their order reflect OF_chain()
35497aa1417Scdi 	 * symantics since this is what older NetBSD kernels rely on.
35597aa1417Scdi 	 * (see sparc64/include/bootinfo.h for specification).
356e144281cSmrg 	 */
35797aa1417Scdi 	DPRINTF(("jump_to_kernel(%lx, %lx, %lx, %lx, %lx) @ %p\n", (long)ofw,
35897aa1417Scdi 				(long)args, (long)l, (long)ofw, (long)ofw,
35997aa1417Scdi 				(void*)marks[MARK_ENTRY]));
36097aa1417Scdi 	(*(entry_t)marks[MARK_ENTRY])((long)ofw, (long)args, (long)l, (long)ofw,
36197aa1417Scdi 				      (long)ofw);
36297aa1417Scdi 	printf("Returned from kernel entry point!\n");
363e144281cSmrg }
364e144281cSmrg 
36597aa1417Scdi static void
start_kernel(char * kernel,char * bootline,void * ofw,int isfloppy,int boothowto)366a47afdb7Smartin start_kernel(char *kernel, char *bootline, void *ofw, int isfloppy,
367a47afdb7Smartin 	int boothowto)
36897aa1417Scdi {
36997aa1417Scdi 	int fd;
370d48a59cfSmartin 	u_long marks[MARK_MAX] = {0};
371d5a8010aSchristos 	int flags = LOAD_ALL;
372d48a59cfSmartin 
373d5a8010aSchristos 	if (isfloppy)
374d5a8010aSchristos 		flags &= ~LOAD_BACKWARDS;
375e144281cSmrg 
37697aa1417Scdi 	/*
37797aa1417Scdi 	 * First, load headers using default allocator and check whether kernel
37897aa1417Scdi 	 * entry address matches kernel text load address. If yes, this is the
37997aa1417Scdi 	 * old kernel designed for ofwboot v1.8 and therefore it must be mapped
38097aa1417Scdi 	 * by PROM. Otherwise, map the kernel with 4MB permanent pages.
38197aa1417Scdi 	 */
38297aa1417Scdi 	loadfile_set_allocator(LOADFILE_NOP_ALLOCATOR);
38397aa1417Scdi 	if ( (fd = loadfile(kernel, marks, LOAD_HDR|COUNT_TEXT)) != -1) {
38497aa1417Scdi 		if (COMPAT_BOOT(marks) || compatmode) {
38597aa1417Scdi 			(void)printf("[c] ");
38697aa1417Scdi 			loadfile_set_allocator(LOADFILE_OFW_ALLOCATOR);
38797aa1417Scdi 		} else {
38897aa1417Scdi 			loadfile_set_allocator(LOADFILE_MMU_ALLOCATOR);
389e144281cSmrg 		}
39097aa1417Scdi 		(void)printf("Loading %s: ", kernel);
39197aa1417Scdi 
39226c80400Schristos 		if (fdloadfile(fd, marks, flags) != -1) {
393deb09ce5Smartin 			close(fd);
394a47afdb7Smartin 			jump_to_kernel(marks, kernel, bootline, ofw, boothowto);
395e144281cSmrg 		}
396e144281cSmrg 	}
39797aa1417Scdi 	(void)printf("Failed to load '%s'.\n", kernel);
398e144281cSmrg }
399e144281cSmrg 
400e3218c43Smartin static void
help(void)401e3218c43Smartin help(void)
402e3218c43Smartin {
403e3218c43Smartin 	printf( "enter a special command\n"
404e3218c43Smartin 		"  halt\n"
405e3218c43Smartin 		"  exit\n"
406e3218c43Smartin 		"    to return to OpenFirmware\n"
407e3218c43Smartin 		"  ?\n"
408e3218c43Smartin 		"  help\n"
409e3218c43Smartin 		"    to display this message\n"
410e3218c43Smartin 		"or a boot specification:\n"
411e3218c43Smartin 		"  [device] [kernel] [options]\n"
412e3218c43Smartin 		"\n"
413e3218c43Smartin 		"for example:\n"
414e3218c43Smartin 		"  disk:a netbsd -s\n");
415e3218c43Smartin }
416e3218c43Smartin 
4179df63719Smartin static void
do_config_command(const char * cmd,char * arg)418e9c95bf5Srtr do_config_command(const char *cmd, char *arg)
4199df63719Smartin {
4209df63719Smartin 	DPRINTF(("do_config_command: %s\n", cmd));
4219df63719Smartin 	if (strcmp(cmd, "bootpartition") == 0) {
4229df63719Smartin 		char *c;
4239df63719Smartin 
4249df63719Smartin 		DPRINTF(("switching boot partition to %s from %s\n",
4259df63719Smartin 		    arg, bootdev));
4269df63719Smartin 		c = strrchr(bootdev, ':');
4279df63719Smartin 		if (!c) return;
4289df63719Smartin 		if (c[1] == 0) return;
4299df63719Smartin 		if (strlen(arg) > strlen(c)) return;
4309df63719Smartin 		strcpy(c, arg);
4319df63719Smartin 		DPRINTF(("new boot device: %s\n", bootdev));
4329df63719Smartin 		bootinfo_pass_bootdev = true;
4339df63719Smartin 	}
4349df63719Smartin }
4359df63719Smartin 
4369df63719Smartin static void
check_boot_config(void)4379df63719Smartin check_boot_config(void)
4389df63719Smartin {
439e9c95bf5Srtr 	if (!root_fs_quickseekable)
4402e67acc4Smartin 		return;
4419df63719Smartin 
442e9c95bf5Srtr 	perform_bootcfg(BOOTCFG_FILENAME, &do_config_command, 32768);
4439df63719Smartin }
4449df63719Smartin 
445e144281cSmrg void
main(void * ofw)44697aa1417Scdi main(void *ofw)
447e144281cSmrg {
448a47afdb7Smartin 	int boothowto, i = 0, isfloppy, kboothowto;
449e144281cSmrg 
45097aa1417Scdi 	char kernel[PROM_MAX_PATH];
45197aa1417Scdi 	char bootline[PROM_MAX_PATH];
45297aa1417Scdi 
45397aa1417Scdi 	/* Initialize OpenFirmware */
45497aa1417Scdi 	romp = ofw;
45597aa1417Scdi 	prom_init();
456e144281cSmrg 
4574c2f43b8Smartin 	printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev);
458e144281cSmrg 
45997aa1417Scdi 	/* Figure boot arguments */
46097aa1417Scdi 	strncpy(bootdev, prom_getbootpath(), sizeof(bootdev) - 1);
461a47afdb7Smartin 	kboothowto = boothowto =
462a47afdb7Smartin 	    bootoptions(prom_getbootargs(), bootdev, kernel, bootline);
4637709732cSchristos 	isfloppy = bootdev_isfloppy(bootdev);
46497aa1417Scdi 
46597aa1417Scdi 	for (;; *kernel = '\0') {
466e144281cSmrg 		if (boothowto & RB_ASKNAME) {
467c95f237aStsutsui 			char cmdline[PROM_MAX_PATH];
46897aa1417Scdi 
469e144281cSmrg 			printf("Boot: ");
4702357cddaSdholland 			kgets(cmdline, sizeof(cmdline));
47197aa1417Scdi 
472e3218c43Smartin 			if (!strcmp(cmdline,"exit") ||
473e3218c43Smartin 			    !strcmp(cmdline,"halt")) {
47497aa1417Scdi 				prom_halt();
475e3218c43Smartin 			} else if (!strcmp(cmdline, "?") ||
476e3218c43Smartin 				   !strcmp(cmdline, "help")) {
477e3218c43Smartin 				help();
478e3218c43Smartin 				continue;
479e144281cSmrg 			}
480e3218c43Smartin 
481e3218c43Smartin 			boothowto  = bootoptions(cmdline, bootdev, kernel,
482e3218c43Smartin 			    bootline);
483e3218c43Smartin 			boothowto |= RB_ASKNAME;
484e3218c43Smartin 			i = 0;
48597aa1417Scdi 		}
48697aa1417Scdi 
48797aa1417Scdi 		if (*kernel == '\0') {
48897aa1417Scdi 			if (kernelnames[i] == NULL) {
48997aa1417Scdi 				boothowto |= RB_ASKNAME;
49097aa1417Scdi 				continue;
49197aa1417Scdi 			}
49297aa1417Scdi 			strncpy(kernel, kernelnames[i++], PROM_MAX_PATH);
49397aa1417Scdi 		} else if (i == 0) {
494e144281cSmrg 			/*
49597aa1417Scdi 			 * Kernel name was passed via command line -- ask user
49697aa1417Scdi 			 * again if requested image fails to boot.
497e144281cSmrg 			 */
49897aa1417Scdi 			boothowto |= RB_ASKNAME;
49997aa1417Scdi 		}
50097aa1417Scdi 
5019df63719Smartin 		check_boot_config();
502a47afdb7Smartin 		start_kernel(kernel, bootline, ofw, isfloppy, kboothowto);
50397aa1417Scdi 
50497aa1417Scdi 		/*
50597aa1417Scdi 		 * Try next name from kernel name list if not in askname mode,
50697aa1417Scdi 		 * enter askname on reaching list's end.
50797aa1417Scdi 		 */
50897aa1417Scdi 		if ((boothowto & RB_ASKNAME) == 0 && (kernelnames[i] != NULL)) {
50997aa1417Scdi 			printf(": trying %s...\n", kernelnames[i]);
510e144281cSmrg 		} else {
511e144281cSmrg 			printf("\n");
512e144281cSmrg 			boothowto |= RB_ASKNAME;
513e144281cSmrg 		}
514e144281cSmrg 	}
515e144281cSmrg 
51697aa1417Scdi 	(void)printf("Boot failed! Exiting to the Firmware.\n");
51797aa1417Scdi 	prom_halt();
518e144281cSmrg }
519