1 /* $NetBSD: boot2.c,v 1.60 2013/08/30 16:42:17 jmcneill Exp $ */
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
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
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>
88 extern struct x86_boot_params boot_params
;
90 extern const char bootprog_name
[], bootprog_rev
[], bootprog_kernrev
[];
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 *);
124 void command_menu(char *);
126 void command_modules(char *);
127 void command_multiboot(char *);
129 void command_load_mods(char *);
132 const struct bootblk_command commands
[] = {
133 { "help", command_help
},
134 { "?", command_help
},
135 { "ls", command_ls
},
136 { "quit", command_quit
},
137 { "boot", command_boot
},
138 { "dev", command_dev
},
139 { "consdev", command_consdev
},
141 { "menu", command_menu
},
143 { "modules", command_modules
},
144 { "load", module_add
},
146 { "load_mods", command_load_mods
},
148 { "multiboot", command_multiboot
},
149 { "vesa", command_vesa
},
150 { "splash", splash_add
},
151 { "rndseed", rnd_add
},
153 { "userconf", userconf_add
},
158 parsebootfile(const char *fname
, char **fsname
, char **devname
,
159 int *unit
, int *partition
, const char **file
)
164 *devname
= default_devname
;
165 *unit
= default_unit
;
166 *partition
= default_partition
;
167 *file
= default_filename
;
172 if ((col
= strchr(fname
, ':')) != NULL
) { /* device given */
173 static char savedevname
[MAXDEVNAME
+1];
178 devlen
= col
- fname
;
179 if (devlen
> MAXDEVNAME
)
182 #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
183 if (!isvalidname(fname
[i
]))
186 savedevname
[i
] = fname
[i
];
188 } while (isvalidname(fname
[i
]));
189 savedevname
[i
] = '\0';
191 #define isnum(c) ((c) >= '0' && (c) <= '9')
193 if (!isnum(fname
[i
]))
197 u
+= fname
[i
++] - '0';
198 } while (isnum(fname
[i
]));
201 #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
203 if (!isvalidpart(fname
[i
]))
205 p
= fname
[i
++] - 'a';
211 *devname
= savedevname
;
224 sprint_bootsel(const char *filename
)
226 char *fsname
, *devname
;
231 if (parsebootfile(filename
, &fsname
, &devname
, &unit
,
232 &partition
, &file
) == 0) {
233 sprintf(buf
, "%s%d%c:%s", devname
, unit
, 'a' + partition
, file
);
248 bootit(const char *filename
, int howto
, int tell
)
252 printf("booting %s", sprint_bootsel(filename
));
254 printf(" (howto 0x%x)", howto
);
258 if (exec_netbsd(filename
, 0, howto
, boot_biosdev
< 0x80, clearit
) < 0)
259 printf("boot: %s: %s\n", sprint_bootsel(filename
),
262 printf("boot returned\n");
272 if (bootconf
.banner
[0]) {
273 for (n
= 0; bootconf
.banner
[n
] && n
< MAXBANNER
; n
++)
274 printf("%s\n", bootconf
.banner
[n
]);
279 ">> %s, Revision %s (from NetBSD %s)\n"
280 ">> Memory: %d/%d k\n",
281 bootprog_name
, bootprog_rev
, bootprog_kernrev
,
282 getbasemem(), getextmem());
285 "--- Welcome to MINIX 3. This is the boot monitor. ---\n"
287 getbasemem(), getextmem());
296 * Called from the initial entry point boot_start in biosboot.S
298 * biosdev: BIOS drive number the system booted from
299 * biossector: Sector number of the NetBSD partition
302 boot2(int biosdev
, uint64_t biossector
)
304 extern char twiddle_toggle
;
308 twiddle_toggle
= 1; /* no twiddling until we're ready */
310 initio(boot_params
.bp_consdev
);
317 boot_modules_enabled
= !(boot_params
.bp_flags
318 & X86_BP_FLAGS_NOMODULES
);
319 if (boot_params
.bp_flags
& X86_BP_FLAGS_RESET_VIDEO
)
324 /* need to remember these */
325 boot_biosdev
= biosdev
;
326 boot_biossector
= biossector
;
328 /* try to set default device to what BIOS tells us */
329 bios2dev(biosdev
, biossector
, &default_devname
, &default_unit
,
332 /* if the user types "boot" without filename */
333 default_filename
= DEFFILENAME
;
336 if (!(boot_params
.bp_flags
& X86_BP_FLAGS_NOBOOTCONF
)) {
337 parsebootconf(BOOTCONF
);
339 bootconf
.timeout
= boot_params
.bp_timeout
;
344 * If console set in boot.cfg, switch to it.
345 * This will print the banner, so we don't need to explicitly do it
347 if (bootconf
.consdev
)
348 command_consdev(bootconf
.consdev
);
352 /* Display the menu, if applicable */
354 if (bootconf
.nummenu
> 0) {
355 /* Does not return */
364 printf("Press return to boot now, any other key for boot menu\n");
365 for (currname
= 0; currname
< NUMNAMES
; currname
++) {
366 printf("booting %s - starting in ",
367 sprint_bootsel(names
[currname
][0]));
370 c
= awaitkey(boot_params
.bp_timeout
, 1);
372 c
= awaitkey((bootconf
.timeout
< 0) ? 0 : bootconf
.timeout
, 1);
374 if ((c
!= '\r') && (c
!= '\n') && (c
!= '\0')) {
375 if ((boot_params
.bp_flags
& X86_BP_FLAGS_PASSWORD
) == 0) {
376 /* do NOT ask for password */
377 bootmenu(); /* does not return */
379 /* DO ask for password */
380 if (check_password((char *)boot_params
.bp_password
)) {
382 printf("type \"?\" or \"help\" for help.\n");
383 bootmenu(); /* does not return */
386 printf("Wrong password.\n");
394 * try pairs of names[] entries, foo and foo.gz
396 /* don't print "booting..." again */
397 bootit(names
[currname
][0], 0, 0);
398 /* since it failed, try compressed bootfile. */
399 bootit(names
[currname
][1], 0, 1);
402 bootmenu(); /* does not return */
407 command_help(char *arg
)
410 printf("commands are:\n"
411 "boot [xdNx:][filename] [-12acdqsvxz]\n"
412 " (ex. \"hd0a:netbsd.old -s\"\n"
415 "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
416 "vesa {modenum|on|off|enabled|disabled|list}\n"
418 "menu (reenters boot menu, if defined in boot.cfg)\n"
420 "modules {on|off|enabled|disabled}\n"
421 "load {path_to_module}\n"
423 "load_mods {path_to_modules}, pattern might be used\n"
424 #endif /* defined(__minix) */
425 "multiboot [xdNx:][filename] [<args>]\n"
426 "userconf {command}\n"
427 "rndseed {path_to_rndseed_file}\n"
433 command_ls(char *arg
)
435 const char *save
= default_filename
;
437 default_filename
= "/";
438 #if !defined(__minix)
442 #endif /* !defined(__minix) */
443 default_filename
= save
;
448 command_load_mods(char *arg
)
450 const char *save
= default_filename
;
452 default_filename
= "/";
454 default_filename
= save
;
456 #endif /* defined(__minix) */
460 command_quit(char *arg
)
463 printf("Exiting...\n");
466 /* Note: we shouldn't get to this point! */
467 panic("Could not reboot!");
471 command_boot(char *arg
)
476 if (!parseboot(arg
, &filename
, &howto
))
479 tell
= ((howto
& AB_VERBOSE
) != 0);
480 if (filename
!= NULL
) {
481 bootit(filename
, howto
, tell
);
488 for (i
= 0; i
< NUMNAMES
; i
++) {
489 bootit(names
[i
][0], howto
, tell
);
490 bootit(names
[i
][1], howto
, tell
);
496 command_dev(char *arg
)
498 static char savedevname
[MAXDEVNAME
+ 1];
499 char *fsname
, *devname
;
500 const char *file
; /* dummy */
504 printf("default %s%d%c\n", default_devname
, default_unit
,
505 'a' + default_partition
);
509 if (strchr(arg
, ':') == NULL
||
510 parsebootfile(arg
, &fsname
, &devname
, &default_unit
,
511 &default_partition
, &file
)) {
516 /* put to own static storage */
517 strncpy(savedevname
, devname
, MAXDEVNAME
+ 1);
518 default_devname
= savedevname
;
521 static const struct cons_devs
{
525 { "pc", CONSDEV_PC
},
526 { "com0", CONSDEV_COM0
},
527 { "com1", CONSDEV_COM1
},
528 { "com2", CONSDEV_COM2
},
529 { "com3", CONSDEV_COM3
},
530 { "com0kbd", CONSDEV_COM0KBD
},
531 { "com1kbd", CONSDEV_COM1KBD
},
532 { "com2kbd", CONSDEV_COM2KBD
},
533 { "com3kbd", CONSDEV_COM3KBD
},
534 { "auto", CONSDEV_AUTO
},
539 command_consdev(char *arg
)
541 const struct cons_devs
*cdp
;
543 for (cdp
= cons_devs
; cdp
->name
; cdp
++) {
544 if (strcmp(arg
, cdp
->name
) == 0) {
550 printf("invalid console device.\n");
556 command_menu(char *arg
)
559 if (bootconf
.nummenu
> 0) {
560 /* Does not return */
563 printf("No menu defined in boot.cfg\n");
569 command_modules(char *arg
)
572 if (strcmp(arg
, "enabled") == 0 ||
573 strcmp(arg
, "on") == 0)
574 boot_modules_enabled
= true;
575 else if (strcmp(arg
, "disabled") == 0 ||
576 strcmp(arg
, "off") == 0)
577 boot_modules_enabled
= false;
579 printf("invalid flag, must be 'enabled' or 'disabled'.\n");
583 command_multiboot(char *arg
)
588 if (exec_multiboot(filename
, gettrailer(arg
)) < 0)
589 printf("multiboot: %s: %s\n", sprint_bootsel(filename
),
592 printf("boot returned\n");