blob: 295c10f2425cfc1d3cc8813e334262b5efc8630b [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk47d1a6e2002-11-03 00:01:44 +00002/*
3 * (C) Copyright 2000
4 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
wdenk47d1a6e2002-11-03 00:01:44 +00005 */
6
7#include <common.h>
Simon Glass24b852a2015-11-08 23:47:45 -07008#include <console.h>
Simon Glassd6ea5302015-06-23 15:38:33 -06009#include <debug_uart.h>
Simon Glass7b3c4c32017-07-27 09:31:04 -060010#include <dm.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060011#include <env.h>
wdenk47d1a6e2002-11-03 00:01:44 +000012#include <stdarg.h>
Jeroen Hofstee482f4692014-10-08 22:57:48 +020013#include <iomux.h>
wdenk47d1a6e2002-11-03 00:01:44 +000014#include <malloc.h>
Simon Glass4e6bafa2017-06-15 21:37:52 -060015#include <mapmem.h>
Simon Glass91b136c2013-11-10 10:27:01 -070016#include <os.h>
Joe Hershberger849d5d92012-12-11 22:16:29 -060017#include <serial.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020018#include <stdio_dev.h>
wdenk27b207f2003-07-24 23:38:38 +000019#include <exports.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060020#include <env_internal.h>
Andreas J. Reichel64407462016-07-13 12:56:51 +020021#include <watchdog.h>
Simon Glassc05ed002020-05-10 11:40:11 -060022#include <linux/delay.h>
wdenk47d1a6e2002-11-03 00:01:44 +000023
Wolfgang Denkd87080b2006-03-31 18:32:53 +020024DECLARE_GLOBAL_DATA_PTR;
25
Joe Hershberger849d5d92012-12-11 22:16:29 -060026static 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
Patrick Delaunayc04f8562020-12-18 12:46:43 +010047 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
Joe Hershberger849d5d92012-12-11 22:16:29 -060056 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}
67U_BOOT_ENV_CALLBACK(console, on_console);
68
Joe Hershbergere080d542012-12-11 22:16:30 -060069#ifdef CONFIG_SILENT_CONSOLE
70static int on_silent(const char *name, const char *value, enum env_op op,
71 int flags)
72{
Patrick Delaunayc04f8562020-12-18 12:46:43 +010073 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;
Joe Hershbergere080d542012-12-11 22:16:30 -060080
81 if (value != NULL)
82 gd->flags |= GD_FLG_SILENT;
83 else
84 gd->flags &= ~GD_FLG_SILENT;
85
86 return 0;
87}
88U_BOOT_ENV_CALLBACK(silent, on_silent);
89#endif
90
Patrick Delaunay1e993712020-12-18 12:46:45 +010091#ifdef CONFIG_CONSOLE_RECORD
92/* helper function: access to gd->console_out and gd->console_in */
93static 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
101static 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
109static 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
119static 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
130static void console_record_putc(char c)
131{
132}
133
134static void console_record_puts(const char *s)
135{
136}
137
138static int console_record_getc(void)
139{
140 return -1;
141}
142
143static int console_record_tstc(void)
144{
145 return 0;
146}
147#endif
148
Simon Glassb0265422017-01-16 07:03:26 -0700149#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
wdenk47d1a6e2002-11-03 00:01:44 +0000150/*
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 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200155#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100156extern int overwrite_console(void);
157#define OVERWRITE_CONSOLE overwrite_console()
wdenk47d1a6e2002-11-03 00:01:44 +0000158#else
wdenk83e40ba2005-03-31 18:42:15 +0000159#define OVERWRITE_CONSOLE 0
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200160#endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
wdenk47d1a6e2002-11-03 00:01:44 +0000161
Simon Glassb0265422017-01-16 07:03:26 -0700162#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
wdenk47d1a6e2002-11-03 00:01:44 +0000163
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200164static int console_setfile(int file, struct stdio_dev * dev)
wdenk47d1a6e2002-11-03 00:01:44 +0000165{
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 /* Start new device */
176 if (dev->start) {
Simon Glass709ea542014-07-23 06:54:59 -0600177 error = dev->start(dev);
wdenk47d1a6e2002-11-03 00:01:44 +0000178 /* If it's not started dont use it */
179 if (error < 0)
180 break;
181 }
182
183 /* Assign the new device (leaving the existing one started) */
184 stdio_devices[file] = dev;
185
186 /*
187 * Update monitor functions
188 * (to use the console stuff by other applications)
189 */
190 switch (file) {
191 case stdin:
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200192 gd->jt->getc = getchar;
Martin Dorwig49cad542015-01-26 15:22:54 -0700193 gd->jt->tstc = tstc;
wdenk47d1a6e2002-11-03 00:01:44 +0000194 break;
195 case stdout:
Martin Dorwig49cad542015-01-26 15:22:54 -0700196 gd->jt->putc = putc;
197 gd->jt->puts = puts;
198 gd->jt->printf = printf;
wdenk47d1a6e2002-11-03 00:01:44 +0000199 break;
200 }
201 break;
202
203 default: /* Invalid file ID */
204 error = -1;
205 }
206 return error;
207}
208
Simon Glass42f9f912017-07-27 09:31:03 -0600209/**
210 * console_dev_is_serial() - Check if a stdio device is a serial device
211 *
212 * @sdev: Device to check
Simon Glass7b3c4c32017-07-27 09:31:04 -0600213 * @return true if this device is in the serial uclass (or for pre-driver-model,
214 * whether it is called "serial".
Simon Glass42f9f912017-07-27 09:31:03 -0600215 */
216static bool console_dev_is_serial(struct stdio_dev *sdev)
217{
218 bool is_serial;
219
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100220 if (IS_ENABLED(CONFIG_DM_SERIAL) && (sdev->flags & DEV_FLAGS_DM)) {
Simon Glass7b3c4c32017-07-27 09:31:04 -0600221 struct udevice *dev = sdev->priv;
222
223 is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100224 } else {
225 is_serial = !strcmp(sdev->name, "serial");
226 }
Simon Glass42f9f912017-07-27 09:31:03 -0600227
228 return is_serial;
229}
230
Simon Glassb0265422017-01-16 07:03:26 -0700231#if CONFIG_IS_ENABLED(CONSOLE_MUX)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100232/** Console I/O multiplexing *******************************************/
233
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200234static struct stdio_dev *tstcdev;
235struct stdio_dev **console_devices[MAX_FILES];
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100236int cd_count[MAX_FILES];
237
Patrick Delaunay45375ad2020-12-18 12:46:44 +0100238static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
239{
240 console_devices[file][0] = dev;
241}
242
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100243/*
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200244 * This depends on tstc() always being called before getchar().
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100245 * This is guaranteed to be true because this routine is called
246 * only from fgetc() which assures it.
247 * No attempt is made to demultiplex multiple input sources.
248 */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100249static int console_getc(int file)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100250{
251 unsigned char ret;
252
253 /* This is never called with testcdev == NULL */
Simon Glass709ea542014-07-23 06:54:59 -0600254 ret = tstcdev->getc(tstcdev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100255 tstcdev = NULL;
256 return ret;
257}
258
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100259static int console_tstc(int file)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100260{
261 int i, ret;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200262 struct stdio_dev *dev;
Joe Hershbergerb2f58d82018-07-02 20:06:48 -0500263 int prev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100264
Joe Hershbergerb2f58d82018-07-02 20:06:48 -0500265 prev = disable_ctrlc(1);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100266 for (i = 0; i < cd_count[file]; i++) {
267 dev = console_devices[file][i];
268 if (dev->tstc != NULL) {
Simon Glass709ea542014-07-23 06:54:59 -0600269 ret = dev->tstc(dev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100270 if (ret > 0) {
271 tstcdev = dev;
Joe Hershbergerb2f58d82018-07-02 20:06:48 -0500272 disable_ctrlc(prev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100273 return ret;
274 }
275 }
276 }
Joe Hershbergerb2f58d82018-07-02 20:06:48 -0500277 disable_ctrlc(prev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100278
279 return 0;
280}
281
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100282static void console_putc(int file, const char c)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100283{
284 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200285 struct stdio_dev *dev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100286
287 for (i = 0; i < cd_count[file]; i++) {
288 dev = console_devices[file][i];
289 if (dev->putc != NULL)
Simon Glass709ea542014-07-23 06:54:59 -0600290 dev->putc(dev, c);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100291 }
292}
293
Simon Glass493a4c82020-07-02 21:12:13 -0600294/**
295 * console_puts_select() - Output a string to all console devices
296 *
297 * @file: File number to output to (e,g, stdout, see stdio.h)
298 * @serial_only: true to output only to serial, false to output to everything
299 * else
300 * @s: String to output
301 */
302static void console_puts_select(int file, bool serial_only, const char *s)
Siarhei Siamashka27669662015-01-08 09:02:31 +0200303{
304 int i;
305 struct stdio_dev *dev;
306
307 for (i = 0; i < cd_count[file]; i++) {
Simon Glass493a4c82020-07-02 21:12:13 -0600308 bool is_serial;
309
Siarhei Siamashka27669662015-01-08 09:02:31 +0200310 dev = console_devices[file][i];
Simon Glass493a4c82020-07-02 21:12:13 -0600311 is_serial = console_dev_is_serial(dev);
312 if (dev->puts && serial_only == is_serial)
Hans de Goedea8552c72015-05-05 13:13:36 +0200313 dev->puts(dev, s);
Siarhei Siamashka27669662015-01-08 09:02:31 +0200314 }
315}
Siarhei Siamashka27669662015-01-08 09:02:31 +0200316
Simon Glass493a4c82020-07-02 21:12:13 -0600317void console_puts_select_stderr(bool serial_only, const char *s)
318{
319 console_puts_select(stderr, serial_only, s);
320}
321
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100322static void console_puts(int file, const char *s)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100323{
324 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200325 struct stdio_dev *dev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100326
327 for (i = 0; i < cd_count[file]; i++) {
328 dev = console_devices[file][i];
329 if (dev->puts != NULL)
Simon Glass709ea542014-07-23 06:54:59 -0600330 dev->puts(dev, s);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100331 }
332}
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100333
Tom Rini5e63c962019-10-30 09:18:43 -0400334#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200335static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100336{
337 iomux_doenv(file, dev->name);
338}
Tom Rini5e63c962019-10-30 09:18:43 -0400339#endif
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100340#else
Patrick Delaunay45375ad2020-12-18 12:46:44 +0100341
342static void __maybe_unused console_devices_set(int file, struct stdio_dev *dev)
343{
344}
345
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100346static inline int console_getc(int file)
347{
Simon Glass709ea542014-07-23 06:54:59 -0600348 return stdio_devices[file]->getc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100349}
350
351static inline int console_tstc(int file)
352{
Simon Glass709ea542014-07-23 06:54:59 -0600353 return stdio_devices[file]->tstc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100354}
355
356static inline void console_putc(int file, const char c)
357{
Simon Glass709ea542014-07-23 06:54:59 -0600358 stdio_devices[file]->putc(stdio_devices[file], c);
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100359}
360
Simon Glass493a4c82020-07-02 21:12:13 -0600361void console_puts_select(int file, bool serial_only, const char *s)
Siarhei Siamashka27669662015-01-08 09:02:31 +0200362{
Simon Glass493a4c82020-07-02 21:12:13 -0600363 if (serial_only == console_dev_is_serial(stdio_devices[file]))
Hans de Goedea8552c72015-05-05 13:13:36 +0200364 stdio_devices[file]->puts(stdio_devices[file], s);
Siarhei Siamashka27669662015-01-08 09:02:31 +0200365}
Siarhei Siamashka27669662015-01-08 09:02:31 +0200366
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100367static inline void console_puts(int file, const char *s)
368{
Simon Glass709ea542014-07-23 06:54:59 -0600369 stdio_devices[file]->puts(stdio_devices[file], s);
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100370}
371
Tom Rini5e63c962019-10-30 09:18:43 -0400372#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200373static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100374{
375 console_setfile(file, dev);
376}
Tom Rini5e63c962019-10-30 09:18:43 -0400377#endif
Simon Glassb0265422017-01-16 07:03:26 -0700378#endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100379
wdenk47d1a6e2002-11-03 00:01:44 +0000380/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
381
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200382int serial_printf(const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000383{
384 va_list args;
385 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200386 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000387
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100388 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000389
390 /* For this to work, printbuffer must be larger than
391 * anything we ever want to print.
392 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000393 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100394 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000395
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100396 serial_puts(printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200397 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000398}
399
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100400int fgetc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000401{
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100402 if (file < MAX_FILES) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100403 /*
404 * Effectively poll for input wherever it may be available.
405 */
406 for (;;) {
Andreas J. Reichel64407462016-07-13 12:56:51 +0200407 WATCHDOG_RESET();
Patrick Delaunay273a1252018-08-03 13:38:44 +0200408#if CONFIG_IS_ENABLED(CONSOLE_MUX)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100409 /*
410 * Upper layer may have already called tstc() so
411 * check for that first.
412 */
413 if (tstcdev != NULL)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100414 return console_getc(file);
415 console_tstc(file);
Patrick Delaunay273a1252018-08-03 13:38:44 +0200416#else
417 if (console_tstc(file))
418 return console_getc(file);
419#endif
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100420 /*
421 * If the watchdog must be rate-limited then it should
422 * already be handled in board-specific code.
423 */
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100424 if (IS_ENABLED(CONFIG_WATCHDOG))
425 udelay(1);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100426 }
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100427 }
wdenk47d1a6e2002-11-03 00:01:44 +0000428
429 return -1;
430}
431
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100432int ftstc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000433{
434 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100435 return console_tstc(file);
wdenk47d1a6e2002-11-03 00:01:44 +0000436
437 return -1;
438}
439
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100440void fputc(int file, const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000441{
442 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100443 console_putc(file, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000444}
445
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100446void fputs(int file, const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000447{
448 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100449 console_puts(file, s);
wdenk47d1a6e2002-11-03 00:01:44 +0000450}
451
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200452int fprintf(int file, const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000453{
454 va_list args;
455 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200456 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000457
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100458 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000459
460 /* For this to work, printbuffer must be larger than
461 * anything we ever want to print.
462 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000463 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100464 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000465
466 /* Send to desired file */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100467 fputs(file, printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200468 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000469}
470
471/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
472
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200473int getchar(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000474{
Patrick Delaunay1e993712020-12-18 12:46:45 +0100475 int ch;
476
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100477 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100478 return 0;
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100479
Graeme Russe3e454c2011-08-29 02:14:05 +0000480 if (!gd->have_console)
481 return 0;
482
Patrick Delaunay1e993712020-12-18 12:46:45 +0100483 ch = console_record_getc();
484 if (ch != -1)
485 return ch;
Simon Glass9854a872015-11-08 23:47:48 -0700486
wdenk47d1a6e2002-11-03 00:01:44 +0000487 if (gd->flags & GD_FLG_DEVINIT) {
488 /* Get from the standard input */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100489 return fgetc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000490 }
491
492 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100493 return serial_getc();
wdenk47d1a6e2002-11-03 00:01:44 +0000494}
495
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100496int tstc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000497{
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100498 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100499 return 0;
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100500
Graeme Russe3e454c2011-08-29 02:14:05 +0000501 if (!gd->have_console)
502 return 0;
Patrick Delaunay1e993712020-12-18 12:46:45 +0100503
504 if (console_record_tstc())
505 return 1;
506
wdenk47d1a6e2002-11-03 00:01:44 +0000507 if (gd->flags & GD_FLG_DEVINIT) {
508 /* Test the standard input */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100509 return ftstc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000510 }
511
512 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100513 return serial_tstc();
wdenk47d1a6e2002-11-03 00:01:44 +0000514}
515
Siarhei Siamashka27669662015-01-08 09:02:31 +0200516#define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0
517#define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1
518
Simon Glass8f925582016-10-17 20:12:36 -0600519#if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
Graeme Russ9558b482011-09-01 00:48:27 +0000520#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ)
521
522static void pre_console_putc(const char c)
523{
Simon Glass4e6bafa2017-06-15 21:37:52 -0600524 char *buffer;
525
526 buffer = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
Graeme Russ9558b482011-09-01 00:48:27 +0000527
528 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
Simon Glass4e6bafa2017-06-15 21:37:52 -0600529
530 unmap_sysmem(buffer);
Graeme Russ9558b482011-09-01 00:48:27 +0000531}
532
Soeren Mochbe135cc2017-11-04 16:14:09 +0100533static void pre_console_puts(const char *s)
534{
535 while (*s)
536 pre_console_putc(*s++);
537}
538
Siarhei Siamashka27669662015-01-08 09:02:31 +0200539static void print_pre_console_buffer(int flushpoint)
Graeme Russ9558b482011-09-01 00:48:27 +0000540{
Hans de Goedea8552c72015-05-05 13:13:36 +0200541 unsigned long in = 0, out = 0;
Hans de Goedea8552c72015-05-05 13:13:36 +0200542 char buf_out[CONFIG_PRE_CON_BUF_SZ + 1];
Simon Glass4e6bafa2017-06-15 21:37:52 -0600543 char *buf_in;
Graeme Russ9558b482011-09-01 00:48:27 +0000544
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100545 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
Patrick Delaunay13551b92019-08-02 14:58:10 +0200546 return;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200547
Simon Glass4e6bafa2017-06-15 21:37:52 -0600548 buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
Graeme Russ9558b482011-09-01 00:48:27 +0000549 if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
Hans de Goedea8552c72015-05-05 13:13:36 +0200550 in = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ;
Graeme Russ9558b482011-09-01 00:48:27 +0000551
Hans de Goedea8552c72015-05-05 13:13:36 +0200552 while (in < gd->precon_buf_idx)
553 buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)];
Simon Glass4e6bafa2017-06-15 21:37:52 -0600554 unmap_sysmem(buf_in);
Hans de Goedea8552c72015-05-05 13:13:36 +0200555
556 buf_out[out] = 0;
557
558 switch (flushpoint) {
559 case PRE_CONSOLE_FLUSHPOINT1_SERIAL:
560 puts(buf_out);
561 break;
562 case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL:
Simon Glass493a4c82020-07-02 21:12:13 -0600563 console_puts_select(stdout, false, buf_out);
Hans de Goedea8552c72015-05-05 13:13:36 +0200564 break;
565 }
Graeme Russ9558b482011-09-01 00:48:27 +0000566}
567#else
568static inline void pre_console_putc(const char c) {}
Soeren Mochbe135cc2017-11-04 16:14:09 +0100569static inline void pre_console_puts(const char *s) {}
Siarhei Siamashka27669662015-01-08 09:02:31 +0200570static inline void print_pre_console_buffer(int flushpoint) {}
Graeme Russ9558b482011-09-01 00:48:27 +0000571#endif
572
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100573void putc(const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000574{
Patrick Delaunay93cdb522020-11-27 11:20:56 +0100575 if (!gd)
576 return;
Patrick Delaunay1e993712020-12-18 12:46:45 +0100577
578 console_record_putc(c);
579
Simon Glass64e9b4f2017-12-04 13:48:19 -0700580 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100581 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass64e9b4f2017-12-04 13:48:19 -0700582 os_putc(c);
583 return;
584 }
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100585
Simon Glassd6ea5302015-06-23 15:38:33 -0600586 /* if we don't have a console yet, use the debug UART */
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100587 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glassd6ea5302015-06-23 15:38:33 -0600588 printch(c);
589 return;
590 }
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100591
592 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunay13551b92019-08-02 14:58:10 +0200593 if (!(gd->flags & GD_FLG_DEVINIT))
594 pre_console_putc(c);
wdenkf6e20fc2004-02-08 19:38:38 +0000595 return;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200596 }
wdenka6cccae2004-02-06 21:48:22 +0000597
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100598 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100599 return;
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100600
Graeme Russe3e454c2011-08-29 02:14:05 +0000601 if (!gd->have_console)
Graeme Russ9558b482011-09-01 00:48:27 +0000602 return pre_console_putc(c);
Graeme Russe3e454c2011-08-29 02:14:05 +0000603
wdenk47d1a6e2002-11-03 00:01:44 +0000604 if (gd->flags & GD_FLG_DEVINIT) {
605 /* Send to the standard output */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100606 fputc(stdout, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000607 } else {
608 /* Send directly to the handler */
Siarhei Siamashka27669662015-01-08 09:02:31 +0200609 pre_console_putc(c);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100610 serial_putc(c);
wdenk47d1a6e2002-11-03 00:01:44 +0000611 }
612}
613
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100614void puts(const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000615{
Patrick Delaunay93cdb522020-11-27 11:20:56 +0100616 if (!gd)
617 return;
Patrick Delaunay1e993712020-12-18 12:46:45 +0100618
619 console_record_puts(s);
620
Simon Glass36bcea62018-11-15 18:44:04 -0700621 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100622 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass36bcea62018-11-15 18:44:04 -0700623 os_puts(s);
624 return;
625 }
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100626
627 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Soeren Mochbe135cc2017-11-04 16:14:09 +0100628 while (*s) {
629 int ch = *s++;
630
631 printch(ch);
632 }
633 return;
634 }
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100635
636 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunay13551b92019-08-02 14:58:10 +0200637 if (!(gd->flags & GD_FLG_DEVINIT))
638 pre_console_puts(s);
Soeren Mochbe135cc2017-11-04 16:14:09 +0100639 return;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200640 }
Soeren Mochbe135cc2017-11-04 16:14:09 +0100641
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100642 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Soeren Mochbe135cc2017-11-04 16:14:09 +0100643 return;
Soeren Mochbe135cc2017-11-04 16:14:09 +0100644
645 if (!gd->have_console)
646 return pre_console_puts(s);
647
648 if (gd->flags & GD_FLG_DEVINIT) {
649 /* Send to the standard output */
650 fputs(stdout, s);
651 } else {
652 /* Send directly to the handler */
653 pre_console_puts(s);
654 serial_puts(s);
655 }
wdenk47d1a6e2002-11-03 00:01:44 +0000656}
657
Simon Glass9854a872015-11-08 23:47:48 -0700658#ifdef CONFIG_CONSOLE_RECORD
659int console_record_init(void)
660{
661 int ret;
662
Heinrich Schuchardta3a9e042020-02-12 18:23:49 +0100663 ret = membuff_new((struct membuff *)&gd->console_out,
664 CONFIG_CONSOLE_RECORD_OUT_SIZE);
Simon Glass9854a872015-11-08 23:47:48 -0700665 if (ret)
666 return ret;
Heinrich Schuchardta3a9e042020-02-12 18:23:49 +0100667 ret = membuff_new((struct membuff *)&gd->console_in,
668 CONFIG_CONSOLE_RECORD_IN_SIZE);
Simon Glass9854a872015-11-08 23:47:48 -0700669
670 return ret;
671}
672
673void console_record_reset(void)
674{
Heinrich Schuchardta3a9e042020-02-12 18:23:49 +0100675 membuff_purge((struct membuff *)&gd->console_out);
676 membuff_purge((struct membuff *)&gd->console_in);
Simon Glass9854a872015-11-08 23:47:48 -0700677}
678
Simon Glassbd347152020-07-28 19:41:11 -0600679int console_record_reset_enable(void)
Simon Glass9854a872015-11-08 23:47:48 -0700680{
681 console_record_reset();
682 gd->flags |= GD_FLG_RECORD;
Simon Glassbd347152020-07-28 19:41:11 -0600683
684 return 0;
Simon Glass9854a872015-11-08 23:47:48 -0700685}
Simon Glassb6123122020-01-27 08:49:54 -0700686
687int console_record_readline(char *str, int maxlen)
688{
Heinrich Schuchardta3a9e042020-02-12 18:23:49 +0100689 return membuff_readline((struct membuff *)&gd->console_out, str,
690 maxlen, ' ');
Simon Glassb6123122020-01-27 08:49:54 -0700691}
692
693int console_record_avail(void)
694{
Heinrich Schuchardta3a9e042020-02-12 18:23:49 +0100695 return membuff_avail((struct membuff *)&gd->console_out);
Simon Glassb6123122020-01-27 08:49:54 -0700696}
697
Simon Glass9854a872015-11-08 23:47:48 -0700698#endif
699
wdenk47d1a6e2002-11-03 00:01:44 +0000700/* test if ctrl-c was pressed */
701static int ctrlc_disabled = 0; /* see disable_ctrl() */
702static int ctrlc_was_pressed = 0;
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100703int ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000704{
wdenk47d1a6e2002-11-03 00:01:44 +0000705 if (!ctrlc_disabled && gd->have_console) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100706 if (tstc()) {
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200707 switch (getchar()) {
wdenk47d1a6e2002-11-03 00:01:44 +0000708 case 0x03: /* ^C - Control C */
709 ctrlc_was_pressed = 1;
710 return 1;
711 default:
712 break;
713 }
714 }
715 }
Simon Glass8969ea32014-09-14 12:40:15 -0600716
wdenk47d1a6e2002-11-03 00:01:44 +0000717 return 0;
718}
Pierre Auberta5dffa42014-04-24 10:30:07 +0200719/* Reads user's confirmation.
720 Returns 1 if user's input is "y", "Y", "yes" or "YES"
721*/
722int confirm_yesno(void)
723{
724 int i;
725 char str_input[5];
wdenk47d1a6e2002-11-03 00:01:44 +0000726
Pierre Auberta5dffa42014-04-24 10:30:07 +0200727 /* Flush input */
728 while (tstc())
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200729 getchar();
Pierre Auberta5dffa42014-04-24 10:30:07 +0200730 i = 0;
731 while (i < sizeof(str_input)) {
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200732 str_input[i] = getchar();
Pierre Auberta5dffa42014-04-24 10:30:07 +0200733 putc(str_input[i]);
734 if (str_input[i] == '\r')
735 break;
736 i++;
737 }
738 putc('\n');
739 if (strncmp(str_input, "y\r", 2) == 0 ||
740 strncmp(str_input, "Y\r", 2) == 0 ||
741 strncmp(str_input, "yes\r", 4) == 0 ||
742 strncmp(str_input, "YES\r", 4) == 0)
743 return 1;
744 return 0;
745}
wdenk47d1a6e2002-11-03 00:01:44 +0000746/* pass 1 to disable ctrlc() checking, 0 to enable.
747 * returns previous state
748 */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100749int disable_ctrlc(int disable)
wdenk47d1a6e2002-11-03 00:01:44 +0000750{
751 int prev = ctrlc_disabled; /* save previous state */
752
753 ctrlc_disabled = disable;
754 return prev;
755}
756
757int had_ctrlc (void)
758{
759 return ctrlc_was_pressed;
760}
761
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100762void clear_ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000763{
764 ctrlc_was_pressed = 0;
765}
766
wdenk47d1a6e2002-11-03 00:01:44 +0000767/** U-Boot INIT FUNCTIONS *************************************************/
768
Mike Frysingerd7be3052010-10-20 07:18:03 -0400769struct stdio_dev *search_device(int flags, const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200770{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200771 struct stdio_dev *dev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200772
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200773 dev = stdio_get_by_name(name);
Simon Glassa2931b32016-02-06 14:31:37 -0700774#ifdef CONFIG_VIDCONSOLE_AS_LCD
Patrick Delaunay27b5b9e2020-07-01 14:56:10 +0200775 if (!dev && !strcmp(name, CONFIG_VIDCONSOLE_AS_NAME))
Simon Glassa2931b32016-02-06 14:31:37 -0700776 dev = stdio_get_by_name("vidconsole");
777#endif
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200778
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100779 if (dev && (dev->flags & flags))
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200780 return dev;
781
782 return NULL;
783}
784
Mike Frysingerd7be3052010-10-20 07:18:03 -0400785int console_assign(int file, const char *devname)
wdenk47d1a6e2002-11-03 00:01:44 +0000786{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200787 int flag;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200788 struct stdio_dev *dev;
wdenk47d1a6e2002-11-03 00:01:44 +0000789
790 /* Check for valid file */
791 switch (file) {
792 case stdin:
793 flag = DEV_FLAGS_INPUT;
794 break;
795 case stdout:
796 case stderr:
797 flag = DEV_FLAGS_OUTPUT;
798 break;
799 default:
800 return -1;
801 }
802
803 /* Check for valid device name */
804
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200805 dev = search_device(flag, devname);
wdenk47d1a6e2002-11-03 00:01:44 +0000806
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100807 if (dev)
808 return console_setfile(file, dev);
wdenk47d1a6e2002-11-03 00:01:44 +0000809
810 return -1;
811}
812
Patrick Delaunay13551b92019-08-02 14:58:10 +0200813/* return true if the 'silent' flag is removed */
814static bool console_update_silent(void)
Chris Packham43e0a3d2016-09-23 15:59:43 +1200815{
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100816 unsigned long flags = gd->flags;
817
818 if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
819 return false;
820
Patrick Delaunay13551b92019-08-02 14:58:10 +0200821 if (env_get("silent")) {
Chris Packham43e0a3d2016-09-23 15:59:43 +1200822 gd->flags |= GD_FLG_SILENT;
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100823 return false;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200824 }
Patrick Delaunay13551b92019-08-02 14:58:10 +0200825
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100826 gd->flags &= ~GD_FLG_SILENT;
827
828 return !!(flags & GD_FLG_SILENT);
Chris Packham43e0a3d2016-09-23 15:59:43 +1200829}
830
Simon Glassb0895382017-06-15 21:37:50 -0600831int console_announce_r(void)
832{
833#if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
834 char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
835
836 display_options_get_banner(false, buf, sizeof(buf));
837
Simon Glass493a4c82020-07-02 21:12:13 -0600838 console_puts_select(stdout, false, buf);
Simon Glassb0895382017-06-15 21:37:50 -0600839#endif
840
841 return 0;
842}
843
wdenk47d1a6e2002-11-03 00:01:44 +0000844/* Called before relocation - use serial functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100845int console_init_f(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000846{
wdenk47d1a6e2002-11-03 00:01:44 +0000847 gd->have_console = 1;
wdenkf72da342003-10-10 10:05:42 +0000848
Chris Packham43e0a3d2016-09-23 15:59:43 +1200849 console_update_silent();
wdenkf72da342003-10-10 10:05:42 +0000850
Siarhei Siamashka27669662015-01-08 09:02:31 +0200851 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
Graeme Russ9558b482011-09-01 00:48:27 +0000852
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100853 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000854}
855
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200856void stdio_print_current_devices(void)
857{
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200858 /* Print information */
859 puts("In: ");
860 if (stdio_devices[stdin] == NULL) {
861 puts("No input devices available!\n");
862 } else {
863 printf ("%s\n", stdio_devices[stdin]->name);
864 }
865
866 puts("Out: ");
867 if (stdio_devices[stdout] == NULL) {
868 puts("No output devices available!\n");
869 } else {
870 printf ("%s\n", stdio_devices[stdout]->name);
871 }
872
873 puts("Err: ");
874 if (stdio_devices[stderr] == NULL) {
875 puts("No error devices available!\n");
876 } else {
877 printf ("%s\n", stdio_devices[stderr]->name);
878 }
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200879}
880
Simon Glassb0265422017-01-16 07:03:26 -0700881#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
wdenk47d1a6e2002-11-03 00:01:44 +0000882/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100883int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000884{
885 char *stdinname, *stdoutname, *stderrname;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200886 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
wdenk6e592382004-04-18 17:39:38 +0000887 int i;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100888 int iomux_err = 0;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200889 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +0000890
Patrick Delaunaybf46be72019-08-02 14:58:09 +0200891 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunay13551b92019-08-02 14:58:10 +0200892 if (console_update_silent())
893 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
894 else
895 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Patrick Delaunaybf46be72019-08-02 14:58:09 +0200896
wdenk47d1a6e2002-11-03 00:01:44 +0000897 /* set default handlers at first */
Martin Dorwig49cad542015-01-26 15:22:54 -0700898 gd->jt->getc = serial_getc;
899 gd->jt->tstc = serial_tstc;
900 gd->jt->putc = serial_putc;
901 gd->jt->puts = serial_puts;
902 gd->jt->printf = serial_printf;
wdenk47d1a6e2002-11-03 00:01:44 +0000903
904 /* stdin stdout and stderr are in environment */
905 /* scan for it */
Simon Glass00caae62017-08-03 12:22:12 -0600906 stdinname = env_get("stdin");
907 stdoutname = env_get("stdout");
908 stderrname = env_get("stderr");
wdenk47d1a6e2002-11-03 00:01:44 +0000909
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200910 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100911 inputdev = search_device(DEV_FLAGS_INPUT, stdinname);
912 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
913 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname);
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100914 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
915 iomux_err = iomux_doenv(stdin, stdinname);
916 iomux_err += iomux_doenv(stdout, stdoutname);
917 iomux_err += iomux_doenv(stderr, stderrname);
918 if (!iomux_err)
919 /* Successful, so skip all the code below. */
920 goto done;
921 }
wdenk47d1a6e2002-11-03 00:01:44 +0000922 }
923 /* if the devices are overwritten or not found, use default device */
924 if (inputdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100925 inputdev = search_device(DEV_FLAGS_INPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000926 }
927 if (outputdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100928 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000929 }
930 if (errdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100931 errdev = search_device(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000932 }
933 /* Initializes output console first */
934 if (outputdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100935 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100936 console_doenv(stdout, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000937 }
938 if (errdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100939 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100940 console_doenv(stderr, errdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000941 }
942 if (inputdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100943 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100944 console_doenv(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000945 }
946
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100947done:
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100948
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100949 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
950 stdio_print_current_devices();
951
Simon Glassa2931b32016-02-06 14:31:37 -0700952#ifdef CONFIG_VIDCONSOLE_AS_LCD
Patrick Delaunay27b5b9e2020-07-01 14:56:10 +0200953 if (strstr(stdoutname, CONFIG_VIDCONSOLE_AS_NAME))
Anatolij Gustschin22b897a2020-05-23 17:11:20 +0200954 printf("Warning: Please change '%s' to 'vidconsole' in stdout/stderr environment vars\n",
Patrick Delaunay27b5b9e2020-07-01 14:56:10 +0200955 CONFIG_VIDCONSOLE_AS_NAME);
Simon Glassa2931b32016-02-06 14:31:37 -0700956#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000957
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100958 if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
959 /* set the environment variables (will overwrite previous env settings) */
960 for (i = 0; i < MAX_FILES; i++)
961 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +0000962 }
wdenk47d1a6e2002-11-03 00:01:44 +0000963
Joe Hershbergerc4e00572012-12-11 22:16:19 -0600964 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
965
wdenk47d1a6e2002-11-03 00:01:44 +0000966#if 0
967 /* If nothing usable installed, use only the initial console */
968 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100969 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000970#endif
Patrick Delaunay13551b92019-08-02 14:58:10 +0200971 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100972 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000973}
974
Simon Glassb0265422017-01-16 07:03:26 -0700975#else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
wdenk47d1a6e2002-11-03 00:01:44 +0000976
977/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100978int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000979{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200980 struct stdio_dev *inputdev = NULL, *outputdev = NULL;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200981 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200982 struct list_head *list = stdio_get_list();
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200983 struct list_head *pos;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200984 struct stdio_dev *dev;
Patrick Delaunay13551b92019-08-02 14:58:10 +0200985 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +0000986
Patrick Delaunaybf46be72019-08-02 14:58:09 +0200987 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunay13551b92019-08-02 14:58:10 +0200988 if (console_update_silent())
989 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
990 else
991 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Chris Packham43e0a3d2016-09-23 15:59:43 +1200992
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100993 /*
994 * suppress all output if splash screen is enabled and we have
Anatolij Gustschina7490812010-03-16 15:29:33 +0100995 * a bmp to display. We redirect the output from frame buffer
996 * console to serial console in this case or suppress it if
997 * "silent" mode was requested.
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100998 */
Patrick Delaunayc04f8562020-12-18 12:46:43 +0100999 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
Anatolij Gustschina7490812010-03-16 15:29:33 +01001000 if (!(gd->flags & GD_FLG_SILENT))
1001 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
1002 }
wdenkf72da342003-10-10 10:05:42 +00001003
wdenk47d1a6e2002-11-03 00:01:44 +00001004 /* Scan devices looking for input and output devices */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +02001005 list_for_each(pos, list) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +02001006 dev = list_entry(pos, struct stdio_dev, list);
wdenk47d1a6e2002-11-03 00:01:44 +00001007
1008 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
1009 inputdev = dev;
1010 }
1011 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
1012 outputdev = dev;
1013 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +02001014 if(inputdev && outputdev)
1015 break;
wdenk47d1a6e2002-11-03 00:01:44 +00001016 }
1017
1018 /* Initializes output console first */
1019 if (outputdev != NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +01001020 console_setfile(stdout, outputdev);
1021 console_setfile(stderr, outputdev);
Patrick Delaunay45375ad2020-12-18 12:46:44 +01001022 console_devices_set(stdout, outputdev);
1023 console_devices_set(stderr, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001024 }
1025
1026 /* Initializes input console */
1027 if (inputdev != NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +01001028 console_setfile(stdin, inputdev);
Patrick Delaunay45375ad2020-12-18 12:46:44 +01001029 console_devices_set(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001030 }
1031
Patrick Delaunayc04f8562020-12-18 12:46:43 +01001032 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1033 stdio_print_current_devices();
wdenk47d1a6e2002-11-03 00:01:44 +00001034
1035 /* Setting environment variables */
Tom Rini27b42252018-05-03 09:12:26 -04001036 for (i = 0; i < MAX_FILES; i++) {
Simon Glass382bee52017-08-03 12:22:09 -06001037 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +00001038 }
1039
Joe Hershbergerc4e00572012-12-11 22:16:19 -06001040 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1041
wdenk47d1a6e2002-11-03 00:01:44 +00001042#if 0
1043 /* If nothing usable installed, use only the initial console */
1044 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +01001045 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001046#endif
Patrick Delaunay13551b92019-08-02 14:58:10 +02001047 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +01001048 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001049}
1050
Simon Glassb0265422017-01-16 07:03:26 -07001051#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */