unstack - fix ipcvecs
[minix.git] / sys / arch / i386 / stand / boot / boot2.c
blob695f6215cdd402c892e8b9cd3e6d8b952ae03ce2
1 /* $NetBSD: boot2.c,v 1.57 2011/12/25 06:09:09 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
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.
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.
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
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.
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.
68 /* Based on stand/biosboot/main.c */
70 #include <sys/types.h>
71 #include <sys/reboot.h>
72 #include <sys/bootblock.h>
74 #include <lib/libsa/stand.h>
75 #include <lib/libsa/ufs.h>
76 #include <lib/libkern/libkern.h>
78 #include <libi386.h>
79 #include <bootmod.h>
80 #include <bootmenu.h>
81 #include <vbe.h>
82 #include "devopen.h"
84 #ifdef SUPPORT_PS2
85 #include <biosmca.h>
86 #endif
88 extern struct x86_boot_params boot_params;
90 extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
92 int errno;
94 int boot_biosdev;
95 daddr_t boot_biossector;
97 static const char * const names[][2] = {
98 { "netbsd", "netbsd.gz" },
99 { "onetbsd", "onetbsd.gz" },
100 { "netbsd.old", "netbsd.old.gz" },
103 #define NUMNAMES (sizeof(names)/sizeof(names[0]))
104 #define DEFFILENAME names[0][0]
106 #define MAXDEVNAME 16
108 static char *default_devname;
109 static int default_unit, default_partition;
110 static const char *default_filename;
112 char *sprint_bootsel(const char *);
113 void bootit(const char *, int, int);
114 void print_banner(void);
115 void boot2(int, uint64_t);
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 *);
123 void command_modules(char *);
124 void command_multiboot(char *);
125 void command_load_mods(char *);
127 const struct bootblk_command commands[] = {
128 { "help", command_help },
129 { "?", command_help },
130 { "ls", command_ls },
131 { "quit", command_quit },
132 { "boot", command_boot },
133 { "dev", command_dev },
134 { "consdev", command_consdev },
135 { "modules", command_modules },
136 { "load", module_add },
137 { "load_mods", command_load_mods },
138 { "multiboot", command_multiboot },
139 { "vesa", command_vesa },
140 { "splash", splash_add },
141 { "rndseed", rnd_add },
142 { "userconf", userconf_add },
143 { NULL, NULL },
147 parsebootfile(const char *fname, char **fsname, char **devname,
148 int *unit, int *partition, const char **file)
150 const char *col;
152 *fsname = "ufs";
153 *devname = default_devname;
154 *unit = default_unit;
155 *partition = default_partition;
156 *file = default_filename;
158 if (fname == NULL)
159 return 0;
161 if ((col = strchr(fname, ':')) != NULL) { /* device given */
162 static char savedevname[MAXDEVNAME+1];
163 int devlen;
164 int u = 0, p = 0;
165 int i = 0;
167 devlen = col - fname;
168 if (devlen > MAXDEVNAME)
169 return EINVAL;
171 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
172 if (!isvalidname(fname[i]))
173 return EINVAL;
174 do {
175 savedevname[i] = fname[i];
176 i++;
177 } while (isvalidname(fname[i]));
178 savedevname[i] = '\0';
180 #define isnum(c) ((c) >= '0' && (c) <= '9')
181 if (i < devlen) {
182 if (!isnum(fname[i]))
183 return EUNIT;
184 do {
185 u *= 10;
186 u += fname[i++] - '0';
187 } while (isnum(fname[i]));
190 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
191 if (i < devlen) {
192 if (!isvalidpart(fname[i]))
193 return EPART;
194 p = fname[i++] - 'a';
197 if (i != devlen)
198 return ENXIO;
200 *devname = savedevname;
201 *unit = u;
202 *partition = p;
203 fname = col + 1;
206 if (*fname)
207 *file = fname;
209 return 0;
212 char *
213 sprint_bootsel(const char *filename)
215 char *fsname, *devname;
216 int unit, partition;
217 const char *file;
218 static char buf[80];
220 if (parsebootfile(filename, &fsname, &devname, &unit,
221 &partition, &file) == 0) {
222 sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
223 return buf;
225 return "(invalid)";
228 static void
229 clearit(void)
232 if (bootconf.clear)
233 clear_pc_screen();
236 void
237 bootit(const char *filename, int howto, int tell)
240 if (tell) {
241 printf("booting %s", sprint_bootsel(filename));
242 if (howto)
243 printf(" (howto 0x%x)", howto);
244 printf("\n");
247 if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
248 printf("boot: %s: %s\n", sprint_bootsel(filename),
249 strerror(errno));
250 else
251 printf("boot returned\n");
254 void
255 print_banner(void)
258 clearit();
259 #ifndef SMALL
260 int n;
261 if (bootconf.banner[0]) {
262 for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++)
263 printf("%s\n", bootconf.banner[n]);
264 } else {
265 #endif /* !SMALL */
266 #ifndef __minix
267 printf("\n"
268 ">> %s, Revision %s (from NetBSD %s)\n"
269 ">> Memory: %d/%d k\n",
270 bootprog_name, bootprog_rev, bootprog_kernrev,
271 getbasemem(), getextmem());
272 #else
273 printf("\n"
274 "--- Welcome to MINIX 3. This is the boot monitor. ---\n"
275 "Memory: %d/%d k\n",
276 getbasemem(), getextmem());
277 #endif
279 #ifndef SMALL
281 #endif /* !SMALL */
285 * Called from the initial entry point boot_start in biosboot.S
287 * biosdev: BIOS drive number the system booted from
288 * biossector: Sector number of the NetBSD partition
290 void
291 boot2(int biosdev, uint64_t biossector)
293 extern char twiddle_toggle;
294 int currname;
295 char c;
297 twiddle_toggle = 1; /* no twiddling until we're ready */
299 initio(boot_params.bp_consdev);
301 #ifdef SUPPORT_PS2
302 biosmca();
303 #endif
304 gateA20();
306 boot_modules_enabled = !(boot_params.bp_flags
307 & X86_BP_FLAGS_NOMODULES);
308 if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
309 biosvideomode();
311 vbe_init();
313 /* need to remember these */
314 boot_biosdev = biosdev;
315 boot_biossector = biossector;
317 /* try to set default device to what BIOS tells us */
318 bios2dev(biosdev, biossector, &default_devname, &default_unit,
319 &default_partition);
321 /* if the user types "boot" without filename */
322 default_filename = DEFFILENAME;
324 #ifndef SMALL
325 if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
326 parsebootconf(BOOTCONF);
327 } else {
328 bootconf.timeout = boot_params.bp_timeout;
333 * If console set in boot.cfg, switch to it.
334 * This will print the banner, so we don't need to explicitly do it
336 if (bootconf.consdev)
337 command_consdev(bootconf.consdev);
338 else
339 print_banner();
341 /* Display the menu, if applicable */
342 twiddle_toggle = 0;
343 if (bootconf.nummenu > 0) {
344 /* Does not return */
345 doboottypemenu();
348 #else
349 twiddle_toggle = 0;
350 print_banner();
351 #endif
353 printf("Press return to boot now, any other key for boot menu\n");
354 for (currname = 0; currname < NUMNAMES; currname++) {
355 printf("booting %s - starting in ",
356 sprint_bootsel(names[currname][0]));
358 #ifdef SMALL
359 c = awaitkey(boot_params.bp_timeout, 1);
360 #else
361 c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
362 #endif
363 if ((c != '\r') && (c != '\n') && (c != '\0')) {
364 if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
365 /* do NOT ask for password */
366 bootmenu(); /* does not return */
367 } else {
368 /* DO ask for password */
369 if (check_password((char *)boot_params.bp_password)) {
370 /* password ok */
371 printf("type \"?\" or \"help\" for help.\n");
372 bootmenu(); /* does not return */
373 } else {
374 /* bad password */
375 printf("Wrong password.\n");
376 currname = 0;
377 continue;
383 * try pairs of names[] entries, foo and foo.gz
385 /* don't print "booting..." again */
386 bootit(names[currname][0], 0, 0);
387 /* since it failed, try compressed bootfile. */
388 bootit(names[currname][1], 0, 1);
391 bootmenu(); /* does not return */
394 /* ARGSUSED */
395 void
396 command_help(char *arg)
399 printf("commands are:\n"
400 "boot [xdNx:][filename] [-12acdqsvxz]\n"
401 " (ex. \"hd0a:netbsd.old -s\"\n"
402 "ls [path]\n"
403 "dev xd[N[x]]:\n"
404 "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
405 "vesa {modenum|on|off|enabled|disabled|list}\n"
406 "modules {on|off|enabled|disabled}\n"
407 "load {path_to_module}\n"
408 "load_mods {path_to_modules}, pattern might be used\n"
409 "multiboot [xdNx:][filename] [<args>]\n"
410 "userconf {command}\n"
411 "rndseed {path_to_rndseed_file}\n"
412 "help|?\n"
413 "quit\n");
416 void
417 command_ls(char *arg)
419 const char *save = default_filename;
421 default_filename = "/";
422 ls(arg, NULL);
423 default_filename = save;
426 void
427 command_load_mods(char *arg)
429 const char *save = default_filename;
431 default_filename = "/";
432 ls(arg, module_add);
433 default_filename = save;
436 /* ARGSUSED */
437 void
438 command_quit(char *arg)
441 printf("Exiting...\n");
442 delay(1000000);
443 reboot();
444 /* Note: we shouldn't get to this point! */
445 panic("Could not reboot!");
448 void
449 command_boot(char *arg)
451 char *filename;
452 int howto;
454 if (parseboot(arg, &filename, &howto))
455 bootit(filename, howto, (howto & AB_VERBOSE) != 0);
458 void
459 command_dev(char *arg)
461 static char savedevname[MAXDEVNAME + 1];
462 char *fsname, *devname;
463 const char *file; /* dummy */
465 if (*arg == '\0') {
466 biosdisk_probe();
467 printf("default %s%d%c\n", default_devname, default_unit,
468 'a' + default_partition);
469 return;
472 if (strchr(arg, ':') == NULL ||
473 parsebootfile(arg, &fsname, &devname, &default_unit,
474 &default_partition, &file)) {
475 command_help(NULL);
476 return;
479 /* put to own static storage */
480 strncpy(savedevname, devname, MAXDEVNAME + 1);
481 default_devname = savedevname;
484 static const struct cons_devs {
485 const char *name;
486 u_int tag;
487 } cons_devs[] = {
488 { "pc", CONSDEV_PC },
489 { "com0", CONSDEV_COM0 },
490 { "com1", CONSDEV_COM1 },
491 { "com2", CONSDEV_COM2 },
492 { "com3", CONSDEV_COM3 },
493 { "com0kbd", CONSDEV_COM0KBD },
494 { "com1kbd", CONSDEV_COM1KBD },
495 { "com2kbd", CONSDEV_COM2KBD },
496 { "com3kbd", CONSDEV_COM3KBD },
497 { "auto", CONSDEV_AUTO },
498 { NULL, 0 }
501 void
502 command_consdev(char *arg)
504 const struct cons_devs *cdp;
506 for (cdp = cons_devs; cdp->name; cdp++) {
507 if (strcmp(arg, cdp->name) == 0) {
508 initio(cdp->tag);
509 print_banner();
510 return;
513 printf("invalid console device.\n");
516 void
517 command_modules(char *arg)
520 if (strcmp(arg, "enabled") == 0 ||
521 strcmp(arg, "on") == 0)
522 boot_modules_enabled = true;
523 else if (strcmp(arg, "disabled") == 0 ||
524 strcmp(arg, "off") == 0)
525 boot_modules_enabled = false;
526 else
527 printf("invalid flag, must be 'enabled' or 'disabled'.\n");
530 void
531 command_multiboot(char *arg)
533 char *filename;
535 filename = arg;
536 if (exec_multiboot(filename, gettrailer(arg)) < 0)
537 printf("multiboot: %s: %s\n", sprint_bootsel(filename),
538 strerror(errno));
539 else
540 printf("boot returned\n");