etc/protocols - sync with NetBSD-8
[minix.git] / sys / arch / i386 / stand / boot / boot2.c
blob6c02bbee37cf08fb6f874bec53532bb52a8a60b4
1 /* $NetBSD: boot2.c,v 1.65 2015/06/11 15:56:53 khorben 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/bootcfg.h>
76 #include <lib/libsa/ufs.h>
77 #include <lib/libkern/libkern.h>
79 #include <libi386.h>
80 #include <bootmod.h>
81 #include <bootmenu.h>
82 #include <vbe.h>
83 #include "devopen.h"
85 #ifdef SUPPORT_PS2
86 #include <biosmca.h>
87 #endif
89 extern struct x86_boot_params boot_params;
91 extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
93 int errno;
95 int boot_biosdev;
96 daddr_t boot_biossector;
98 static const char * const names[][2] = {
99 { "netbsd", "netbsd.gz" },
100 { "onetbsd", "onetbsd.gz" },
101 { "netbsd.old", "netbsd.old.gz" },
104 #define NUMNAMES (sizeof(names)/sizeof(names[0]))
105 #define DEFFILENAME names[0][0]
107 #define MAXDEVNAME 16
109 static char *default_devname;
110 static int default_unit, default_partition;
111 static const char *default_filename;
113 char *sprint_bootsel(const char *);
114 static void bootit(const char *, int);
115 void print_banner(void);
116 void boot2(int, uint64_t);
118 void command_help(char *);
119 #if LIBSA_ENABLE_LS_OP
120 void command_ls(char *);
121 #endif
122 void command_quit(char *);
123 void command_boot(char *);
124 void command_dev(char *);
125 void command_consdev(char *);
126 #ifndef SMALL
127 void command_menu(char *);
128 #endif
129 void command_modules(char *);
130 void command_multiboot(char *);
131 #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
132 void command_load_mods(char *);
133 #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
135 const struct bootblk_command commands[] = {
136 { "help", command_help },
137 { "?", command_help },
138 #if LIBSA_ENABLE_LS_OP
139 { "ls", command_ls },
140 #endif
141 { "quit", command_quit },
142 { "boot", command_boot },
143 { "dev", command_dev },
144 { "consdev", command_consdev },
145 #ifndef SMALL
146 { "menu", command_menu },
147 #endif
148 { "modules", command_modules },
149 { "load", module_add },
150 #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
151 { "load_mods", command_load_mods },
152 #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
153 { "multiboot", command_multiboot },
154 { "vesa", command_vesa },
155 { "splash", splash_add },
156 { "rndseed", rnd_add },
157 { "fs", fs_add },
158 { "userconf", userconf_add },
159 { NULL, NULL },
163 parsebootfile(const char *fname, char **fsname, char **devname,
164 int *unit, int *partition, const char **file)
166 const char *col;
168 *fsname = "ufs";
169 *devname = default_devname;
170 *unit = default_unit;
171 *partition = default_partition;
172 *file = default_filename;
174 if (fname == NULL)
175 return 0;
177 if ((col = strchr(fname, ':')) != NULL) { /* device given */
178 static char savedevname[MAXDEVNAME+1];
179 int devlen;
180 int u = 0, p = 0;
181 int i = 0;
183 devlen = col - fname;
184 if (devlen > MAXDEVNAME)
185 return EINVAL;
187 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
188 if (!isvalidname(fname[i]))
189 return EINVAL;
190 do {
191 savedevname[i] = fname[i];
192 i++;
193 } while (isvalidname(fname[i]));
194 savedevname[i] = '\0';
196 #define isnum(c) ((c) >= '0' && (c) <= '9')
197 if (i < devlen) {
198 if (!isnum(fname[i]))
199 return EUNIT;
200 do {
201 u *= 10;
202 u += fname[i++] - '0';
203 } while (isnum(fname[i]));
206 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
207 if (i < devlen) {
208 if (!isvalidpart(fname[i]))
209 return EPART;
210 p = fname[i++] - 'a';
213 if (i != devlen)
214 return ENXIO;
216 *devname = savedevname;
217 *unit = u;
218 *partition = p;
219 fname = col + 1;
222 if (*fname)
223 *file = fname;
225 return 0;
228 char *
229 sprint_bootsel(const char *filename)
231 char *fsname, *devname;
232 int unit, partition;
233 const char *file;
234 static char buf[80];
236 if (parsebootfile(filename, &fsname, &devname, &unit,
237 &partition, &file) == 0) {
238 snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
239 'a' + partition, file);
240 return buf;
242 return "(invalid)";
245 static void
246 clearit(void)
249 if (bootcfg_info.clear)
250 clear_pc_screen();
253 static void
254 bootit(const char *filename, int howto)
256 if (howto & AB_VERBOSE)
257 printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
258 howto);
260 if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
261 printf("boot: %s: %s\n", sprint_bootsel(filename),
262 strerror(errno));
263 else
264 printf("boot returned\n");
267 void
268 print_banner(void)
271 clearit();
272 #ifndef SMALL
273 int n;
274 if (bootcfg_info.banner[0]) {
275 for (n = 0; bootcfg_info.banner[n]
276 && n < BOOTCFG_MAXBANNER; n++)
277 printf("%s\n", bootcfg_info.banner[n]);
278 } else {
279 #endif /* !SMALL */
280 #if !defined(__minix)
281 printf("\n"
282 ">> %s, Revision %s (from NetBSD %s)\n"
283 ">> Memory: %d/%d k\n",
284 bootprog_name, bootprog_rev, bootprog_kernrev,
285 getbasemem(), getextmem());
286 #else
287 printf("\n"
288 "--- Welcome to MINIX 3. This is the boot monitor. ---\n"
289 "Memory: %d/%d k\n",
290 getbasemem(), getextmem());
291 #endif /* !defined(__minix) */
293 #ifndef SMALL
295 #endif /* !SMALL */
299 * Called from the initial entry point boot_start in biosboot.S
301 * biosdev: BIOS drive number the system booted from
302 * biossector: Sector number of the NetBSD partition
304 void
305 boot2(int biosdev, uint64_t biossector)
307 extern char twiddle_toggle;
308 int currname;
309 char c;
311 twiddle_toggle = 1; /* no twiddling until we're ready */
313 initio(boot_params.bp_consdev);
315 #ifdef SUPPORT_PS2
316 biosmca();
317 #endif
318 gateA20();
320 boot_modules_enabled = !(boot_params.bp_flags
321 & X86_BP_FLAGS_NOMODULES);
322 if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
323 biosvideomode();
325 vbe_init();
327 /* need to remember these */
328 boot_biosdev = biosdev;
329 boot_biossector = biossector;
331 /* try to set default device to what BIOS tells us */
332 bios2dev(biosdev, biossector, &default_devname, &default_unit,
333 &default_partition);
335 /* if the user types "boot" without filename */
336 default_filename = DEFFILENAME;
338 #ifndef SMALL
339 if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
340 parsebootconf(BOOTCFG_FILENAME);
341 } else {
342 bootcfg_info.timeout = boot_params.bp_timeout;
347 * If console set in boot.cfg, switch to it.
348 * This will print the banner, so we don't need to explicitly do it
350 if (bootcfg_info.consdev)
351 command_consdev(bootcfg_info.consdev);
352 else
353 print_banner();
355 /* Display the menu, if applicable */
356 twiddle_toggle = 0;
357 if (bootcfg_info.nummenu > 0) {
358 /* Does not return */
359 doboottypemenu();
362 #else
363 twiddle_toggle = 0;
364 print_banner();
365 #endif
367 printf("Press return to boot now, any other key for boot menu\n");
368 for (currname = 0; currname < NUMNAMES; currname++) {
369 printf("booting %s - starting in ",
370 sprint_bootsel(names[currname][0]));
372 #ifdef SMALL
373 c = awaitkey(boot_params.bp_timeout, 1);
374 #else
375 c = awaitkey((bootcfg_info.timeout < 0) ? 0
376 : bootcfg_info.timeout, 1);
377 #endif
378 if ((c != '\r') && (c != '\n') && (c != '\0')) {
379 if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
380 /* do NOT ask for password */
381 bootmenu(); /* does not return */
382 } else {
383 /* DO ask for password */
384 if (check_password((char *)boot_params.bp_password)) {
385 /* password ok */
386 printf("type \"?\" or \"help\" for help.\n");
387 bootmenu(); /* does not return */
388 } else {
389 /* bad password */
390 printf("Wrong password.\n");
391 currname = 0;
392 continue;
398 * try pairs of names[] entries, foo and foo.gz
400 /* don't print "booting..." again */
401 bootit(names[currname][0], 0);
402 /* since it failed, try compressed bootfile. */
403 bootit(names[currname][1], AB_VERBOSE);
406 bootmenu(); /* does not return */
409 /* ARGSUSED */
410 void
411 command_help(char *arg)
414 printf("commands are:\n"
415 "boot [xdNx:][filename] [-12acdqsvxz]\n"
416 " (ex. \"hd0a:netbsd.old -s\"\n"
417 #if LIBSA_ENABLE_LS_OP
418 "ls [path]\n"
419 #endif
420 "dev xd[N[x]]:\n"
421 "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
422 "vesa {modenum|on|off|enabled|disabled|list}\n"
423 #ifndef SMALL
424 "menu (reenters boot menu, if defined in boot.cfg)\n"
425 #endif
426 "modules {on|off|enabled|disabled}\n"
427 "load {path_to_module}\n"
428 #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
429 "load_mods {path_to_modules}, pattern might be used\n"
430 #endif /*defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
431 "multiboot [xdNx:][filename] [<args>]\n"
432 "splash {path_to_image_file}\n"
433 "userconf {command}\n"
434 "rndseed {path_to_rndseed_file}\n"
435 "help|?\n"
436 "quit\n");
439 #if LIBSA_ENABLE_LS_OP
440 void
441 command_ls(char *arg)
443 const char *save = default_filename;
445 default_filename = "/";
446 ls(arg);
447 default_filename = save;
449 #endif
451 #if defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP
452 void
453 command_load_mods(char *arg)
455 const char *save = default_filename;
457 default_filename = "/";
458 load_mods(arg, module_add);
459 default_filename = save;
461 #endif /* defined(__minix) && LIBSA_ENABLE_LOAD_MODS_OP */
463 /* ARGSUSED */
464 void
465 command_quit(char *arg)
468 printf("Exiting...\n");
469 delay(1000000);
470 reboot();
471 /* Note: we shouldn't get to this point! */
472 panic("Could not reboot!");
475 void
476 command_boot(char *arg)
478 char *filename;
479 int howto;
481 if (!parseboot(arg, &filename, &howto))
482 return;
484 if (filename != NULL) {
485 bootit(filename, howto);
486 } else {
487 int i;
489 #ifndef SMALL
490 if (howto == 0)
491 bootdefault();
492 #endif
493 for (i = 0; i < NUMNAMES; i++) {
494 bootit(names[i][0], howto);
495 bootit(names[i][1], howto);
500 void
501 command_dev(char *arg)
503 static char savedevname[MAXDEVNAME + 1];
504 char *fsname, *devname;
505 const char *file; /* dummy */
507 if (*arg == '\0') {
508 biosdisk_probe();
509 printf("default %s%d%c\n", default_devname, default_unit,
510 'a' + default_partition);
511 return;
514 if (strchr(arg, ':') == NULL ||
515 parsebootfile(arg, &fsname, &devname, &default_unit,
516 &default_partition, &file)) {
517 command_help(NULL);
518 return;
521 /* put to own static storage */
522 strncpy(savedevname, devname, MAXDEVNAME + 1);
523 default_devname = savedevname;
526 static const struct cons_devs {
527 const char *name;
528 u_int tag;
529 } cons_devs[] = {
530 { "pc", CONSDEV_PC },
531 { "com0", CONSDEV_COM0 },
532 { "com1", CONSDEV_COM1 },
533 { "com2", CONSDEV_COM2 },
534 { "com3", CONSDEV_COM3 },
535 { "com0kbd", CONSDEV_COM0KBD },
536 { "com1kbd", CONSDEV_COM1KBD },
537 { "com2kbd", CONSDEV_COM2KBD },
538 { "com3kbd", CONSDEV_COM3KBD },
539 { "auto", CONSDEV_AUTO },
540 { NULL, 0 }
543 void
544 command_consdev(char *arg)
546 const struct cons_devs *cdp;
548 for (cdp = cons_devs; cdp->name; cdp++) {
549 if (strcmp(arg, cdp->name) == 0) {
550 initio(cdp->tag);
551 print_banner();
552 return;
555 printf("invalid console device.\n");
558 #ifndef SMALL
559 /* ARGSUSED */
560 void
561 command_menu(char *arg)
564 if (bootcfg_info.nummenu > 0) {
565 /* Does not return */
566 doboottypemenu();
567 } else {
568 printf("No menu defined in boot.cfg\n");
571 #endif /* !SMALL */
573 void
574 command_modules(char *arg)
577 if (strcmp(arg, "enabled") == 0 ||
578 strcmp(arg, "on") == 0)
579 boot_modules_enabled = true;
580 else if (strcmp(arg, "disabled") == 0 ||
581 strcmp(arg, "off") == 0)
582 boot_modules_enabled = false;
583 else
584 printf("invalid flag, must be 'enabled' or 'disabled'.\n");
587 void
588 command_multiboot(char *arg)
590 char *filename;
592 filename = arg;
593 if (exec_multiboot(filename, gettrailer(arg)) < 0)
594 printf("multiboot: %s: %s\n", sprint_bootsel(filename),
595 strerror(errno));
596 else
597 printf("boot returned\n");