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