1 /**	$MirOS: src/sys/stand/boot/boot.c,v 1.22 2009/10/24 16:04:38 tg Exp $	*/
2 /*	$OpenBSD: boot.c,v 1.36 2007/06/26 10:34:41 tom Exp $	*/
3 
4 /*
5  * Copyright (c) 2002, 2003, 2004, 2006, 2009 Thorsten Glaser
6  * Copyright (c) 2003 Dale Rahn
7  * Copyright (c) 1997,1998 Michael Shalayeff
8  * All rights reserved.
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  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32 
33 #include <sys/param.h>
34 #include <sys/reboot.h>
35 #include <sys/stat.h>
36 #include <libsa.h>
37 #include <lib/libsa/loadfile.h>
38 #ifdef IN_PXEBOOT
39 #include <pxe.h>
40 
41 extern int have_pxe;
42 extern BOOTPLAYER bootplayer;
43 #endif
44 
45 #include "cmd.h"
46 
47 #ifndef MBSD_PREFIX
48 #define MBSD_PREFIX ""
49 #endif
50 
51 static const char *const kernels[] = {
52 	MBSD_PREFIX "/bsd",
53 #if !defined(SMALL_BOOT)
54 	MBSD_PREFIX "/bsd.old",
55 #endif
56 	NULL
57 };
58 
59 char prog_ident[40];
60 char *progname = "BOOT";
61 
62 extern const char version[];
63 extern int doboot;
64 int bootprompt = 1;
65 uint32_t hook_value = 0;
66 
67 void
boot(dev_t bootdev)68 boot(dev_t bootdev)
69 {
70 	const char *bootfile = kernels[0];
71 	int fd, i = 0, try = 0, st = -1;
72 	u_long marks[MARK_MAX];
73 #ifdef IN_PXEBOOT
74 	uint32_t ip;
75 #endif
76 #if defined(IN_PXEBOOT) || !defined(SMALL_BOOT)
77 	char myconf[64];
78 #endif
79 
80 	machdep();
81 
82 	snprintf(prog_ident, sizeof(prog_ident),
83 	    "MirBSD boot %s", version);
84 	printf(">> %s\n>> booting from device %Xh",
85 	    prog_ident, bootdev);
86 
87 	devboot(bootdev, cmd.bootdev);
88 	printf(" = %s\n", cmd.bootdev);
89 	memcpy(cmd.image, bootfile, strlen(bootfile) + 1);
90 
91 	cmd.conf = NULL;
92 	if (strlen(cmd_buf)) {
93 		/* command line was passed from previous loader */
94 		cmd.cmd = NULL;
95 		cmd.timeout = 0;
96 		doboot = 0;
97 		if (docmd())
98 			goto try_boot;
99 		st = 0;
100 		bootprompt = 1;
101 		goto try_cmd;
102 	}
103 #ifdef IN_PXEBOOT
104 	ip = bootplayer.yip;
105 
106 	/*
107 	 * Let's be non-intrusive.. We try to get our /$IP/boot.cfg
108 	 * first, and if that fails, fall back to /boot.cfg, and
109 	 * if that fails, do no boot.cfg at all.
110 	 * Pim van Pelt / Paul de Weerd 20040328
111 	 */
112 	if (have_pxe > 0) {
113 		cmd.boothowto = 0;
114 		snprintf(myconf, sizeof (myconf),
115 		    MBSD_PREFIX "/%d.%d.%d.%d/boot.cfg",
116 		    ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, ip >> 24);
117 		cmd.conf = myconf;
118 		cmd.addr = (void *)DEFAULT_KERNEL_ADDRESS;
119 		cmd.timeout = 5;
120 
121 		st = read_conf();
122 	} else
123 #endif
124 #if !defined(SMALL_BOOT)
125 	if (hook_value) {
126 		cmd.boothowto = 0;
127 		snprintf(myconf, sizeof (myconf), MBSD_PREFIX "/boot.%d",
128 		    (hook_value % 999));
129 		cmd.conf = myconf;
130 		cmd.addr = (void *)DEFAULT_KERNEL_ADDRESS;
131 		cmd.timeout = 5;
132 
133 		st = read_conf();
134 	}
135 #endif
136 
137 	if (st < 0) {
138 #if defined(IN_PXEBOOT) || !defined(SMALL_BOOT)
139 		if (cmd.conf)
140 			printf("Attempt to read %s failed.\n", cmd.conf);
141 #endif
142 		cmd.boothowto = 0;
143 		cmd.conf = MBSD_PREFIX "/boot.cfg";
144 		cmd.addr = (void *)DEFAULT_KERNEL_ADDRESS;
145 		cmd.timeout = 5;
146 
147 		st = read_conf();
148 	}
149 	if (!bootprompt)
150 		snprintf(cmd.path, sizeof cmd.path, "%s:%s",
151 		    cmd.bootdev, cmd.image);
152 
153  try_cmd:
154 	while (1) {
155 		/* no boot.cfg, or no boot cmd in there */
156 		if (bootprompt && st <= 0)
157 			do {
158 				printf("boot> ");
159 			} while(!getcmd());
160  try_boot:
161 		st = 0;
162 		bootprompt = 1;	/* allow reselect should we fail */
163 
164 		printf("booting %s: ", cmd.path);
165 		marks[MARK_START] = (u_long)cmd.addr;
166 		if ((fd = loadfile(cmd.path, marks, LOAD_ALL)) != -1) {
167 			close(fd);
168 			break;
169 		}
170 
171 		if (kernels[++i] == NULL) {
172 			try += 1;
173 			bootfile = kernels[i = 0];
174 		} else
175 			bootfile = kernels[i];
176 		memcpy(cmd.image, bootfile, strlen(bootfile) + 1);
177 		printf(" failed(%d).%s%s\n", errno,
178 		    (cmd.timeout) ? " will try " : "",
179 		    (cmd.timeout) ? bootfile : "");
180 
181 		if (cmd.timeout) {
182 			if (try < 2)
183 				cmd.timeout++;
184 			else {
185 				printf("Turning timeout off.\n");
186 				cmd.timeout = doboot = 0;
187 			}
188 		}
189 	}
190 
191 	/* exec */
192 	run_loadfile(marks, cmd.boothowto);
193 }
194