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