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