1 1.7 rin /* $NetBSD: boot2.c,v 1.7 2022/04/30 03:37:09 rin Exp $ */ 2 1.1 uwe 3 1.1 uwe /* 4 1.1 uwe * Copyright (c) 2003 5 1.1 uwe * David Laight. All rights reserved 6 1.1 uwe * Copyright (c) 1996, 1997, 1999 7 1.1 uwe * Matthias Drochner. All rights reserved. 8 1.1 uwe * Copyright (c) 1996, 1997 9 1.1 uwe * Perry E. Metzger. All rights reserved. 10 1.1 uwe * Copyright (c) 1997 11 1.1 uwe * Jason R. Thorpe. All rights reserved 12 1.1 uwe * 13 1.1 uwe * Redistribution and use in source and binary forms, with or without 14 1.1 uwe * modification, are permitted provided that the following conditions 15 1.1 uwe * are met: 16 1.1 uwe * 1. Redistributions of source code must retain the above copyright 17 1.1 uwe * notice, this list of conditions and the following disclaimer. 18 1.1 uwe * 2. Redistributions in binary form must reproduce the above copyright 19 1.1 uwe * notice, this list of conditions and the following disclaimer in the 20 1.1 uwe * documentation and/or other materials provided with the distribution. 21 1.1 uwe * 3. All advertising materials mentioning features or use of this software 22 1.1 uwe * must display the following acknowledgements: 23 1.1 uwe * This product includes software developed for the NetBSD Project 24 1.1 uwe * by Matthias Drochner. 25 1.1 uwe * This product includes software developed for the NetBSD Project 26 1.1 uwe * by Perry E. Metzger. 27 1.1 uwe * 4. The names of the authors may not be used to endorse or promote products 28 1.1 uwe * derived from this software without specific prior written permission. 29 1.1 uwe * 30 1.1 uwe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 1.1 uwe * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 1.1 uwe * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 1.1 uwe * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 1.1 uwe * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 1.1 uwe * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 1.1 uwe * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 1.1 uwe * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 1.1 uwe * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 1.1 uwe * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 1.1 uwe */ 41 1.1 uwe 42 1.1 uwe /* Based on stand/biosboot/main.c */ 43 1.1 uwe 44 1.1 uwe #include <sys/types.h> 45 1.1 uwe #include <sys/reboot.h> 46 1.1 uwe #include <sys/bootblock.h> 47 1.1 uwe #include <sys/boot_flag.h> 48 1.1 uwe 49 1.1 uwe #include <lib/libsa/stand.h> 50 1.1 uwe #include <lib/libsa/loadfile.h> 51 1.1 uwe #include <lib/libsa/ufs.h> 52 1.1 uwe #include <lib/libkern/libkern.h> 53 1.1 uwe 54 1.1 uwe #include "biosdisk.h" 55 1.1 uwe 56 1.1 uwe #include "boot.h" 57 1.1 uwe #include "bootinfo.h" 58 1.1 uwe #include "cons.h" 59 1.1 uwe 60 1.1 uwe int errno; 61 1.1 uwe 62 1.1 uwe extern struct landisk_boot_params boot_params; 63 1.1 uwe 64 1.1 uwe static const char * const names[][2] = { 65 1.1 uwe { "netbsd", "netbsd.gz" }, 66 1.1 uwe { "netbsd.old", "netbsd.old.gz", }, 67 1.1 uwe { "onetbsd", "onetbsd.gz" }, 68 1.1 uwe }; 69 1.1 uwe 70 1.1 uwe #define NUMNAMES (sizeof(names) / sizeof(names[0])) 71 1.1 uwe #define DEFFILENAME names[0][0] 72 1.1 uwe 73 1.1 uwe #define MAXDEVNAME 16 74 1.1 uwe 75 1.1 uwe static char *default_devname; 76 1.1 uwe static uint default_unit, default_partition; 77 1.1 uwe static const char *default_filename; 78 1.1 uwe 79 1.1 uwe char *sprint_bootsel(const char *filename); 80 1.1 uwe void bootit(const char *filename, int howto, int tell); 81 1.1 uwe void print_banner(void); 82 1.1 uwe void boot2(uint32_t boot_biossector); 83 1.1 uwe 84 1.1 uwe int exec_netbsd(const char *file, int howto); 85 1.1 uwe 86 1.1 uwe static char *gettrailer(char *arg); 87 1.1 uwe static int parseopts(const char *opts, int *howto); 88 1.1 uwe static int parseboot(char *arg, char **filename, int *howto); 89 1.1 uwe 90 1.1 uwe void bootmenu(void); 91 1.1 uwe static void bootcmd_help(char *); 92 1.1 uwe static void bootcmd_ls(char *); 93 1.1 uwe static void bootcmd_quit(char *); 94 1.1 uwe static void bootcmd_halt(char *); 95 1.1 uwe static void bootcmd_boot(char *); 96 1.1 uwe static void bootcmd_monitor(char *); 97 1.1 uwe 98 1.1 uwe static const struct bootblk_command { 99 1.1 uwe const char *c_name; 100 1.1 uwe void (*c_fn)(char *arg); 101 1.1 uwe } bootcmds[] = { 102 1.1 uwe { "help", bootcmd_help }, 103 1.1 uwe { "?", bootcmd_help }, 104 1.1 uwe { "ls", bootcmd_ls }, 105 1.1 uwe { "quit", bootcmd_quit }, 106 1.1 uwe { "halt", bootcmd_halt }, 107 1.1 uwe { "boot", bootcmd_boot }, 108 1.1 uwe { "!", bootcmd_monitor }, 109 1.1 uwe { NULL, NULL }, 110 1.1 uwe }; 111 1.1 uwe 112 1.1 uwe int 113 1.1 uwe parsebootfile(const char *fname, char **devname, 114 1.1 uwe uint *unit, uint *partition, const char **file) 115 1.1 uwe { 116 1.1 uwe const char *col; 117 1.1 uwe 118 1.1 uwe *devname = default_devname; 119 1.1 uwe *unit = default_unit; 120 1.1 uwe *partition = default_partition; 121 1.1 uwe *file = default_filename; 122 1.1 uwe 123 1.1 uwe if (fname == NULL) 124 1.1 uwe return (0); 125 1.1 uwe 126 1.1 uwe if((col = strchr(fname, ':'))) { /* device given */ 127 1.1 uwe static char savedevname[MAXDEVNAME+1]; 128 1.1 uwe int devlen; 129 1.1 uwe unsigned int u = 0, p = 0; 130 1.1 uwe int i = 0; 131 1.1 uwe 132 1.1 uwe devlen = col - fname; 133 1.1 uwe if (devlen > MAXDEVNAME) 134 1.1 uwe return (EINVAL); 135 1.1 uwe 136 1.1 uwe #define isvalidname(c) ((c) >= 'a' && (c) <= 'z') 137 1.1 uwe if (!isvalidname(fname[i])) 138 1.1 uwe return (EINVAL); 139 1.1 uwe do { 140 1.1 uwe savedevname[i] = fname[i]; 141 1.1 uwe i++; 142 1.1 uwe } while (isvalidname(fname[i])); 143 1.1 uwe savedevname[i] = '\0'; 144 1.1 uwe 145 1.1 uwe #define isnum(c) ((c) >= '0' && (c) <= '9') 146 1.1 uwe if (i < devlen) { 147 1.1 uwe if (!isnum(fname[i])) 148 1.1 uwe return (EUNIT); 149 1.1 uwe do { 150 1.1 uwe u *= 10; 151 1.1 uwe u += fname[i++] - '0'; 152 1.1 uwe } while (isnum(fname[i])); 153 1.1 uwe } 154 1.1 uwe 155 1.1 uwe #define isvalidpart(c) ((c) >= 'a' && (c) <= 'p') 156 1.1 uwe if (i < devlen) { 157 1.1 uwe if (!isvalidpart(fname[i])) 158 1.1 uwe return (EPART); 159 1.1 uwe p = fname[i++] - 'a'; 160 1.1 uwe } 161 1.1 uwe 162 1.1 uwe if (i != devlen) 163 1.1 uwe return (ENXIO); 164 1.1 uwe 165 1.1 uwe *devname = savedevname; 166 1.1 uwe *unit = u; 167 1.1 uwe *partition = p; 168 1.1 uwe fname = col + 1; 169 1.1 uwe } 170 1.1 uwe 171 1.1 uwe if (*fname) 172 1.1 uwe *file = fname; 173 1.1 uwe 174 1.1 uwe return (0); 175 1.1 uwe } 176 1.1 uwe 177 1.1 uwe char * 178 1.1 uwe sprint_bootsel(const char *filename) 179 1.1 uwe { 180 1.1 uwe static char buf[80]; 181 1.1 uwe char *devname; 182 1.1 uwe uint unit, partition; 183 1.1 uwe const char *file; 184 1.1 uwe 185 1.1 uwe if (parsebootfile(filename, &devname, &unit, &partition, &file) == 0) { 186 1.4 christos snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit, 187 1.4 christos 'a' + partition, file); 188 1.1 uwe return (buf); 189 1.1 uwe } 190 1.1 uwe return ("(invalid)"); 191 1.1 uwe } 192 1.1 uwe 193 1.1 uwe void 194 1.1 uwe bootit(const char *filename, int howto, int tell) 195 1.1 uwe { 196 1.1 uwe 197 1.1 uwe if (tell) { 198 1.1 uwe printf("booting %s", sprint_bootsel(filename)); 199 1.1 uwe if (howto) 200 1.1 uwe printf(" (howto 0x%x)", howto); 201 1.1 uwe printf("\n"); 202 1.1 uwe } 203 1.1 uwe 204 1.1 uwe if (exec_netbsd(filename, howto) < 0) { 205 1.1 uwe printf("boot: %s: %s\n", sprint_bootsel(filename), 206 1.1 uwe strerror(errno)); 207 1.1 uwe } else { 208 1.1 uwe printf("boot returned\n"); 209 1.1 uwe } 210 1.1 uwe } 211 1.1 uwe 212 1.1 uwe void 213 1.1 uwe print_banner(void) 214 1.1 uwe { 215 1.1 uwe extern const char bootprog_name[]; 216 1.1 uwe extern const char bootprog_rev[]; 217 1.1 uwe 218 1.1 uwe printf("\n"); 219 1.1 uwe printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 220 1.1 uwe } 221 1.1 uwe 222 1.1 uwe void 223 1.1 uwe boot2(uint32_t boot_biossector) 224 1.1 uwe { 225 1.1 uwe int currname; 226 1.1 uwe int c; 227 1.1 uwe 228 1.1 uwe /* Initialize hardware */ 229 1.1 uwe tick_init(); 230 1.1 uwe 231 1.1 uwe /* Initialize console */ 232 1.1 uwe cninit(boot_params.bp_consdev); 233 1.1 uwe 234 1.1 uwe print_banner(); 235 1.1 uwe 236 1.1 uwe /* try to set default device to what BIOS tells us */ 237 1.1 uwe bios2dev(0x40, &default_devname, &default_unit, 238 1.1 uwe boot_biossector, &default_partition); 239 1.1 uwe 240 1.1 uwe /* if the user types "boot" without filename */ 241 1.1 uwe default_filename = DEFFILENAME; 242 1.1 uwe 243 1.1 uwe printf("Press return to boot now, any other key for boot menu\n"); 244 1.1 uwe currname = 0; 245 1.1 uwe for (;;) { 246 1.1 uwe printf("booting %s - starting in ", 247 1.1 uwe sprint_bootsel(names[currname][0])); 248 1.1 uwe 249 1.1 uwe c = awaitkey(boot_params.bp_timeout, 1); 250 1.1 uwe if ((c != '\r') && (c != '\n') && (c != '\0')) { 251 1.1 uwe printf("type \"?\" or \"help\" for help.\n"); 252 1.1 uwe bootmenu(); /* does not return */ 253 1.1 uwe } 254 1.1 uwe 255 1.1 uwe /* 256 1.1 uwe * try pairs of names[] entries, foo and foo.gz 257 1.1 uwe */ 258 1.1 uwe /* don't print "booting..." again */ 259 1.1 uwe bootit(names[currname][0], 0, 0); 260 1.1 uwe /* since it failed, try compressed bootfile. */ 261 1.1 uwe bootit(names[currname][1], 0, 1); 262 1.1 uwe /* since it failed, try switching bootfile. */ 263 1.1 uwe currname = (currname + 1) % NUMNAMES; 264 1.1 uwe } 265 1.1 uwe } 266 1.1 uwe 267 1.1 uwe int 268 1.1 uwe exec_netbsd(const char *file, int howto) 269 1.1 uwe { 270 1.1 uwe static char bibuf[BOOTINFO_MAXSIZE]; 271 1.1 uwe u_long marks[MARK_MAX]; 272 1.1 uwe int fd; 273 1.1 uwe 274 1.1 uwe BI_ALLOC(6); /* XXX */ 275 1.1 uwe 276 1.1 uwe marks[MARK_START] = 0; /* loadaddr */ 277 1.1 uwe if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1) 278 1.1 uwe goto out; 279 1.1 uwe 280 1.1 uwe printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], 281 1.1 uwe marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); 282 1.1 uwe 283 1.1 uwe { 284 1.1 uwe struct btinfo_common *help; 285 1.1 uwe char *p; 286 1.1 uwe int i; 287 1.1 uwe 288 1.1 uwe p = bibuf; 289 1.1 uwe memcpy(p, &bootinfo->nentries, sizeof(bootinfo->nentries)); 290 1.1 uwe p += sizeof(bootinfo->nentries); 291 1.1 uwe for (i = 0; i < bootinfo->nentries; i++) { 292 1.1 uwe help = (struct btinfo_common *)(bootinfo->entry[i]); 293 1.1 uwe memcpy(p, help, help->len); 294 1.1 uwe p += help->len; 295 1.1 uwe } 296 1.1 uwe } 297 1.1 uwe 298 1.1 uwe cache_flush(); 299 1.1 uwe cache_disable(); 300 1.1 uwe 301 1.1 uwe (*(void (*)(int, void *))marks[MARK_ENTRY])(howto, bibuf); 302 1.1 uwe panic("exec returned"); 303 1.1 uwe 304 1.1 uwe out: 305 1.1 uwe BI_FREE(); 306 1.1 uwe bootinfo = 0; 307 1.1 uwe return (-1); 308 1.1 uwe } 309 1.1 uwe 310 1.1 uwe /* 311 1.1 uwe * boot menu 312 1.1 uwe */ 313 1.1 uwe /* ARGSUSED */ 314 1.1 uwe static void 315 1.1 uwe bootcmd_help(char *arg) 316 1.1 uwe { 317 1.1 uwe 318 1.1 uwe printf("commands are:\n" 319 1.1 uwe "boot [xdNx:][filename] [-acdqsv]\n" 320 1.1 uwe " (ex. \"hd0a:netbsd.old -s\"\n" 321 1.1 uwe "ls [path]\n" 322 1.1 uwe "help|?\n" 323 1.1 uwe "halt\n" 324 1.1 uwe "quit\n"); 325 1.1 uwe } 326 1.1 uwe 327 1.1 uwe static void 328 1.1 uwe bootcmd_ls(char *arg) 329 1.1 uwe { 330 1.1 uwe const char *save = default_filename; 331 1.1 uwe 332 1.1 uwe default_filename = "/"; 333 1.3 tsutsui ls(arg); 334 1.1 uwe default_filename = save; 335 1.1 uwe } 336 1.1 uwe 337 1.1 uwe /* ARGSUSED */ 338 1.1 uwe static void 339 1.1 uwe bootcmd_quit(char *arg) 340 1.1 uwe { 341 1.1 uwe 342 1.1 uwe printf("Exiting...\n"); 343 1.1 uwe delay(1000); 344 1.1 uwe reboot(); 345 1.1 uwe /* Note: we shouldn't get to this point! */ 346 1.1 uwe panic("Could not reboot!"); 347 1.1 uwe exit(0); 348 1.1 uwe } 349 1.1 uwe 350 1.1 uwe /* ARGSUSED */ 351 1.1 uwe static void 352 1.1 uwe bootcmd_halt(char *arg) 353 1.1 uwe { 354 1.1 uwe 355 1.1 uwe printf("Exiting...\n"); 356 1.1 uwe delay(1000); 357 1.1 uwe halt(); 358 1.1 uwe /* Note: we shouldn't get to this point! */ 359 1.1 uwe panic("Could not halt!"); 360 1.1 uwe exit(0); 361 1.1 uwe } 362 1.1 uwe 363 1.1 uwe static void 364 1.1 uwe bootcmd_boot(char *arg) 365 1.1 uwe { 366 1.1 uwe char *filename; 367 1.1 uwe int howto; 368 1.1 uwe 369 1.1 uwe if (parseboot(arg, &filename, &howto)) { 370 1.1 uwe bootit(filename, howto, 1); 371 1.1 uwe } 372 1.1 uwe } 373 1.1 uwe 374 1.1 uwe /* ARGSUSED */ 375 1.1 uwe static void 376 1.1 uwe bootcmd_monitor(char *arg) 377 1.1 uwe { 378 1.1 uwe 379 1.1 uwe db_monitor(); 380 1.1 uwe printf("\n"); 381 1.1 uwe } 382 1.1 uwe 383 1.1 uwe static void 384 1.1 uwe docommand(const struct bootblk_command * const cmds, char *arg) 385 1.1 uwe { 386 1.1 uwe char *options; 387 1.1 uwe int i; 388 1.1 uwe 389 1.1 uwe options = gettrailer(arg); 390 1.1 uwe 391 1.1 uwe for (i = 0; cmds[i].c_name != NULL; i++) { 392 1.1 uwe if (strcmp(arg, cmds[i].c_name) == 0) { 393 1.1 uwe (*cmds[i].c_fn)(options); 394 1.1 uwe return; 395 1.1 uwe } 396 1.1 uwe } 397 1.1 uwe 398 1.1 uwe printf("unknown command\n"); 399 1.1 uwe bootcmd_help(NULL); 400 1.1 uwe } 401 1.1 uwe 402 1.1 uwe void 403 1.1 uwe bootmenu(void) 404 1.1 uwe { 405 1.1 uwe char input[256]; 406 1.1 uwe char *c; 407 1.1 uwe 408 1.1 uwe for (;;) { 409 1.1 uwe c = input; 410 1.1 uwe 411 1.1 uwe input[0] = '\0'; 412 1.1 uwe printf("> "); 413 1.6 dholland kgets(input, sizeof(input)); 414 1.1 uwe 415 1.1 uwe /* 416 1.1 uwe * Skip leading whitespace. 417 1.1 uwe */ 418 1.1 uwe while (*c == ' ') { 419 1.1 uwe c++; 420 1.1 uwe } 421 1.1 uwe if (*c != '\0') { 422 1.1 uwe docommand(bootcmds, c); 423 1.1 uwe } 424 1.1 uwe } 425 1.1 uwe } 426 1.1 uwe 427 1.1 uwe /* 428 1.1 uwe * from arch/i386/stand/lib/parseutil.c 429 1.1 uwe */ 430 1.1 uwe /* 431 1.1 uwe * chops the head from the arguments and returns the arguments if any, 432 1.1 uwe * or possibly an empty string. 433 1.1 uwe */ 434 1.1 uwe static char * 435 1.1 uwe gettrailer(char *arg) 436 1.1 uwe { 437 1.1 uwe char *options; 438 1.1 uwe 439 1.1 uwe if ((options = strchr(arg, ' ')) == NULL) 440 1.1 uwe return (""); 441 1.1 uwe else 442 1.1 uwe *options++ = '\0'; 443 1.1 uwe 444 1.1 uwe /* trim leading blanks */ 445 1.5 dholland while (*options == ' ') 446 1.1 uwe options++; 447 1.1 uwe 448 1.1 uwe return (options); 449 1.1 uwe } 450 1.1 uwe 451 1.1 uwe static int 452 1.1 uwe parseopts(const char *opts, int *howto) 453 1.1 uwe { 454 1.1 uwe int r, tmpopt = 0; 455 1.1 uwe 456 1.1 uwe opts++; /* skip - */ 457 1.1 uwe while (*opts && *opts != ' ') { 458 1.1 uwe r = 0; 459 1.1 uwe BOOT_FLAG(*opts, r); 460 1.1 uwe if (r == 0) { 461 1.1 uwe printf("-%c: unknown flag\n", *opts); 462 1.1 uwe bootcmd_help(NULL); 463 1.1 uwe return (0); 464 1.1 uwe } 465 1.1 uwe tmpopt |= r; 466 1.1 uwe opts++; 467 1.1 uwe } 468 1.1 uwe 469 1.1 uwe *howto = tmpopt; 470 1.1 uwe return (1); 471 1.1 uwe } 472 1.1 uwe 473 1.1 uwe static int 474 1.1 uwe parseboot(char *arg, char **filename, int *howto) 475 1.1 uwe { 476 1.1 uwe char *opts = NULL; 477 1.1 uwe 478 1.1 uwe *filename = 0; 479 1.1 uwe *howto = 0; 480 1.1 uwe 481 1.1 uwe /* if there were no arguments */ 482 1.7 rin if (*arg == '\0') 483 1.1 uwe return (1); 484 1.1 uwe 485 1.1 uwe /* format is... */ 486 1.1 uwe /* [[xxNx:]filename] [-adqsv] */ 487 1.1 uwe 488 1.1 uwe /* check for just args */ 489 1.1 uwe if (arg[0] == '-') { 490 1.1 uwe opts = arg; 491 1.1 uwe } else { 492 1.1 uwe /* there's a file name */ 493 1.1 uwe *filename = arg; 494 1.1 uwe 495 1.1 uwe opts = gettrailer(arg); 496 1.7 rin if (*opts == '\0') { 497 1.1 uwe opts = NULL; 498 1.1 uwe } else if (*opts != '-') { 499 1.1 uwe printf("invalid arguments\n"); 500 1.1 uwe bootcmd_help(NULL); 501 1.1 uwe return (0); 502 1.1 uwe } 503 1.1 uwe } 504 1.1 uwe 505 1.1 uwe /* at this point, we have dealt with filenames. */ 506 1.1 uwe 507 1.1 uwe /* now, deal with options */ 508 1.1 uwe if (opts) { 509 1.1 uwe if (parseopts(opts, howto) == 0) { 510 1.1 uwe return (0); 511 1.1 uwe } 512 1.1 uwe } 513 1.1 uwe return (1); 514 1.1 uwe } 515 1.1 uwe 516 1.1 uwe /* 517 1.1 uwe * for common/lib/libc/arch/sh3/gen/udivsi3.S 518 1.1 uwe */ 519 1.1 uwe int raise(int sig); 520 1.1 uwe 521 1.1 uwe /*ARGSUSED*/ 522 1.1 uwe int 523 1.1 uwe raise(int sig) 524 1.1 uwe { 525 1.1 uwe 526 1.1 uwe return 0; 527 1.1 uwe } 528