Annotation of src/sys/arch/i386/stand/boot/boot2.c, Revision 1.30
1.30 ! lukem 1: /* $NetBSD: boot2.c,v 1.29 2008/05/06 09:48:00 apb Exp $ */
1.25 ad 2:
3: /*-
4: * Copyright (c) 2008 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
1.1 dsl 28:
29: /*
30: * Copyright (c) 2003
31: * David Laight. All rights reserved
32: * Copyright (c) 1996, 1997, 1999
33: * Matthias Drochner. All rights reserved.
34: * Copyright (c) 1996, 1997
35: * Perry E. Metzger. All rights reserved.
36: * Copyright (c) 1997
37: * Jason R. Thorpe. All rights reserved
38: *
39: * Redistribution and use in source and binary forms, with or without
40: * modification, are permitted provided that the following conditions
41: * are met:
42: * 1. Redistributions of source code must retain the above copyright
43: * notice, this list of conditions and the following disclaimer.
44: * 2. Redistributions in binary form must reproduce the above copyright
45: * notice, this list of conditions and the following disclaimer in the
46: * documentation and/or other materials provided with the distribution.
47: * 3. All advertising materials mentioning features or use of this software
48: * must display the following acknowledgements:
49: * This product includes software developed for the NetBSD Project
50: * by Matthias Drochner.
51: * This product includes software developed for the NetBSD Project
52: * by Perry E. Metzger.
53: * 4. The names of the authors may not be used to endorse or promote products
54: * derived from this software without specific prior written permission.
55: *
56: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
58: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
59: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
60: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
61: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
62: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
63: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
64: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
65: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66: */
67:
68: /* Based on stand/biosboot/main.c */
69:
1.5 christos 70: #include <sys/types.h>
1.1 dsl 71: #include <sys/reboot.h>
72: #include <sys/bootblock.h>
73:
74: #include <lib/libsa/stand.h>
75: #include <lib/libsa/ufs.h>
76: #include <lib/libkern/libkern.h>
77:
78: #include <libi386.h>
79: #include "devopen.h"
1.25 ad 80: #include "bootmod.h"
1.1 dsl 81:
1.17 sborrill 82: #ifdef SUPPORT_USTARFS
83: #include "ustarfs.h"
84: #endif
1.1 dsl 85: #ifdef SUPPORT_PS2
86: #include <biosmca.h>
87: #endif
88:
1.4 lukem 89: extern struct x86_boot_params boot_params;
1.1 dsl 90:
91: extern const char bootprog_name[], bootprog_rev[], bootprog_date[],
92: bootprog_maker[];
93:
1.11 junyoung 94: int errno;
95:
96: int boot_biosdev;
97: u_int boot_biossector;
98:
1.1 dsl 99: static const char * const names[][2] = {
1.8 junyoung 100: { "netbsd", "netbsd.gz" },
101: { "onetbsd", "onetbsd.gz" },
102: { "netbsd.old", "netbsd.old.gz" },
1.1 dsl 103: };
104:
105: #define NUMNAMES (sizeof(names)/sizeof(names[0]))
106: #define DEFFILENAME names[0][0]
107:
108: #define MAXDEVNAME 16
109:
1.15 sborrill 110: #ifndef SMALL
111: #define BOOTCONF "boot.cfg"
112: #define MAXMENU 10
1.28 chris 113: #define MAXBANNER 12
1.26 sborrill 114: #define COMMAND_SEPARATOR ';'
1.15 sborrill 115: #endif /* !SMALL */
116:
1.1 dsl 117: static char *default_devname;
118: static int default_unit, default_partition;
119: static const char *default_filename;
120:
121: char *sprint_bootsel(const char *);
122: void bootit(const char *, int, int);
123: void print_banner(void);
1.11 junyoung 124: void boot2(int, u_int);
1.1 dsl 125:
1.15 sborrill 126: #ifndef SMALL
127: void parsebootconf(const char *);
128: void doboottypemenu(void);
129: int atoi(const char *);
130: #endif /* !SMALL */
131:
1.1 dsl 132: void command_help(char *);
133: void command_ls(char *);
134: void command_quit(char *);
135: void command_boot(char *);
136: void command_dev(char *);
137: void command_consdev(char *);
1.25 ad 138: void command_modules(char *);
139: void command_load(char *);
1.1 dsl 140:
141: const struct bootblk_command commands[] = {
142: { "help", command_help },
143: { "?", command_help },
144: { "ls", command_ls },
145: { "quit", command_quit },
146: { "boot", command_boot },
147: { "dev", command_dev },
148: { "consdev", command_consdev },
1.25 ad 149: { "modules", command_modules },
150: { "load", command_load },
1.1 dsl 151: { NULL, NULL },
152: };
153:
1.15 sborrill 154: #ifndef SMALL
155: struct bootconf_def {
156: char *banner[MAXBANNER]; /* Banner text */
157: char *command[MAXMENU]; /* Menu commands per entry*/
158: char *consdev; /* Console device */
159: int def; /* Default menu option */
160: char *desc[MAXMENU]; /* Menu text per entry */
161: int nummenu; /* Number of menu items */
162: int timeout; /* Timeout in seconds */
163: } bootconf;
164: #endif /* !SMALL */
165:
1.1 dsl 166: int
167: parsebootfile(const char *fname, char **fsname, char **devname,
1.11 junyoung 168: int *unit, int *partition, const char **file)
1.1 dsl 169: {
170: const char *col;
171:
172: *fsname = "ufs";
173: *devname = default_devname;
174: *unit = default_unit;
175: *partition = default_partition;
176: *file = default_filename;
177:
178: if (fname == NULL)
1.7 junyoung 179: return 0;
1.1 dsl 180:
1.8 junyoung 181: if ((col = strchr(fname, ':')) != NULL) { /* device given */
1.1 dsl 182: static char savedevname[MAXDEVNAME+1];
183: int devlen;
1.11 junyoung 184: int u = 0, p = 0;
1.1 dsl 185: int i = 0;
186:
187: devlen = col - fname;
188: if (devlen > MAXDEVNAME)
1.6 junyoung 189: return EINVAL;
1.1 dsl 190:
191: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
192: if (!isvalidname(fname[i]))
1.6 junyoung 193: return EINVAL;
1.1 dsl 194: do {
195: savedevname[i] = fname[i];
196: i++;
197: } while (isvalidname(fname[i]));
198: savedevname[i] = '\0';
199:
200: #define isnum(c) ((c) >= '0' && (c) <= '9')
201: if (i < devlen) {
202: if (!isnum(fname[i]))
1.6 junyoung 203: return EUNIT;
1.1 dsl 204: do {
205: u *= 10;
206: u += fname[i++] - '0';
207: } while (isnum(fname[i]));
208: }
209:
210: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
211: if (i < devlen) {
212: if (!isvalidpart(fname[i]))
1.6 junyoung 213: return EPART;
1.1 dsl 214: p = fname[i++] - 'a';
215: }
216:
217: if (i != devlen)
1.6 junyoung 218: return ENXIO;
1.1 dsl 219:
220: *devname = savedevname;
221: *unit = u;
222: *partition = p;
223: fname = col + 1;
224: }
225:
226: if (*fname)
227: *file = fname;
228:
1.6 junyoung 229: return 0;
1.1 dsl 230: }
231:
232: char *
233: sprint_bootsel(const char *filename)
234: {
235: char *fsname, *devname;
236: int unit, partition;
237: const char *file;
238: static char buf[80];
239:
240: if (parsebootfile(filename, &fsname, &devname, &unit,
241: &partition, &file) == 0) {
242: sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
1.6 junyoung 243: return buf;
1.1 dsl 244: }
1.6 junyoung 245: return "(invalid)";
1.1 dsl 246: }
247:
248: void
249: bootit(const char *filename, int howto, int tell)
250: {
251:
252: if (tell) {
253: printf("booting %s", sprint_bootsel(filename));
254: if (howto)
255: printf(" (howto 0x%x)", howto);
256: printf("\n");
257: }
258:
259: if (exec_netbsd(filename, 0, howto) < 0)
260: printf("boot: %s: %s\n", sprint_bootsel(filename),
261: strerror(errno));
262: else
263: printf("boot returned\n");
264: }
265:
266: void
267: print_banner(void)
268: {
1.15 sborrill 269: #ifndef SMALL
270: int n;
271: if (bootconf.banner[0]) {
1.22 sborrill 272: for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++)
1.15 sborrill 273: printf("%s\n", bootconf.banner[n]);
274: } else {
275: #endif /* !SMALL */
276: printf("\n");
277: printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
278: printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
279: printf(">> Memory: %d/%d k\n", getbasemem(), getextmem());
280:
281: #ifndef SMALL
282: }
283: #endif /* !SMALL */
284: }
285:
286: #ifndef SMALL
287: int
288: atoi(const char *in)
289: {
290: char *c;
291: int ret;
292:
293: ret = 0;
294: c = (char *)in;
295: if (*c == '-')
296: c++;
297: for (; isnum(*c); c++)
298: ret = (ret * 10) + (*c - '0');
299:
300: return (*in == '-') ? -ret : ret;
301: }
302:
303: /*
1.20 sborrill 304: * This function parses a boot.cfg file in the root of the filesystem
1.15 sborrill 305: * (if present) and populates the global boot configuration.
306: *
307: * The file consists of a number of lines each terminated by \n
308: * The lines are in the format keyword=value. There should be spaces
309: * around the = sign.
310: *
311: * The recognised keywords are:
312: * banner: text displayed instead of the normal welcome text
313: * menu: Descriptive text:command to use
314: * timeout: Timeout in seconds (overrides that set by installboot)
315: * default: the default menu option to use if Return is pressed
316: * consdev: the console device to use
317: *
1.20 sborrill 318: * Example boot.cfg file:
1.15 sborrill 319: * banner=Welcome to NetBSD
320: * banner=Please choose the boot type from the following menu
321: * menu=Boot NetBSD:boot netbsd
322: * menu=Boot into single user mode:boot netbsd -s
1.21 apb 323: * menu=:boot hd1a:netbsd -cs
1.15 sborrill 324: * menu=Goto boot comand line:prompt
325: * timeout=10
326: * consdev=com0
327: * default=1
328: */
329: void
330: parsebootconf(const char *conf)
331: {
332: char *bc, *c;
333: int cmenu, cbanner, len;
334: int fd, err, off;
335: struct stat st;
1.21 apb 336: char *key, *value, *v2;
1.24 ad 337: extern char twiddle_toggle;
1.17 sborrill 338: #ifdef SUPPORT_USTARFS
339: void *op_open;
340: #endif
1.15 sborrill 341:
342: /* Clear bootconf structure */
343: bzero((void *)&bootconf, sizeof(bootconf));
344:
345: /* Set timeout to configured */
346: bootconf.timeout = boot_params.bp_timeout;
347:
1.17 sborrill 348: /* don't try to open BOOTCONF if the target fs is ustarfs */
349: #ifdef SUPPORT_USTARFS
350: #if !defined(LIBSA_SINGLE_FILESYSTEM)
351: fd = open("boot", 0); /* assume we are loaded as "boot" from here */
352: if (fd < 0)
353: op_open = NULL; /* XXX */
354: else {
355: op_open = files[fd].f_ops->open;
356: close(fd);
357: }
358: #else
359: op_open = file_system[0].open;
360: #endif /* !LIBSA_SINGLE_FILESYSTEM */
361: if (op_open == ustarfs_open)
1.15 sborrill 362: return;
1.17 sborrill 363: #endif /* SUPPORT_USTARFS */
1.1 dsl 364:
1.15 sborrill 365: fd = open(BOOTCONF, 0);
366: if (fd < 0)
367: return;
368:
1.17 sborrill 369: err = fstat(fd, &st);
370: if (err == -1) {
371: close(fd);
372: return;
373: }
374:
1.15 sborrill 375: bc = alloc(st.st_size + 1);
376: if (bc == NULL) {
377: printf("Could not allocate memory for boot configuration\n");
378: return;
379: }
380:
1.24 ad 381: twiddle_toggle = 1;
1.15 sborrill 382: off = 0;
383: do {
384: len = read(fd, bc + off, 1024);
385: if (len <= 0)
386: break;
387: off += len;
388: } while (len > 0);
389: bc[off] = '\0';
1.24 ad 390: twiddle_toggle = 0;
1.15 sborrill 391:
392: close(fd);
1.20 sborrill 393: /* bc now contains the whole boot.cfg file */
1.15 sborrill 394:
395: cmenu = 0;
396: cbanner = 0;
397: for(c = bc; *c; c++) {
398: key = c;
399: /* Look for = separator between key and value */
400: for (; *c && *c != '='; c++)
401: continue;
402: if (*c == '\0')
403: break; /* break if at end of data */
404:
405: /* zero terminate key which points to keyword */
406: *c++ = 0;
407: value = c;
408: /* Look for end of line (or file) and zero terminate value */
409: for (; *c && *c != '\n'; c++)
410: continue;
411: *c = 0;
412:
413: if (!strncmp(key, "menu", 4)) {
1.21 apb 414: /*
415: * Parse "menu=<description>:<command>". If the
416: * description is empty ("menu=:<command>)",
417: * then re-use the command as the description.
418: * Note that the command may contain embedded
419: * colons.
420: */
1.15 sborrill 421: if (cmenu >= MAXMENU)
422: continue;
423: bootconf.desc[cmenu] = value;
1.21 apb 424: for (v2=value; *v2 && *v2 != ':'; v2++)
1.15 sborrill 425: continue;
1.21 apb 426: if (*v2) {
427: *v2++ = 0;
428: bootconf.command[cmenu] = v2;
429: if (! *value)
430: bootconf.desc[cmenu] = v2;
1.15 sborrill 431: cmenu++;
432: } else {
433: /* No delimiter means invalid line */
434: bootconf.desc[cmenu] = NULL;
435: }
436: } else if (!strncmp(key, "banner", 6)) {
437: if (cbanner < MAXBANNER)
438: bootconf.banner[cbanner++] = value;
439: } else if (!strncmp(key, "timeout", 7)) {
440: if (!isnum(*value))
441: bootconf.timeout = -1;
442: else
443: bootconf.timeout = atoi(value);
444: } else if (!strncmp(key, "default", 7)) {
445: bootconf.def = atoi(value) - 1;
446: } else if (!strncmp(key, "consdev", 7)) {
447: bootconf.consdev = value;
1.25 ad 448: } else if (!strncmp(key, "load", 6)) {
449: command_load(value);
1.15 sborrill 450: }
451: }
452: bootconf.nummenu = cmenu;
453: if (bootconf.def < 0)
454: bootconf.def = 0;
455: if (bootconf.def >= cmenu)
456: bootconf.def = cmenu - 1;
457: }
458:
459: /*
460: * doboottypemenu will render the menu and parse any user input
461: */
462:
463: void
464: doboottypemenu(void)
465: {
466: int choice;
1.26 sborrill 467: char input[80], c, *ic, *oc;
1.15 sborrill 468:
1.16 sborrill 469: printf("\n");
1.15 sborrill 470: /* Display menu */
471: for (choice = 0; bootconf.desc[choice]; choice++)
472: printf(" %d. %s\n", choice+1, bootconf.desc[choice]);
473:
474: choice = -1;
475: for(;;) {
476: input[0] = '\0';
477:
478: if (bootconf.timeout < 0) {
479: printf("\nOption: [%d]:", bootconf.def + 1);
480: gets(input);
481: if (input[0] == '\0') choice = bootconf.def;
482: if (input[0] >= '1' &&
483: input[0] <= bootconf.nummenu + '0')
484: choice = input[0] - '1';
485: } else if (bootconf.timeout == 0)
486: choice = bootconf.def;
487: else {
1.29 apb 488: printf("\nChoose an option; RETURN for default; "
1.30 ! lukem 489: "SPACE to stop countdown.\n");
1.15 sborrill 490: printf("Option %d will be chosen in ",
491: bootconf.def + 1);
492: c = awaitkey(bootconf.timeout, 1);
493: if (c >= '1' && c <= bootconf.nummenu + '0')
494: choice = c - '1';
495: else if (c == '\r' || c == '\n' || c == '\0')
496: /* default if timed out or Return pressed */
497: choice = bootconf.def;
498: else {
499: /* If any other key pressed, drop to menu */
500: bootconf.timeout = -1;
501: choice = -1;
502: }
503: }
504: if (choice < 0)
505: continue;
506: if (!strcmp(bootconf.command[choice], "prompt") &&
507: ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 ||
508: check_password(boot_params.bp_password))) {
509: printf("type \"?\" or \"help\" for help.\n");
510: bootmenu(); /* does not return */
1.26 sborrill 511: } else {
512: ic = bootconf.command[choice];
513: /* Split command string at ; into separate commands */
514: do {
515: oc = input;
516: /* Look for ; separator */
517: for (; *ic && *ic != COMMAND_SEPARATOR; ic++)
518: *oc++ = *ic;
519: if (*input == '\0')
520: continue;
521: /* Strip out any trailing spaces */
522: oc--;
523: for (; *oc ==' ' && oc > input; oc--);
524: *++oc = '\0';
525: if (*ic == COMMAND_SEPARATOR)
526: ic++;
527: /* Stop silly command strings like ;;; */
528: if (*input != '\0')
529: docommand(input);
530: /* Skip leading spaces */
531: for (; *ic == ' '; ic++);
532: } while (*ic);
533: }
1.15 sborrill 534:
535: }
1.1 dsl 536: }
1.15 sborrill 537: #endif /* !SMALL */
1.1 dsl 538:
1.11 junyoung 539: /*
540: * Called from the initial entry point boot_start in biosboot.S
541: *
542: * biosdev: BIOS drive number the system booted from
543: * biossector: Sector number of the NetBSD partition
544: */
1.1 dsl 545: void
1.11 junyoung 546: boot2(int biosdev, u_int biossector)
1.1 dsl 547: {
548: int currname;
549: char c;
550:
551: initio(boot_params.bp_consdev);
552:
553: #ifdef SUPPORT_PS2
554: biosmca();
555: #endif
556: gateA20();
557:
1.4 lukem 558: if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
1.1 dsl 559: biosvideomode();
560:
1.11 junyoung 561: /* need to remember these */
562: boot_biosdev = biosdev;
563: boot_biossector = biossector;
564:
1.1 dsl 565: /* try to set default device to what BIOS tells us */
1.11 junyoung 566: bios2dev(biosdev, biossector, &default_devname, &default_unit,
567: &default_partition);
1.1 dsl 568:
569: /* if the user types "boot" without filename */
570: default_filename = DEFFILENAME;
571:
1.15 sborrill 572: #ifndef SMALL
573: parsebootconf(BOOTCONF);
574:
575: /*
1.20 sborrill 576: * If console set in boot.cfg, switch to it.
1.15 sborrill 577: * This will print the banner, so we don't need to explicitly do it
578: */
579: if (bootconf.consdev)
580: command_consdev(bootconf.consdev);
581: else
582: print_banner();
583:
584: /* Display the menu, if applicable */
585: if (bootconf.nummenu > 0) {
586: /* Does not return */
587: doboottypemenu();
588: }
589: #else
590: print_banner();
591: #endif
592:
1.1 dsl 593: printf("Press return to boot now, any other key for boot menu\n");
1.10 junyoung 594: for (currname = 0; currname < NUMNAMES; currname++) {
1.1 dsl 595: printf("booting %s - starting in ",
596: sprint_bootsel(names[currname][0]));
597:
1.15 sborrill 598: #ifdef SMALL
1.1 dsl 599: c = awaitkey(boot_params.bp_timeout, 1);
1.15 sborrill 600: #else
601: c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
602: #endif
1.1 dsl 603: if ((c != '\r') && (c != '\n') && (c != '\0') &&
1.4 lukem 604: ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0
1.9 junyoung 605: || check_password(boot_params.bp_password))) {
1.1 dsl 606: printf("type \"?\" or \"help\" for help.\n");
607: bootmenu(); /* does not return */
608: }
609:
610: /*
611: * try pairs of names[] entries, foo and foo.gz
612: */
613: /* don't print "booting..." again */
614: bootit(names[currname][0], 0, 0);
615: /* since it failed, try compressed bootfile. */
616: bootit(names[currname][1], 0, 1);
617: }
1.10 junyoung 618:
619: bootmenu(); /* does not return */
1.1 dsl 620: }
621:
622: /* ARGSUSED */
623: void
624: command_help(char *arg)
625: {
626:
627: printf("commands are:\n"
1.23 ad 628: "boot [xdNx:][filename] [-12acdqsvxz]\n"
1.8 junyoung 629: " (ex. \"hd0a:netbsd.old -s\"\n"
630: "ls [path]\n"
631: "dev xd[N[x]]:\n"
632: "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
1.25 ad 633: "modules {enabled|disabled}\n"
634: "load {path_to_module}\n"
1.8 junyoung 635: "help|?\n"
636: "quit\n");
1.1 dsl 637: }
638:
639: void
640: command_ls(char *arg)
641: {
642: const char *save = default_filename;
643:
644: default_filename = "/";
645: ufs_ls(arg);
646: default_filename = save;
647: }
648:
649: /* ARGSUSED */
650: void
651: command_quit(char *arg)
652: {
653:
654: printf("Exiting...\n");
655: delay(1000000);
656: reboot();
657: /* Note: we shouldn't get to this point! */
658: panic("Could not reboot!");
659: exit(0);
660: }
661:
662: void
663: command_boot(char *arg)
664: {
665: char *filename;
666: int howto;
667:
668: if (parseboot(arg, &filename, &howto))
669: bootit(filename, howto, 1);
670: }
671:
672: void
673: command_dev(char *arg)
674: {
675: static char savedevname[MAXDEVNAME + 1];
676: char *fsname, *devname;
677: const char *file; /* dummy */
678:
679: if (*arg == '\0') {
680: printf("%s%d%c:\n", default_devname, default_unit,
681: 'a' + default_partition);
682: return;
683: }
684:
1.13 ws 685: if (strchr(arg, ':') == NULL ||
1.1 dsl 686: parsebootfile(arg, &fsname, &devname, &default_unit,
687: &default_partition, &file)) {
688: command_help(NULL);
689: return;
690: }
691:
692: /* put to own static storage */
693: strncpy(savedevname, devname, MAXDEVNAME + 1);
694: default_devname = savedevname;
695: }
696:
697: static const struct cons_devs {
1.8 junyoung 698: const char *name;
1.9 junyoung 699: u_int tag;
1.1 dsl 700: } cons_devs[] = {
701: { "pc", CONSDEV_PC },
702: { "com0", CONSDEV_COM0 },
703: { "com1", CONSDEV_COM1 },
704: { "com2", CONSDEV_COM2 },
705: { "com3", CONSDEV_COM3 },
706: { "com0kbd", CONSDEV_COM0KBD },
707: { "com1kbd", CONSDEV_COM1KBD },
708: { "com2kbd", CONSDEV_COM2KBD },
709: { "com3kbd", CONSDEV_COM3KBD },
710: { "auto", CONSDEV_AUTO },
1.8 junyoung 711: { NULL, 0 }
712: };
1.1 dsl 713:
714: void
715: command_consdev(char *arg)
716: {
717: const struct cons_devs *cdp;
718:
719: for (cdp = cons_devs; cdp->name; cdp++) {
1.6 junyoung 720: if (strcmp(arg, cdp->name) == 0) {
1.1 dsl 721: initio(cdp->tag);
722: print_banner();
723: return;
724: }
725: }
726: printf("invalid console device.\n");
727: }
1.25 ad 728:
729: void
730: command_modules(char *arg)
731: {
732:
733: if (strcmp(arg, "enabled") == 0 ||
734: strcmp(arg, "on") == 0)
735: boot_modules_enabled = true;
736: else if (strcmp(arg, "disabled") == 0 ||
737: strcmp(arg, "off") == 0)
738: boot_modules_enabled = false;
739: else
740: printf("invalid flag, must be 'enabled' or 'disabled'.\n");
741: }
742:
743: void
744: command_load(char *arg)
745: {
746: boot_module_t *bm, *bmp;
747: size_t len;
748: char *str;
749:
750: bm = alloc(sizeof(boot_module_t));
751: len = strlen(arg) + 1;
752: str = alloc(len);
753: if (bm == NULL || str == NULL) {
754: printf("couldn't allocate module\n");
755: return;
756: }
757: memcpy(str, arg, len);
758: bm->bm_path = str;
759: bm->bm_next = NULL;
760: if (boot_modules == NULL)
761: boot_modules = bm;
762: else {
763: for (bmp = boot_modules; bmp->bm_next;
764: bmp = bmp->bm_next)
765: ;
766: bmp->bm_next = bm;
767: }
768: }
CVSweb <webmaster@jp.NetBSD.org>