Annotation of src/sys/arch/landisk/stand/boot/boot2.c, Revision 1.3.6.1
1.3.6.1 ! tls 1: /* $NetBSD$ */
1.1 uwe 2:
3: /*
4: * Copyright (c) 2003
5: * David Laight. All rights reserved
6: * Copyright (c) 1996, 1997, 1999
7: * Matthias Drochner. All rights reserved.
8: * Copyright (c) 1996, 1997
9: * Perry E. Metzger. All rights reserved.
10: * Copyright (c) 1997
11: * Jason R. Thorpe. All rights reserved
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgements:
23: * This product includes software developed for the NetBSD Project
24: * by Matthias Drochner.
25: * This product includes software developed for the NetBSD Project
26: * by Perry E. Metzger.
27: * 4. The names of the authors may not be used to endorse or promote products
28: * derived from this software without specific prior written permission.
29: *
30: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
31: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
34: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40: */
41:
42: /* Based on stand/biosboot/main.c */
43:
44: #include <sys/types.h>
45: #include <sys/reboot.h>
46: #include <sys/bootblock.h>
47: #include <sys/boot_flag.h>
48:
49: #include <lib/libsa/stand.h>
50: #include <lib/libsa/loadfile.h>
51: #include <lib/libsa/ufs.h>
52: #include <lib/libkern/libkern.h>
53:
54: #include "biosdisk.h"
55:
56: #include "boot.h"
57: #include "bootinfo.h"
58: #include "cons.h"
59:
60: int errno;
61:
62: extern struct landisk_boot_params boot_params;
63:
64: static const char * const names[][2] = {
65: { "netbsd", "netbsd.gz" },
66: { "netbsd.old", "netbsd.old.gz", },
67: { "onetbsd", "onetbsd.gz" },
68: };
69:
70: #define NUMNAMES (sizeof(names) / sizeof(names[0]))
71: #define DEFFILENAME names[0][0]
72:
73: #define MAXDEVNAME 16
74:
75: static char *default_devname;
76: static uint default_unit, default_partition;
77: static const char *default_filename;
78:
79: char *sprint_bootsel(const char *filename);
80: void bootit(const char *filename, int howto, int tell);
81: void print_banner(void);
82: void boot2(uint32_t boot_biossector);
83:
84: int exec_netbsd(const char *file, int howto);
85:
86: static char *gettrailer(char *arg);
87: static int parseopts(const char *opts, int *howto);
88: static int parseboot(char *arg, char **filename, int *howto);
89:
90: void bootmenu(void);
91: static void bootcmd_help(char *);
92: static void bootcmd_ls(char *);
93: static void bootcmd_quit(char *);
94: static void bootcmd_halt(char *);
95: static void bootcmd_boot(char *);
96: static void bootcmd_monitor(char *);
97:
98: static const struct bootblk_command {
99: const char *c_name;
100: void (*c_fn)(char *arg);
101: } bootcmds[] = {
102: { "help", bootcmd_help },
103: { "?", bootcmd_help },
104: { "ls", bootcmd_ls },
105: { "quit", bootcmd_quit },
106: { "halt", bootcmd_halt },
107: { "boot", bootcmd_boot },
108: { "!", bootcmd_monitor },
109: { NULL, NULL },
110: };
111:
112: int
113: parsebootfile(const char *fname, char **devname,
114: uint *unit, uint *partition, const char **file)
115: {
116: const char *col;
117:
118: *devname = default_devname;
119: *unit = default_unit;
120: *partition = default_partition;
121: *file = default_filename;
122:
123: if (fname == NULL)
124: return (0);
125:
126: if((col = strchr(fname, ':'))) { /* device given */
127: static char savedevname[MAXDEVNAME+1];
128: int devlen;
129: unsigned int u = 0, p = 0;
130: int i = 0;
131:
132: devlen = col - fname;
133: if (devlen > MAXDEVNAME)
134: return (EINVAL);
135:
136: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
137: if (!isvalidname(fname[i]))
138: return (EINVAL);
139: do {
140: savedevname[i] = fname[i];
141: i++;
142: } while (isvalidname(fname[i]));
143: savedevname[i] = '\0';
144:
145: #define isnum(c) ((c) >= '0' && (c) <= '9')
146: if (i < devlen) {
147: if (!isnum(fname[i]))
148: return (EUNIT);
149: do {
150: u *= 10;
151: u += fname[i++] - '0';
152: } while (isnum(fname[i]));
153: }
154:
155: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'p')
156: if (i < devlen) {
157: if (!isvalidpart(fname[i]))
158: return (EPART);
159: p = fname[i++] - 'a';
160: }
161:
162: if (i != devlen)
163: return (ENXIO);
164:
165: *devname = savedevname;
166: *unit = u;
167: *partition = p;
168: fname = col + 1;
169: }
170:
171: if (*fname)
172: *file = fname;
173:
174: return (0);
175: }
176:
177: char *
178: sprint_bootsel(const char *filename)
179: {
180: static char buf[80];
181: char *devname;
182: uint unit, partition;
183: const char *file;
184:
185: if (parsebootfile(filename, &devname, &unit, &partition, &file) == 0) {
1.3.6.1 ! tls 186: snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
! 187: 'a' + partition, file);
1.1 uwe 188: return (buf);
189: }
190: return ("(invalid)");
191: }
192:
193: void
194: bootit(const char *filename, int howto, int tell)
195: {
196:
197: if (tell) {
198: printf("booting %s", sprint_bootsel(filename));
199: if (howto)
200: printf(" (howto 0x%x)", howto);
201: printf("\n");
202: }
203:
204: if (exec_netbsd(filename, howto) < 0) {
205: printf("boot: %s: %s\n", sprint_bootsel(filename),
206: strerror(errno));
207: } else {
208: printf("boot returned\n");
209: }
210: }
211:
212: void
213: print_banner(void)
214: {
215: extern const char bootprog_name[];
216: extern const char bootprog_rev[];
217:
218: printf("\n");
219: printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
220: }
221:
222: void
223: boot2(uint32_t boot_biossector)
224: {
225: int currname;
226: int c;
227:
228: /* Initialize hardware */
229: tick_init();
230:
231: /* Initialize console */
232: cninit(boot_params.bp_consdev);
233:
234: print_banner();
235:
236: /* try to set default device to what BIOS tells us */
237: bios2dev(0x40, &default_devname, &default_unit,
238: boot_biossector, &default_partition);
239:
240: /* if the user types "boot" without filename */
241: default_filename = DEFFILENAME;
242:
243: printf("Press return to boot now, any other key for boot menu\n");
244: currname = 0;
245: for (;;) {
246: printf("booting %s - starting in ",
247: sprint_bootsel(names[currname][0]));
248:
249: c = awaitkey(boot_params.bp_timeout, 1);
250: if ((c != '\r') && (c != '\n') && (c != '\0')) {
251: printf("type \"?\" or \"help\" for help.\n");
252: bootmenu(); /* does not return */
253: }
254:
255: /*
256: * try pairs of names[] entries, foo and foo.gz
257: */
258: /* don't print "booting..." again */
259: bootit(names[currname][0], 0, 0);
260: /* since it failed, try compressed bootfile. */
261: bootit(names[currname][1], 0, 1);
262: /* since it failed, try switching bootfile. */
263: currname = (currname + 1) % NUMNAMES;
264: }
265: }
266:
267: int
268: exec_netbsd(const char *file, int howto)
269: {
270: static char bibuf[BOOTINFO_MAXSIZE];
271: u_long marks[MARK_MAX];
272: int fd;
273:
274: BI_ALLOC(6); /* XXX */
275:
276: marks[MARK_START] = 0; /* loadaddr */
277: if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1)
278: goto out;
279:
280: printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
281: marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
282:
283: {
284: struct btinfo_common *help;
285: char *p;
286: int i;
287:
288: p = bibuf;
289: memcpy(p, &bootinfo->nentries, sizeof(bootinfo->nentries));
290: p += sizeof(bootinfo->nentries);
291: for (i = 0; i < bootinfo->nentries; i++) {
292: help = (struct btinfo_common *)(bootinfo->entry[i]);
293: memcpy(p, help, help->len);
294: p += help->len;
295: }
296: }
297:
298: cache_flush();
299: cache_disable();
300:
301: (*(void (*)(int, void *))marks[MARK_ENTRY])(howto, bibuf);
302: panic("exec returned");
303:
304: out:
305: BI_FREE();
306: bootinfo = 0;
307: return (-1);
308: }
309:
310: /*
311: * boot menu
312: */
313: /* ARGSUSED */
314: static void
315: bootcmd_help(char *arg)
316: {
317:
318: printf("commands are:\n"
319: "boot [xdNx:][filename] [-acdqsv]\n"
320: " (ex. \"hd0a:netbsd.old -s\"\n"
321: "ls [path]\n"
322: "help|?\n"
323: "halt\n"
324: "quit\n");
325: }
326:
327: static void
328: bootcmd_ls(char *arg)
329: {
330: const char *save = default_filename;
331:
332: default_filename = "/";
1.3 tsutsui 333: ls(arg);
1.1 uwe 334: default_filename = save;
335: }
336:
337: /* ARGSUSED */
338: static void
339: bootcmd_quit(char *arg)
340: {
341:
342: printf("Exiting...\n");
343: delay(1000);
344: reboot();
345: /* Note: we shouldn't get to this point! */
346: panic("Could not reboot!");
347: exit(0);
348: }
349:
350: /* ARGSUSED */
351: static void
352: bootcmd_halt(char *arg)
353: {
354:
355: printf("Exiting...\n");
356: delay(1000);
357: halt();
358: /* Note: we shouldn't get to this point! */
359: panic("Could not halt!");
360: exit(0);
361: }
362:
363: static void
364: bootcmd_boot(char *arg)
365: {
366: char *filename;
367: int howto;
368:
369: if (parseboot(arg, &filename, &howto)) {
370: bootit(filename, howto, 1);
371: }
372: }
373:
374: /* ARGSUSED */
375: static void
376: bootcmd_monitor(char *arg)
377: {
378:
379: db_monitor();
380: printf("\n");
381: }
382:
383: static void
384: docommand(const struct bootblk_command * const cmds, char *arg)
385: {
386: char *options;
387: int i;
388:
389: options = gettrailer(arg);
390:
391: for (i = 0; cmds[i].c_name != NULL; i++) {
392: if (strcmp(arg, cmds[i].c_name) == 0) {
393: (*cmds[i].c_fn)(options);
394: return;
395: }
396: }
397:
398: printf("unknown command\n");
399: bootcmd_help(NULL);
400: }
401:
402: void
403: bootmenu(void)
404: {
405: char input[256];
406: char *c;
407:
408: for (;;) {
409: c = input;
410:
411: input[0] = '\0';
412: printf("> ");
413: gets(input);
414:
415: /*
416: * Skip leading whitespace.
417: */
418: while (*c == ' ') {
419: c++;
420: }
421: if (*c != '\0') {
422: docommand(bootcmds, c);
423: }
424: }
425: }
426:
427: /*
428: * from arch/i386/stand/lib/parseutil.c
429: */
430: /*
431: * chops the head from the arguments and returns the arguments if any,
432: * or possibly an empty string.
433: */
434: static char *
435: gettrailer(char *arg)
436: {
437: char *options;
438:
439: if ((options = strchr(arg, ' ')) == NULL)
440: return ("");
441: else
442: *options++ = '\0';
443:
444: /* trim leading blanks */
445: while (*options && *options == ' ')
446: options++;
447:
448: return (options);
449: }
450:
451: static int
452: parseopts(const char *opts, int *howto)
453: {
454: int r, tmpopt = 0;
455:
456: opts++; /* skip - */
457: while (*opts && *opts != ' ') {
458: r = 0;
459: BOOT_FLAG(*opts, r);
460: if (r == 0) {
461: printf("-%c: unknown flag\n", *opts);
462: bootcmd_help(NULL);
463: return (0);
464: }
465: tmpopt |= r;
466: opts++;
467: }
468:
469: *howto = tmpopt;
470: return (1);
471: }
472:
473: static int
474: parseboot(char *arg, char **filename, int *howto)
475: {
476: char *opts = NULL;
477:
478: *filename = 0;
479: *howto = 0;
480:
481: /* if there were no arguments */
482: if (*arg == NULL)
483: return (1);
484:
485: /* format is... */
486: /* [[xxNx:]filename] [-adqsv] */
487:
488: /* check for just args */
489: if (arg[0] == '-') {
490: opts = arg;
491: } else {
492: /* there's a file name */
493: *filename = arg;
494:
495: opts = gettrailer(arg);
496: if (*opts == NULL) {
497: opts = NULL;
498: } else if (*opts != '-') {
499: printf("invalid arguments\n");
500: bootcmd_help(NULL);
501: return (0);
502: }
503: }
504:
505: /* at this point, we have dealt with filenames. */
506:
507: /* now, deal with options */
508: if (opts) {
509: if (parseopts(opts, howto) == 0) {
510: return (0);
511: }
512: }
513: return (1);
514: }
515:
516: /*
517: * for common/lib/libc/arch/sh3/gen/udivsi3.S
518: */
519: int raise(int sig);
520:
521: /*ARGSUSED*/
522: int
523: raise(int sig)
524: {
525:
526: return 0;
527: }
CVSweb <webmaster@jp.NetBSD.org>