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