1 /* $NetBSD: main.c,v 1.5 2005/12/11 12:17:34 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Naoto Shimazaki. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY NAOTO SHIMAZAKI AND CONTRIBUTORS ``AS IS'' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE NAOTO OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Boot loader for L-Card+ 31 * 32 * ROM Map 33 * ------- 34 * ROM1 35 * BFFF FFFF ------------------------------ 36 * 37 * reserved 38 * 39 * BF80 0000 ------------------------------ 40 * 41 * ROM0 42 * BFFF FFFF ------------------------------ 43 * 44 * user storage (max 2Mbytes) 45 * 46 * BFE0 0000 ------------------------------ 47 * 48 * reserved 49 * 50 * BFD4 0000 ------------------------------ 51 * 52 * boot params 53 * 54 * BFD2 0000 ------------------------------ 55 * 56 * second boot loader (mirror image) 57 * or Linux Kernel 58 * 59 * BFD0 0000 ------------------------------ 60 * 61 * first boot loader (L-Card+ original loader) 62 * 63 * reset vector 64 * BFC0 0000 ------------------------------ 65 * 66 * gziped kernel image (max 4Mbytes) 67 * 68 * BF80 0000 ------------------------------ 69 * 70 * 71 * 72 * RAM Map 73 * ------- 74 * 75 * 80FF FFFF ------------------------------ 76 * ROM ICE work 77 * 80FF FE00 ------------------------------ 78 * ROM ICE stack 79 * 80FF FDA8 ------------------------------ 80 * 81 * 82 * 83 * kernel 84 * 8004 0000 ------------------------------ 85 * kernel stack (growing to lower) 86 * 87 * 88 * boot loader heap (growing to upper) 89 * boot loader text & data (at exec time) 90 * 8000 1000 ------------------------------ 91 * vector table 92 * 8000 0000 ------------------------------ 93 * 94 * virtual memory space 95 * 96 * 0000 0000 ------------------------------ 97 * 98 * 99 * 100 * ROMCS0 <-> ROMCS3 mapping 101 * 102 * ROMCS0 ROMCS3 103 * BE7F FFFF <-> BFFF FFFF 104 * BE40 0000 <-> BFC0 0000 reset vector 105 * BE00 0000 <-> BF80 0000 106 * 107 * 108 */ 109 #include <sys/cdefs.h> 110 __KERNEL_RCSID(0, "$NetBSD: main.c,v 1.5 2005/12/11 12:17:34 christos Exp $"); 111 112 #include <lib/libsa/stand.h> 113 114 #include <lib/libsa/loadfile.h> 115 #include <lib/libkern/libkern.h> 116 117 #include <hpcmips/vr/vripreg.h> 118 #include <hpcmips/vr/cmureg.h> 119 #include <hpcmips/vr/vr4181giureg.h> 120 121 #include "extern.h" 122 #include "i28f128reg.h" 123 124 /* XXX */ 125 #define ISABRGCTL 0x00 126 #define ISABRGSTS 0x02 127 #define XISACTL 0x04 128 129 #define BOOTTIMEOUT 9 /* must less than 10 */ 130 #define LINEBUFLEN 80 131 132 extern const char bootprog_rev[]; 133 extern const char bootprog_name[]; 134 extern const char bootprog_date[]; 135 extern const char bootprog_maker[]; 136 137 static void command_help(char *opt); 138 static void command_dump(char *opt); 139 static void command_boot(char *opt); 140 static void command_load(char *opt); 141 static void command_fill(char *opt); 142 static void command_write(char *opt); 143 static void command_option(char *subcmd); 144 static void opt_subcmd_print(char *opt); 145 static void opt_subcmd_read(char *opt); 146 static void opt_subcmd_write(char *opt); 147 static void opt_subcmd_path(char *opt); 148 static void opt_subcmd_bootp(char *opt); 149 static void opt_subcmd_ip(char *opt); 150 151 152 struct boot_option bootopts; 153 154 static struct bootmenu_command commands[] = { 155 { "?", command_help }, 156 { "h", command_help }, 157 { "d", command_dump }, 158 { "b", command_boot }, 159 { "l", command_load }, 160 { "f", command_fill }, 161 { "w", command_write }, 162 { "o", command_option }, 163 { NULL, NULL }, 164 }; 165 166 static struct bootmenu_command opt_subcommands[] = { 167 { "p", opt_subcmd_print }, 168 { "r", opt_subcmd_read }, 169 { "w", opt_subcmd_write }, 170 { "path", opt_subcmd_path }, 171 { "bootp", opt_subcmd_bootp }, 172 { "ip", opt_subcmd_ip }, 173 { NULL, NULL }, 174 }; 175 176 static void 177 print_banner(void) 178 { 179 printf("\n"); 180 printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev); 181 printf(">> (%s, %s)\n", bootprog_maker, bootprog_date); 182 #if 0 183 printf(">> Memory: %d/%d k\n", getbasemem(), getextmem()); 184 #endif 185 } 186 187 static void 188 init_devices(void) 189 { 190 /* Init RTC */ 191 REGWRITE_2(VRETIMEH, 0, 0); 192 REGWRITE_2(VRETIMEM, 0, 0); 193 REGWRITE_2(VRETIMEL, 0, 0); 194 195 196 /* 197 * CLKSPEEDREG 0x6012 198 * DIV DIV2 mode 199 * CLKSP 18 (0x12) 200 * PClock (CPU clock) 65.536MHz 201 * PClock = (18.432MHz / CLKSP) x 64 202 * = (18.432MHz / 18) x 64 203 * = 65.536MHz 204 * TClock (peripheral clock) 32.768MHz 205 * TClock = PClock / DIV 206 * = 65.536MHz / 2 207 * = 32.768MHz 208 */ 209 210 /* 211 * setup ISA BUS clock freqency 212 * 213 * set PCLK (internal peripheral clock) to 32.768MHz (TClock / 1) 214 * set External ISA bus clock to 10.922MHz (TClock / 3) 215 */ 216 REGWRITE_2(VR4181_ISABRG_ADDR, ISABRGCTL, 0x0003); 217 REGWRITE_2(VR4181_ISABRG_ADDR, XISACTL, 0x0401); 218 219 /* 220 * setup peripheral's clock supply 221 * 222 * CSU: disable 223 * AIU: enable (AIU, ADU, ADU18M) 224 * PIU: disable 225 * SIU: enable (SIU18M) 226 */ 227 REGWRITE_2(VR4181_CMU_ADDR, 0, CMUMASK_SIU | CMUMASK_AIU); 228 229 /* 230 * setup GPIO 231 */ 232 #if 0 233 /* L-Card+ generic setup */ 234 /* 235 * pin mode comment 236 * GP0 : GPI not used 237 * GP1 : GPI not used 238 * GP2 : GPO LED6 (0: on 1: off) 239 * GP3 : PCS0 chip select for CS8900A Lan controller 240 * GP4 : GPI IRQ input from CS8900A 241 * GP5 : GPI not used 242 * GP6 : GPI not used 243 * GP7 : GPI reserved by TANBAC TB0193 244 */ 245 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PIOD_L_REG_W, 0xffff); 246 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE0_REG_W, 247 GP3_PCS0 | GP2_GPO); 248 /* 249 * pin mode comment 250 * GP8 : GPO LED5 (0: on 1: off) 251 * GP9 : GPI CD2 252 * GP10: GPI CD1 253 * GP11: GPI not used 254 * GP12: GPI not used 255 * GP13: GPI not used 256 * GP14: GPI not used 257 * GP15: GPI not used 258 */ 259 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE1_REG_W, GP8_GPO); 260 /* 261 * pin mode comment 262 * GP16: IORD ISA bus 263 * GP17: IOWR ISA bus 264 * GP18: IORDY ISA bus 265 * GP19: GPI not used 266 * GP20: GPI not used 267 * GP21: RESET resets CS8900A 268 * GP22: ROMCS0 ROM chip select 269 * GP23: ROMCS1 ROM chip select 270 */ 271 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE2_REG_W, 272 GP23_ROMCS1 | GP22_ROMCS0 | GP21_RESET 273 | GP18_IORDY | GP17_IOWR | GP16_IORD); 274 /* 275 * GP24: ROMCS2 ROM chip select 276 * GP25: RxD1 SIU1 277 * GP26: TxD1 SIU1 278 * GP27: RTS1 SIU1 279 * GP28: CTS1 SIU1 280 * GP29: GPI LED3 281 * GP30: GPI reserved by TANBAC TB0193 282 * GP31: GPI LED4 283 */ 284 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE3_REG_W, 285 GP30_GPI 286 | GP28_CTS1 | GP27_RTS1 | GP26_TxD1 | GP25_RxD1 287 | GP24_ROMCS2); 288 #else 289 /* e-care node specific setup */ 290 /* 291 * pin mode comment 292 * GP0 : GPO ECNRTC_RST 293 * GP1 : GPO ECNRTC_CLK 294 * GP2 : GPO LED6 (0: on 1: off) 295 * GP3 : PCS0 chip select for CS8900A Lan controller 296 * GP4 : GPI IRQ input from CS8900A 297 * GP5 : GPO ECNRTC_DIR 298 * GP6 : GPO ECNRTC_OUT 299 * GP7 : GPI reserved by TANBAC TB0193 300 */ 301 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PIOD_L_REG_W, 0xffff); 302 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE0_REG_W, 303 GP6_GPO | GP5_GPO | GP3_PCS0 304 | GP2_GPO | GP1_GPO | GP0_GPO); 305 306 /* 307 * pin mode comment 308 * GP8 : GPO LED5 (0: on 1: off) 309 * GP9 : GPI CD2 310 * GP10: GPI CD1 311 * GP11: GPI not used 312 * GP12: GPI ECNRTC_IN 313 * GP13: GPI not used 314 * GP14: GPI not used 315 * GP15: GPI not used 316 */ 317 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE1_REG_W, 318 GP12_GPI | GP8_GPO); 319 320 /* 321 * pin mode comment 322 * GP16: IORD ISA bus 323 * GP17: IOWR ISA bus 324 * GP18: IORDY ISA bus 325 * GP19: GPI not used 326 * GP20: GPI not used 327 * GP21: RESET resets CS8900A 328 * GP22: ROMCS0 ROM chip select 329 * GP23: ROMCS1 ROM chip select 330 */ 331 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE2_REG_W, 332 GP23_ROMCS1 | GP22_ROMCS0 | GP21_RESET 333 | GP18_IORDY | GP17_IOWR | GP16_IORD); 334 /* 335 * GP24: ROMCS2 ROM chip select 336 * GP25: RxD1 SIU1 337 * GP26: TxD1 SIU1 338 * GP27: RTS1 SIU1 339 * GP28: CTS1 SIU1 340 * GP29: GPI LED3 341 * GP30: GPI reserved by TANBAC TB0193 342 * GP31: GPI LED4 343 */ 344 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_MODE3_REG_W, 345 GP30_GPI 346 | GP28_CTS1 | GP27_RTS1 | GP26_TxD1 | GP25_RxD1 347 | GP24_ROMCS2); 348 #endif 349 350 #if 0 351 /* 352 * setup interrupt 353 * 354 * I4TYP: falling edge trigger 355 * GIMSK4: unmask 356 * GIEN4: enable 357 * other: unused, mask, disable 358 */ 359 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTTYP_L_REG_W, 360 I4TYP_HIGH_LEVEL); 361 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTMASK_REG_W, 362 0xffffU & ~GIMSK4); 363 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_INTEN_REG_W, GIEN4); 364 #endif 365 366 /* 367 * programmable chip select 368 * 369 * PCS0 is used to select CS8900A Ethernet controller 370 * on TB0193 371 * 372 * PCS0: 373 * 0x14010000 - 0x14010fff 374 * I/O access, 16bit cycle, both of read/write 375 * PCS1: unused 376 */ 377 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0STRA_REG_W, 0x0000); 378 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0STPA_REG_W, 0x0fff); 379 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCS0HIA_REG_W, 0x1401); 380 REGWRITE_2(VR4181_GIU81_ADDR, VR4181GIU_PCSMODE_REG_W, 381 PCS0MIOB_IO | PCS0DSIZE_16BIT | PCS0MD_READWRITE); 382 } 383 384 /* 385 * chops the head from the arguments and returns the arguments if any, 386 * or possibly an empty string. 387 */ 388 static char * 389 get_next_arg(char *arg) 390 { 391 char *opt; 392 393 if ((opt = strchr(arg, ' ')) == NULL) { 394 opt = ""; 395 } else { 396 *opt++ = '\0'; 397 } 398 399 /* trim leading blanks */ 400 while (*opt == ' ') 401 opt++; 402 403 return opt; 404 } 405 406 static void 407 command_help(char *opt) 408 { 409 printf("commands are:\n" 410 "boot:\tb\n" 411 "dump:\td addr [addr]\n" 412 "fill:\tf addr addr char\n" 413 "load:\tl [offset] (with following S-Record)\n" 414 "write:\tw dst src len\n" 415 "option:\to subcommand [params]\n" 416 "help:\th|?\n" 417 "\n" 418 "option subcommands are:\n" 419 "print:\to p\n" 420 "read:\to r\n" 421 "write:\to w\n" 422 "path:\to path pathname\n" 423 "bootp:\to bootp yes|no\n" 424 "ip:\to ip remote local netmask gateway\n" 425 ); 426 } 427 428 static void 429 bad_param(void) 430 { 431 printf("bad param\n"); 432 command_help(NULL); 433 } 434 435 static const u_int8_t print_cnv[] = { 436 '0', '1', '2', '3', '4', '5', '6', '7', 437 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 438 439 static void 440 printhexul(u_int32_t n) 441 { 442 int i; 443 444 for (i = 28; i >= 0; i -= 4) 445 putchar(print_cnv[(n >> i) & 0x0f]); 446 } 447 448 static void 449 printhexuc(u_int8_t n) 450 { 451 int i; 452 453 for (i = 4; i >= 0; i -= 4) 454 putchar(print_cnv[(n >> i) & 0x0f]); 455 } 456 457 static void 458 command_dump(char *opt) 459 { 460 char *endptr; 461 const char *p; 462 const char *line_fence; 463 const char *limit; 464 465 p = (const char *) strtoul(opt, &endptr, 16); 466 if (opt == endptr) { 467 bad_param(); 468 return; 469 } 470 471 opt = get_next_arg(opt); 472 limit = (const char *) strtoul(opt, &endptr, 16); 473 if (opt == endptr) { 474 limit = p + 256; 475 } 476 477 for (;;) { 478 printhexul((u_int32_t) p); 479 putchar(' '); 480 line_fence = p + 16; 481 while (p < line_fence) { 482 printhexuc(*p++); 483 putchar(' '); 484 if (p >= limit) { 485 putchar('\n'); 486 return; 487 } 488 } 489 putchar('\n'); 490 if (ISKEY) { 491 if (getchar() == '\x03') 492 break; 493 } 494 } 495 } 496 497 static void 498 command_boot(char *opt) 499 { 500 u_long marks[MARK_MAX]; 501 502 marks[MARK_START] = 0; 503 if (loadfile(bootopts.b_pathname, marks, LOAD_KERNEL)) { 504 printf("loadfile failed\n"); 505 return; 506 } 507 start_netbsd(); 508 /* no return */ 509 } 510 511 /* 512 * loading S-Record 513 */ 514 static int 515 load_srec(char *offset) 516 { 517 char s2lbuf[9]; 518 char c; 519 char rectype; 520 u_int32_t reclen; 521 u_int32_t reclen_bk; 522 u_int32_t recaddr; 523 char *endptr; 524 char *p; 525 u_int32_t sum; 526 int err = 0; 527 528 for (;;) { 529 /* 530 * the first step is to read a S-Record. 531 */ 532 if ((c = getchar()) != 'S') 533 goto out; 534 535 rectype = getchar(); 536 537 s2lbuf[0] = getchar(); 538 s2lbuf[1] = getchar(); 539 s2lbuf[2] = '\0'; 540 reclen_bk = reclen = strtoul(s2lbuf, &endptr, 16); 541 if (endptr != &s2lbuf[2]) 542 goto out; 543 sum = reclen; 544 545 p = s2lbuf; 546 547 switch (rectype) { 548 case '0': 549 /* just ignore */ 550 do { 551 c = getchar(); 552 } while (c != '\r' && c != '\n'); 553 continue; 554 555 case '3': 556 *p++ = getchar(); 557 *p++ = getchar(); 558 reclen--; 559 /* FALLTHRU */ 560 case '2': 561 *p++ = getchar(); 562 *p++ = getchar(); 563 reclen--; 564 /* FALLTHRU */ 565 case '1': 566 *p++ = getchar(); 567 *p++ = getchar(); 568 *p++ = getchar(); 569 *p++ = getchar(); 570 *p = '\0'; 571 reclen -= 2; 572 573 recaddr = strtoul(s2lbuf, &endptr, 16); 574 if (endptr != p) 575 goto out; 576 sum += (recaddr >> 24) & 0xff; 577 sum += (recaddr >> 16) & 0xff; 578 sum += (recaddr >> 8) & 0xff; 579 sum += recaddr & 0xff; 580 581 p = offset + recaddr; 582 /* 583 * XXX 584 * address range is must be chaked here! 585 */ 586 reclen--; 587 s2lbuf[2] = '\0'; 588 while (reclen > 0) { 589 s2lbuf[0] = getchar(); 590 s2lbuf[1] = getchar(); 591 *p = (u_int8_t) strtoul(s2lbuf, &endptr, 16); 592 if (endptr != &s2lbuf[2]) 593 goto out; 594 sum += *p++; 595 reclen--; 596 } 597 break; 598 599 case '7': 600 case '8': 601 case '9': 602 goto out2; 603 604 default: 605 goto out; 606 } 607 608 s2lbuf[0] = getchar(); 609 s2lbuf[1] = getchar(); 610 s2lbuf[2] = '\0'; 611 sum += (strtoul(s2lbuf, &endptr, 16) & 0xff); 612 sum &= 0xff; 613 if (sum != 0xff) { 614 printf("checksum error\n"); 615 err = 1; 616 goto out2; 617 } 618 619 c = getchar(); 620 if (c != '\r' && c != '\n') 621 goto out; 622 } 623 /* never reach */ 624 return 1; 625 626 out: 627 printf("invalid S-Record\n"); 628 err = 1; 629 630 out2: 631 do { 632 c = getchar(); 633 } while (c != '\r' && c != '\n'); 634 635 return err; 636 } 637 638 static void 639 command_load(char *opt) 640 { 641 char *endptr; 642 char *offset; 643 644 offset = (char *) strtoul(opt, &endptr, 16); 645 if (opt == endptr) 646 offset = 0; 647 load_srec(offset); 648 } 649 650 static void 651 command_fill(char *opt) 652 { 653 char *endptr; 654 char *p; 655 char *limit; 656 int c; 657 658 p = (char *) strtoul(opt, &endptr, 16); 659 if (opt == endptr) { 660 bad_param(); 661 return; 662 } 663 664 opt = get_next_arg(opt); 665 limit = (char *) strtoul(opt, &endptr, 16); 666 if (opt == endptr) { 667 bad_param(); 668 return; 669 } 670 671 opt = get_next_arg(opt); 672 c = strtoul(opt, &endptr, 16); 673 if (opt == endptr) 674 c = '\0'; 675 676 memset(p, c, limit - p); 677 } 678 679 static void 680 check_write_verify_flash(u_int32_t src, u_int32_t dst, size_t len) 681 { 682 int status; 683 684 if ((dst & I28F128_BLOCK_MASK) != 0) { 685 printf("dst addr must be aligned to block boundary (0x%x)\n", 686 I28F128_BLOCK_SIZE); 687 return; 688 } 689 690 if (i28f128_probe((void *) dst)) { 691 printf("dst addr is not a intel 28F128\n"); 692 } else { 693 printf("intel 28F128 detected\n"); 694 } 695 696 if ((status = i28f128_region_write((void *) dst, (void *) src, len)) 697 != 0) { 698 printf("write mem to flash failed status = %x\n", status); 699 return; 700 } 701 702 printf("verifying..."); 703 if (memcmp((void *) dst, (void *) src, len)) { 704 printf("verify error\n"); 705 return; 706 } 707 printf("ok\n"); 708 709 printf("writing memory to flash succeeded\n"); 710 } 711 712 static void 713 command_write(char *opt) 714 { 715 char *endptr; 716 u_int32_t src; 717 u_int32_t dst; 718 size_t len; 719 720 dst = strtoul(opt, &endptr, 16); 721 if (opt == endptr) 722 goto out; 723 724 opt = get_next_arg(opt); 725 src = strtoul(opt, &endptr, 16); 726 if (opt == endptr) 727 goto out; 728 729 opt = get_next_arg(opt); 730 len = strtoul(opt, &endptr, 16); 731 if (opt == endptr) 732 goto out; 733 734 check_write_verify_flash(src, dst, len); 735 return; 736 737 out: 738 bad_param(); 739 return; 740 } 741 742 static void 743 command_option(char *subcmd) 744 { 745 char *opt; 746 int i; 747 748 opt = get_next_arg(subcmd); 749 750 /* dispatch subcommand */ 751 for (i = 0; opt_subcommands[i].c_name != NULL; i++) { 752 if (strcmp(subcmd, opt_subcommands[i].c_name) == 0) { 753 opt_subcommands[i].c_fn(opt); 754 break; 755 } 756 } 757 if (opt_subcommands[i].c_name == NULL) { 758 printf("unknown option subcommand\n"); 759 command_help(NULL); 760 } 761 } 762 763 static void 764 opt_subcmd_print(char *opt) 765 { 766 printf("boot options:\n" 767 "magic:\t\t%s\n" 768 "pathname:\t`%s'\n" 769 "bootp:\t\t%s\n", 770 bootopts.b_magic == BOOTOPT_MAGIC ? "ok" : "bad", 771 bootopts.b_pathname, 772 bootopts.b_flags & B_F_USE_BOOTP ? "yes" : "no"); 773 printf("remote IP:\t%s\n", inet_ntoa(bootopts.b_remote_ip)); 774 printf("local IP:\t%s\n", inet_ntoa(bootopts.b_local_ip)); 775 printf("netmask:\t%s\n", intoa(bootopts.b_netmask)); 776 printf("gateway IP:\t%s\n", inet_ntoa(bootopts.b_gate_ip)); 777 } 778 779 static void 780 opt_subcmd_read(char *opt) 781 { 782 bootopts = *((struct boot_option *) BOOTOPTS_BASE); 783 if (bootopts.b_magic != BOOTOPT_MAGIC) 784 bootopts.b_pathname[0] = '\0'; 785 } 786 787 static void 788 opt_subcmd_write(char *opt) 789 { 790 bootopts.b_magic = BOOTOPT_MAGIC; 791 792 check_write_verify_flash((u_int32_t) &bootopts, BOOTOPTS_BASE, 793 sizeof bootopts); 794 } 795 796 static void 797 opt_subcmd_path(char *opt) 798 { 799 strlcpy(bootopts.b_pathname, opt, sizeof bootopts.b_pathname); 800 } 801 802 static void 803 opt_subcmd_bootp(char *opt) 804 { 805 if (strcmp(opt, "yes") == 0) { 806 bootopts.b_flags |= B_F_USE_BOOTP; 807 } else if (strcmp(opt, "no") == 0) { 808 bootopts.b_flags &= ~B_F_USE_BOOTP; 809 } else { 810 bad_param(); 811 } 812 } 813 814 static void 815 opt_subcmd_ip(char *opt) 816 { 817 bootopts.b_remote_ip.s_addr = inet_addr(opt); 818 opt = get_next_arg(opt); 819 bootopts.b_local_ip.s_addr = inet_addr(opt); 820 opt = get_next_arg(opt); 821 bootopts.b_netmask = inet_addr(opt); 822 opt = get_next_arg(opt); 823 bootopts.b_gate_ip.s_addr = inet_addr(opt); 824 } 825 826 static void 827 bootmenu(void) 828 { 829 char input[LINEBUFLEN]; 830 char *cmd; 831 char *opt; 832 int i; 833 834 for (;;) { 835 836 /* input a line */ 837 input[0] = '\0'; 838 printf("> "); 839 gets(input); 840 cmd = input; 841 842 /* skip leading whitespace. */ 843 while(*cmd == ' ') 844 cmd++; 845 846 if(*cmd) { 847 /* here, some command entered */ 848 849 opt = get_next_arg(cmd); 850 851 /* dispatch command */ 852 for (i = 0; commands[i].c_name != NULL; i++) { 853 if (strcmp(cmd, commands[i].c_name) == 0) { 854 commands[i].c_fn(opt); 855 break; 856 } 857 } 858 if (commands[i].c_name == NULL) { 859 printf("unknown command\n"); 860 command_help(NULL); 861 } 862 } 863 864 } 865 } 866 867 static char 868 awaitkey(void) 869 { 870 int i; 871 int j; 872 char c = 0; 873 874 while (ISKEY) 875 getchar(); 876 877 for (i = BOOTTIMEOUT; i > 0; i--) { 878 printf("%d\b", i); 879 for (j = 0; j < 1000000; j++) { 880 if (ISKEY) { 881 while (ISKEY) 882 c = getchar(); 883 goto out; 884 } 885 } 886 } 887 888 out: 889 printf("0\n"); 890 return(c); 891 } 892 893 __dead void 894 _rtt(void) 895 { 896 for (;;) 897 ; 898 } 899 900 int 901 main(void) 902 { 903 char c; 904 905 init_devices(); 906 907 comcninit(); 908 909 opt_subcmd_read(NULL); 910 911 print_banner(); 912 913 c = awaitkey(); 914 if (c != '\r' && c != '\n' && c != '\0') { 915 printf("type \"?\" or \"h\" for help.\n"); 916 bootmenu(); /* does not return */ 917 } 918 919 command_boot(NULL); 920 /* 921 * command_boot() returns only if it failed to boot. 922 * we enter to boot menu in this case. 923 */ 924 bootmenu(); 925 926 return 0; 927 } 928