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