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