Annotation of src/sys/arch/i386/stand/boot/boot2.c, Revision 1.62
1.62 ! christos 1: /* $NetBSD: boot2.c,v 1.61 2014/03/20 01:15:29 christos Exp $ */
1.25 ad 2:
3: /*-
1.54 uebayasi 4: * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
1.25 ad 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>
1.40 ad 79: #include <bootmod.h>
80: #include <bootmenu.h>
1.43 jmcneill 81: #include <vbe.h>
1.1 dsl 82: #include "devopen.h"
83:
84: #ifdef SUPPORT_PS2
85: #include <biosmca.h>
86: #endif
87:
1.4 lukem 88: extern struct x86_boot_params boot_params;
1.1 dsl 89:
1.32 perry 90: extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
1.1 dsl 91:
1.11 junyoung 92: int errno;
93:
94: int boot_biosdev;
1.51 jakllsch 95: daddr_t boot_biossector;
1.11 junyoung 96:
1.1 dsl 97: static const char * const names[][2] = {
1.8 junyoung 98: { "netbsd", "netbsd.gz" },
99: { "onetbsd", "onetbsd.gz" },
100: { "netbsd.old", "netbsd.old.gz" },
1.1 dsl 101: };
102:
103: #define NUMNAMES (sizeof(names)/sizeof(names[0]))
104: #define DEFFILENAME names[0][0]
105:
106: #define MAXDEVNAME 16
107:
108: static char *default_devname;
109: static int default_unit, default_partition;
110: static const char *default_filename;
111:
112: char *sprint_bootsel(const char *);
113: void bootit(const char *, int, int);
114: void print_banner(void);
1.51 jakllsch 115: void boot2(int, uint64_t);
1.1 dsl 116:
117: void command_help(char *);
1.61 christos 118: #if LIBSA_ENABLE_LS_OP
1.1 dsl 119: void command_ls(char *);
1.61 christos 120: #endif
1.1 dsl 121: void command_quit(char *);
122: void command_boot(char *);
123: void command_dev(char *);
124: void command_consdev(char *);
1.59 he 125: #ifndef SMALL
126: void command_menu(char *);
127: #endif
1.25 ad 128: void command_modules(char *);
1.38 joerg 129: void command_multiboot(char *);
1.1 dsl 130:
131: const struct bootblk_command commands[] = {
132: { "help", command_help },
133: { "?", command_help },
1.61 christos 134: #if LIBSA_ENABLE_LS_OP
1.1 dsl 135: { "ls", command_ls },
1.61 christos 136: #endif
1.1 dsl 137: { "quit", command_quit },
138: { "boot", command_boot },
139: { "dev", command_dev },
140: { "consdev", command_consdev },
1.59 he 141: #ifndef SMALL
142: { "menu", command_menu },
143: #endif
1.25 ad 144: { "modules", command_modules },
1.40 ad 145: { "load", module_add },
1.38 joerg 146: { "multiboot", command_multiboot },
1.43 jmcneill 147: { "vesa", command_vesa },
1.52 jmcneill 148: { "splash", splash_add },
1.56 tls 149: { "rndseed", rnd_add },
1.60 jmcneill 150: { "fs", fs_add },
1.54 uebayasi 151: { "userconf", userconf_add },
1.1 dsl 152: { NULL, NULL },
153: };
154:
155: int
156: parsebootfile(const char *fname, char **fsname, char **devname,
1.11 junyoung 157: int *unit, int *partition, const char **file)
1.1 dsl 158: {
159: const char *col;
160:
161: *fsname = "ufs";
162: *devname = default_devname;
163: *unit = default_unit;
164: *partition = default_partition;
165: *file = default_filename;
166:
167: if (fname == NULL)
1.7 junyoung 168: return 0;
1.1 dsl 169:
1.8 junyoung 170: if ((col = strchr(fname, ':')) != NULL) { /* device given */
1.1 dsl 171: static char savedevname[MAXDEVNAME+1];
172: int devlen;
1.11 junyoung 173: int u = 0, p = 0;
1.1 dsl 174: int i = 0;
175:
176: devlen = col - fname;
177: if (devlen > MAXDEVNAME)
1.6 junyoung 178: return EINVAL;
1.1 dsl 179:
180: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
181: if (!isvalidname(fname[i]))
1.6 junyoung 182: return EINVAL;
1.1 dsl 183: do {
184: savedevname[i] = fname[i];
185: i++;
186: } while (isvalidname(fname[i]));
187: savedevname[i] = '\0';
188:
189: #define isnum(c) ((c) >= '0' && (c) <= '9')
190: if (i < devlen) {
191: if (!isnum(fname[i]))
1.6 junyoung 192: return EUNIT;
1.1 dsl 193: do {
194: u *= 10;
195: u += fname[i++] - '0';
196: } while (isnum(fname[i]));
197: }
198:
199: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
200: if (i < devlen) {
201: if (!isvalidpart(fname[i]))
1.6 junyoung 202: return EPART;
1.1 dsl 203: p = fname[i++] - 'a';
204: }
205:
206: if (i != devlen)
1.6 junyoung 207: return ENXIO;
1.1 dsl 208:
209: *devname = savedevname;
210: *unit = u;
211: *partition = p;
212: fname = col + 1;
213: }
214:
215: if (*fname)
216: *file = fname;
217:
1.6 junyoung 218: return 0;
1.1 dsl 219: }
220:
221: char *
222: sprint_bootsel(const char *filename)
223: {
224: char *fsname, *devname;
225: int unit, partition;
226: const char *file;
227: static char buf[80];
228:
229: if (parsebootfile(filename, &fsname, &devname, &unit,
230: &partition, &file) == 0) {
1.62 ! christos 231: snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
! 232: 'a' + partition, file);
1.6 junyoung 233: return buf;
1.1 dsl 234: }
1.6 junyoung 235: return "(invalid)";
1.1 dsl 236: }
237:
1.44 ad 238: static void
239: clearit(void)
240: {
241:
242: if (bootconf.clear)
243: clear_pc_screen();
244: }
245:
1.1 dsl 246: void
247: bootit(const char *filename, int howto, int tell)
248: {
249:
250: if (tell) {
251: printf("booting %s", sprint_bootsel(filename));
252: if (howto)
253: printf(" (howto 0x%x)", howto);
254: printf("\n");
255: }
256:
1.44 ad 257: if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
1.1 dsl 258: printf("boot: %s: %s\n", sprint_bootsel(filename),
259: strerror(errno));
260: else
261: printf("boot returned\n");
262: }
263:
264: void
265: print_banner(void)
266: {
1.41 christos 267:
1.44 ad 268: clearit();
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 */
1.32 perry 276: printf("\n"
277: ">> %s, Revision %s (from NetBSD %s)\n"
278: ">> Memory: %d/%d k\n",
279: bootprog_name, bootprog_rev, bootprog_kernrev,
280: getbasemem(), getextmem());
1.15 sborrill 281:
282: #ifndef SMALL
283: }
284: #endif /* !SMALL */
285: }
286:
1.11 junyoung 287: /*
288: * Called from the initial entry point boot_start in biosboot.S
289: *
290: * biosdev: BIOS drive number the system booted from
291: * biossector: Sector number of the NetBSD partition
292: */
1.1 dsl 293: void
1.51 jakllsch 294: boot2(int biosdev, uint64_t biossector)
1.1 dsl 295: {
1.31 ad 296: extern char twiddle_toggle;
1.1 dsl 297: int currname;
298: char c;
299:
1.31 ad 300: twiddle_toggle = 1; /* no twiddling until we're ready */
301:
1.1 dsl 302: initio(boot_params.bp_consdev);
303:
304: #ifdef SUPPORT_PS2
305: biosmca();
306: #endif
307: gateA20();
308:
1.47 drochner 309: boot_modules_enabled = !(boot_params.bp_flags
310: & X86_BP_FLAGS_NOMODULES);
1.4 lukem 311: if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
1.1 dsl 312: biosvideomode();
313:
1.43 jmcneill 314: vbe_init();
315:
1.11 junyoung 316: /* need to remember these */
317: boot_biosdev = biosdev;
318: boot_biossector = biossector;
319:
1.1 dsl 320: /* try to set default device to what BIOS tells us */
1.11 junyoung 321: bios2dev(biosdev, biossector, &default_devname, &default_unit,
322: &default_partition);
1.1 dsl 323:
324: /* if the user types "boot" without filename */
325: default_filename = DEFFILENAME;
326:
1.15 sborrill 327: #ifndef SMALL
1.53 jakllsch 328: if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
1.46 drochner 329: parsebootconf(BOOTCONF);
1.53 jakllsch 330: } else {
331: bootconf.timeout = boot_params.bp_timeout;
332: }
333:
1.15 sborrill 334:
335: /*
1.20 sborrill 336: * If console set in boot.cfg, switch to it.
1.15 sborrill 337: * This will print the banner, so we don't need to explicitly do it
338: */
339: if (bootconf.consdev)
340: command_consdev(bootconf.consdev);
341: else
342: print_banner();
343:
344: /* Display the menu, if applicable */
1.31 ad 345: twiddle_toggle = 0;
1.15 sborrill 346: if (bootconf.nummenu > 0) {
347: /* Does not return */
348: doboottypemenu();
349: }
1.43 jmcneill 350:
1.15 sborrill 351: #else
1.31 ad 352: twiddle_toggle = 0;
353: print_banner();
1.15 sborrill 354: #endif
355:
1.1 dsl 356: printf("Press return to boot now, any other key for boot menu\n");
1.10 junyoung 357: for (currname = 0; currname < NUMNAMES; currname++) {
1.1 dsl 358: printf("booting %s - starting in ",
359: sprint_bootsel(names[currname][0]));
360:
1.15 sborrill 361: #ifdef SMALL
1.1 dsl 362: c = awaitkey(boot_params.bp_timeout, 1);
1.15 sborrill 363: #else
364: c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
365: #endif
1.48 hubertf 366: if ((c != '\r') && (c != '\n') && (c != '\0')) {
367: if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
368: /* do NOT ask for password */
1.1 dsl 369: bootmenu(); /* does not return */
1.48 hubertf 370: } else {
371: /* DO ask for password */
1.55 mrg 372: if (check_password((char *)boot_params.bp_password)) {
1.48 hubertf 373: /* password ok */
374: printf("type \"?\" or \"help\" for help.\n");
375: bootmenu(); /* does not return */
376: } else {
377: /* bad password */
378: printf("Wrong password.\n");
379: currname = 0;
380: continue;
381: }
382: }
1.1 dsl 383: }
384:
385: /*
386: * try pairs of names[] entries, foo and foo.gz
387: */
388: /* don't print "booting..." again */
389: bootit(names[currname][0], 0, 0);
390: /* since it failed, try compressed bootfile. */
391: bootit(names[currname][1], 0, 1);
392: }
1.10 junyoung 393:
394: bootmenu(); /* does not return */
1.1 dsl 395: }
396:
397: /* ARGSUSED */
398: void
399: command_help(char *arg)
400: {
401:
402: printf("commands are:\n"
1.23 ad 403: "boot [xdNx:][filename] [-12acdqsvxz]\n"
1.8 junyoung 404: " (ex. \"hd0a:netbsd.old -s\"\n"
1.61 christos 405: #if LIBSA_ENABLE_LS_OP
1.8 junyoung 406: "ls [path]\n"
1.61 christos 407: #endif
1.8 junyoung 408: "dev xd[N[x]]:\n"
409: "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
1.49 jym 410: "vesa {modenum|on|off|enabled|disabled|list}\n"
1.59 he 411: #ifndef SMALL
412: "menu (reenters boot menu, if defined in boot.cfg)\n"
413: #endif
1.49 jym 414: "modules {on|off|enabled|disabled}\n"
1.25 ad 415: "load {path_to_module}\n"
1.38 joerg 416: "multiboot [xdNx:][filename] [<args>]\n"
1.54 uebayasi 417: "userconf {command}\n"
1.56 tls 418: "rndseed {path_to_rndseed_file}\n"
1.8 junyoung 419: "help|?\n"
420: "quit\n");
1.1 dsl 421: }
422:
1.61 christos 423: #if LIBSA_ENABLE_LS_OP
1.1 dsl 424: void
425: command_ls(char *arg)
426: {
427: const char *save = default_filename;
428:
429: default_filename = "/";
1.57 tsutsui 430: ls(arg);
1.1 dsl 431: default_filename = save;
432: }
1.61 christos 433: #endif
1.1 dsl 434:
435: /* ARGSUSED */
436: void
437: command_quit(char *arg)
438: {
439:
440: printf("Exiting...\n");
441: delay(1000000);
442: reboot();
443: /* Note: we shouldn't get to this point! */
444: panic("Could not reboot!");
445: }
446:
447: void
448: command_boot(char *arg)
449: {
450: char *filename;
1.58 riastrad 451: int howto, tell;
1.1 dsl 452:
1.58 riastrad 453: if (!parseboot(arg, &filename, &howto))
454: return;
455:
456: tell = ((howto & AB_VERBOSE) != 0);
457: if (filename != NULL) {
458: bootit(filename, howto, tell);
459: } else {
460: int i;
1.59 he 461:
462: #ifndef SMALL
463: bootdefault();
464: #endif
1.58 riastrad 465: for (i = 0; i < NUMNAMES; i++) {
466: bootit(names[i][0], howto, tell);
467: bootit(names[i][1], howto, tell);
468: }
469: }
1.1 dsl 470: }
471:
472: void
473: command_dev(char *arg)
474: {
475: static char savedevname[MAXDEVNAME + 1];
476: char *fsname, *devname;
477: const char *file; /* dummy */
478:
479: if (*arg == '\0') {
1.45 jmcneill 480: biosdisk_probe();
481: printf("default %s%d%c\n", default_devname, default_unit,
1.1 dsl 482: 'a' + default_partition);
483: return;
484: }
485:
1.13 ws 486: if (strchr(arg, ':') == NULL ||
1.1 dsl 487: parsebootfile(arg, &fsname, &devname, &default_unit,
488: &default_partition, &file)) {
489: command_help(NULL);
490: return;
491: }
492:
493: /* put to own static storage */
494: strncpy(savedevname, devname, MAXDEVNAME + 1);
495: default_devname = savedevname;
496: }
497:
498: static const struct cons_devs {
1.8 junyoung 499: const char *name;
1.9 junyoung 500: u_int tag;
1.1 dsl 501: } cons_devs[] = {
502: { "pc", CONSDEV_PC },
503: { "com0", CONSDEV_COM0 },
504: { "com1", CONSDEV_COM1 },
505: { "com2", CONSDEV_COM2 },
506: { "com3", CONSDEV_COM3 },
507: { "com0kbd", CONSDEV_COM0KBD },
508: { "com1kbd", CONSDEV_COM1KBD },
509: { "com2kbd", CONSDEV_COM2KBD },
510: { "com3kbd", CONSDEV_COM3KBD },
511: { "auto", CONSDEV_AUTO },
1.8 junyoung 512: { NULL, 0 }
513: };
1.1 dsl 514:
515: void
516: command_consdev(char *arg)
517: {
518: const struct cons_devs *cdp;
519:
520: for (cdp = cons_devs; cdp->name; cdp++) {
1.6 junyoung 521: if (strcmp(arg, cdp->name) == 0) {
1.1 dsl 522: initio(cdp->tag);
523: print_banner();
524: return;
525: }
526: }
527: printf("invalid console device.\n");
528: }
1.25 ad 529:
1.59 he 530: #ifndef SMALL
531: /* ARGSUSED */
532: void
533: command_menu(char *arg)
534: {
535:
536: if (bootconf.nummenu > 0) {
537: /* Does not return */
538: doboottypemenu();
539: } else {
540: printf("No menu defined in boot.cfg\n");
541: }
542: }
543: #endif /* !SMALL */
544:
1.25 ad 545: void
546: command_modules(char *arg)
547: {
548:
549: if (strcmp(arg, "enabled") == 0 ||
550: strcmp(arg, "on") == 0)
551: boot_modules_enabled = true;
552: else if (strcmp(arg, "disabled") == 0 ||
553: strcmp(arg, "off") == 0)
554: boot_modules_enabled = false;
555: else
556: printf("invalid flag, must be 'enabled' or 'disabled'.\n");
557: }
558:
559: void
1.38 joerg 560: command_multiboot(char *arg)
561: {
562: char *filename;
563:
564: filename = arg;
565: if (exec_multiboot(filename, gettrailer(arg)) < 0)
566: printf("multiboot: %s: %s\n", sprint_bootsel(filename),
567: strerror(errno));
568: else
569: printf("boot returned\n");
570: }
571:
CVSweb <webmaster@jp.NetBSD.org>