boot.c revision 1.29 1 1.29 martin /* $NetBSD: boot.c,v 1.29 2012/05/28 19:24:30 martin Exp $ */
2 1.12 cdi
3 1.1 mrg /*
4 1.1 mrg * Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved.
5 1.1 mrg * Copyright (c) 1997 Jason R. Thorpe. All rights reserved.
6 1.1 mrg * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7 1.1 mrg * Copyright (C) 1995, 1996 TooLs GmbH.
8 1.1 mrg * All rights reserved.
9 1.1 mrg *
10 1.1 mrg * ELF support derived from NetBSD/alpha's boot loader, written
11 1.1 mrg * by Christopher G. Demetriou.
12 1.1 mrg *
13 1.1 mrg * Redistribution and use in source and binary forms, with or without
14 1.1 mrg * modification, are permitted provided that the following conditions
15 1.1 mrg * are met:
16 1.1 mrg * 1. Redistributions of source code must retain the above copyright
17 1.1 mrg * notice, this list of conditions and the following disclaimer.
18 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright
19 1.1 mrg * notice, this list of conditions and the following disclaimer in the
20 1.1 mrg * documentation and/or other materials provided with the distribution.
21 1.1 mrg * 3. All advertising materials mentioning features or use of this software
22 1.1 mrg * must display the following acknowledgement:
23 1.1 mrg * This product includes software developed by TooLs GmbH.
24 1.1 mrg * 4. The name of TooLs GmbH may not be used to endorse or promote products
25 1.1 mrg * derived from this software without specific prior written permission.
26 1.1 mrg *
27 1.1 mrg * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
28 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 1.1 mrg * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 1.1 mrg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 1.1 mrg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
33 1.1 mrg * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34 1.1 mrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35 1.1 mrg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 1.1 mrg * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 1.1 mrg */
38 1.1 mrg
39 1.1 mrg /*
40 1.1 mrg * First try for the boot code
41 1.1 mrg *
42 1.1 mrg * Input syntax is:
43 1.1 mrg * [promdev[{:|,}partition]]/[filename] [flags]
44 1.1 mrg */
45 1.1 mrg
46 1.1 mrg #include <lib/libsa/stand.h>
47 1.12 cdi #include <lib/libsa/loadfile.h>
48 1.1 mrg #include <lib/libkern/libkern.h>
49 1.1 mrg
50 1.1 mrg #include <sys/param.h>
51 1.1 mrg #include <sys/reboot.h>
52 1.1 mrg #include <sys/disklabel.h>
53 1.2 jdolecek #include <sys/boot_flag.h>
54 1.1 mrg
55 1.1 mrg #include <machine/cpu.h>
56 1.12 cdi #include <machine/promlib.h>
57 1.12 cdi #include <machine/bootinfo.h>
58 1.25 christos #include <sparc/stand/common/isfloppy.h>
59 1.1 mrg
60 1.12 cdi #include "boot.h"
61 1.1 mrg #include "ofdev.h"
62 1.1 mrg #include "openfirm.h"
63 1.1 mrg
64 1.12 cdi
65 1.12 cdi #define COMPAT_BOOT(marks) (marks[MARK_START] == marks[MARK_ENTRY])
66 1.12 cdi
67 1.12 cdi
68 1.12 cdi typedef void (*entry_t)(long o0, long bootargs, long bootsize, long o3,
69 1.12 cdi long ofw);
70 1.1 mrg
71 1.1 mrg /*
72 1.1 mrg * Boot device is derived from ROM provided information, or if there is none,
73 1.1 mrg * this list is used in sequence, to find a kernel.
74 1.1 mrg */
75 1.12 cdi const char *kernelnames[] = {
76 1.12 cdi "netbsd",
77 1.12 cdi "netbsd.gz",
78 1.12 cdi "netbsd.old",
79 1.12 cdi "netbsd.old.gz",
80 1.12 cdi "onetbsd",
81 1.12 cdi "onetbsd.gz",
82 1.1 mrg "vmunix ",
83 1.1 mrg #ifdef notyet
84 1.1 mrg "netbsd.pl ",
85 1.1 mrg "netbsd.pl.gz ",
86 1.1 mrg "netbsd.el ",
87 1.1 mrg "netbsd.el.gz ",
88 1.1 mrg #endif
89 1.1 mrg NULL
90 1.1 mrg };
91 1.1 mrg
92 1.12 cdi char bootdev[PROM_MAX_PATH];
93 1.22 martin bool root_fs_quickseekable = true; /* unset for tftp boots */
94 1.22 martin static bool bootinfo_pass_bootdev = false;
95 1.1 mrg
96 1.12 cdi int debug = 0;
97 1.12 cdi int compatmode = 0;
98 1.26 mrg extern char twiddle_toggle;
99 1.1 mrg
100 1.1 mrg #if 0
101 1.1 mrg static void
102 1.13 uwe prom2boot(char *dev)
103 1.1 mrg {
104 1.1 mrg char *cp, *lp = 0;
105 1.1 mrg int handle;
106 1.1 mrg char devtype[16];
107 1.1 mrg
108 1.1 mrg for (cp = dev; *cp; cp++)
109 1.1 mrg if (*cp == ':')
110 1.1 mrg lp = cp;
111 1.1 mrg if (!lp)
112 1.1 mrg lp = cp;
113 1.1 mrg *lp = 0;
114 1.1 mrg }
115 1.1 mrg #endif
116 1.1 mrg
117 1.12 cdi static int
118 1.15 martin bootoptions(const char *ap, char *loaddev, char *kernel, char *options)
119 1.1 mrg {
120 1.12 cdi int v = 0;
121 1.15 martin const char *start1 = NULL, *end1 = NULL, *start2 = NULL, *end2 = NULL;
122 1.15 martin const char *path;
123 1.17 martin char partition, *pp;
124 1.12 cdi
125 1.12 cdi *kernel = '\0';
126 1.12 cdi *options = '\0';
127 1.12 cdi
128 1.12 cdi if (ap == NULL) {
129 1.12 cdi return (0);
130 1.12 cdi }
131 1.12 cdi
132 1.12 cdi while (*ap == ' ') {
133 1.12 cdi ap++;
134 1.12 cdi }
135 1.12 cdi
136 1.12 cdi if (*ap != '-') {
137 1.15 martin start1 = ap;
138 1.12 cdi while (*ap != '\0' && *ap != ' ') {
139 1.12 cdi ap++;
140 1.12 cdi }
141 1.15 martin end1 = ap;
142 1.1 mrg
143 1.12 cdi while (*ap != '\0' && *ap == ' ') {
144 1.12 cdi ap++;
145 1.12 cdi }
146 1.15 martin
147 1.15 martin if (*ap != '-') {
148 1.15 martin start2 = ap;
149 1.15 martin while (*ap != '\0' && *ap != ' ') {
150 1.15 martin ap++;
151 1.15 martin }
152 1.15 martin end2 = ap;
153 1.15 martin while (*ap != '\0' && *ap == ' ') {
154 1.15 martin ap++;
155 1.15 martin }
156 1.15 martin }
157 1.15 martin }
158 1.15 martin if (end2 == start2) {
159 1.15 martin start2 = end2 = NULL;
160 1.15 martin }
161 1.15 martin if (end1 == start1) {
162 1.15 martin start1 = end1 = NULL;
163 1.15 martin }
164 1.15 martin
165 1.15 martin if (start1 == NULL) {
166 1.15 martin /* only options */
167 1.15 martin } else if (start2 == NULL) {
168 1.15 martin memcpy(kernel, start1, (end1 - start1));
169 1.15 martin kernel[end1 - start1] = '\0';
170 1.15 martin path = filename(kernel, &partition);
171 1.16 martin if (path == NULL) {
172 1.16 martin strcpy(loaddev, kernel);
173 1.16 martin kernel[0] = '\0';
174 1.16 martin } else if (path != kernel) {
175 1.15 martin /* copy device part */
176 1.15 martin memcpy(loaddev, kernel, path-kernel);
177 1.15 martin loaddev[path-kernel] = '\0';
178 1.17 martin if (partition) {
179 1.17 martin pp = loaddev + strlen(loaddev);
180 1.17 martin pp[0] = ':';
181 1.17 martin pp[1] = partition;
182 1.17 martin pp[2] = '\0';
183 1.17 martin }
184 1.15 martin /* and kernel path */
185 1.15 martin strcpy(kernel, path);
186 1.15 martin }
187 1.15 martin } else {
188 1.15 martin memcpy(loaddev, start1, (end1-start1));
189 1.15 martin loaddev[end1-start1] = '\0';
190 1.15 martin memcpy(kernel, start2, (end2 - start2));
191 1.15 martin kernel[end2 - start2] = '\0';
192 1.1 mrg }
193 1.12 cdi
194 1.26 mrg twiddle_toggle = 1;
195 1.12 cdi strcpy(options, ap);
196 1.12 cdi while (*ap != '\0' && *ap != ' ' && *ap != '\t' && *ap != '\n') {
197 1.12 cdi BOOT_FLAG(*ap, v);
198 1.12 cdi switch(*ap++) {
199 1.1 mrg case 'D':
200 1.1 mrg debug = 2;
201 1.1 mrg break;
202 1.12 cdi case 'C':
203 1.12 cdi compatmode = 1;
204 1.12 cdi break;
205 1.26 mrg case 'T':
206 1.26 mrg twiddle_toggle = 1 - twiddle_toggle;
207 1.26 mrg break;
208 1.2 jdolecek default:
209 1.1 mrg break;
210 1.1 mrg }
211 1.1 mrg }
212 1.12 cdi
213 1.12 cdi if (((v & RB_KDB) != 0) && (debug == 0)) {
214 1.12 cdi debug = 1;
215 1.12 cdi }
216 1.12 cdi
217 1.15 martin DPRINTF(("bootoptions: device='%s', kernel='%s', options='%s'\n",
218 1.15 martin loaddev, kernel, options));
219 1.12 cdi return (v);
220 1.1 mrg }
221 1.1 mrg
222 1.12 cdi /*
223 1.12 cdi * The older (those relying on ofwboot v1.8 and earlier) kernels can't handle
224 1.12 cdi * ksyms information unless it resides in a dedicated memory allocated from
225 1.12 cdi * PROM and aligned on NBPG boundary. This is because the kernels calculate
226 1.12 cdi * their ends on their own, they use address of 'end[]' reference which follows
227 1.12 cdi * text segment. Ok, allocate some memory from PROM and copy symbol information
228 1.12 cdi * over there.
229 1.12 cdi */
230 1.12 cdi static void
231 1.12 cdi ksyms_copyout(void **ssym, void **esym)
232 1.12 cdi {
233 1.28 tsutsui uint8_t *addr;
234 1.28 tsutsui int kssize = (int)(long)((char *)*esym - (char *)*ssym + 1);
235 1.12 cdi
236 1.12 cdi DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p, kssize = %d\n",
237 1.12 cdi *ssym, *esym, kssize));
238 1.1 mrg
239 1.12 cdi if ( (addr = OF_claim(0, kssize, NBPG)) == (void *)-1) {
240 1.12 cdi panic("ksyms_copyout(): no space for symbol table");
241 1.12 cdi }
242 1.12 cdi
243 1.12 cdi memcpy(addr, *ssym, kssize);
244 1.12 cdi *ssym = addr;
245 1.12 cdi *esym = addr + kssize - 1;
246 1.12 cdi
247 1.12 cdi DPRINTF(("ksyms_copyout(): ssym = %p, esym = %p\n", *ssym, *esym));
248 1.12 cdi }
249 1.12 cdi
250 1.12 cdi /*
251 1.12 cdi * Prepare boot information and jump directly to the kernel.
252 1.12 cdi */
253 1.1 mrg static void
254 1.29 martin jump_to_kernel(u_long *marks, char *kernel, char *args, void *ofw,
255 1.29 martin int boothowto)
256 1.1 mrg {
257 1.1 mrg int l, machine_tag;
258 1.12 cdi long newargs[4];
259 1.12 cdi void *ssym, *esym;
260 1.12 cdi vaddr_t bootinfo;
261 1.12 cdi struct btinfo_symtab bi_sym;
262 1.12 cdi struct btinfo_kernend bi_kend;
263 1.29 martin struct btinfo_boothowto bi_howto;
264 1.12 cdi char *cp;
265 1.12 cdi char bootline[PROM_MAX_PATH * 2];
266 1.1 mrg
267 1.12 cdi /* Compose kernel boot line. */
268 1.12 cdi strncpy(bootline, kernel, sizeof(bootline));
269 1.12 cdi cp = bootline + strlen(bootline);
270 1.12 cdi if (*args) {
271 1.12 cdi *cp++ = ' ';
272 1.12 cdi strncpy(bootline, args, sizeof(bootline) - (cp - bootline));
273 1.12 cdi }
274 1.12 cdi *cp = 0; args = bootline;
275 1.12 cdi
276 1.12 cdi /* Record symbol information in the bootinfo. */
277 1.12 cdi bootinfo = bi_init(marks[MARK_END]);
278 1.12 cdi bi_sym.nsym = marks[MARK_NSYM];
279 1.12 cdi bi_sym.ssym = marks[MARK_SYM];
280 1.12 cdi bi_sym.esym = marks[MARK_END];
281 1.12 cdi bi_add(&bi_sym, BTINFO_SYMTAB, sizeof(bi_sym));
282 1.12 cdi bi_kend.addr= bootinfo + BOOTINFO_SIZE;
283 1.12 cdi bi_add(&bi_kend, BTINFO_KERNEND, sizeof(bi_kend));
284 1.29 martin bi_howto.boothowto = boothowto;
285 1.29 martin bi_add(&bi_howto, BTINFO_BOOTHOWTO, sizeof(bi_howto));
286 1.22 martin if (bootinfo_pass_bootdev) {
287 1.22 martin struct {
288 1.22 martin struct btinfo_common common;
289 1.22 martin char name[256];
290 1.22 martin } info;
291 1.22 martin
292 1.22 martin strcpy(info.name, bootdev);
293 1.22 martin bi_add(&info, BTINFO_BOOTDEV, strlen(bootdev)
294 1.22 martin +sizeof(struct btinfo_bootdev));
295 1.22 martin }
296 1.22 martin
297 1.14 martin sparc64_finalize_tlb(marks[MARK_DATA]);
298 1.12 cdi sparc64_bi_add();
299 1.12 cdi
300 1.12 cdi ssym = (void*)(long)marks[MARK_SYM];
301 1.12 cdi esym = (void*)(long)marks[MARK_END];
302 1.12 cdi
303 1.12 cdi DPRINTF(("jump_to_kernel(): ssym = %p, esym = %p\n", ssym, esym));
304 1.12 cdi
305 1.12 cdi /* Adjust ksyms pointers, if needed. */
306 1.12 cdi if (COMPAT_BOOT(marks) || compatmode) {
307 1.12 cdi ksyms_copyout(&ssym, &esym);
308 1.12 cdi }
309 1.1 mrg
310 1.1 mrg freeall();
311 1.1 mrg /*
312 1.1 mrg * When we come in args consists of a pointer to the boot
313 1.1 mrg * string. We need to fix it so it takes into account
314 1.1 mrg * other params such as romp.
315 1.1 mrg */
316 1.1 mrg
317 1.1 mrg /*
318 1.1 mrg * Stash pointer to end of symbol table after the argument
319 1.1 mrg * strings.
320 1.1 mrg */
321 1.1 mrg l = strlen(args) + 1;
322 1.20 cegger memcpy(args + l, &esym, sizeof(esym));
323 1.1 mrg l += sizeof(esym);
324 1.1 mrg
325 1.1 mrg /*
326 1.1 mrg * Tell the kernel we're an OpenFirmware system.
327 1.1 mrg */
328 1.1 mrg machine_tag = SPARC_MACHINE_OPENFIRMWARE;
329 1.20 cegger memcpy(args + l, &machine_tag, sizeof(machine_tag));
330 1.1 mrg l += sizeof(machine_tag);
331 1.1 mrg
332 1.1 mrg /*
333 1.1 mrg * Since we don't need the boot string (we can get it from /chosen)
334 1.1 mrg * we won't pass it in. Just pass in esym and magic #
335 1.1 mrg */
336 1.1 mrg newargs[0] = SPARC_MACHINE_OPENFIRMWARE;
337 1.1 mrg newargs[1] = (long)esym;
338 1.1 mrg newargs[2] = (long)ssym;
339 1.12 cdi newargs[3] = (long)(void*)bootinfo;
340 1.1 mrg args = (char *)newargs;
341 1.1 mrg l = sizeof(newargs);
342 1.1 mrg
343 1.1 mrg /* if -D is set then pause in the PROM. */
344 1.12 cdi if (debug > 1) callrom();
345 1.12 cdi
346 1.12 cdi /*
347 1.12 cdi * Jump directly to the kernel. Solaris kernel and Sun PROM
348 1.12 cdi * flash updates expect ROMP vector in %o0, so we do. Format
349 1.12 cdi * of other parameters and their order reflect OF_chain()
350 1.12 cdi * symantics since this is what older NetBSD kernels rely on.
351 1.12 cdi * (see sparc64/include/bootinfo.h for specification).
352 1.12 cdi */
353 1.12 cdi DPRINTF(("jump_to_kernel(%lx, %lx, %lx, %lx, %lx) @ %p\n", (long)ofw,
354 1.12 cdi (long)args, (long)l, (long)ofw, (long)ofw,
355 1.12 cdi (void*)marks[MARK_ENTRY]));
356 1.12 cdi (*(entry_t)marks[MARK_ENTRY])((long)ofw, (long)args, (long)l, (long)ofw,
357 1.12 cdi (long)ofw);
358 1.12 cdi printf("Returned from kernel entry point!\n");
359 1.1 mrg }
360 1.1 mrg
361 1.12 cdi static void
362 1.29 martin start_kernel(char *kernel, char *bootline, void *ofw, int isfloppy,
363 1.29 martin int boothowto)
364 1.1 mrg {
365 1.1 mrg int fd;
366 1.12 cdi u_long marks[MARK_MAX];
367 1.24 christos int flags = LOAD_ALL;
368 1.24 christos if (isfloppy)
369 1.24 christos flags &= ~LOAD_BACKWARDS;
370 1.1 mrg
371 1.1 mrg /*
372 1.12 cdi * First, load headers using default allocator and check whether kernel
373 1.12 cdi * entry address matches kernel text load address. If yes, this is the
374 1.12 cdi * old kernel designed for ofwboot v1.8 and therefore it must be mapped
375 1.12 cdi * by PROM. Otherwise, map the kernel with 4MB permanent pages.
376 1.1 mrg */
377 1.12 cdi loadfile_set_allocator(LOADFILE_NOP_ALLOCATOR);
378 1.12 cdi if ( (fd = loadfile(kernel, marks, LOAD_HDR|COUNT_TEXT)) != -1) {
379 1.12 cdi if (COMPAT_BOOT(marks) || compatmode) {
380 1.12 cdi (void)printf("[c] ");
381 1.12 cdi loadfile_set_allocator(LOADFILE_OFW_ALLOCATOR);
382 1.12 cdi } else {
383 1.12 cdi loadfile_set_allocator(LOADFILE_MMU_ALLOCATOR);
384 1.12 cdi }
385 1.12 cdi (void)printf("Loading %s: ", kernel);
386 1.1 mrg
387 1.23 christos if (fdloadfile(fd, marks, flags) != -1) {
388 1.21 martin close(fd);
389 1.29 martin jump_to_kernel(marks, kernel, bootline, ofw, boothowto);
390 1.1 mrg }
391 1.1 mrg }
392 1.12 cdi (void)printf("Failed to load '%s'.\n", kernel);
393 1.1 mrg }
394 1.1 mrg
395 1.15 martin static void
396 1.15 martin help(void)
397 1.15 martin {
398 1.15 martin printf( "enter a special command\n"
399 1.15 martin " halt\n"
400 1.15 martin " exit\n"
401 1.15 martin " to return to OpenFirmware\n"
402 1.15 martin " ?\n"
403 1.15 martin " help\n"
404 1.15 martin " to display this message\n"
405 1.15 martin "or a boot specification:\n"
406 1.15 martin " [device] [kernel] [options]\n"
407 1.15 martin "\n"
408 1.15 martin "for example:\n"
409 1.15 martin " disk:a netbsd -s\n");
410 1.15 martin }
411 1.15 martin
412 1.22 martin static void
413 1.22 martin do_config_command(const char *cmd, const char *arg)
414 1.22 martin {
415 1.22 martin DPRINTF(("do_config_command: %s\n", cmd));
416 1.22 martin if (strcmp(cmd, "bootpartition") == 0) {
417 1.22 martin char *c;
418 1.22 martin
419 1.22 martin DPRINTF(("switching boot partition to %s from %s\n",
420 1.22 martin arg, bootdev));
421 1.22 martin c = strrchr(bootdev, ':');
422 1.22 martin if (!c) return;
423 1.22 martin if (c[1] == 0) return;
424 1.22 martin if (strlen(arg) > strlen(c)) return;
425 1.22 martin strcpy(c, arg);
426 1.22 martin DPRINTF(("new boot device: %s\n", bootdev));
427 1.22 martin bootinfo_pass_bootdev = true;
428 1.22 martin }
429 1.22 martin }
430 1.22 martin
431 1.22 martin static void
432 1.22 martin parse_boot_config(char *cfg, size_t len)
433 1.22 martin {
434 1.22 martin const char *cmd = NULL, *arg = NULL;
435 1.22 martin
436 1.22 martin while (len) {
437 1.22 martin if (isspace(*cfg)) {
438 1.22 martin cfg++; len--; continue;
439 1.22 martin }
440 1.22 martin if (*cfg == ';' || *cfg == '#') {
441 1.22 martin while (len && *cfg != '\r' && *cfg != '\n') {
442 1.22 martin cfg++; len--;
443 1.22 martin }
444 1.22 martin continue;
445 1.22 martin }
446 1.22 martin cmd = cfg;
447 1.22 martin while (len && !isspace(*cfg)) {
448 1.22 martin cfg++; len--;
449 1.22 martin }
450 1.22 martin *cfg = 0;
451 1.22 martin if (len > 0) {
452 1.22 martin cfg++; len--;
453 1.22 martin while (isspace(*cfg) && len) {
454 1.22 martin cfg++; len--;
455 1.22 martin }
456 1.22 martin if (len > 0 ) {
457 1.22 martin arg = cfg;
458 1.22 martin while (len && !isspace(*cfg)) {
459 1.22 martin cfg++; len--;
460 1.22 martin }
461 1.22 martin *cfg = 0;
462 1.22 martin }
463 1.22 martin }
464 1.22 martin do_config_command(cmd, arg);
465 1.22 martin if (len > 0) {
466 1.22 martin cfg++; len--;
467 1.22 martin }
468 1.22 martin }
469 1.22 martin }
470 1.22 martin
471 1.22 martin static void
472 1.22 martin check_boot_config(void)
473 1.22 martin {
474 1.28 tsutsui int fd, off, len;
475 1.22 martin struct stat st;
476 1.22 martin char *bc;
477 1.22 martin
478 1.22 martin if (!root_fs_quickseekable) return;
479 1.22 martin DPRINTF(("checking for /boot.cfg...\n"));
480 1.22 martin fd = open("/boot.cfg", 0);
481 1.22 martin if (fd < 0) return;
482 1.22 martin DPRINTF(("found /boot.cfg\n"));
483 1.22 martin if (fstat(fd, &st) == -1 || st.st_size > 32*1024) {
484 1.22 martin close(fd);
485 1.22 martin return;
486 1.22 martin }
487 1.22 martin bc = alloc(st.st_size+1);
488 1.22 martin off = 0;
489 1.22 martin do {
490 1.22 martin len = read(fd, bc+off, 1024);
491 1.22 martin if (len <= 0)
492 1.22 martin break;
493 1.22 martin off += len;
494 1.22 martin } while (len > 0);
495 1.22 martin bc[off] = 0;
496 1.22 martin close(fd);
497 1.22 martin
498 1.22 martin parse_boot_config(bc, off);
499 1.22 martin }
500 1.22 martin
501 1.12 cdi void
502 1.12 cdi main(void *ofw)
503 1.12 cdi {
504 1.29 martin int boothowto, i = 0, isfloppy, kboothowto;
505 1.1 mrg
506 1.12 cdi char kernel[PROM_MAX_PATH];
507 1.12 cdi char bootline[PROM_MAX_PATH];
508 1.1 mrg
509 1.12 cdi /* Initialize OpenFirmware */
510 1.12 cdi romp = ofw;
511 1.12 cdi prom_init();
512 1.1 mrg
513 1.7 martin printf("\r>> %s, Revision %s\n", bootprog_name, bootprog_rev);
514 1.1 mrg
515 1.12 cdi /* Figure boot arguments */
516 1.12 cdi strncpy(bootdev, prom_getbootpath(), sizeof(bootdev) - 1);
517 1.29 martin kboothowto = boothowto =
518 1.29 martin bootoptions(prom_getbootargs(), bootdev, kernel, bootline);
519 1.25 christos isfloppy = bootdev_isfloppy(bootdev);
520 1.12 cdi
521 1.12 cdi for (;; *kernel = '\0') {
522 1.1 mrg if (boothowto & RB_ASKNAME) {
523 1.28 tsutsui char cmdline[PROM_MAX_PATH];
524 1.12 cdi
525 1.1 mrg printf("Boot: ");
526 1.12 cdi gets(cmdline);
527 1.12 cdi
528 1.15 martin if (!strcmp(cmdline,"exit") ||
529 1.15 martin !strcmp(cmdline,"halt")) {
530 1.12 cdi prom_halt();
531 1.15 martin } else if (!strcmp(cmdline, "?") ||
532 1.15 martin !strcmp(cmdline, "help")) {
533 1.15 martin help();
534 1.15 martin continue;
535 1.12 cdi }
536 1.15 martin
537 1.15 martin boothowto = bootoptions(cmdline, bootdev, kernel,
538 1.15 martin bootline);
539 1.15 martin boothowto |= RB_ASKNAME;
540 1.15 martin i = 0;
541 1.1 mrg }
542 1.12 cdi
543 1.12 cdi if (*kernel == '\0') {
544 1.12 cdi if (kernelnames[i] == NULL) {
545 1.12 cdi boothowto |= RB_ASKNAME;
546 1.12 cdi continue;
547 1.12 cdi }
548 1.12 cdi strncpy(kernel, kernelnames[i++], PROM_MAX_PATH);
549 1.12 cdi } else if (i == 0) {
550 1.12 cdi /*
551 1.12 cdi * Kernel name was passed via command line -- ask user
552 1.12 cdi * again if requested image fails to boot.
553 1.12 cdi */
554 1.12 cdi boothowto |= RB_ASKNAME;
555 1.12 cdi }
556 1.12 cdi
557 1.22 martin check_boot_config();
558 1.29 martin start_kernel(kernel, bootline, ofw, isfloppy, kboothowto);
559 1.12 cdi
560 1.1 mrg /*
561 1.12 cdi * Try next name from kernel name list if not in askname mode,
562 1.12 cdi * enter askname on reaching list's end.
563 1.1 mrg */
564 1.12 cdi if ((boothowto & RB_ASKNAME) == 0 && (kernelnames[i] != NULL)) {
565 1.12 cdi printf(": trying %s...\n", kernelnames[i]);
566 1.1 mrg } else {
567 1.1 mrg printf("\n");
568 1.1 mrg boothowto |= RB_ASKNAME;
569 1.1 mrg }
570 1.1 mrg }
571 1.1 mrg
572 1.12 cdi (void)printf("Boot failed! Exiting to the Firmware.\n");
573 1.12 cdi prom_halt();
574 1.1 mrg }
575