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