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