]> Git Repo - u-boot.git/blame - common/console.c
microblaze: cache: improve dcache Kconfig options
[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>
7b3c4c3a 10#include <dm.h>
9fb625ce 11#include <env.h>
47d1a6e1 12#include <stdarg.h>
482f4691 13#include <iomux.h>
47d1a6e1 14#include <malloc.h>
4e6bafa5 15#include <mapmem.h>
91b136c7 16#include <os.h>
849d5d9c 17#include <serial.h>
52cb4d4f 18#include <stdio_dev.h>
27b207fd 19#include <exports.h>
f3998fdc 20#include <env_internal.h>
64407467 21#include <watchdog.h>
401d1c4f 22#include <asm/global_data.h>
c05ed00a 23#include <linux/delay.h>
47d1a6e1 24
d87080b7
WD
25DECLARE_GLOBAL_DATA_PTR;
26
849d5d9c
JH
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
c04f8568
PD
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
849d5d9c
JH
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
e080d545
JH
70#ifdef CONFIG_SILENT_CONSOLE
71static int on_silent(const char *name, const char *value, enum env_op op,
72 int flags)
73{
c04f8568
PD
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;
e080d545
JH
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
1e993710
PD
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;
c1a2bb4f
SG
98 if (gd->console_out.start &&
99 !membuff_putbyte((struct membuff *)&gd->console_out, c))
100 gd->flags |= GD_FLG_RECORD_OVF;
1e993710
PD
101}
102
103static void console_record_puts(const char *s)
104{
105 if (!(gd->flags & GD_FLG_RECORD))
106 return;
c1a2bb4f
SG
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 }
1e993710
PD
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
b0265429 156#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
47d1a6e1
WD
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 */
6d0f6bcf 162#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
ec6f1499
JCPV
163extern int overwrite_console(void);
164#define OVERWRITE_CONSOLE overwrite_console()
47d1a6e1 165#else
83e40ba7 166#define OVERWRITE_CONSOLE 0
6d0f6bcf 167#endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
47d1a6e1 168
b0265429 169#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
47d1a6e1 170
52cb4d4f 171static int console_setfile(int file, struct stdio_dev * dev)
47d1a6e1
WD
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:
41f668b9
AS
182 error = console_start(file, dev);
183 if (error)
184 break;
47d1a6e1
WD
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:
c670aeee 195 gd->jt->getc = getchar;
49cad547 196 gd->jt->tstc = tstc;
47d1a6e1
WD
197 break;
198 case stdout:
49cad547
MD
199 gd->jt->putc = putc;
200 gd->jt->puts = puts;
201 gd->jt->printf = printf;
47d1a6e1
WD
202 break;
203 }
204 break;
205
206 default: /* Invalid file ID */
207 error = -1;
208 }
209 return error;
210}
211
42f9f915
SG
212/**
213 * console_dev_is_serial() - Check if a stdio device is a serial device
214 *
215 * @sdev: Device to check
185f812c 216 * Return: true if this device is in the serial uclass (or for pre-driver-model,
7b3c4c3a 217 * whether it is called "serial".
42f9f915
SG
218 */
219static bool console_dev_is_serial(struct stdio_dev *sdev)
220{
221 bool is_serial;
222
c04f8568 223 if (IS_ENABLED(CONFIG_DM_SERIAL) && (sdev->flags & DEV_FLAGS_DM)) {
7b3c4c3a
SG
224 struct udevice *dev = sdev->priv;
225
226 is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
c04f8568
PD
227 } else {
228 is_serial = !strcmp(sdev->name, "serial");
229 }
42f9f915
SG
230
231 return is_serial;
232}
233
b0265429 234#if CONFIG_IS_ENABLED(CONSOLE_MUX)
16a28ef2
GJ
235/** Console I/O multiplexing *******************************************/
236
a17b38ce 237/* tstcdev: save the last stdio device with pending characters, with tstc != 0 */
52cb4d4f
JCPV
238static struct stdio_dev *tstcdev;
239struct stdio_dev **console_devices[MAX_FILES];
16a28ef2
GJ
240int cd_count[MAX_FILES];
241
09d8f077 242static void console_devices_set(int file, struct stdio_dev *dev)
45375adc
PD
243{
244 console_devices[file][0] = dev;
20a7d351 245 cd_count[file] = 1;
45375adc
PD
246}
247
95aaf402
AS
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{
b672c161 261 int i;
95aaf402
AS
262
263 for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
264 if (i == file)
265 continue;
266
b672c161
AS
267 if (iomux_match_device(console_devices[i], cd_count[i], sdev) >= 0)
268 return false;
95aaf402
AS
269 }
270 return true;
271}
272
16a28ef2 273/*
c670aeee 274 * This depends on tstc() always being called before getchar().
16a28ef2
GJ
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 */
5f032010 279static int console_getc(int file)
16a28ef2
GJ
280{
281 unsigned char ret;
282
283 /* This is never called with testcdev == NULL */
709ea543 284 ret = tstcdev->getc(tstcdev);
16a28ef2
GJ
285 tstcdev = NULL;
286 return ret;
287}
288
a17b38ce
PD
289/* Upper layer may have already called tstc(): check the saved result */
290static bool console_has_tstc(void)
291{
292 return !!tstcdev;
293}
294
5f032010 295static int console_tstc(int file)
16a28ef2
GJ
296{
297 int i, ret;
52cb4d4f 298 struct stdio_dev *dev;
b2f58d8e 299 int prev;
16a28ef2 300
b2f58d8e 301 prev = disable_ctrlc(1);
400797ca 302 for_each_console_dev(i, file, dev) {
16a28ef2 303 if (dev->tstc != NULL) {
709ea543 304 ret = dev->tstc(dev);
16a28ef2
GJ
305 if (ret > 0) {
306 tstcdev = dev;
b2f58d8e 307 disable_ctrlc(prev);
16a28ef2
GJ
308 return ret;
309 }
310 }
311 }
b2f58d8e 312 disable_ctrlc(prev);
16a28ef2
GJ
313
314 return 0;
315}
316
5f032010 317static void console_putc(int file, const char c)
16a28ef2
GJ
318{
319 int i;
52cb4d4f 320 struct stdio_dev *dev;
16a28ef2 321
400797ca 322 for_each_console_dev(i, file, dev) {
16a28ef2 323 if (dev->putc != NULL)
709ea543 324 dev->putc(dev, c);
16a28ef2
GJ
325 }
326}
327
493a4c8a
SG
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)
27669667
SS
337{
338 int i;
339 struct stdio_dev *dev;
340
400797ca
AS
341 for_each_console_dev(i, file, dev) {
342 bool is_serial = console_dev_is_serial(dev);
493a4c8a 343
493a4c8a 344 if (dev->puts && serial_only == is_serial)
a8552c7c 345 dev->puts(dev, s);
27669667
SS
346 }
347}
27669667 348
493a4c8a
SG
349void console_puts_select_stderr(bool serial_only, const char *s)
350{
4057e277
SG
351 if (gd->flags & GD_FLG_DEVINIT)
352 console_puts_select(stderr, serial_only, s);
493a4c8a
SG
353}
354
5f032010 355static void console_puts(int file, const char *s)
16a28ef2
GJ
356{
357 int i;
52cb4d4f 358 struct stdio_dev *dev;
16a28ef2 359
400797ca 360 for_each_console_dev(i, file, dev) {
16a28ef2 361 if (dev->puts != NULL)
709ea543 362 dev->puts(dev, s);
16a28ef2
GJ
363 }
364}
5f032010 365
5e63c96a 366#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
52cb4d4f 367static inline void console_doenv(int file, struct stdio_dev *dev)
5f032010
JCPV
368{
369 iomux_doenv(file, dev->name);
370}
5e63c96a 371#endif
5f032010 372#else
45375adc 373
09d8f077 374static void console_devices_set(int file, struct stdio_dev *dev)
45375adc
PD
375{
376}
377
95aaf402
AS
378static inline bool console_needs_start_stop(int file, struct stdio_dev *sdev)
379{
380 return true;
381}
382
5f032010
JCPV
383static inline int console_getc(int file)
384{
709ea543 385 return stdio_devices[file]->getc(stdio_devices[file]);
5f032010
JCPV
386}
387
a17b38ce
PD
388static bool console_has_tstc(void)
389{
390 return false;
391}
392
5f032010
JCPV
393static inline int console_tstc(int file)
394{
709ea543 395 return stdio_devices[file]->tstc(stdio_devices[file]);
5f032010
JCPV
396}
397
398static inline void console_putc(int file, const char c)
399{
709ea543 400 stdio_devices[file]->putc(stdio_devices[file], c);
5f032010
JCPV
401}
402
493a4c8a 403void console_puts_select(int file, bool serial_only, const char *s)
27669667 404{
4057e277
SG
405 if ((gd->flags & GD_FLG_DEVINIT) &&
406 serial_only == console_dev_is_serial(stdio_devices[file]))
a8552c7c 407 stdio_devices[file]->puts(stdio_devices[file], s);
27669667 408}
27669667 409
5f032010
JCPV
410static inline void console_puts(int file, const char *s)
411{
709ea543 412 stdio_devices[file]->puts(stdio_devices[file], s);
5f032010
JCPV
413}
414
5e63c96a 415#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
52cb4d4f 416static inline void console_doenv(int file, struct stdio_dev *dev)
5f032010
JCPV
417{
418 console_setfile(file, dev);
419}
5e63c96a 420#endif
b0265429 421#endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
16a28ef2 422
09d8f077
AS
423static void __maybe_unused console_setfile_and_devices(int file, struct stdio_dev *dev)
424{
425 console_setfile(file, dev);
426 console_devices_set(file, dev);
427}
428
41f668b9
AS
429int console_start(int file, struct stdio_dev *sdev)
430{
431 int error;
432
95aaf402
AS
433 if (!console_needs_start_stop(file, sdev))
434 return 0;
435
41f668b9
AS
436 /* Start new device */
437 if (sdev->start) {
438 error = sdev->start(sdev);
439 /* If it's not started don't use it */
440 if (error < 0)
441 return error;
442 }
443 return 0;
444}
445
446void console_stop(int file, struct stdio_dev *sdev)
447{
95aaf402
AS
448 if (!console_needs_start_stop(file, sdev))
449 return;
450
41f668b9
AS
451 if (sdev->stop)
452 sdev->stop(sdev);
453}
454
47d1a6e1
WD
455/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
456
d9c27253 457int serial_printf(const char *fmt, ...)
47d1a6e1
WD
458{
459 va_list args;
460 uint i;
6d0f6bcf 461 char printbuffer[CONFIG_SYS_PBSIZE];
47d1a6e1 462
ec6f1499 463 va_start(args, fmt);
47d1a6e1
WD
464
465 /* For this to work, printbuffer must be larger than
466 * anything we ever want to print.
467 */
068af6f8 468 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
ec6f1499 469 va_end(args);
47d1a6e1 470
ec6f1499 471 serial_puts(printbuffer);
d9c27253 472 return i;
47d1a6e1
WD
473}
474
ec6f1499 475int fgetc(int file)
47d1a6e1 476{
16a28ef2 477 if (file < MAX_FILES) {
16a28ef2
GJ
478 /*
479 * Effectively poll for input wherever it may be available.
480 */
481 for (;;) {
64407467 482 WATCHDOG_RESET();
a17b38ce
PD
483 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
484 /*
485 * Upper layer may have already called tstc() so
486 * check for that first.
487 */
488 if (console_has_tstc())
489 return console_getc(file);
490 console_tstc(file);
491 } else {
492 if (console_tstc(file))
493 return console_getc(file);
494 }
495
16a28ef2
GJ
496 /*
497 * If the watchdog must be rate-limited then it should
498 * already be handled in board-specific code.
499 */
c04f8568
PD
500 if (IS_ENABLED(CONFIG_WATCHDOG))
501 udelay(1);
16a28ef2 502 }
16a28ef2 503 }
47d1a6e1
WD
504
505 return -1;
506}
507
ec6f1499 508int ftstc(int file)
47d1a6e1
WD
509{
510 if (file < MAX_FILES)
5f032010 511 return console_tstc(file);
47d1a6e1
WD
512
513 return -1;
514}
515
ec6f1499 516void fputc(int file, const char c)
47d1a6e1
WD
517{
518 if (file < MAX_FILES)
5f032010 519 console_putc(file, c);
47d1a6e1
WD
520}
521
ec6f1499 522void fputs(int file, const char *s)
47d1a6e1
WD
523{
524 if (file < MAX_FILES)
5f032010 525 console_puts(file, s);
47d1a6e1
WD
526}
527
d9c27253 528int fprintf(int file, const char *fmt, ...)
47d1a6e1
WD
529{
530 va_list args;
531 uint i;
6d0f6bcf 532 char printbuffer[CONFIG_SYS_PBSIZE];
47d1a6e1 533
ec6f1499 534 va_start(args, fmt);
47d1a6e1
WD
535
536 /* For this to work, printbuffer must be larger than
537 * anything we ever want to print.
538 */
068af6f8 539 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
ec6f1499 540 va_end(args);
47d1a6e1
WD
541
542 /* Send to desired file */
ec6f1499 543 fputs(file, printbuffer);
d9c27253 544 return i;
47d1a6e1
WD
545}
546
547/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
548
c670aeee 549int getchar(void)
47d1a6e1 550{
1e993710
PD
551 int ch;
552
c04f8568 553 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
f5c3ba79 554 return 0;
f5c3ba79 555
e3e454cd
GR
556 if (!gd->have_console)
557 return 0;
558
1e993710
PD
559 ch = console_record_getc();
560 if (ch != -1)
561 return ch;
9854a874 562
47d1a6e1
WD
563 if (gd->flags & GD_FLG_DEVINIT) {
564 /* Get from the standard input */
ec6f1499 565 return fgetc(stdin);
47d1a6e1
WD
566 }
567
568 /* Send directly to the handler */
ec6f1499 569 return serial_getc();
47d1a6e1
WD
570}
571
ec6f1499 572int tstc(void)
47d1a6e1 573{
c04f8568 574 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
f5c3ba79 575 return 0;
f5c3ba79 576
e3e454cd
GR
577 if (!gd->have_console)
578 return 0;
1e993710
PD
579
580 if (console_record_tstc())
581 return 1;
582
47d1a6e1
WD
583 if (gd->flags & GD_FLG_DEVINIT) {
584 /* Test the standard input */
ec6f1499 585 return ftstc(stdin);
47d1a6e1
WD
586 }
587
588 /* Send directly to the handler */
ec6f1499 589 return serial_tstc();
47d1a6e1
WD
590}
591
27669667
SS
592#define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0
593#define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1
594
8f925584 595#if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
cff29636 596#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_VAL(PRE_CON_BUF_SZ))
9558b48a
GR
597
598static void pre_console_putc(const char c)
599{
4e6bafa5
SG
600 char *buffer;
601
cff29636 602 buffer = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
9558b48a
GR
603
604 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
4e6bafa5
SG
605
606 unmap_sysmem(buffer);
9558b48a
GR
607}
608
be135cc5
SM
609static void pre_console_puts(const char *s)
610{
611 while (*s)
612 pre_console_putc(*s++);
613}
614
27669667 615static void print_pre_console_buffer(int flushpoint)
9558b48a 616{
a8552c7c 617 unsigned long in = 0, out = 0;
cff29636 618 char buf_out[CONFIG_VAL(PRE_CON_BUF_SZ) + 1];
4e6bafa5 619 char *buf_in;
9558b48a 620
c04f8568 621 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
13551b91 622 return;
13551b91 623
cff29636
RV
624 buf_in = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
625 if (gd->precon_buf_idx > CONFIG_VAL(PRE_CON_BUF_SZ))
626 in = gd->precon_buf_idx - CONFIG_VAL(PRE_CON_BUF_SZ);
9558b48a 627
a8552c7c
HG
628 while (in < gd->precon_buf_idx)
629 buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)];
4e6bafa5 630 unmap_sysmem(buf_in);
a8552c7c
HG
631
632 buf_out[out] = 0;
633
634 switch (flushpoint) {
635 case PRE_CONSOLE_FLUSHPOINT1_SERIAL:
636 puts(buf_out);
637 break;
638 case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL:
493a4c8a 639 console_puts_select(stdout, false, buf_out);
a8552c7c
HG
640 break;
641 }
9558b48a
GR
642}
643#else
644static inline void pre_console_putc(const char c) {}
be135cc5 645static inline void pre_console_puts(const char *s) {}
27669667 646static inline void print_pre_console_buffer(int flushpoint) {}
9558b48a
GR
647#endif
648
ec6f1499 649void putc(const char c)
47d1a6e1 650{
93cdb52b
PD
651 if (!gd)
652 return;
1e993710
PD
653
654 console_record_putc(c);
655
64e9b4f3 656 /* sandbox can send characters to stdout before it has a console */
c04f8568 657 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
64e9b4f3
SG
658 os_putc(c);
659 return;
660 }
c04f8568 661
d6ea5307 662 /* if we don't have a console yet, use the debug UART */
c04f8568 663 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
d6ea5307
SG
664 printch(c);
665 return;
666 }
c04f8568
PD
667
668 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
13551b91
PD
669 if (!(gd->flags & GD_FLG_DEVINIT))
670 pre_console_putc(c);
f6e20fc6 671 return;
13551b91 672 }
a6cccaea 673
c04f8568 674 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
f5c3ba79 675 return;
f5c3ba79 676
e3e454cd 677 if (!gd->have_console)
9558b48a 678 return pre_console_putc(c);
e3e454cd 679
47d1a6e1
WD
680 if (gd->flags & GD_FLG_DEVINIT) {
681 /* Send to the standard output */
ec6f1499 682 fputc(stdout, c);
47d1a6e1
WD
683 } else {
684 /* Send directly to the handler */
27669667 685 pre_console_putc(c);
ec6f1499 686 serial_putc(c);
47d1a6e1
WD
687 }
688}
689
ec6f1499 690void puts(const char *s)
47d1a6e1 691{
93cdb52b
PD
692 if (!gd)
693 return;
1e993710
PD
694
695 console_record_puts(s);
696
36bcea62 697 /* sandbox can send characters to stdout before it has a console */
c04f8568 698 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
36bcea62
SG
699 os_puts(s);
700 return;
701 }
c04f8568
PD
702
703 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
be135cc5
SM
704 while (*s) {
705 int ch = *s++;
706
707 printch(ch);
708 }
709 return;
710 }
c04f8568
PD
711
712 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
13551b91
PD
713 if (!(gd->flags & GD_FLG_DEVINIT))
714 pre_console_puts(s);
be135cc5 715 return;
13551b91 716 }
be135cc5 717
c04f8568 718 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
be135cc5 719 return;
be135cc5
SM
720
721 if (!gd->have_console)
722 return pre_console_puts(s);
723
724 if (gd->flags & GD_FLG_DEVINIT) {
725 /* Send to the standard output */
726 fputs(stdout, s);
727 } else {
728 /* Send directly to the handler */
729 pre_console_puts(s);
730 serial_puts(s);
731 }
47d1a6e1
WD
732}
733
9854a874
SG
734#ifdef CONFIG_CONSOLE_RECORD
735int console_record_init(void)
736{
737 int ret;
738
a3a9e046 739 ret = membuff_new((struct membuff *)&gd->console_out,
8ce465e4
SG
740 gd->flags & GD_FLG_RELOC ?
741 CONFIG_CONSOLE_RECORD_OUT_SIZE :
742 CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
9854a874
SG
743 if (ret)
744 return ret;
a3a9e046
HS
745 ret = membuff_new((struct membuff *)&gd->console_in,
746 CONFIG_CONSOLE_RECORD_IN_SIZE);
9854a874
SG
747
748 return ret;
749}
750
751void console_record_reset(void)
752{
a3a9e046
HS
753 membuff_purge((struct membuff *)&gd->console_out);
754 membuff_purge((struct membuff *)&gd->console_in);
c1a2bb4f 755 gd->flags &= ~GD_FLG_RECORD_OVF;
9854a874
SG
756}
757
bd347155 758int console_record_reset_enable(void)
9854a874
SG
759{
760 console_record_reset();
761 gd->flags |= GD_FLG_RECORD;
bd347155
SG
762
763 return 0;
9854a874 764}
b6123128
SG
765
766int console_record_readline(char *str, int maxlen)
767{
c1a2bb4f
SG
768 if (gd->flags & GD_FLG_RECORD_OVF)
769 return -ENOSPC;
770
a3a9e046
HS
771 return membuff_readline((struct membuff *)&gd->console_out, str,
772 maxlen, ' ');
b6123128
SG
773}
774
775int console_record_avail(void)
776{
a3a9e046 777 return membuff_avail((struct membuff *)&gd->console_out);
b6123128
SG
778}
779
25c8b9f2
SJ
780int console_in_puts(const char *str)
781{
782 return membuff_put((struct membuff *)&gd->console_in, str, strlen(str));
783}
784
9854a874
SG
785#endif
786
47d1a6e1
WD
787/* test if ctrl-c was pressed */
788static int ctrlc_disabled = 0; /* see disable_ctrl() */
789static int ctrlc_was_pressed = 0;
ec6f1499 790int ctrlc(void)
47d1a6e1 791{
47d1a6e1 792 if (!ctrlc_disabled && gd->have_console) {
ec6f1499 793 if (tstc()) {
c670aeee 794 switch (getchar()) {
47d1a6e1
WD
795 case 0x03: /* ^C - Control C */
796 ctrlc_was_pressed = 1;
797 return 1;
798 default:
799 break;
800 }
801 }
802 }
8969ea3e 803
47d1a6e1
WD
804 return 0;
805}
a5dffa4b
PA
806/* Reads user's confirmation.
807 Returns 1 if user's input is "y", "Y", "yes" or "YES"
808*/
809int confirm_yesno(void)
810{
811 int i;
812 char str_input[5];
813
814 /* Flush input */
815 while (tstc())
c670aeee 816 getchar();
a5dffa4b
PA
817 i = 0;
818 while (i < sizeof(str_input)) {
c670aeee 819 str_input[i] = getchar();
a5dffa4b
PA
820 putc(str_input[i]);
821 if (str_input[i] == '\r')
822 break;
823 i++;
824 }
825 putc('\n');
826 if (strncmp(str_input, "y\r", 2) == 0 ||
827 strncmp(str_input, "Y\r", 2) == 0 ||
828 strncmp(str_input, "yes\r", 4) == 0 ||
829 strncmp(str_input, "YES\r", 4) == 0)
830 return 1;
831 return 0;
832}
47d1a6e1
WD
833/* pass 1 to disable ctrlc() checking, 0 to enable.
834 * returns previous state
835 */
ec6f1499 836int disable_ctrlc(int disable)
47d1a6e1
WD
837{
838 int prev = ctrlc_disabled; /* save previous state */
839
840 ctrlc_disabled = disable;
841 return prev;
842}
843
844int had_ctrlc (void)
845{
846 return ctrlc_was_pressed;
847}
848
ec6f1499 849void clear_ctrlc(void)
47d1a6e1
WD
850{
851 ctrlc_was_pressed = 0;
852}
853
47d1a6e1
WD
854/** U-Boot INIT FUNCTIONS *************************************************/
855
3232487d 856struct stdio_dev *console_search_dev(int flags, const char *name)
c1de7a6d 857{
52cb4d4f 858 struct stdio_dev *dev;
c1de7a6d 859
52cb4d4f 860 dev = stdio_get_by_name(name);
a2931b30 861#ifdef CONFIG_VIDCONSOLE_AS_LCD
27b5b9ec 862 if (!dev && !strcmp(name, CONFIG_VIDCONSOLE_AS_NAME))
a2931b30
SG
863 dev = stdio_get_by_name("vidconsole");
864#endif
c1de7a6d 865
ec6f1499 866 if (dev && (dev->flags & flags))
c1de7a6d
JCPV
867 return dev;
868
869 return NULL;
870}
871
d7be3056 872int console_assign(int file, const char *devname)
47d1a6e1 873{
c1de7a6d 874 int flag;
52cb4d4f 875 struct stdio_dev *dev;
47d1a6e1
WD
876
877 /* Check for valid file */
7b9ca3f8
AS
878 flag = stdio_file_to_flags(file);
879 if (flag < 0)
880 return flag;
47d1a6e1
WD
881
882 /* Check for valid device name */
883
3232487d 884 dev = console_search_dev(flag, devname);
47d1a6e1 885
ec6f1499
JCPV
886 if (dev)
887 return console_setfile(file, dev);
47d1a6e1
WD
888
889 return -1;
890}
891
13551b91
PD
892/* return true if the 'silent' flag is removed */
893static bool console_update_silent(void)
47d1a6e1 894{
c04f8568 895 unsigned long flags = gd->flags;
13551b91 896
c04f8568
PD
897 if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
898 return false;
13551b91 899
c04f8568
PD
900 if (env_get("silent")) {
901 gd->flags |= GD_FLG_SILENT;
902 return false;
13551b91 903 }
13551b91 904
c04f8568
PD
905 gd->flags &= ~GD_FLG_SILENT;
906
907 return !!(flags & GD_FLG_SILENT);
43e0a3de
CP
908}
909
b0895384
SG
910int console_announce_r(void)
911{
912#if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
913 char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
914
915 display_options_get_banner(false, buf, sizeof(buf));
916
493a4c8a 917 console_puts_select(stdout, false, buf);
b0895384
SG
918#endif
919
920 return 0;
921}
922
43e0a3de
CP
923/* Called before relocation - use serial functions */
924int console_init_f(void)
925{
926 gd->have_console = 1;
927
928 console_update_silent();
f72da340 929
27669667 930 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
9558b48a 931
ec6f1499 932 return 0;
47d1a6e1
WD
933}
934
7e3be7cf
JCPV
935void stdio_print_current_devices(void)
936{
7e3be7cf
JCPV
937 /* Print information */
938 puts("In: ");
939 if (stdio_devices[stdin] == NULL) {
940 puts("No input devices available!\n");
941 } else {
942 printf ("%s\n", stdio_devices[stdin]->name);
943 }
944
945 puts("Out: ");
946 if (stdio_devices[stdout] == NULL) {
947 puts("No output devices available!\n");
948 } else {
949 printf ("%s\n", stdio_devices[stdout]->name);
950 }
951
952 puts("Err: ");
953 if (stdio_devices[stderr] == NULL) {
954 puts("No error devices available!\n");
955 } else {
956 printf ("%s\n", stdio_devices[stderr]->name);
957 }
7e3be7cf
JCPV
958}
959
b0265429 960#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
47d1a6e1 961/* Called after the relocation - use desired console functions */
ec6f1499 962int console_init_r(void)
47d1a6e1
WD
963{
964 char *stdinname, *stdoutname, *stderrname;
52cb4d4f 965 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
6e592385 966 int i;
16a28ef2 967 int iomux_err = 0;
13551b91 968 int flushpoint;
47d1a6e1 969
bf46be72 970 /* update silent for env loaded from flash (initr_env) */
13551b91
PD
971 if (console_update_silent())
972 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
973 else
974 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
bf46be72 975
47d1a6e1 976 /* set default handlers at first */
49cad547
MD
977 gd->jt->getc = serial_getc;
978 gd->jt->tstc = serial_tstc;
979 gd->jt->putc = serial_putc;
980 gd->jt->puts = serial_puts;
981 gd->jt->printf = serial_printf;
47d1a6e1
WD
982
983 /* stdin stdout and stderr are in environment */
984 /* scan for it */
00caae6d
SG
985 stdinname = env_get("stdin");
986 stdoutname = env_get("stdout");
987 stderrname = env_get("stderr");
47d1a6e1 988
53677ef1 989 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
3232487d
AS
990 inputdev = console_search_dev(DEV_FLAGS_INPUT, stdinname);
991 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, stdoutname);
992 errdev = console_search_dev(DEV_FLAGS_OUTPUT, stderrname);
c04f8568
PD
993 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
994 iomux_err = iomux_doenv(stdin, stdinname);
995 iomux_err += iomux_doenv(stdout, stdoutname);
996 iomux_err += iomux_doenv(stderr, stderrname);
997 if (!iomux_err)
998 /* Successful, so skip all the code below. */
999 goto done;
1000 }
47d1a6e1
WD
1001 }
1002 /* if the devices are overwritten or not found, use default device */
1003 if (inputdev == NULL) {
3232487d 1004 inputdev = console_search_dev(DEV_FLAGS_INPUT, "serial");
47d1a6e1
WD
1005 }
1006 if (outputdev == NULL) {
3232487d 1007 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
47d1a6e1
WD
1008 }
1009 if (errdev == NULL) {
3232487d 1010 errdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
47d1a6e1
WD
1011 }
1012 /* Initializes output console first */
1013 if (outputdev != NULL) {
16a28ef2 1014 /* need to set a console if not done above. */
5f032010 1015 console_doenv(stdout, outputdev);
47d1a6e1
WD
1016 }
1017 if (errdev != NULL) {
16a28ef2 1018 /* need to set a console if not done above. */
5f032010 1019 console_doenv(stderr, errdev);
47d1a6e1
WD
1020 }
1021 if (inputdev != NULL) {
16a28ef2 1022 /* need to set a console if not done above. */
5f032010 1023 console_doenv(stdin, inputdev);
47d1a6e1
WD
1024 }
1025
16a28ef2 1026done:
16a28ef2 1027
c04f8568
PD
1028 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1029 stdio_print_current_devices();
1030
a2931b30 1031#ifdef CONFIG_VIDCONSOLE_AS_LCD
27b5b9ec 1032 if (strstr(stdoutname, CONFIG_VIDCONSOLE_AS_NAME))
22b897a1 1033 printf("Warning: Please change '%s' to 'vidconsole' in stdout/stderr environment vars\n",
27b5b9ec 1034 CONFIG_VIDCONSOLE_AS_NAME);
a2931b30 1035#endif
47d1a6e1 1036
c04f8568
PD
1037 if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
1038 /* set the environment variables (will overwrite previous env settings) */
1039 for (i = 0; i < MAX_FILES; i++)
1040 env_set(stdio_names[i], stdio_devices[i]->name);
47d1a6e1 1041 }
47d1a6e1 1042
c4e0057f
JH
1043 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1044
13551b91 1045 print_pre_console_buffer(flushpoint);
ec6f1499 1046 return 0;
47d1a6e1
WD
1047}
1048
b0265429 1049#else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
47d1a6e1
WD
1050
1051/* Called after the relocation - use desired console functions */
ec6f1499 1052int console_init_r(void)
47d1a6e1 1053{
52cb4d4f 1054 struct stdio_dev *inputdev = NULL, *outputdev = NULL;
c1de7a6d 1055 int i;
52cb4d4f 1056 struct list_head *list = stdio_get_list();
c1de7a6d 1057 struct list_head *pos;
52cb4d4f 1058 struct stdio_dev *dev;
13551b91 1059 int flushpoint;
47d1a6e1 1060
bf46be72 1061 /* update silent for env loaded from flash (initr_env) */
13551b91
PD
1062 if (console_update_silent())
1063 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
1064 else
1065 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
43e0a3de 1066
ec6f1499
JCPV
1067 /*
1068 * suppress all output if splash screen is enabled and we have
a7490816
AG
1069 * a bmp to display. We redirect the output from frame buffer
1070 * console to serial console in this case or suppress it if
1071 * "silent" mode was requested.
ec6f1499 1072 */
c04f8568 1073 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
a7490816 1074 if (!(gd->flags & GD_FLG_SILENT))
3232487d 1075 outputdev = console_search_dev (DEV_FLAGS_OUTPUT, "serial");
a7490816 1076 }
f72da340 1077
47d1a6e1 1078 /* Scan devices looking for input and output devices */
c1de7a6d 1079 list_for_each(pos, list) {
52cb4d4f 1080 dev = list_entry(pos, struct stdio_dev, list);
47d1a6e1
WD
1081
1082 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
1083 inputdev = dev;
1084 }
1085 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
1086 outputdev = dev;
1087 }
c1de7a6d
JCPV
1088 if(inputdev && outputdev)
1089 break;
47d1a6e1
WD
1090 }
1091
1092 /* Initializes output console first */
1093 if (outputdev != NULL) {
09d8f077
AS
1094 console_setfile_and_devices(stdout, outputdev);
1095 console_setfile_and_devices(stderr, outputdev);
47d1a6e1
WD
1096 }
1097
1098 /* Initializes input console */
09d8f077
AS
1099 if (inputdev != NULL)
1100 console_setfile_and_devices(stdin, inputdev);
47d1a6e1 1101
c04f8568
PD
1102 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1103 stdio_print_current_devices();
47d1a6e1
WD
1104
1105 /* Setting environment variables */
27b4225b 1106 for (i = 0; i < MAX_FILES; i++) {
382bee57 1107 env_set(stdio_names[i], stdio_devices[i]->name);
47d1a6e1
WD
1108 }
1109
c4e0057f
JH
1110 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1111
13551b91 1112 print_pre_console_buffer(flushpoint);
ec6f1499 1113 return 0;
47d1a6e1
WD
1114}
1115
b0265429 1116#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
This page took 0.508196 seconds and 4 git commands to generate.