1 /* $NetBSD: main.c,v 1.27 2010/12/20 01:12:45 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 142 /* 143 * If console set in boot.cfg, switch to it. 144 * This will print the banner, so we don't need to explicitly do it 145 */ 146 if (bootconf.consdev) 147 command_consdev(bootconf.consdev); 148 else 149 print_banner(); 150 151 /* Display the menu, if applicable */ 152 twiddle_toggle = 0; 153 if (bootconf.nummenu > 0) { 154 /* Does not return */ 155 doboottypemenu(); 156 } 157 #else 158 twiddle_toggle = 0; 159 print_banner(); 160 #endif 161 162 printf("Press return to boot now, any other key for boot menu\n"); 163 printf("booting netbsd - starting in "); 164 165 #ifdef SMALL 166 c = awaitkey(boot_params.bp_timeout, 1); 167 #else 168 c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1); 169 #endif 170 if ((c != '\r') && (c != '\n') && (c != '\0') && 171 ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 172 || check_password((char *)boot_params.bp_password))) { 173 printf("type \"?\" or \"help\" for help.\n"); 174 bootmenu(); /* does not return */ 175 } 176 177 /* 178 * The file name provided here is just a default. If the 179 * DHCP server provides a file name, we'll use that instead. 180 */ 181 bootit("netbsd", 0); 182 183 /* 184 * If that fails, let the BIOS try the next boot device. 185 */ 186 return (1); 187 } 188 189 /* ARGSUSED */ 190 void 191 command_help(char *arg) 192 { 193 printf("commands are:\n" 194 "boot [filename] [-adsqv]\n" 195 " (ex. \"netbsd.old -s\"\n" 196 "consdev {pc|com[0123]|com[0123]kbd|auto}\n" 197 "vesa {modenum|on|off|enabled|disabled|list}\n" 198 "multiboot [filename] [<args>]\n" 199 "modules {on|off|enabled|disabled}\n" 200 "load {path_to_module}\n" 201 "help|?\n" 202 "quit\n"); 203 } 204 205 /* ARGSUSED */ 206 void 207 command_quit(char *arg) 208 { 209 210 printf("Exiting...\n"); 211 delay(1000000); 212 reboot(); 213 /* Note: we shouldn't get to this point! */ 214 panic("Could not reboot!"); 215 } 216 217 void 218 command_boot(char *arg) 219 { 220 char *filename; 221 int howto; 222 223 if (parseboot(arg, &filename, &howto)) 224 bootit(filename, howto); 225 } 226 227 static const struct cons_devs { 228 const char *name; 229 u_int tag; 230 } cons_devs[] = { 231 { "pc", CONSDEV_PC }, 232 { "com0", CONSDEV_COM0 }, 233 { "com1", CONSDEV_COM1 }, 234 { "com2", CONSDEV_COM2 }, 235 { "com3", CONSDEV_COM3 }, 236 { "com0kbd", CONSDEV_COM0KBD }, 237 { "com1kbd", CONSDEV_COM1KBD }, 238 { "com2kbd", CONSDEV_COM2KBD }, 239 { "com3kbd", CONSDEV_COM3KBD }, 240 { "auto", CONSDEV_AUTO }, 241 { 0, 0 } }; 242 243 void 244 command_consdev(char *arg) 245 { 246 const struct cons_devs *cdp; 247 248 for (cdp = cons_devs; cdp->name; cdp++) { 249 if (!strcmp(arg, cdp->name)) { 250 initio(cdp->tag); 251 print_banner(); 252 return; 253 } 254 } 255 printf("invalid console device.\n"); 256 } 257 void 258 command_modules(char *arg) 259 { 260 if (strcmp(arg, "enabled") == 0 || 261 strcmp(arg, "on") == 0) 262 boot_modules_enabled = true; 263 else if (strcmp(arg, "disabled") == 0 || 264 strcmp(arg, "off") == 0) 265 boot_modules_enabled = false; 266 else 267 printf("invalid flag, must be 'enabled' or 'disabled'.\n"); 268 } 269 270 void 271 command_multiboot(char *arg) 272 { 273 char *filename; 274 275 filename = arg; 276 if (exec_multiboot(filename, gettrailer(arg)) < 0) 277 printf("multiboot: %s: %s\n", filename, 278 strerror(errno)); 279 else 280 printf("boot returned\n"); 281 } 282