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