1 /* 2 * (C) Copyright 2000 3 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <console.h> 10 #include <debug_uart.h> 11 #include <dm.h> 12 #include <stdarg.h> 13 #include <iomux.h> 14 #include <malloc.h> 15 #include <mapmem.h> 16 #include <os.h> 17 #include <serial.h> 18 #include <stdio_dev.h> 19 #include <exports.h> 20 #include <environment.h> 21 #include <watchdog.h> 22 #include <vsprintf.h> 23 24 #ifdef CONFIG_PSTORE 25 #include <asm/arch/pstore.h> 26 #endif 27 28 DECLARE_GLOBAL_DATA_PTR; 29 30 static uspinlock_t console_lock; 31 32 static int on_console(const char *name, const char *value, enum env_op op, 33 int flags) 34 { 35 int console = -1; 36 37 /* Check for console redirection */ 38 if (strcmp(name, "stdin") == 0) 39 console = stdin; 40 else if (strcmp(name, "stdout") == 0) 41 console = stdout; 42 else if (strcmp(name, "stderr") == 0) 43 console = stderr; 44 45 /* if not actually setting a console variable, we don't care */ 46 if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0) 47 return 0; 48 49 switch (op) { 50 case env_op_create: 51 case env_op_overwrite: 52 53 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 54 if (iomux_doenv(console, value)) 55 return 1; 56 #else 57 /* Try assigning specified device */ 58 if (console_assign(console, value) < 0) 59 return 1; 60 #endif 61 return 0; 62 63 case env_op_delete: 64 if ((flags & H_FORCE) == 0) 65 printf("Can't delete \"%s\"\n", name); 66 return 1; 67 68 default: 69 return 0; 70 } 71 } 72 U_BOOT_ENV_CALLBACK(console, on_console); 73 74 #ifdef CONFIG_SILENT_CONSOLE 75 static int on_silent(const char *name, const char *value, enum env_op op, 76 int flags) 77 { 78 #if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET) 79 if (flags & H_INTERACTIVE) 80 return 0; 81 #endif 82 #if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC) 83 if ((flags & H_INTERACTIVE) == 0) 84 return 0; 85 #endif 86 87 if (value != NULL) 88 gd->flags |= GD_FLG_SILENT; 89 else 90 gd->flags &= ~GD_FLG_SILENT; 91 92 return 0; 93 } 94 U_BOOT_ENV_CALLBACK(silent, on_silent); 95 #endif 96 97 #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) 98 /* 99 * if overwrite_console returns 1, the stdin, stderr and stdout 100 * are switched to the serial port, else the settings in the 101 * environment are used 102 */ 103 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE 104 extern int overwrite_console(void); 105 #define OVERWRITE_CONSOLE overwrite_console() 106 #else 107 #define OVERWRITE_CONSOLE 0 108 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */ 109 110 #endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */ 111 112 static int console_setfile(int file, struct stdio_dev * dev) 113 { 114 int error = 0; 115 116 if (dev == NULL) 117 return -1; 118 119 switch (file) { 120 case stdin: 121 case stdout: 122 case stderr: 123 /* Start new device */ 124 if (dev->start) { 125 error = dev->start(dev); 126 /* If it's not started dont use it */ 127 if (error < 0) 128 break; 129 } 130 131 /* Assign the new device (leaving the existing one started) */ 132 stdio_devices[file] = dev; 133 134 /* 135 * Update monitor functions 136 * (to use the console stuff by other applications) 137 */ 138 switch (file) { 139 case stdin: 140 gd->jt->getc = getc; 141 gd->jt->tstc = tstc; 142 break; 143 case stdout: 144 gd->jt->putc = putc; 145 gd->jt->puts = puts; 146 gd->jt->printf = printf; 147 break; 148 } 149 break; 150 151 default: /* Invalid file ID */ 152 error = -1; 153 } 154 return error; 155 } 156 157 /** 158 * console_dev_is_serial() - Check if a stdio device is a serial device 159 * 160 * @sdev: Device to check 161 * @return true if this device is in the serial uclass (or for pre-driver-model, 162 * whether it is called "serial". 163 */ 164 static bool console_dev_is_serial(struct stdio_dev *sdev) 165 { 166 bool is_serial; 167 168 #ifdef CONFIG_DM_SERIAL 169 if (sdev->flags & DEV_FLAGS_DM) { 170 struct udevice *dev = sdev->priv; 171 172 is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL; 173 } else 174 #endif 175 is_serial = !strcmp(sdev->name, "serial"); 176 177 return is_serial; 178 } 179 180 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 181 /** Console I/O multiplexing *******************************************/ 182 183 static struct stdio_dev *tstcdev; 184 struct stdio_dev **console_devices[MAX_FILES]; 185 int cd_count[MAX_FILES]; 186 187 /* 188 * This depends on tstc() always being called before getc(). 189 * This is guaranteed to be true because this routine is called 190 * only from fgetc() which assures it. 191 * No attempt is made to demultiplex multiple input sources. 192 */ 193 static int console_getc(int file) 194 { 195 unsigned char ret; 196 197 /* This is never called with testcdev == NULL */ 198 ret = tstcdev->getc(tstcdev); 199 tstcdev = NULL; 200 return ret; 201 } 202 203 static int console_tstc(int file) 204 { 205 int i, ret; 206 struct stdio_dev *dev; 207 208 disable_ctrlc(1); 209 for (i = 0; i < cd_count[file]; i++) { 210 dev = console_devices[file][i]; 211 if (dev->tstc != NULL) { 212 ret = dev->tstc(dev); 213 if (ret > 0) { 214 tstcdev = dev; 215 disable_ctrlc(0); 216 return ret; 217 } 218 } 219 } 220 disable_ctrlc(0); 221 222 return 0; 223 } 224 225 static void console_putc(int file, const char c) 226 { 227 int i; 228 struct stdio_dev *dev; 229 230 for (i = 0; i < cd_count[file]; i++) { 231 dev = console_devices[file][i]; 232 if (dev->putc != NULL) 233 dev->putc(dev, c); 234 } 235 } 236 237 static void console_puts_noserial(int file, const char *s) 238 { 239 int i; 240 struct stdio_dev *dev; 241 242 for (i = 0; i < cd_count[file]; i++) { 243 dev = console_devices[file][i]; 244 if (dev->puts != NULL && !console_dev_is_serial(dev)) 245 dev->puts(dev, s); 246 } 247 } 248 249 static void console_puts(int file, const char *s) 250 { 251 int i; 252 struct stdio_dev *dev; 253 254 for (i = 0; i < cd_count[file]; i++) { 255 dev = console_devices[file][i]; 256 if (dev->puts != NULL) 257 dev->puts(dev, s); 258 } 259 } 260 261 static inline void console_doenv(int file, struct stdio_dev *dev) 262 { 263 iomux_doenv(file, dev->name); 264 } 265 266 static void console_clear(int file) 267 { 268 int i; 269 struct stdio_dev *dev; 270 271 for (i = 0; i < cd_count[file]; i++) { 272 dev = console_devices[file][i]; 273 if (dev->clear != NULL) 274 dev->clear(dev); 275 } 276 } 277 #else 278 static inline int console_getc(int file) 279 { 280 return stdio_devices[file]->getc(stdio_devices[file]); 281 } 282 283 static inline int console_tstc(int file) 284 { 285 return stdio_devices[file]->tstc(stdio_devices[file]); 286 } 287 288 static inline void console_putc(int file, const char c) 289 { 290 stdio_devices[file]->putc(stdio_devices[file], c); 291 } 292 293 static inline void console_puts_noserial(int file, const char *s) 294 { 295 if (!console_dev_is_serial(stdio_devices[file])) 296 stdio_devices[file]->puts(stdio_devices[file], s); 297 } 298 299 static inline void console_puts(int file, const char *s) 300 { 301 stdio_devices[file]->puts(stdio_devices[file], s); 302 } 303 304 static inline void console_clear(int file) 305 { 306 if (stdio_devices[file]->clear) 307 stdio_devices[file]->clear(stdio_devices[file]); 308 } 309 310 static inline void console_doenv(int file, struct stdio_dev *dev) 311 { 312 console_setfile(file, dev); 313 } 314 #endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */ 315 316 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ 317 318 int serial_printf(const char *fmt, ...) 319 { 320 va_list args; 321 uint i; 322 char printbuffer[CONFIG_SYS_PBSIZE]; 323 324 va_start(args, fmt); 325 326 /* For this to work, printbuffer must be larger than 327 * anything we ever want to print. 328 */ 329 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 330 va_end(args); 331 332 serial_puts(printbuffer); 333 return i; 334 } 335 336 int fgetc(int file) 337 { 338 if (file < MAX_FILES) { 339 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 340 /* 341 * Effectively poll for input wherever it may be available. 342 */ 343 for (;;) { 344 WATCHDOG_RESET(); 345 /* 346 * Upper layer may have already called tstc() so 347 * check for that first. 348 */ 349 if (tstcdev != NULL) 350 return console_getc(file); 351 console_tstc(file); 352 #ifdef CONFIG_WATCHDOG 353 /* 354 * If the watchdog must be rate-limited then it should 355 * already be handled in board-specific code. 356 */ 357 udelay(1); 358 #endif 359 } 360 #else 361 return console_getc(file); 362 #endif 363 } 364 365 return -1; 366 } 367 368 int ftstc(int file) 369 { 370 if (file < MAX_FILES) 371 return console_tstc(file); 372 373 return -1; 374 } 375 376 void fputc(int file, const char c) 377 { 378 if (file < MAX_FILES) 379 console_putc(file, c); 380 } 381 382 void fputs(int file, const char *s) 383 { 384 if (file < MAX_FILES) 385 console_puts(file, s); 386 } 387 388 void fclear(int file) 389 { 390 if (file < MAX_FILES) 391 console_clear(file); 392 } 393 394 int fprintf(int file, const char *fmt, ...) 395 { 396 va_list args; 397 uint i; 398 char printbuffer[CONFIG_SYS_PBSIZE]; 399 400 va_start(args, fmt); 401 402 /* For this to work, printbuffer must be larger than 403 * anything we ever want to print. 404 */ 405 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 406 va_end(args); 407 408 /* Send to desired file */ 409 fputs(file, printbuffer); 410 return i; 411 } 412 413 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ 414 415 int getc(void) 416 { 417 if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) 418 return 0; 419 420 if (!gd->have_console) 421 return 0; 422 423 #ifdef CONFIG_CONSOLE_RECORD 424 if (gd->console_in.start) { 425 int ch; 426 427 ch = membuff_getbyte((struct membuff *)&gd->console_in); 428 if (ch != -1) 429 return 1; 430 } 431 #endif 432 if (gd->flags & GD_FLG_DEVINIT) { 433 /* Get from the standard input */ 434 return fgetc(stdin); 435 } 436 437 /* Send directly to the handler */ 438 return serial_getc(); 439 } 440 441 int tstc(void) 442 { 443 if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) 444 return 0; 445 446 if (!gd->have_console) 447 return 0; 448 #ifdef CONFIG_CONSOLE_RECORD 449 if (gd->console_in.start) { 450 if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1) 451 return 1; 452 } 453 #endif 454 if (gd->flags & GD_FLG_DEVINIT) { 455 /* Test the standard input */ 456 return ftstc(stdin); 457 } 458 459 /* Send directly to the handler */ 460 return serial_tstc(); 461 } 462 463 void flushc(void) 464 { 465 if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) 466 return; 467 468 #ifdef CONFIG_DEBUG_UART_NS16550 469 debug_uart_flushc(); 470 #endif 471 } 472 473 #define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0 474 #define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1 475 476 #if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER) 477 #define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ) 478 479 static void pre_console_putc(const char c) 480 { 481 char *buffer; 482 483 buffer = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ); 484 485 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c; 486 487 unmap_sysmem(buffer); 488 } 489 490 static void print_pre_console_buffer(int flushpoint) 491 { 492 unsigned long in = 0, out = 0; 493 char buf_out[CONFIG_PRE_CON_BUF_SZ + 1]; 494 char *buf_in; 495 496 buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ); 497 if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ) 498 in = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ; 499 500 while (in < gd->precon_buf_idx) 501 buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)]; 502 unmap_sysmem(buf_in); 503 504 buf_out[out] = 0; 505 506 switch (flushpoint) { 507 case PRE_CONSOLE_FLUSHPOINT1_SERIAL: 508 puts(buf_out); 509 break; 510 case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL: 511 console_puts_noserial(stdout, buf_out); 512 break; 513 } 514 } 515 #else 516 static inline void pre_console_putc(const char c) {} 517 static inline void print_pre_console_buffer(int flushpoint) {} 518 #endif 519 520 void putc(const char c) 521 { 522 if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) 523 return; 524 525 #ifdef CONFIG_PSTORE 526 putc_to_ram(c); 527 #endif 528 529 #ifdef CONFIG_CONSOLE_RECORD 530 if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start) 531 membuff_putbyte((struct membuff *)&gd->console_out, c); 532 #endif 533 #ifdef CONFIG_SILENT_CONSOLE 534 if (gd->flags & GD_FLG_SILENT) 535 return; 536 #endif 537 538 #ifdef CONFIG_DEBUG_UART 539 /* if we don't have a console yet, use the debug UART */ 540 if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) { 541 printch(c); 542 return; 543 } 544 #endif 545 if (!gd->have_console) 546 return pre_console_putc(c); 547 548 if (gd->flags & GD_FLG_DEVINIT) { 549 /* Send to the standard output */ 550 fputc(stdout, c); 551 } else { 552 /* Send directly to the handler */ 553 pre_console_putc(c); 554 serial_putc(c); 555 } 556 } 557 558 #if ((!defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF)) && \ 559 defined(CONFIG_BOOTSTAGE_PRINTF_TIMESTAMP)) 560 static void vspfunc(char *buf, size_t size, char *format, ...) 561 { 562 va_list ap; 563 564 va_start(ap, format); 565 vsnprintf(buf, size, format, ap); 566 va_end(ap); 567 } 568 569 void puts(const char *s) 570 { 571 unsigned long ts_sec, ts_msec, us, delta_ms; 572 char pr_timestamp[32], *p; 573 int cpu; 574 575 u_spin_lock(&console_lock); 576 577 while (*s) { 578 if (*s == '\n') { 579 gd->new_line = 1; 580 putc(*s++); 581 continue; 582 } 583 584 if (gd->new_line) { 585 us = (get_ticks() / (gd->arch.timer_rate_hz / 1000000)); 586 if (gd->last_us) 587 delta_ms = DIV_ROUND_UP(us - gd->last_us, 1000); 588 else 589 delta_ms = 0; 590 gd->last_us = us; 591 gd->new_line = 0; 592 593 ts_sec = us / 1000000; 594 ts_msec = us % 1000000; 595 cpu = read_mpidr() & 0xfff; 596 vspfunc(pr_timestamp, sizeof(pr_timestamp), 597 "[%5lu.%06lu:%x:%03d] ", ts_sec, ts_msec, cpu, delta_ms); 598 p = pr_timestamp; 599 while (*p) 600 putc(*p++); 601 } 602 603 putc(*s++); 604 } 605 606 u_spin_unlock(&console_lock); 607 } 608 #else 609 void puts(const char *s) 610 { 611 u_spin_lock(&console_lock); 612 613 while (*s) 614 putc(*s++); 615 616 u_spin_unlock(&console_lock); 617 } 618 #endif 619 620 621 #ifdef CONFIG_CONSOLE_RECORD 622 int console_record_init(void) 623 { 624 int ret; 625 626 ret = membuff_new((struct membuff *)&gd->console_out, 627 CONFIG_CONSOLE_RECORD_OUT_SIZE); 628 if (ret) 629 return ret; 630 ret = membuff_new((struct membuff *)&gd->console_in, 631 CONFIG_CONSOLE_RECORD_IN_SIZE); 632 633 return ret; 634 } 635 636 void console_record_reset(void) 637 { 638 membuff_purge((struct membuff *)&gd->console_out); 639 membuff_purge((struct membuff *)&gd->console_in); 640 } 641 642 void console_record_reset_enable(void) 643 { 644 console_record_reset(); 645 gd->flags |= GD_FLG_RECORD; 646 } 647 648 /* Print and remove data from buffer */ 649 void console_record_print_purge(void) 650 { 651 unsigned long flags; 652 char c; 653 654 if (!gd || !(gd->flags & GD_FLG_RECORD)) 655 return; 656 657 /* Remove some bits to avoid running unexpected branch in putc() */ 658 flags = gd->flags; 659 gd->flags &= ~(GD_FLG_RECORD | GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE); 660 661 printf("\n\n## Console Record: \n"); 662 while (!membuff_isempty((struct membuff *)&gd->console_out)) { 663 c = membuff_getbyte((struct membuff *)&gd->console_out); 664 putc(c); 665 } 666 667 gd->flags = flags; 668 } 669 #endif 670 671 /* test if ctrl-c was pressed */ 672 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 673 static int ctrlc_was_pressed = 0; 674 int ctrlc(void) 675 { 676 #ifndef CONFIG_SANDBOX 677 if (!ctrlc_disabled && gd->have_console) { 678 if (tstc()) { 679 switch (getc()) { 680 case 0x03: /* ^C - Control C */ 681 ctrlc_was_pressed = 1; 682 return 1; 683 default: 684 break; 685 } 686 } 687 } 688 #endif 689 690 return 0; 691 } 692 /* Reads user's confirmation. 693 Returns 1 if user's input is "y", "Y", "yes" or "YES" 694 */ 695 int confirm_yesno(void) 696 { 697 int i; 698 char str_input[5]; 699 700 /* Flush input */ 701 while (tstc()) 702 getc(); 703 i = 0; 704 while (i < sizeof(str_input)) { 705 str_input[i] = getc(); 706 putc(str_input[i]); 707 if (str_input[i] == '\r') 708 break; 709 i++; 710 } 711 putc('\n'); 712 if (strncmp(str_input, "y\r", 2) == 0 || 713 strncmp(str_input, "Y\r", 2) == 0 || 714 strncmp(str_input, "yes\r", 4) == 0 || 715 strncmp(str_input, "YES\r", 4) == 0) 716 return 1; 717 return 0; 718 } 719 /* pass 1 to disable ctrlc() checking, 0 to enable. 720 * returns previous state 721 */ 722 int disable_ctrlc(int disable) 723 { 724 int prev = ctrlc_disabled; /* save previous state */ 725 726 ctrlc_disabled = disable; 727 return prev; 728 } 729 730 int had_ctrlc (void) 731 { 732 return ctrlc_was_pressed; 733 } 734 735 void clear_ctrlc(void) 736 { 737 ctrlc_was_pressed = 0; 738 } 739 740 /** U-Boot INIT FUNCTIONS *************************************************/ 741 742 struct stdio_dev *search_device(int flags, const char *name) 743 { 744 struct stdio_dev *dev; 745 746 dev = stdio_get_by_name(name); 747 #ifdef CONFIG_VIDCONSOLE_AS_LCD 748 if (!dev && !strcmp(name, "lcd")) 749 dev = stdio_get_by_name("vidconsole"); 750 #endif 751 752 if (dev && (dev->flags & flags)) 753 return dev; 754 755 return NULL; 756 } 757 758 int console_assign(int file, const char *devname) 759 { 760 int flag; 761 struct stdio_dev *dev; 762 763 /* Check for valid file */ 764 switch (file) { 765 case stdin: 766 flag = DEV_FLAGS_INPUT; 767 break; 768 case stdout: 769 case stderr: 770 flag = DEV_FLAGS_OUTPUT; 771 break; 772 default: 773 return -1; 774 } 775 776 /* Check for valid device name */ 777 778 dev = search_device(flag, devname); 779 780 if (dev) 781 return console_setfile(file, dev); 782 783 return -1; 784 } 785 786 static void console_update_silent(void) 787 { 788 #ifdef CONFIG_SILENT_CONSOLE 789 if (env_get("silent") != NULL) { 790 printf("U-Boot: enable silent console\n"); 791 gd->flags |= GD_FLG_SILENT; 792 } else { 793 gd->flags &= ~GD_FLG_SILENT; 794 } 795 #endif 796 } 797 798 int console_announce_r(void) 799 { 800 #if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER) 801 char buf[DISPLAY_OPTIONS_BANNER_LENGTH]; 802 803 display_options_get_banner(false, buf, sizeof(buf)); 804 805 console_puts_noserial(stdout, buf); 806 #endif 807 808 return 0; 809 } 810 811 /* Called before relocation - use serial functions */ 812 int console_init_f(void) 813 { 814 gd->have_console = 1; 815 816 console_update_silent(); 817 818 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL); 819 820 return 0; 821 } 822 823 void stdio_print_current_devices(void) 824 { 825 /* Print information */ 826 puts("In: "); 827 if (stdio_devices[stdin] == NULL) { 828 puts("No input devices available!\n"); 829 } else { 830 printf ("%s\n", stdio_devices[stdin]->name); 831 } 832 833 puts("Out: "); 834 if (stdio_devices[stdout] == NULL) { 835 puts("No output devices available!\n"); 836 } else { 837 printf ("%s\n", stdio_devices[stdout]->name); 838 } 839 840 puts("Err: "); 841 if (stdio_devices[stderr] == NULL) { 842 puts("No error devices available!\n"); 843 } else { 844 printf ("%s\n", stdio_devices[stderr]->name); 845 } 846 } 847 848 #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) 849 /* Called after the relocation - use desired console functions */ 850 int console_init_r(void) 851 { 852 char *stdinname, *stdoutname, *stderrname; 853 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 854 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 855 int i; 856 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 857 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 858 int iomux_err = 0; 859 #endif 860 861 /* set default handlers at first */ 862 gd->jt->getc = serial_getc; 863 gd->jt->tstc = serial_tstc; 864 gd->jt->putc = serial_putc; 865 gd->jt->puts = serial_puts; 866 gd->jt->printf = serial_printf; 867 868 /* stdin stdout and stderr are in environment */ 869 /* scan for it */ 870 stdinname = env_get("stdin"); 871 stdoutname = env_get("stdout"); 872 stderrname = env_get("stderr"); 873 874 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ 875 inputdev = search_device(DEV_FLAGS_INPUT, stdinname); 876 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname); 877 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname); 878 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 879 iomux_err = iomux_doenv(stdin, stdinname); 880 iomux_err += iomux_doenv(stdout, stdoutname); 881 iomux_err += iomux_doenv(stderr, stderrname); 882 if (!iomux_err) 883 /* Successful, so skip all the code below. */ 884 goto done; 885 #endif 886 } 887 /* if the devices are overwritten or not found, use default device */ 888 if (inputdev == NULL) { 889 inputdev = search_device(DEV_FLAGS_INPUT, "serial"); 890 } 891 if (outputdev == NULL) { 892 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 893 } 894 if (errdev == NULL) { 895 errdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 896 } 897 /* Initializes output console first */ 898 if (outputdev != NULL) { 899 /* need to set a console if not done above. */ 900 console_doenv(stdout, outputdev); 901 } 902 if (errdev != NULL) { 903 /* need to set a console if not done above. */ 904 console_doenv(stderr, errdev); 905 } 906 if (inputdev != NULL) { 907 /* need to set a console if not done above. */ 908 console_doenv(stdin, inputdev); 909 } 910 911 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 912 done: 913 #endif 914 915 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 916 stdio_print_current_devices(); 917 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 918 #ifdef CONFIG_VIDCONSOLE_AS_LCD 919 if (strstr(stdoutname, "lcd")) 920 printf("Warning: Please change 'lcd' to 'vidconsole' in stdout/stderr environment vars\n"); 921 #endif 922 923 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 924 /* set the environment variables (will overwrite previous env settings) */ 925 for (i = 0; i < 3; i++) { 926 env_set(stdio_names[i], stdio_devices[i]->name); 927 } 928 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 929 930 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 931 932 #if 0 933 /* If nothing usable installed, use only the initial console */ 934 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 935 return 0; 936 #endif 937 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL); 938 return 0; 939 } 940 941 #else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */ 942 943 /* Called after the relocation - use desired console functions */ 944 int console_init_r(void) 945 { 946 struct stdio_dev *inputdev = NULL, *outputdev = NULL; 947 int i; 948 struct list_head *list = stdio_get_list(); 949 struct list_head *pos; 950 struct stdio_dev *dev; 951 952 console_update_silent(); 953 954 #ifdef CONFIG_SPLASH_SCREEN 955 /* 956 * suppress all output if splash screen is enabled and we have 957 * a bmp to display. We redirect the output from frame buffer 958 * console to serial console in this case or suppress it if 959 * "silent" mode was requested. 960 */ 961 if (env_get("splashimage") != NULL) { 962 if (!(gd->flags & GD_FLG_SILENT)) 963 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 964 } 965 #endif 966 967 /* Scan devices looking for input and output devices */ 968 list_for_each(pos, list) { 969 dev = list_entry(pos, struct stdio_dev, list); 970 971 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 972 inputdev = dev; 973 } 974 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 975 outputdev = dev; 976 } 977 if(inputdev && outputdev) 978 break; 979 } 980 981 /* Initializes output console first */ 982 if (outputdev != NULL) { 983 console_setfile(stdout, outputdev); 984 console_setfile(stderr, outputdev); 985 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 986 console_devices[stdout][0] = outputdev; 987 console_devices[stderr][0] = outputdev; 988 #endif 989 } 990 991 /* Initializes input console */ 992 if (inputdev != NULL) { 993 console_setfile(stdin, inputdev); 994 #if CONFIG_IS_ENABLED(CONSOLE_MUX) 995 console_devices[stdin][0] = inputdev; 996 #endif 997 } 998 999 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 1000 stdio_print_current_devices(); 1001 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 1002 1003 /* Setting environment variables */ 1004 for (i = 0; i < 3; i++) { 1005 env_set(stdio_names[i], stdio_devices[i]->name); 1006 } 1007 1008 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 1009 1010 #if 0 1011 /* If nothing usable installed, use only the initial console */ 1012 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 1013 return 0; 1014 #endif 1015 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL); 1016 return 0; 1017 } 1018 1019 #endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */ 1020