1 /* 2 * (C) Copyright 2000 3 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <stdarg.h> 26 #include <malloc.h> 27 #include <serial.h> 28 #include <stdio_dev.h> 29 #include <exports.h> 30 #include <environment.h> 31 32 DECLARE_GLOBAL_DATA_PTR; 33 34 static int on_console(const char *name, const char *value, enum env_op op, 35 int flags) 36 { 37 int console = -1; 38 39 /* Check for console redirection */ 40 if (strcmp(name, "stdin") == 0) 41 console = stdin; 42 else if (strcmp(name, "stdout") == 0) 43 console = stdout; 44 else if (strcmp(name, "stderr") == 0) 45 console = stderr; 46 47 /* if not actually setting a console variable, we don't care */ 48 if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0) 49 return 0; 50 51 switch (op) { 52 case env_op_create: 53 case env_op_overwrite: 54 55 #ifdef CONFIG_CONSOLE_MUX 56 if (iomux_doenv(console, value)) 57 return 1; 58 #else 59 /* Try assigning specified device */ 60 if (console_assign(console, value) < 0) 61 return 1; 62 #endif /* CONFIG_CONSOLE_MUX */ 63 return 0; 64 65 case env_op_delete: 66 if ((flags & H_FORCE) == 0) 67 printf("Can't delete \"%s\"\n", name); 68 return 1; 69 70 default: 71 return 0; 72 } 73 } 74 U_BOOT_ENV_CALLBACK(console, on_console); 75 76 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV 77 /* 78 * if overwrite_console returns 1, the stdin, stderr and stdout 79 * are switched to the serial port, else the settings in the 80 * environment are used 81 */ 82 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE 83 extern int overwrite_console(void); 84 #define OVERWRITE_CONSOLE overwrite_console() 85 #else 86 #define OVERWRITE_CONSOLE 0 87 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */ 88 89 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 90 91 static int console_setfile(int file, struct stdio_dev * dev) 92 { 93 int error = 0; 94 95 if (dev == NULL) 96 return -1; 97 98 switch (file) { 99 case stdin: 100 case stdout: 101 case stderr: 102 /* Start new device */ 103 if (dev->start) { 104 error = dev->start(); 105 /* If it's not started dont use it */ 106 if (error < 0) 107 break; 108 } 109 110 /* Assign the new device (leaving the existing one started) */ 111 stdio_devices[file] = dev; 112 113 /* 114 * Update monitor functions 115 * (to use the console stuff by other applications) 116 */ 117 switch (file) { 118 case stdin: 119 gd->jt[XF_getc] = dev->getc; 120 gd->jt[XF_tstc] = dev->tstc; 121 break; 122 case stdout: 123 gd->jt[XF_putc] = dev->putc; 124 gd->jt[XF_puts] = dev->puts; 125 gd->jt[XF_printf] = printf; 126 break; 127 } 128 break; 129 130 default: /* Invalid file ID */ 131 error = -1; 132 } 133 return error; 134 } 135 136 #if defined(CONFIG_CONSOLE_MUX) 137 /** Console I/O multiplexing *******************************************/ 138 139 static struct stdio_dev *tstcdev; 140 struct stdio_dev **console_devices[MAX_FILES]; 141 int cd_count[MAX_FILES]; 142 143 /* 144 * This depends on tstc() always being called before getc(). 145 * This is guaranteed to be true because this routine is called 146 * only from fgetc() which assures it. 147 * No attempt is made to demultiplex multiple input sources. 148 */ 149 static int console_getc(int file) 150 { 151 unsigned char ret; 152 153 /* This is never called with testcdev == NULL */ 154 ret = tstcdev->getc(); 155 tstcdev = NULL; 156 return ret; 157 } 158 159 static int console_tstc(int file) 160 { 161 int i, ret; 162 struct stdio_dev *dev; 163 164 disable_ctrlc(1); 165 for (i = 0; i < cd_count[file]; i++) { 166 dev = console_devices[file][i]; 167 if (dev->tstc != NULL) { 168 ret = dev->tstc(); 169 if (ret > 0) { 170 tstcdev = dev; 171 disable_ctrlc(0); 172 return ret; 173 } 174 } 175 } 176 disable_ctrlc(0); 177 178 return 0; 179 } 180 181 static void console_putc(int file, const char c) 182 { 183 int i; 184 struct stdio_dev *dev; 185 186 for (i = 0; i < cd_count[file]; i++) { 187 dev = console_devices[file][i]; 188 if (dev->putc != NULL) 189 dev->putc(c); 190 } 191 } 192 193 static void console_puts(int file, const char *s) 194 { 195 int i; 196 struct stdio_dev *dev; 197 198 for (i = 0; i < cd_count[file]; i++) { 199 dev = console_devices[file][i]; 200 if (dev->puts != NULL) 201 dev->puts(s); 202 } 203 } 204 205 static inline void console_printdevs(int file) 206 { 207 iomux_printdevs(file); 208 } 209 210 static inline void console_doenv(int file, struct stdio_dev *dev) 211 { 212 iomux_doenv(file, dev->name); 213 } 214 #else 215 static inline int console_getc(int file) 216 { 217 return stdio_devices[file]->getc(); 218 } 219 220 static inline int console_tstc(int file) 221 { 222 return stdio_devices[file]->tstc(); 223 } 224 225 static inline void console_putc(int file, const char c) 226 { 227 stdio_devices[file]->putc(c); 228 } 229 230 static inline void console_puts(int file, const char *s) 231 { 232 stdio_devices[file]->puts(s); 233 } 234 235 static inline void console_printdevs(int file) 236 { 237 printf("%s\n", stdio_devices[file]->name); 238 } 239 240 static inline void console_doenv(int file, struct stdio_dev *dev) 241 { 242 console_setfile(file, dev); 243 } 244 #endif /* defined(CONFIG_CONSOLE_MUX) */ 245 246 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ 247 248 int serial_printf(const char *fmt, ...) 249 { 250 va_list args; 251 uint i; 252 char printbuffer[CONFIG_SYS_PBSIZE]; 253 254 va_start(args, fmt); 255 256 /* For this to work, printbuffer must be larger than 257 * anything we ever want to print. 258 */ 259 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 260 va_end(args); 261 262 serial_puts(printbuffer); 263 return i; 264 } 265 266 int fgetc(int file) 267 { 268 if (file < MAX_FILES) { 269 #if defined(CONFIG_CONSOLE_MUX) 270 /* 271 * Effectively poll for input wherever it may be available. 272 */ 273 for (;;) { 274 /* 275 * Upper layer may have already called tstc() so 276 * check for that first. 277 */ 278 if (tstcdev != NULL) 279 return console_getc(file); 280 console_tstc(file); 281 #ifdef CONFIG_WATCHDOG 282 /* 283 * If the watchdog must be rate-limited then it should 284 * already be handled in board-specific code. 285 */ 286 udelay(1); 287 #endif 288 } 289 #else 290 return console_getc(file); 291 #endif 292 } 293 294 return -1; 295 } 296 297 int ftstc(int file) 298 { 299 if (file < MAX_FILES) 300 return console_tstc(file); 301 302 return -1; 303 } 304 305 void fputc(int file, const char c) 306 { 307 if (file < MAX_FILES) 308 console_putc(file, c); 309 } 310 311 void fputs(int file, const char *s) 312 { 313 if (file < MAX_FILES) 314 console_puts(file, s); 315 } 316 317 int fprintf(int file, const char *fmt, ...) 318 { 319 va_list args; 320 uint i; 321 char printbuffer[CONFIG_SYS_PBSIZE]; 322 323 va_start(args, fmt); 324 325 /* For this to work, printbuffer must be larger than 326 * anything we ever want to print. 327 */ 328 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 329 va_end(args); 330 331 /* Send to desired file */ 332 fputs(file, printbuffer); 333 return i; 334 } 335 336 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ 337 338 int getc(void) 339 { 340 #ifdef CONFIG_DISABLE_CONSOLE 341 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 342 return 0; 343 #endif 344 345 if (!gd->have_console) 346 return 0; 347 348 if (gd->flags & GD_FLG_DEVINIT) { 349 /* Get from the standard input */ 350 return fgetc(stdin); 351 } 352 353 /* Send directly to the handler */ 354 return serial_getc(); 355 } 356 357 int tstc(void) 358 { 359 #ifdef CONFIG_DISABLE_CONSOLE 360 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 361 return 0; 362 #endif 363 364 if (!gd->have_console) 365 return 0; 366 367 if (gd->flags & GD_FLG_DEVINIT) { 368 /* Test the standard input */ 369 return ftstc(stdin); 370 } 371 372 /* Send directly to the handler */ 373 return serial_tstc(); 374 } 375 376 #ifdef CONFIG_PRE_CONSOLE_BUFFER 377 #define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ) 378 379 static void pre_console_putc(const char c) 380 { 381 char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR; 382 383 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c; 384 } 385 386 static void pre_console_puts(const char *s) 387 { 388 while (*s) 389 pre_console_putc(*s++); 390 } 391 392 static void print_pre_console_buffer(void) 393 { 394 unsigned long i = 0; 395 char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR; 396 397 if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ) 398 i = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ; 399 400 while (i < gd->precon_buf_idx) 401 putc(buffer[CIRC_BUF_IDX(i++)]); 402 } 403 #else 404 static inline void pre_console_putc(const char c) {} 405 static inline void pre_console_puts(const char *s) {} 406 static inline void print_pre_console_buffer(void) {} 407 #endif 408 409 void putc(const char c) 410 { 411 #ifdef CONFIG_SILENT_CONSOLE 412 if (gd->flags & GD_FLG_SILENT) 413 return; 414 #endif 415 416 #ifdef CONFIG_DISABLE_CONSOLE 417 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 418 return; 419 #endif 420 421 if (!gd->have_console) 422 return pre_console_putc(c); 423 424 if (gd->flags & GD_FLG_DEVINIT) { 425 /* Send to the standard output */ 426 fputc(stdout, c); 427 } else { 428 /* Send directly to the handler */ 429 serial_putc(c); 430 } 431 } 432 433 void puts(const char *s) 434 { 435 #ifdef CONFIG_SILENT_CONSOLE 436 if (gd->flags & GD_FLG_SILENT) 437 return; 438 #endif 439 440 #ifdef CONFIG_DISABLE_CONSOLE 441 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 442 return; 443 #endif 444 445 if (!gd->have_console) 446 return pre_console_puts(s); 447 448 if (gd->flags & GD_FLG_DEVINIT) { 449 /* Send to the standard output */ 450 fputs(stdout, s); 451 } else { 452 /* Send directly to the handler */ 453 serial_puts(s); 454 } 455 } 456 457 int printf(const char *fmt, ...) 458 { 459 va_list args; 460 uint i; 461 char printbuffer[CONFIG_SYS_PBSIZE]; 462 463 #ifndef CONFIG_PRE_CONSOLE_BUFFER 464 if (!gd->have_console) 465 return 0; 466 #endif 467 468 va_start(args, fmt); 469 470 /* For this to work, printbuffer must be larger than 471 * anything we ever want to print. 472 */ 473 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 474 va_end(args); 475 476 /* Print the string */ 477 puts(printbuffer); 478 return i; 479 } 480 481 int vprintf(const char *fmt, va_list args) 482 { 483 uint i; 484 char printbuffer[CONFIG_SYS_PBSIZE]; 485 486 #ifndef CONFIG_PRE_CONSOLE_BUFFER 487 if (!gd->have_console) 488 return 0; 489 #endif 490 491 /* For this to work, printbuffer must be larger than 492 * anything we ever want to print. 493 */ 494 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 495 496 /* Print the string */ 497 puts(printbuffer); 498 return i; 499 } 500 501 /* test if ctrl-c was pressed */ 502 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 503 static int ctrlc_was_pressed = 0; 504 int ctrlc(void) 505 { 506 if (!ctrlc_disabled && gd->have_console) { 507 if (tstc()) { 508 switch (getc()) { 509 case 0x03: /* ^C - Control C */ 510 ctrlc_was_pressed = 1; 511 return 1; 512 default: 513 break; 514 } 515 } 516 } 517 return 0; 518 } 519 520 /* pass 1 to disable ctrlc() checking, 0 to enable. 521 * returns previous state 522 */ 523 int disable_ctrlc(int disable) 524 { 525 int prev = ctrlc_disabled; /* save previous state */ 526 527 ctrlc_disabled = disable; 528 return prev; 529 } 530 531 int had_ctrlc (void) 532 { 533 return ctrlc_was_pressed; 534 } 535 536 void clear_ctrlc(void) 537 { 538 ctrlc_was_pressed = 0; 539 } 540 541 #ifdef CONFIG_MODEM_SUPPORT_DEBUG 542 char screen[1024]; 543 char *cursor = screen; 544 int once = 0; 545 inline void dbg(const char *fmt, ...) 546 { 547 va_list args; 548 uint i; 549 char printbuffer[CONFIG_SYS_PBSIZE]; 550 551 if (!once) { 552 memset(screen, 0, sizeof(screen)); 553 once++; 554 } 555 556 va_start(args, fmt); 557 558 /* For this to work, printbuffer must be larger than 559 * anything we ever want to print. 560 */ 561 i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args); 562 va_end(args); 563 564 if ((screen + sizeof(screen) - 1 - cursor) 565 < strlen(printbuffer) + 1) { 566 memset(screen, 0, sizeof(screen)); 567 cursor = screen; 568 } 569 sprintf(cursor, printbuffer); 570 cursor += strlen(printbuffer); 571 572 } 573 #else 574 inline void dbg(const char *fmt, ...) 575 { 576 } 577 #endif 578 579 /** U-Boot INIT FUNCTIONS *************************************************/ 580 581 struct stdio_dev *search_device(int flags, const char *name) 582 { 583 struct stdio_dev *dev; 584 585 dev = stdio_get_by_name(name); 586 587 if (dev && (dev->flags & flags)) 588 return dev; 589 590 return NULL; 591 } 592 593 int console_assign(int file, const char *devname) 594 { 595 int flag; 596 struct stdio_dev *dev; 597 598 /* Check for valid file */ 599 switch (file) { 600 case stdin: 601 flag = DEV_FLAGS_INPUT; 602 break; 603 case stdout: 604 case stderr: 605 flag = DEV_FLAGS_OUTPUT; 606 break; 607 default: 608 return -1; 609 } 610 611 /* Check for valid device name */ 612 613 dev = search_device(flag, devname); 614 615 if (dev) 616 return console_setfile(file, dev); 617 618 return -1; 619 } 620 621 /* Called before relocation - use serial functions */ 622 int console_init_f(void) 623 { 624 gd->have_console = 1; 625 626 #ifdef CONFIG_SILENT_CONSOLE 627 if (getenv("silent") != NULL) 628 gd->flags |= GD_FLG_SILENT; 629 #endif 630 631 print_pre_console_buffer(); 632 633 return 0; 634 } 635 636 void stdio_print_current_devices(void) 637 { 638 /* Print information */ 639 puts("In: "); 640 if (stdio_devices[stdin] == NULL) { 641 puts("No input devices available!\n"); 642 } else { 643 printf ("%s\n", stdio_devices[stdin]->name); 644 } 645 646 puts("Out: "); 647 if (stdio_devices[stdout] == NULL) { 648 puts("No output devices available!\n"); 649 } else { 650 printf ("%s\n", stdio_devices[stdout]->name); 651 } 652 653 puts("Err: "); 654 if (stdio_devices[stderr] == NULL) { 655 puts("No error devices available!\n"); 656 } else { 657 printf ("%s\n", stdio_devices[stderr]->name); 658 } 659 } 660 661 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV 662 /* Called after the relocation - use desired console functions */ 663 int console_init_r(void) 664 { 665 char *stdinname, *stdoutname, *stderrname; 666 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 667 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 668 int i; 669 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 670 #ifdef CONFIG_CONSOLE_MUX 671 int iomux_err = 0; 672 #endif 673 674 /* set default handlers at first */ 675 gd->jt[XF_getc] = serial_getc; 676 gd->jt[XF_tstc] = serial_tstc; 677 gd->jt[XF_putc] = serial_putc; 678 gd->jt[XF_puts] = serial_puts; 679 gd->jt[XF_printf] = serial_printf; 680 681 /* stdin stdout and stderr are in environment */ 682 /* scan for it */ 683 stdinname = getenv("stdin"); 684 stdoutname = getenv("stdout"); 685 stderrname = getenv("stderr"); 686 687 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ 688 inputdev = search_device(DEV_FLAGS_INPUT, stdinname); 689 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname); 690 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname); 691 #ifdef CONFIG_CONSOLE_MUX 692 iomux_err = iomux_doenv(stdin, stdinname); 693 iomux_err += iomux_doenv(stdout, stdoutname); 694 iomux_err += iomux_doenv(stderr, stderrname); 695 if (!iomux_err) 696 /* Successful, so skip all the code below. */ 697 goto done; 698 #endif 699 } 700 /* if the devices are overwritten or not found, use default device */ 701 if (inputdev == NULL) { 702 inputdev = search_device(DEV_FLAGS_INPUT, "serial"); 703 } 704 if (outputdev == NULL) { 705 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 706 } 707 if (errdev == NULL) { 708 errdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 709 } 710 /* Initializes output console first */ 711 if (outputdev != NULL) { 712 /* need to set a console if not done above. */ 713 console_doenv(stdout, outputdev); 714 } 715 if (errdev != NULL) { 716 /* need to set a console if not done above. */ 717 console_doenv(stderr, errdev); 718 } 719 if (inputdev != NULL) { 720 /* need to set a console if not done above. */ 721 console_doenv(stdin, inputdev); 722 } 723 724 #ifdef CONFIG_CONSOLE_MUX 725 done: 726 #endif 727 728 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 729 stdio_print_current_devices(); 730 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 731 732 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 733 /* set the environment variables (will overwrite previous env settings) */ 734 for (i = 0; i < 3; i++) { 735 setenv(stdio_names[i], stdio_devices[i]->name); 736 } 737 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 738 739 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 740 741 #if 0 742 /* If nothing usable installed, use only the initial console */ 743 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 744 return 0; 745 #endif 746 return 0; 747 } 748 749 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 750 751 /* Called after the relocation - use desired console functions */ 752 int console_init_r(void) 753 { 754 struct stdio_dev *inputdev = NULL, *outputdev = NULL; 755 int i; 756 struct list_head *list = stdio_get_list(); 757 struct list_head *pos; 758 struct stdio_dev *dev; 759 760 #ifdef CONFIG_SPLASH_SCREEN 761 /* 762 * suppress all output if splash screen is enabled and we have 763 * a bmp to display. We redirect the output from frame buffer 764 * console to serial console in this case or suppress it if 765 * "silent" mode was requested. 766 */ 767 if (getenv("splashimage") != NULL) { 768 if (!(gd->flags & GD_FLG_SILENT)) 769 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 770 } 771 #endif 772 773 /* Scan devices looking for input and output devices */ 774 list_for_each(pos, list) { 775 dev = list_entry(pos, struct stdio_dev, list); 776 777 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 778 inputdev = dev; 779 } 780 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 781 outputdev = dev; 782 } 783 if(inputdev && outputdev) 784 break; 785 } 786 787 /* Initializes output console first */ 788 if (outputdev != NULL) { 789 console_setfile(stdout, outputdev); 790 console_setfile(stderr, outputdev); 791 #ifdef CONFIG_CONSOLE_MUX 792 console_devices[stdout][0] = outputdev; 793 console_devices[stderr][0] = outputdev; 794 #endif 795 } 796 797 /* Initializes input console */ 798 if (inputdev != NULL) { 799 console_setfile(stdin, inputdev); 800 #ifdef CONFIG_CONSOLE_MUX 801 console_devices[stdin][0] = inputdev; 802 #endif 803 } 804 805 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 806 stdio_print_current_devices(); 807 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 808 809 /* Setting environment variables */ 810 for (i = 0; i < 3; i++) { 811 setenv(stdio_names[i], stdio_devices[i]->name); 812 } 813 814 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 815 816 #if 0 817 /* If nothing usable installed, use only the initial console */ 818 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 819 return 0; 820 #endif 821 822 return 0; 823 } 824 825 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 826