1 /* $NetBSD: main.c,v 1.28 2011/03/18 18:21:38 jakllsch 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 { NULL, NULL }, 80 }; 81 82 static void 83 clearit(void) 84 { 85 86 if (bootconf.clear) 87 clear_pc_screen(); 88 } 89 90 static void 91 alldone(void) 92 { 93 pxe_fini(); 94 clearit(); 95 } 96 97 static int 98 bootit(const char *filename, int howto) 99 { 100 if (exec_netbsd(filename, 0, howto, 0, alldone) < 0) 101 printf("boot: %s\n", strerror(errno)); 102 else 103 printf("boot returned\n"); 104 return (-1); 105 } 106 107 static void 108 print_banner(void) 109 { 110 int base = getbasemem(); 111 int ext = getextmem(); 112 113 clearit(); 114 printf("\n" 115 ">> NetBSD/x86 PXE boot, Revision %s (from NetBSD %s)\n" 116 ">> Memory: %d/%d k\n", 117 bootprog_rev, bootprog_kernrev, 118 base, ext); 119 } 120 121 int 122 main(void) 123 { 124 extern char twiddle_toggle; 125 char c; 126 127 twiddle_toggle = 1; /* no twiddling until we're ready */ 128 129 #ifdef SUPPORT_SERIAL 130 initio(SUPPORT_SERIAL); 131 #else 132 initio(CONSDEV_PC); 133 #endif 134 gateA20(); 135 boot_modules_enabled = !(boot_params.bp_flags 136 & X86_BP_FLAGS_NOMODULES); 137 138 #ifndef SMALL 139 if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) { 140 parsebootconf(BOOTCONF); 141 } else { 142 bootconf.timeout = boot_params.bp_timeout; 143 } 144 145 /* 146 * If console set in boot.cfg, switch to it. 147 * This will print the banner, so we don't need to explicitly do it 148 */ 149 if (bootconf.consdev) 150 command_consdev(bootconf.consdev); 151 else 152 print_banner(); 153 154 /* Display the menu, if applicable */ 155 twiddle_toggle = 0; 156 if (bootconf.nummenu > 0) { 157 /* Does not return */ 158 doboottypemenu(); 159 } 160 #else 161 twiddle_toggle = 0; 162 print_banner(); 163 #endif 164 165 printf("Press return to boot now, any other key for boot menu\n"); 166 printf("booting netbsd - starting in "); 167 168 #ifdef SMALL 169 c = awaitkey(boot_params.bp_timeout, 1); 170 #else 171 c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1); 172 #endif 173 if ((c != '\r') && (c != '\n') && (c != '\0') && 174 ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 175 || check_password((char *)boot_params.bp_password))) { 176 printf("type \"?\" or \"help\" for help.\n"); 177 bootmenu(); /* does not return */ 178 } 179 180 /* 181 * The file name provided here is just a default. If the 182 * DHCP server provides a file name, we'll use that instead. 183 */ 184 bootit("netbsd", 0); 185 186 /* 187 * If that fails, let the BIOS try the next boot device. 188 */ 189 return (1); 190 } 191 192 /* ARGSUSED */ 193 void 194 command_help(char *arg) 195 { 196 printf("commands are:\n" 197 "boot [filename] [-adsqv]\n" 198 " (ex. \"netbsd.old -s\"\n" 199 "consdev {pc|com[0123]|com[0123]kbd|auto}\n" 200 "vesa {modenum|on|off|enabled|disabled|list}\n" 201 "multiboot [filename] [<args>]\n" 202 "modules {on|off|enabled|disabled}\n" 203 "load {path_to_module}\n" 204 "help|?\n" 205 "quit\n"); 206 } 207 208 /* ARGSUSED */ 209 void 210 command_quit(char *arg) 211 { 212 213 printf("Exiting...\n"); 214 delay(1000000); 215 reboot(); 216 /* Note: we shouldn't get to this point! */ 217 panic("Could not reboot!"); 218 } 219 220 void 221 command_boot(char *arg) 222 { 223 char *filename; 224 int howto; 225 226 if (parseboot(arg, &filename, &howto)) 227 bootit(filename, howto); 228 } 229 230 static const struct cons_devs { 231 const char *name; 232 u_int tag; 233 } cons_devs[] = { 234 { "pc", CONSDEV_PC }, 235 { "com0", CONSDEV_COM0 }, 236 { "com1", CONSDEV_COM1 }, 237 { "com2", CONSDEV_COM2 }, 238 { "com3", CONSDEV_COM3 }, 239 { "com0kbd", CONSDEV_COM0KBD }, 240 { "com1kbd", CONSDEV_COM1KBD }, 241 { "com2kbd", CONSDEV_COM2KBD }, 242 { "com3kbd", CONSDEV_COM3KBD }, 243 { "auto", CONSDEV_AUTO }, 244 { 0, 0 } }; 245 246 void 247 command_consdev(char *arg) 248 { 249 const struct cons_devs *cdp; 250 251 for (cdp = cons_devs; cdp->name; cdp++) { 252 if (!strcmp(arg, cdp->name)) { 253 initio(cdp->tag); 254 print_banner(); 255 return; 256 } 257 } 258 printf("invalid console device.\n"); 259 } 260 void 261 command_modules(char *arg) 262 { 263 if (strcmp(arg, "enabled") == 0 || 264 strcmp(arg, "on") == 0) 265 boot_modules_enabled = true; 266 else if (strcmp(arg, "disabled") == 0 || 267 strcmp(arg, "off") == 0) 268 boot_modules_enabled = false; 269 else 270 printf("invalid flag, must be 'enabled' or 'disabled'.\n"); 271 } 272 273 void 274 command_multiboot(char *arg) 275 { 276 char *filename; 277 278 filename = arg; 279 if (exec_multiboot(filename, gettrailer(arg)) < 0) 280 printf("multiboot: %s: %s\n", filename, 281 strerror(errno)); 282 else 283 printf("boot returned\n"); 284 } 285