Annotation of src/sys/arch/i386/stand/boot/boot2.c, Revision 1.63.4.3
1.63.4.3! skrll 1: /* $NetBSD: boot2.c,v 1.63.4.2 2015/09/22 12:05:44 skrll 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>
1.63 rtr 75: #include <lib/libsa/bootcfg.h>
1.1 dsl 76: #include <lib/libsa/ufs.h>
77: #include <lib/libkern/libkern.h>
78:
79: #include <libi386.h>
1.40 ad 80: #include <bootmod.h>
81: #include <bootmenu.h>
1.43 jmcneill 82: #include <vbe.h>
1.1 dsl 83: #include "devopen.h"
84:
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:
1.32 perry 91: extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
1.1 dsl 92:
1.11 junyoung 93: int errno;
94:
95: int boot_biosdev;
1.51 jakllsch 96: daddr_t boot_biossector;
1.11 junyoung 97:
1.1 dsl 98: static const char * const names[][2] = {
1.8 junyoung 99: { "netbsd", "netbsd.gz" },
100: { "onetbsd", "onetbsd.gz" },
101: { "netbsd.old", "netbsd.old.gz" },
1.1 dsl 102: };
103:
104: #define NUMNAMES (sizeof(names)/sizeof(names[0]))
105: #define DEFFILENAME names[0][0]
106:
107: #define MAXDEVNAME 16
108:
109: static char *default_devname;
110: static int default_unit, default_partition;
111: static const char *default_filename;
112:
113: char *sprint_bootsel(const char *);
1.63.4.1 skrll 114: static void bootit(const char *, int);
1.1 dsl 115: void print_banner(void);
1.51 jakllsch 116: void boot2(int, uint64_t);
1.1 dsl 117:
118: void command_help(char *);
1.61 christos 119: #if LIBSA_ENABLE_LS_OP
1.1 dsl 120: void command_ls(char *);
1.61 christos 121: #endif
1.1 dsl 122: void command_quit(char *);
123: void command_boot(char *);
124: void command_dev(char *);
125: void command_consdev(char *);
1.59 he 126: #ifndef SMALL
127: void command_menu(char *);
128: #endif
1.25 ad 129: void command_modules(char *);
1.38 joerg 130: void command_multiboot(char *);
1.1 dsl 131:
132: const struct bootblk_command commands[] = {
133: { "help", command_help },
134: { "?", command_help },
1.61 christos 135: #if LIBSA_ENABLE_LS_OP
1.1 dsl 136: { "ls", command_ls },
1.61 christos 137: #endif
1.1 dsl 138: { "quit", command_quit },
139: { "boot", command_boot },
140: { "dev", command_dev },
141: { "consdev", command_consdev },
1.59 he 142: #ifndef SMALL
143: { "menu", command_menu },
144: #endif
1.25 ad 145: { "modules", command_modules },
1.40 ad 146: { "load", module_add },
1.38 joerg 147: { "multiboot", command_multiboot },
1.43 jmcneill 148: { "vesa", command_vesa },
1.52 jmcneill 149: { "splash", splash_add },
1.56 tls 150: { "rndseed", rnd_add },
1.60 jmcneill 151: { "fs", fs_add },
1.54 uebayasi 152: { "userconf", userconf_add },
1.1 dsl 153: { NULL, NULL },
154: };
155:
156: int
157: parsebootfile(const char *fname, char **fsname, char **devname,
1.11 junyoung 158: int *unit, int *partition, const char **file)
1.1 dsl 159: {
160: const char *col;
161:
162: *fsname = "ufs";
163: *devname = default_devname;
164: *unit = default_unit;
165: *partition = default_partition;
166: *file = default_filename;
167:
168: if (fname == NULL)
1.7 junyoung 169: return 0;
1.1 dsl 170:
1.8 junyoung 171: if ((col = strchr(fname, ':')) != NULL) { /* device given */
1.1 dsl 172: static char savedevname[MAXDEVNAME+1];
173: int devlen;
1.11 junyoung 174: int u = 0, p = 0;
1.1 dsl 175: int i = 0;
176:
177: devlen = col - fname;
178: if (devlen > MAXDEVNAME)
1.6 junyoung 179: return EINVAL;
1.1 dsl 180:
181: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
182: if (!isvalidname(fname[i]))
1.6 junyoung 183: return EINVAL;
1.1 dsl 184: do {
185: savedevname[i] = fname[i];
186: i++;
187: } while (isvalidname(fname[i]));
188: savedevname[i] = '\0';
189:
190: #define isnum(c) ((c) >= '0' && (c) <= '9')
191: if (i < devlen) {
192: if (!isnum(fname[i]))
1.6 junyoung 193: return EUNIT;
1.1 dsl 194: do {
195: u *= 10;
196: u += fname[i++] - '0';
197: } while (isnum(fname[i]));
198: }
199:
200: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
201: if (i < devlen) {
202: if (!isvalidpart(fname[i]))
1.6 junyoung 203: return EPART;
1.1 dsl 204: p = fname[i++] - 'a';
205: }
206:
207: if (i != devlen)
1.6 junyoung 208: return ENXIO;
1.1 dsl 209:
210: *devname = savedevname;
211: *unit = u;
212: *partition = p;
213: fname = col + 1;
214: }
215:
216: if (*fname)
217: *file = fname;
218:
1.6 junyoung 219: return 0;
1.1 dsl 220: }
221:
222: char *
223: sprint_bootsel(const char *filename)
224: {
225: char *fsname, *devname;
226: int unit, partition;
227: const char *file;
228: static char buf[80];
229:
230: if (parsebootfile(filename, &fsname, &devname, &unit,
231: &partition, &file) == 0) {
1.62 christos 232: snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
233: 'a' + partition, file);
1.6 junyoung 234: return buf;
1.1 dsl 235: }
1.6 junyoung 236: return "(invalid)";
1.1 dsl 237: }
238:
1.44 ad 239: static void
240: clearit(void)
241: {
242:
1.63 rtr 243: if (bootcfg_info.clear)
1.44 ad 244: clear_pc_screen();
245: }
246:
1.63.4.1 skrll 247: static void
248: bootit(const char *filename, int howto)
1.1 dsl 249: {
1.63.4.1 skrll 250: if (howto & AB_VERBOSE)
251: printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
252: howto);
1.1 dsl 253:
1.44 ad 254: if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
1.1 dsl 255: printf("boot: %s: %s\n", sprint_bootsel(filename),
256: strerror(errno));
257: else
258: printf("boot returned\n");
259: }
260:
261: void
262: print_banner(void)
263: {
1.41 christos 264:
1.44 ad 265: clearit();
1.15 sborrill 266: #ifndef SMALL
267: int n;
1.63 rtr 268: if (bootcfg_info.banner[0]) {
1.63.4.3! skrll 269: for (n = 0; n < BOOTCFG_MAXBANNER && bootcfg_info.banner[n];
! 270: n++)
1.63 rtr 271: printf("%s\n", bootcfg_info.banner[n]);
1.15 sborrill 272: } else {
273: #endif /* !SMALL */
1.32 perry 274: printf("\n"
275: ">> %s, Revision %s (from NetBSD %s)\n"
276: ">> Memory: %d/%d k\n",
277: bootprog_name, bootprog_rev, bootprog_kernrev,
278: getbasemem(), getextmem());
1.15 sborrill 279:
280: #ifndef SMALL
281: }
282: #endif /* !SMALL */
283: }
284:
1.11 junyoung 285: /*
286: * Called from the initial entry point boot_start in biosboot.S
287: *
288: * biosdev: BIOS drive number the system booted from
289: * biossector: Sector number of the NetBSD partition
290: */
1.1 dsl 291: void
1.51 jakllsch 292: boot2(int biosdev, uint64_t biossector)
1.1 dsl 293: {
1.31 ad 294: extern char twiddle_toggle;
1.1 dsl 295: int currname;
296: char c;
297:
1.31 ad 298: twiddle_toggle = 1; /* no twiddling until we're ready */
299:
1.1 dsl 300: initio(boot_params.bp_consdev);
301:
302: #ifdef SUPPORT_PS2
303: biosmca();
304: #endif
305: gateA20();
306:
1.47 drochner 307: boot_modules_enabled = !(boot_params.bp_flags
308: & X86_BP_FLAGS_NOMODULES);
1.4 lukem 309: if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
1.1 dsl 310: biosvideomode();
311:
1.43 jmcneill 312: vbe_init();
313:
1.11 junyoung 314: /* need to remember these */
315: boot_biosdev = biosdev;
316: boot_biossector = biossector;
317:
1.1 dsl 318: /* try to set default device to what BIOS tells us */
1.11 junyoung 319: bios2dev(biosdev, biossector, &default_devname, &default_unit,
320: &default_partition);
1.1 dsl 321:
322: /* if the user types "boot" without filename */
323: default_filename = DEFFILENAME;
324:
1.15 sborrill 325: #ifndef SMALL
1.53 jakllsch 326: if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
1.63 rtr 327: parsebootconf(BOOTCFG_FILENAME);
1.53 jakllsch 328: } else {
1.63 rtr 329: bootcfg_info.timeout = boot_params.bp_timeout;
1.53 jakllsch 330: }
1.63.4.2 skrll 331:
1.15 sborrill 332:
333: /*
1.20 sborrill 334: * If console set in boot.cfg, switch to it.
1.15 sborrill 335: * This will print the banner, so we don't need to explicitly do it
336: */
1.63 rtr 337: if (bootcfg_info.consdev)
338: command_consdev(bootcfg_info.consdev);
1.63.4.2 skrll 339: else
1.15 sborrill 340: print_banner();
341:
342: /* Display the menu, if applicable */
1.31 ad 343: twiddle_toggle = 0;
1.63 rtr 344: if (bootcfg_info.nummenu > 0) {
1.15 sborrill 345: /* Does not return */
346: doboottypemenu();
347: }
1.43 jmcneill 348:
1.15 sborrill 349: #else
1.31 ad 350: twiddle_toggle = 0;
351: print_banner();
1.15 sborrill 352: #endif
353:
1.1 dsl 354: printf("Press return to boot now, any other key for boot menu\n");
1.10 junyoung 355: for (currname = 0; currname < NUMNAMES; currname++) {
1.1 dsl 356: printf("booting %s - starting in ",
357: sprint_bootsel(names[currname][0]));
358:
1.15 sborrill 359: #ifdef SMALL
1.1 dsl 360: c = awaitkey(boot_params.bp_timeout, 1);
1.15 sborrill 361: #else
1.63 rtr 362: c = awaitkey((bootcfg_info.timeout < 0) ? 0
363: : bootcfg_info.timeout, 1);
1.15 sborrill 364: #endif
1.48 hubertf 365: if ((c != '\r') && (c != '\n') && (c != '\0')) {
366: if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
367: /* do NOT ask for password */
1.1 dsl 368: bootmenu(); /* does not return */
1.48 hubertf 369: } else {
370: /* DO ask for password */
1.55 mrg 371: if (check_password((char *)boot_params.bp_password)) {
1.48 hubertf 372: /* password ok */
373: printf("type \"?\" or \"help\" for help.\n");
374: bootmenu(); /* does not return */
375: } else {
376: /* bad password */
377: printf("Wrong password.\n");
378: currname = 0;
379: continue;
380: }
381: }
1.1 dsl 382: }
383:
384: /*
385: * try pairs of names[] entries, foo and foo.gz
386: */
387: /* don't print "booting..." again */
1.63.4.1 skrll 388: bootit(names[currname][0], 0);
1.1 dsl 389: /* since it failed, try compressed bootfile. */
1.63.4.1 skrll 390: bootit(names[currname][1], AB_VERBOSE);
1.1 dsl 391: }
1.10 junyoung 392:
393: bootmenu(); /* does not return */
1.1 dsl 394: }
395:
396: /* ARGSUSED */
397: void
398: command_help(char *arg)
399: {
400:
401: printf("commands are:\n"
1.23 ad 402: "boot [xdNx:][filename] [-12acdqsvxz]\n"
1.8 junyoung 403: " (ex. \"hd0a:netbsd.old -s\"\n"
1.61 christos 404: #if LIBSA_ENABLE_LS_OP
1.8 junyoung 405: "ls [path]\n"
1.61 christos 406: #endif
1.8 junyoung 407: "dev xd[N[x]]:\n"
408: "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
1.49 jym 409: "vesa {modenum|on|off|enabled|disabled|list}\n"
1.59 he 410: #ifndef SMALL
411: "menu (reenters boot menu, if defined in boot.cfg)\n"
412: #endif
1.49 jym 413: "modules {on|off|enabled|disabled}\n"
1.25 ad 414: "load {path_to_module}\n"
1.38 joerg 415: "multiboot [xdNx:][filename] [<args>]\n"
1.63.4.2 skrll 416: "splash {path_to_image_file}\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.63.4.1 skrll 451: int howto;
1.1 dsl 452:
1.58 riastrad 453: if (!parseboot(arg, &filename, &howto))
454: return;
455:
456: if (filename != NULL) {
1.63.4.1 skrll 457: bootit(filename, howto);
1.58 riastrad 458: } else {
459: int i;
1.59 he 460:
461: #ifndef SMALL
1.63.4.1 skrll 462: if (howto == 0)
463: bootdefault();
1.59 he 464: #endif
1.58 riastrad 465: for (i = 0; i < NUMNAMES; i++) {
1.63.4.1 skrll 466: bootit(names[i][0], howto);
467: bootit(names[i][1], howto);
1.58 riastrad 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:
1.63 rtr 536: if (bootcfg_info.nummenu > 0) {
1.59 he 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>