1 1.34 andvar /* $NetBSD: main.c,v 1.34 2024/09/11 20:15:36 andvar Exp $ */ 2 1.1 perry 3 1.1 perry /* 4 1.1 perry * Copyright (c) 1996, 1997 5 1.1 perry * Matthias Drochner. All rights reserved. 6 1.1 perry * Copyright (c) 1996, 1997 7 1.1 perry * Perry E. Metzger. All rights reserved. 8 1.1 perry * 9 1.1 perry * Redistribution and use in source and binary forms, with or without 10 1.1 perry * modification, are permitted provided that the following conditions 11 1.1 perry * are met: 12 1.1 perry * 1. Redistributions of source code must retain the above copyright 13 1.1 perry * notice, this list of conditions and the following disclaimer. 14 1.1 perry * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 perry * notice, this list of conditions and the following disclaimer in the 16 1.1 perry * documentation and/or other materials provided with the distribution. 17 1.1 perry * 3. All advertising materials mentioning features or use of this software 18 1.1 perry * must display the following acknowledgements: 19 1.1 perry * This product includes software developed for the NetBSD Project 20 1.1 perry * by Matthias Drochner. 21 1.1 perry * This product includes software developed for the NetBSD Project 22 1.1 perry * by Perry E. Metzger. 23 1.1 perry * 4. The names of the authors may not be used to endorse or promote products 24 1.1 perry * derived from this software without specific prior written permission. 25 1.1 perry * 26 1.1 perry * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 1.1 perry * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 1.1 perry * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 1.1 perry * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 1.1 perry * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 1.1 perry * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 1.1 perry * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 1.1 perry * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 1.1 perry * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 1.1 perry * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 1.1 perry */ 37 1.1 perry 38 1.1 perry 39 1.1 perry #include <sys/reboot.h> 40 1.1 perry 41 1.1 perry #include <lib/libkern/libkern.h> 42 1.1 perry #include <lib/libsa/stand.h> 43 1.12 drochner #include <lib/libsa/ufs.h> 44 1.1 perry 45 1.1 perry #include <libi386.h> 46 1.1 perry 47 1.12 drochner int errno; 48 1.1 perry 49 1.23 perry extern char bootprog_name[], bootprog_rev[], bootprog_kernrev[]; 50 1.1 perry 51 1.1 perry #define MAXDEVNAME 16 52 1.1 perry 53 1.2 thorpej static char *current_fsmode; 54 1.2 thorpej static char *default_devname; 55 1.2 thorpej static int default_unit, default_partition; 56 1.2 thorpej static char *default_filename; 57 1.1 perry 58 1.21 dyoung char *sprint_bootsel(const char *); 59 1.21 dyoung static void bootit(const char *, int, int); 60 1.21 dyoung void usage(void); 61 1.21 dyoung int main(int, char **); 62 1.21 dyoung 63 1.21 dyoung void command_help(char *); 64 1.21 dyoung void command_ls(char *); 65 1.21 dyoung void command_quit(char *); 66 1.21 dyoung void command_boot(char *); 67 1.21 dyoung void command_mode(char *); 68 1.21 dyoung void command_dev(char *); 69 1.7 drochner 70 1.17 jdolecek const struct bootblk_command commands[] = { 71 1.7 drochner { "help", command_help }, 72 1.7 drochner { "?", command_help }, 73 1.7 drochner { "ls", command_ls }, 74 1.7 drochner { "quit", command_quit }, 75 1.7 drochner { "boot", command_boot }, 76 1.7 drochner { "mode", command_mode }, 77 1.9 drochner { "dev", command_dev }, 78 1.7 drochner { NULL, NULL }, 79 1.7 drochner }; 80 1.7 drochner 81 1.1 perry int 82 1.27 dsl parsebootfile(const char *fname, char **fsmode, char **devname, int *unit, int *partition, const char **file) 83 1.27 dsl /* fsmode: out */ 84 1.27 dsl /* devname: out */ 85 1.27 dsl /* unit, *partition: out */ 86 1.27 dsl /* file: out */ 87 1.2 thorpej { 88 1.2 thorpej const char *col, *help; 89 1.2 thorpej 90 1.2 thorpej *fsmode = current_fsmode; 91 1.2 thorpej *devname = default_devname; 92 1.2 thorpej *unit = default_unit; 93 1.2 thorpej *partition = default_partition; 94 1.2 thorpej *file = default_filename; 95 1.2 thorpej 96 1.7 drochner if (fname == NULL) 97 1.2 thorpej return (0); 98 1.2 thorpej 99 1.9 drochner if (strcmp(current_fsmode, "dos") && (col = strchr(fname, ':'))) { 100 1.9 drochner /* no DOS, device given */ 101 1.2 thorpej static char savedevname[MAXDEVNAME + 1]; 102 1.2 thorpej int devlen; 103 1.2 thorpej unsigned int u = 0, p = 0; 104 1.2 thorpej int i = 0; 105 1.2 thorpej 106 1.2 thorpej devlen = col - fname; 107 1.2 thorpej if (devlen > MAXDEVNAME) 108 1.2 thorpej return (EINVAL); 109 1.1 perry 110 1.1 perry #define isvalidname(c) ((c) >= 'a' && (c) <= 'z') 111 1.2 thorpej if (!isvalidname(fname[i])) 112 1.2 thorpej return (EINVAL); 113 1.2 thorpej do { 114 1.2 thorpej savedevname[i] = fname[i]; 115 1.2 thorpej i++; 116 1.2 thorpej } while (isvalidname(fname[i])); 117 1.2 thorpej savedevname[i] = '\0'; 118 1.1 perry 119 1.1 perry #define isnum(c) ((c) >= '0' && (c) <= '9') 120 1.2 thorpej if (i < devlen) { 121 1.2 thorpej if (!isnum(fname[i])) 122 1.2 thorpej return (EUNIT); 123 1.2 thorpej do { 124 1.2 thorpej u *= 10; 125 1.2 thorpej u += fname[i++] - '0'; 126 1.2 thorpej } while (isnum(fname[i])); 127 1.2 thorpej } 128 1.7 drochner 129 1.1 perry #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') 130 1.2 thorpej if (i < devlen) { 131 1.2 thorpej if (!isvalidpart(fname[i])) 132 1.2 thorpej return (EPART); 133 1.2 thorpej p = fname[i++] - 'a'; 134 1.2 thorpej } 135 1.2 thorpej if (i != devlen) 136 1.2 thorpej return (ENXIO); 137 1.2 thorpej 138 1.2 thorpej *devname = savedevname; 139 1.2 thorpej *unit = u; 140 1.2 thorpej *partition = p; 141 1.2 thorpej help = col + 1; 142 1.2 thorpej } else 143 1.2 thorpej help = fname; 144 1.1 perry 145 1.2 thorpej if (*help) 146 1.2 thorpej *file = help; 147 1.1 perry 148 1.2 thorpej return (0); 149 1.1 perry } 150 1.1 perry 151 1.12 drochner char * 152 1.26 dsl sprint_bootsel(const char *filename) 153 1.1 perry { 154 1.7 drochner char *fsname, *devname; 155 1.7 drochner int unit, partition; 156 1.7 drochner const char *file; 157 1.7 drochner static char buf[80]; 158 1.7 drochner 159 1.7 drochner if (parsebootfile(filename, &fsname, &devname, &unit, 160 1.7 drochner &partition, &file) == 0) { 161 1.2 thorpej if (!strcmp(fsname, "dos")) 162 1.32 christos snprintf(buf, sizeof(buf), "dos:%s", file); 163 1.2 thorpej else if (!strcmp(fsname, "ufs")) 164 1.32 christos snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit, 165 1.12 drochner 'a' + partition, file); 166 1.7 drochner else goto bad; 167 1.12 drochner return (buf); 168 1.2 thorpej } 169 1.7 drochner bad: 170 1.12 drochner return ("(invalid)"); 171 1.1 perry } 172 1.1 perry 173 1.1 perry static void 174 1.27 dsl bootit(const char *filename, int howto, int tell) 175 1.1 perry { 176 1.24 christos int floppy = strncmp(default_devname, "fd", 2) == 0; 177 1.7 drochner if (tell) { 178 1.7 drochner printf("booting %s", sprint_bootsel(filename)); 179 1.7 drochner if (howto) 180 1.7 drochner printf(" (howto 0x%x)", howto); 181 1.7 drochner printf("\n"); 182 1.7 drochner } 183 1.29 ad if (exec_netbsd(filename, 0, howto, floppy, NULL) < 0) 184 1.7 drochner printf("boot: %s: %s\n", sprint_bootsel(filename), 185 1.7 drochner strerror(errno)); 186 1.2 thorpej else 187 1.2 thorpej printf("boot returned\n"); 188 1.1 perry } 189 1.1 perry 190 1.1 perry static void 191 1.1 perry print_banner(void) 192 1.1 perry { 193 1.5 christos int extmem = getextmem(); 194 1.5 christos 195 1.25 christos clear_pc_screen(); 196 1.25 christos 197 1.23 perry printf("\n" 198 1.23 perry ">> %s, Revision %s (from NetBSD %s)\n" 199 1.34 andvar ">> Memory: %d/%d k\n", 200 1.23 perry bootprog_name, bootprog_rev, bootprog_kernrev, 201 1.34 andvar getbasemem(), extmem); 202 1.2 thorpej } 203 1.2 thorpej 204 1.2 thorpej void 205 1.28 cegger usage(void) 206 1.2 thorpej { 207 1.2 thorpej printf("dosboot [-u] [-c <commands>] [-i] [filename [-bootopts]]\n"); 208 1.2 thorpej } 209 1.2 thorpej 210 1.2 thorpej int 211 1.26 dsl main(int argc, char **argv) 212 1.2 thorpej { 213 1.2 thorpej int ch; 214 1.2 thorpej int interactive = 0; 215 1.2 thorpej int howto; 216 1.2 thorpej extern char *optarg; 217 1.2 thorpej extern int optind; 218 1.2 thorpej 219 1.14 martin #ifdef SUPPORT_SERIAL 220 1.14 martin initio(SUPPORT_SERIAL); 221 1.14 martin #else 222 1.7 drochner initio(CONSDEV_PC); 223 1.14 martin #endif 224 1.2 thorpej gateA20(); 225 1.2 thorpej 226 1.2 thorpej print_banner(); 227 1.2 thorpej 228 1.2 thorpej current_fsmode = "dos"; 229 1.2 thorpej default_devname = "hd"; 230 1.2 thorpej default_unit = 0; 231 1.2 thorpej default_partition = 0; 232 1.2 thorpej default_filename = "netbsd"; 233 1.2 thorpej 234 1.2 thorpej while ((ch = getopt(argc, argv, "c:iu")) != -1) { 235 1.2 thorpej switch (ch) { 236 1.2 thorpej case 'c': 237 1.2 thorpej docommand(optarg); 238 1.2 thorpej return (1); 239 1.2 thorpej break; 240 1.2 thorpej case 'i': 241 1.2 thorpej interactive = 1; 242 1.2 thorpej break; 243 1.2 thorpej case 'u': 244 1.2 thorpej current_fsmode = "ufs"; 245 1.2 thorpej break; 246 1.2 thorpej default: 247 1.2 thorpej usage(); 248 1.2 thorpej return (1); 249 1.2 thorpej } 250 1.2 thorpej } 251 1.2 thorpej 252 1.7 drochner if (interactive) { 253 1.8 drochner printf("type \"?\" or \"help\" for help.\n"); 254 1.2 thorpej bootmenu(); 255 1.7 drochner } 256 1.2 thorpej 257 1.2 thorpej argc -= optind; 258 1.2 thorpej argv += optind; 259 1.2 thorpej 260 1.2 thorpej if (argc > 2) { 261 1.2 thorpej usage(); 262 1.2 thorpej return (1); 263 1.2 thorpej } 264 1.2 thorpej howto = 0; 265 1.2 thorpej if (argc > 1 && !parseopts(argv[1], &howto)) 266 1.2 thorpej return (1); 267 1.1 perry 268 1.2 thorpej bootit((argc > 0 ? argv[0] : "netbsd"), howto, 1); 269 1.2 thorpej return (1); 270 1.7 drochner } 271 1.7 drochner 272 1.7 drochner /* ARGSUSED */ 273 1.7 drochner void 274 1.26 dsl command_help(char *arg) 275 1.7 drochner { 276 1.7 drochner printf("commands are:\n" 277 1.18 itojun "boot [xdNx:][filename] [-acdqsv]\n" 278 1.7 drochner " (ex. \"sd0a:netbsd.old -s\"\n" 279 1.7 drochner "ls [path]\n" 280 1.7 drochner "mode ufs|dos\n" 281 1.9 drochner "dev xd[N[x]]:\n" 282 1.7 drochner "help|?\n" 283 1.7 drochner "quit\n"); 284 1.7 drochner } 285 1.7 drochner 286 1.7 drochner void 287 1.26 dsl command_ls(char *arg) 288 1.7 drochner { 289 1.7 drochner char *help = default_filename; 290 1.7 drochner default_filename = "/"; 291 1.31 tsutsui ls(arg); 292 1.7 drochner default_filename = help; 293 1.7 drochner } 294 1.7 drochner 295 1.7 drochner /* ARGSUSED */ 296 1.7 drochner void 297 1.26 dsl command_quit(char *arg) 298 1.7 drochner { 299 1.7 drochner printf("Exiting... goodbye...\n"); 300 1.30 jakllsch _rtt(); 301 1.7 drochner } 302 1.7 drochner 303 1.7 drochner void 304 1.26 dsl command_boot(char *arg) 305 1.7 drochner { 306 1.7 drochner char *filename; 307 1.7 drochner int howto; 308 1.7 drochner 309 1.7 drochner if (parseboot(arg, &filename, &howto)) 310 1.7 drochner bootit(filename, howto, 1); 311 1.7 drochner } 312 1.7 drochner 313 1.7 drochner void 314 1.26 dsl command_mode(char *arg) 315 1.7 drochner { 316 1.7 drochner if (!strcmp("dos", arg)) 317 1.7 drochner current_fsmode = "dos"; 318 1.7 drochner else if (!strcmp("ufs", arg)) 319 1.7 drochner current_fsmode = "ufs"; 320 1.7 drochner else 321 1.7 drochner printf("invalid mode\n"); 322 1.9 drochner } 323 1.9 drochner 324 1.9 drochner void 325 1.26 dsl command_dev(char *arg) 326 1.9 drochner { 327 1.9 drochner static char savedevname[MAXDEVNAME + 1]; 328 1.9 drochner char *fsname, *devname; 329 1.9 drochner const char *file; /* dummy */ 330 1.9 drochner 331 1.9 drochner if (!strcmp(current_fsmode, "dos")) { 332 1.9 drochner printf("not available in DOS mode\n"); 333 1.9 drochner return; 334 1.9 drochner } 335 1.9 drochner 336 1.9 drochner if (*arg == '\0') { 337 1.9 drochner printf("%s%d%c:\n", default_devname, default_unit, 338 1.9 drochner 'a' + default_partition); 339 1.9 drochner return; 340 1.9 drochner } 341 1.9 drochner 342 1.9 drochner if (!strchr(arg, ':') || 343 1.9 drochner parsebootfile(arg, &fsname, &devname, &default_unit, 344 1.9 drochner &default_partition, &file)) { 345 1.9 drochner command_help(NULL); 346 1.9 drochner return; 347 1.9 drochner } 348 1.9 drochner 349 1.9 drochner /* put to own static storage */ 350 1.9 drochner strncpy(savedevname, devname, MAXDEVNAME + 1); 351 1.9 drochner default_devname = savedevname; 352 1.1 perry } 353