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