1 /* $NetBSD: main.c,v 1.30 2013/03/06 11:34:37 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * Matthias Drochner. All rights reserved. 6 * Copyright (c) 1996 7 * Perry E. Metzger. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgements: 19 * This product includes software developed for the NetBSD Project 20 * by Matthias Drochner. 21 * This product includes software developed for the NetBSD Project 22 * by Perry E. Metzger. 23 * 4. The names of the authors may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 */ 38 39 #include <sys/types.h> 40 #include <sys/reboot.h> 41 #include <sys/bootblock.h> 42 43 #include <lib/libkern/libkern.h> 44 45 #include <lib/libsa/stand.h> 46 47 #include <libi386.h> 48 #include <bootmenu.h> 49 #include <bootmod.h> 50 #include "pxeboot.h" 51 #include "vbe.h" 52 53 extern struct x86_boot_params boot_params; 54 55 int errno; 56 int debug; 57 58 extern char bootprog_name[], bootprog_rev[], bootprog_kernrev[]; 59 60 int main(void); 61 62 void command_help(char *); 63 void command_quit(char *); 64 void command_boot(char *); 65 void command_consdev(char *); 66 void command_modules(char *); 67 void command_multiboot(char *); 68 69 const struct bootblk_command commands[] = { 70 { "help", command_help }, 71 { "?", command_help }, 72 { "quit", command_quit }, 73 { "boot", command_boot }, 74 { "consdev", command_consdev }, 75 { "modules", command_modules }, 76 { "multiboot", command_multiboot }, 77 { "load", module_add }, 78 { "vesa", command_vesa }, 79 { "userconf", userconf_add }, 80 { NULL, NULL }, 81 }; 82 83 static void 84 clearit(void) 85 { 86 87 if (bootconf.clear) 88 clear_pc_screen(); 89 } 90 91 static void 92 alldone(void) 93 { 94 pxe_fini(); 95 clearit(); 96 } 97 98 static int 99 bootit(const char *filename, int howto) 100 { 101 if (exec_netbsd(filename, 0, howto, 0, alldone) < 0) 102 printf("boot: %s\n", strerror(errno)); 103 else 104 printf("boot returned\n"); 105 return (-1); 106 } 107 108 static void 109 print_banner(void) 110 { 111 int base = getbasemem(); 112 int ext = getextmem(); 113 114 clearit(); 115 printf("\n" 116 ">> NetBSD/x86 PXE boot, Revision %s (from NetBSD %s)\n" 117 ">> Memory: %d/%d k\n", 118 bootprog_rev, bootprog_kernrev, 119 base, ext); 120 } 121 122 int 123 main(void) 124 { 125 extern char twiddle_toggle; 126 char c; 127 128 twiddle_toggle = 1; /* no twiddling until we're ready */ 129 130 #ifdef SUPPORT_SERIAL 131 initio(SUPPORT_SERIAL); 132 #else 133 initio(CONSDEV_PC); 134 #endif 135 gateA20(); 136 boot_modules_enabled = !(boot_params.bp_flags 137 & X86_BP_FLAGS_NOMODULES); 138 139 #ifndef SMALL 140 if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) { 141 parsebootconf(BOOTCONF); 142 } else { 143 bootconf.timeout = boot_params.bp_timeout; 144 } 145 146 /* 147 * If console set in boot.cfg, switch to it. 148 * This will print the banner, so we don't need to explicitly do it 149 */ 150 if (bootconf.consdev) 151 command_consdev(bootconf.consdev); 152 else 153 print_banner(); 154 155 /* Display the menu, if applicable */ 156 twiddle_toggle = 0; 157 if (bootconf.nummenu > 0) { 158 /* Does not return */ 159 doboottypemenu(); 160 } 161 #else 162 twiddle_toggle = 0; 163 print_banner(); 164 #endif 165 166 printf("Press return to boot now, any other key for boot menu\n"); 167 printf("booting netbsd - starting in "); 168 169 #ifdef SMALL 170 c = awaitkey(boot_params.bp_timeout, 1); 171 #else 172 c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1); 173 #endif 174 if ((c != '\r') && (c != '\n') && (c != '\0') && 175 ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 176 || check_password((char *)boot_params.bp_password))) { 177 printf("type \"?\" or \"help\" for help.\n"); 178 bootmenu(); /* does not return */ 179 } 180 181 /* 182 * The file name provided here is just a default. If the 183 * DHCP server provides a file name, we'll use that instead. 184 */ 185 bootit("netbsd", 0); 186 187 /* 188 * If that fails, let the BIOS try the next boot device. 189 */ 190 return (1); 191 } 192 193 /* ARGSUSED */ 194 void 195 command_help(char *arg) 196 { 197 printf("commands are:\n" 198 "boot [filename] [-acdsqv]\n" 199 " (ex. \"netbsd.old -s\"\n" 200 "consdev {pc|com[0123]|com[0123]kbd|auto}\n" 201 "vesa {modenum|on|off|enabled|disabled|list}\n" 202 "multiboot [filename] [<args>]\n" 203 "modules {on|off|enabled|disabled}\n" 204 "load {path_to_module}\n" 205 "userconf {command}\n" 206 "help|?\n" 207 "quit\n"); 208 } 209 210 /* ARGSUSED */ 211 void 212 command_quit(char *arg) 213 { 214 215 printf("Exiting...\n"); 216 delay(1000000); 217 reboot(); 218 /* Note: we shouldn't get to this point! */ 219 panic("Could not reboot!"); 220 } 221 222 void 223 command_boot(char *arg) 224 { 225 char *filename; 226 int howto; 227 228 if (parseboot(arg, &filename, &howto)) 229 bootit(filename, howto); 230 } 231 232 static const struct cons_devs { 233 const char *name; 234 u_int tag; 235 } cons_devs[] = { 236 { "pc", CONSDEV_PC }, 237 { "com0", CONSDEV_COM0 }, 238 { "com1", CONSDEV_COM1 }, 239 { "com2", CONSDEV_COM2 }, 240 { "com3", CONSDEV_COM3 }, 241 { "com0kbd", CONSDEV_COM0KBD }, 242 { "com1kbd", CONSDEV_COM1KBD }, 243 { "com2kbd", CONSDEV_COM2KBD }, 244 { "com3kbd", CONSDEV_COM3KBD }, 245 { "auto", CONSDEV_AUTO }, 246 { 0, 0 } }; 247 248 void 249 command_consdev(char *arg) 250 { 251 const struct cons_devs *cdp; 252 253 for (cdp = cons_devs; cdp->name; cdp++) { 254 if (!strcmp(arg, cdp->name)) { 255 initio(cdp->tag); 256 print_banner(); 257 return; 258 } 259 } 260 printf("invalid console device.\n"); 261 } 262 void 263 command_modules(char *arg) 264 { 265 if (strcmp(arg, "enabled") == 0 || 266 strcmp(arg, "on") == 0) 267 boot_modules_enabled = true; 268 else if (strcmp(arg, "disabled") == 0 || 269 strcmp(arg, "off") == 0) 270 boot_modules_enabled = false; 271 else 272 printf("invalid flag, must be 'enabled' or 'disabled'.\n"); 273 } 274 275 void 276 command_multiboot(char *arg) 277 { 278 char *filename; 279 280 filename = arg; 281 if (exec_multiboot(filename, gettrailer(arg)) < 0) 282 printf("multiboot: %s: %s\n", filename, 283 strerror(errno)); 284 else 285 printf("boot returned\n"); 286 } 287