Annotation of src/sys/arch/i386/stand/boot/boot2.c, Revision 1.52
1.52 ! jmcneill 1: /* $NetBSD: boot2.c,v 1.51 2011/01/05 23:13:01 jakllsch 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>
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 *);
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.52 ! jmcneill 138: { "splash", splash_add },
1.1 dsl 139: { NULL, NULL },
140: };
141:
142: int
143: parsebootfile(const char *fname, char **fsname, char **devname,
1.11 junyoung 144: int *unit, int *partition, const char **file)
1.1 dsl 145: {
146: const char *col;
147:
148: *fsname = "ufs";
149: *devname = default_devname;
150: *unit = default_unit;
151: *partition = default_partition;
152: *file = default_filename;
153:
154: if (fname == NULL)
1.7 junyoung 155: return 0;
1.1 dsl 156:
1.8 junyoung 157: if ((col = strchr(fname, ':')) != NULL) { /* device given */
1.1 dsl 158: static char savedevname[MAXDEVNAME+1];
159: int devlen;
1.11 junyoung 160: int u = 0, p = 0;
1.1 dsl 161: int i = 0;
162:
163: devlen = col - fname;
164: if (devlen > MAXDEVNAME)
1.6 junyoung 165: return EINVAL;
1.1 dsl 166:
167: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
168: if (!isvalidname(fname[i]))
1.6 junyoung 169: return EINVAL;
1.1 dsl 170: do {
171: savedevname[i] = fname[i];
172: i++;
173: } while (isvalidname(fname[i]));
174: savedevname[i] = '\0';
175:
176: #define isnum(c) ((c) >= '0' && (c) <= '9')
177: if (i < devlen) {
178: if (!isnum(fname[i]))
1.6 junyoung 179: return EUNIT;
1.1 dsl 180: do {
181: u *= 10;
182: u += fname[i++] - '0';
183: } while (isnum(fname[i]));
184: }
185:
186: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
187: if (i < devlen) {
188: if (!isvalidpart(fname[i]))
1.6 junyoung 189: return EPART;
1.1 dsl 190: p = fname[i++] - 'a';
191: }
192:
193: if (i != devlen)
1.6 junyoung 194: return ENXIO;
1.1 dsl 195:
196: *devname = savedevname;
197: *unit = u;
198: *partition = p;
199: fname = col + 1;
200: }
201:
202: if (*fname)
203: *file = fname;
204:
1.6 junyoung 205: return 0;
1.1 dsl 206: }
207:
208: char *
209: sprint_bootsel(const char *filename)
210: {
211: char *fsname, *devname;
212: int unit, partition;
213: const char *file;
214: static char buf[80];
215:
216: if (parsebootfile(filename, &fsname, &devname, &unit,
217: &partition, &file) == 0) {
218: sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
1.6 junyoung 219: return buf;
1.1 dsl 220: }
1.6 junyoung 221: return "(invalid)";
1.1 dsl 222: }
223:
1.44 ad 224: static void
225: clearit(void)
226: {
227:
228: if (bootconf.clear)
229: clear_pc_screen();
230: }
231:
1.1 dsl 232: void
233: bootit(const char *filename, int howto, int tell)
234: {
235:
236: if (tell) {
237: printf("booting %s", sprint_bootsel(filename));
238: if (howto)
239: printf(" (howto 0x%x)", howto);
240: printf("\n");
241: }
242:
1.44 ad 243: if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
1.1 dsl 244: printf("boot: %s: %s\n", sprint_bootsel(filename),
245: strerror(errno));
246: else
247: printf("boot returned\n");
248: }
249:
250: void
251: print_banner(void)
252: {
1.41 christos 253:
1.44 ad 254: clearit();
1.15 sborrill 255: #ifndef SMALL
256: int n;
257: if (bootconf.banner[0]) {
1.22 sborrill 258: for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++)
1.15 sborrill 259: printf("%s\n", bootconf.banner[n]);
260: } else {
261: #endif /* !SMALL */
1.32 perry 262: printf("\n"
263: ">> %s, Revision %s (from NetBSD %s)\n"
264: ">> Memory: %d/%d k\n",
265: bootprog_name, bootprog_rev, bootprog_kernrev,
266: getbasemem(), getextmem());
1.15 sborrill 267:
268: #ifndef SMALL
269: }
270: #endif /* !SMALL */
271: }
272:
1.11 junyoung 273: /*
274: * Called from the initial entry point boot_start in biosboot.S
275: *
276: * biosdev: BIOS drive number the system booted from
277: * biossector: Sector number of the NetBSD partition
278: */
1.1 dsl 279: void
1.51 jakllsch 280: boot2(int biosdev, uint64_t biossector)
1.1 dsl 281: {
1.31 ad 282: extern char twiddle_toggle;
1.1 dsl 283: int currname;
284: char c;
285:
1.31 ad 286: twiddle_toggle = 1; /* no twiddling until we're ready */
287:
1.1 dsl 288: initio(boot_params.bp_consdev);
289:
290: #ifdef SUPPORT_PS2
291: biosmca();
292: #endif
293: gateA20();
294:
1.47 drochner 295: boot_modules_enabled = !(boot_params.bp_flags
296: & X86_BP_FLAGS_NOMODULES);
1.4 lukem 297: if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
1.1 dsl 298: biosvideomode();
299:
1.43 jmcneill 300: vbe_init();
301:
1.11 junyoung 302: /* need to remember these */
303: boot_biosdev = biosdev;
304: boot_biossector = biossector;
305:
1.1 dsl 306: /* try to set default device to what BIOS tells us */
1.11 junyoung 307: bios2dev(biosdev, biossector, &default_devname, &default_unit,
308: &default_partition);
1.1 dsl 309:
310: /* if the user types "boot" without filename */
311: default_filename = DEFFILENAME;
312:
1.15 sborrill 313: #ifndef SMALL
1.47 drochner 314: if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF))
1.46 drochner 315: parsebootconf(BOOTCONF);
1.15 sborrill 316:
317: /*
1.20 sborrill 318: * If console set in boot.cfg, switch to it.
1.15 sborrill 319: * This will print the banner, so we don't need to explicitly do it
320: */
321: if (bootconf.consdev)
322: command_consdev(bootconf.consdev);
323: else
324: print_banner();
325:
326: /* Display the menu, if applicable */
1.31 ad 327: twiddle_toggle = 0;
1.15 sborrill 328: if (bootconf.nummenu > 0) {
329: /* Does not return */
330: doboottypemenu();
331: }
1.43 jmcneill 332:
1.15 sborrill 333: #else
1.31 ad 334: twiddle_toggle = 0;
335: print_banner();
1.15 sborrill 336: #endif
337:
1.1 dsl 338: printf("Press return to boot now, any other key for boot menu\n");
1.10 junyoung 339: for (currname = 0; currname < NUMNAMES; currname++) {
1.1 dsl 340: printf("booting %s - starting in ",
341: sprint_bootsel(names[currname][0]));
342:
1.15 sborrill 343: #ifdef SMALL
1.1 dsl 344: c = awaitkey(boot_params.bp_timeout, 1);
1.15 sborrill 345: #else
346: c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
347: #endif
1.48 hubertf 348: if ((c != '\r') && (c != '\n') && (c != '\0')) {
349: if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
350: /* do NOT ask for password */
1.1 dsl 351: bootmenu(); /* does not return */
1.48 hubertf 352: } else {
353: /* DO ask for password */
354: if (check_password(boot_params.bp_password)) {
355: /* password ok */
356: printf("type \"?\" or \"help\" for help.\n");
357: bootmenu(); /* does not return */
358: } else {
359: /* bad password */
360: printf("Wrong password.\n");
361: currname = 0;
362: continue;
363: }
364: }
1.1 dsl 365: }
366:
367: /*
368: * try pairs of names[] entries, foo and foo.gz
369: */
370: /* don't print "booting..." again */
371: bootit(names[currname][0], 0, 0);
372: /* since it failed, try compressed bootfile. */
373: bootit(names[currname][1], 0, 1);
374: }
1.10 junyoung 375:
376: bootmenu(); /* does not return */
1.1 dsl 377: }
378:
379: /* ARGSUSED */
380: void
381: command_help(char *arg)
382: {
383:
384: printf("commands are:\n"
1.23 ad 385: "boot [xdNx:][filename] [-12acdqsvxz]\n"
1.8 junyoung 386: " (ex. \"hd0a:netbsd.old -s\"\n"
387: "ls [path]\n"
388: "dev xd[N[x]]:\n"
389: "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
1.49 jym 390: "vesa {modenum|on|off|enabled|disabled|list}\n"
391: "modules {on|off|enabled|disabled}\n"
1.25 ad 392: "load {path_to_module}\n"
1.38 joerg 393: "multiboot [xdNx:][filename] [<args>]\n"
1.8 junyoung 394: "help|?\n"
395: "quit\n");
1.1 dsl 396: }
397:
398: void
399: command_ls(char *arg)
400: {
401: const char *save = default_filename;
402:
403: default_filename = "/";
404: ufs_ls(arg);
405: default_filename = save;
406: }
407:
408: /* ARGSUSED */
409: void
410: command_quit(char *arg)
411: {
412:
413: printf("Exiting...\n");
414: delay(1000000);
415: reboot();
416: /* Note: we shouldn't get to this point! */
417: panic("Could not reboot!");
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>