blob: 48586fd2166246ad41c00e771a3989f1d5b9ddbd [file] [log] [blame]
Tom Rini10e47792018-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
Simon Glass5e392f12024-09-01 16:26:18 -06007#define LOG_CATEGORY LOGC_CONSOLE
8
Simon Glassa73bda42015-11-08 23:47:45 -07009#include <console.h>
Simon Glass7dd27e02015-06-23 15:38:33 -060010#include <debug_uart.h>
Simon Glass1ab16922022-07-31 12:28:48 -060011#include <display_options.h>
Simon Glass10a7fe92017-07-27 09:31:04 -060012#include <dm.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060013#include <env.h>
wdenk47d1a6e2002-11-03 00:01:44 +000014#include <stdarg.h>
Jeroen Hofstee3b46b3b2014-10-08 22:57:48 +020015#include <iomux.h>
wdenk47d1a6e2002-11-03 00:01:44 +000016#include <malloc.h>
Simon Glass46aaad02017-06-15 21:37:52 -060017#include <mapmem.h>
Simon Glass3e9fd242013-11-10 10:27:01 -070018#include <os.h>
Joe Hershberger5c89d6d2012-12-11 22:16:29 -060019#include <serial.h>
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +020020#include <stdio_dev.h>
wdenk874ac262003-07-24 23:38:38 +000021#include <exports.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060022#include <env_internal.h>
Simon Glassffafbe32023-10-01 19:15:23 -060023#include <video_console.h>
Andreas J. Reichel982ca462016-07-13 12:56:51 +020024#include <watchdog.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060025#include <asm/global_data.h>
Simon Glassdbd79542020-05-10 11:40:11 -060026#include <linux/delay.h>
wdenk47d1a6e2002-11-03 00:01:44 +000027
Wolfgang Denk6405a152006-03-31 18:32:53 +020028DECLARE_GLOBAL_DATA_PTR;
29
Simon Glassffafbe32023-10-01 19:15:23 -060030#define CSI "\x1b["
31
Joe Hershberger5c89d6d2012-12-11 22:16:29 -060032static int on_console(const char *name, const char *value, enum env_op op,
33 int flags)
34{
35 int console = -1;
36
37 /* Check for console redirection */
38 if (strcmp(name, "stdin") == 0)
39 console = stdin;
40 else if (strcmp(name, "stdout") == 0)
41 console = stdout;
42 else if (strcmp(name, "stderr") == 0)
43 console = stderr;
44
45 /* if not actually setting a console variable, we don't care */
46 if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0)
47 return 0;
48
49 switch (op) {
50 case env_op_create:
51 case env_op_overwrite:
52
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +010053 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
54 if (iomux_doenv(console, value))
55 return 1;
56 } else {
57 /* Try assigning specified device */
58 if (console_assign(console, value) < 0)
59 return 1;
60 }
61
Joe Hershberger5c89d6d2012-12-11 22:16:29 -060062 return 0;
63
64 case env_op_delete:
65 if ((flags & H_FORCE) == 0)
66 printf("Can't delete \"%s\"\n", name);
67 return 1;
68
69 default:
70 return 0;
71 }
72}
73U_BOOT_ENV_CALLBACK(console, on_console);
74
Joe Hershberger03ddaba2012-12-11 22:16:30 -060075#ifdef CONFIG_SILENT_CONSOLE
76static int on_silent(const char *name, const char *value, enum env_op op,
77 int flags)
78{
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +010079 if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET))
80 if (flags & H_INTERACTIVE)
81 return 0;
82
83 if (!CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC))
84 if ((flags & H_INTERACTIVE) == 0)
85 return 0;
Joe Hershberger03ddaba2012-12-11 22:16:30 -060086
87 if (value != NULL)
88 gd->flags |= GD_FLG_SILENT;
89 else
90 gd->flags &= ~GD_FLG_SILENT;
91
92 return 0;
93}
94U_BOOT_ENV_CALLBACK(silent, on_silent);
95#endif
96
Patrick Delaunayc20847f2020-12-18 12:46:45 +010097#ifdef CONFIG_CONSOLE_RECORD
98/* helper function: access to gd->console_out and gd->console_in */
99static void console_record_putc(const char c)
100{
101 if (!(gd->flags & GD_FLG_RECORD))
102 return;
Simon Glassd6ed4af2021-05-08 06:59:56 -0600103 if (gd->console_out.start &&
Simon Glassf7e87f92025-03-18 16:20:44 +0100104 !membuf_putbyte((struct membuf *)&gd->console_out, c))
Simon Glassd6ed4af2021-05-08 06:59:56 -0600105 gd->flags |= GD_FLG_RECORD_OVF;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100106}
107
108static void console_record_puts(const char *s)
109{
110 if (!(gd->flags & GD_FLG_RECORD))
111 return;
Simon Glassd6ed4af2021-05-08 06:59:56 -0600112 if (gd->console_out.start) {
113 int len = strlen(s);
114
Simon Glassf7e87f92025-03-18 16:20:44 +0100115 if (membuf_put((struct membuf *)&gd->console_out, s, len) !=
Simon Glassd6ed4af2021-05-08 06:59:56 -0600116 len)
117 gd->flags |= GD_FLG_RECORD_OVF;
118 }
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100119}
120
121static int console_record_getc(void)
122{
123 if (!(gd->flags & GD_FLG_RECORD))
124 return -1;
125 if (!gd->console_in.start)
126 return -1;
127
Simon Glassf7e87f92025-03-18 16:20:44 +0100128 return membuf_getbyte((struct membuf *)&gd->console_in);
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100129}
130
131static int console_record_tstc(void)
132{
133 if (!(gd->flags & GD_FLG_RECORD))
134 return 0;
135 if (gd->console_in.start) {
Simon Glassf7e87f92025-03-18 16:20:44 +0100136 if (membuf_peekbyte((struct membuf *)&gd->console_in) != -1)
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100137 return 1;
138 }
139 return 0;
140}
141#else
142static void console_record_putc(char c)
143{
144}
145
146static void console_record_puts(const char *s)
147{
148}
149
150static int console_record_getc(void)
151{
152 return -1;
153}
154
155static int console_record_tstc(void)
156{
157 return 0;
158}
159#endif
160
Simon Glassdfc25352017-01-16 07:03:26 -0700161#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
wdenk47d1a6e2002-11-03 00:01:44 +0000162/*
163 * if overwrite_console returns 1, the stdin, stderr and stdout
164 * are switched to the serial port, else the settings in the
165 * environment are used
166 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200167#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100168extern int overwrite_console(void);
169#define OVERWRITE_CONSOLE overwrite_console()
wdenk47d1a6e2002-11-03 00:01:44 +0000170#else
wdenk61c636e2005-03-31 18:42:15 +0000171#define OVERWRITE_CONSOLE 0
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200172#endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
wdenk47d1a6e2002-11-03 00:01:44 +0000173
Simon Glassdfc25352017-01-16 07:03:26 -0700174#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
wdenk47d1a6e2002-11-03 00:01:44 +0000175
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200176static int console_setfile(int file, struct stdio_dev * dev)
wdenk47d1a6e2002-11-03 00:01:44 +0000177{
178 int error = 0;
179
180 if (dev == NULL)
181 return -1;
182
183 switch (file) {
184 case stdin:
185 case stdout:
186 case stderr:
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200187 error = console_start(file, dev);
188 if (error)
189 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000190
191 /* Assign the new device (leaving the existing one started) */
192 stdio_devices[file] = dev;
193
Simon Glass0e84d962024-09-29 19:49:50 -0600194#ifndef CONFIG_XPL_BUILD
wdenk47d1a6e2002-11-03 00:01:44 +0000195 /*
196 * Update monitor functions
197 * (to use the console stuff by other applications)
198 */
199 switch (file) {
200 case stdin:
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200201 gd->jt->getc = getchar;
Martin Dorwigcb2c2862015-01-26 15:22:54 -0700202 gd->jt->tstc = tstc;
wdenk47d1a6e2002-11-03 00:01:44 +0000203 break;
204 case stdout:
Martin Dorwigcb2c2862015-01-26 15:22:54 -0700205 gd->jt->putc = putc;
206 gd->jt->puts = puts;
Pali Rohár5aceb262022-09-05 11:31:17 +0200207 STDIO_DEV_ASSIGN_FLUSH(gd->jt, flush);
Martin Dorwigcb2c2862015-01-26 15:22:54 -0700208 gd->jt->printf = printf;
wdenk47d1a6e2002-11-03 00:01:44 +0000209 break;
210 }
Simon Glass8a0417f2024-08-21 10:19:24 -0600211#endif
Andre Przywara52b83b62025-03-25 17:47:44 +0000212 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000213 default: /* Invalid file ID */
214 error = -1;
215 }
216 return error;
217}
218
Simon Glass045e4b52017-07-27 09:31:03 -0600219/**
220 * console_dev_is_serial() - Check if a stdio device is a serial device
221 *
222 * @sdev: Device to check
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100223 * Return: true if this device is in the serial uclass (or for pre-driver-model,
Simon Glass10a7fe92017-07-27 09:31:04 -0600224 * whether it is called "serial".
Simon Glass045e4b52017-07-27 09:31:03 -0600225 */
226static bool console_dev_is_serial(struct stdio_dev *sdev)
227{
228 bool is_serial;
229
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100230 if (IS_ENABLED(CONFIG_DM_SERIAL) && (sdev->flags & DEV_FLAGS_DM)) {
Simon Glass10a7fe92017-07-27 09:31:04 -0600231 struct udevice *dev = sdev->priv;
232
233 is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100234 } else {
235 is_serial = !strcmp(sdev->name, "serial");
236 }
Simon Glass045e4b52017-07-27 09:31:03 -0600237
238 return is_serial;
239}
240
Simon Glassdfc25352017-01-16 07:03:26 -0700241#if CONFIG_IS_ENABLED(CONSOLE_MUX)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100242/** Console I/O multiplexing *******************************************/
243
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100244/* tstcdev: save the last stdio device with pending characters, with tstc != 0 */
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200245static struct stdio_dev *tstcdev;
246struct stdio_dev **console_devices[MAX_FILES];
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100247int cd_count[MAX_FILES];
248
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +0200249static void console_devices_set(int file, struct stdio_dev *dev)
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100250{
251 console_devices[file][0] = dev;
Andy Shevchenkof1a852a2021-02-11 17:09:38 +0200252 cd_count[file] = 1;
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100253}
254
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200255/**
256 * console_needs_start_stop() - check if we need to start or stop the STDIO device
257 * @file: STDIO file
258 * @sdev: STDIO device in question
259 *
260 * This function checks if we need to start or stop the stdio device used for
261 * a console. For IOMUX case it simply enforces one time start and one time
262 * stop of the device independently of how many STDIO files are using it. In
263 * other words, we start console once before first STDIO device wants it and
264 * stop after the last is gone.
265 */
266static bool console_needs_start_stop(int file, struct stdio_dev *sdev)
267{
Andy Shevchenko75039f52021-02-11 17:09:41 +0200268 int i;
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200269
270 for (i = 0; i < ARRAY_SIZE(cd_count); i++) {
271 if (i == file)
272 continue;
273
Andy Shevchenko75039f52021-02-11 17:09:41 +0200274 if (iomux_match_device(console_devices[i], cd_count[i], sdev) >= 0)
275 return false;
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200276 }
277 return true;
278}
279
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100280/*
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200281 * This depends on tstc() always being called before getchar().
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100282 * This is guaranteed to be true because this routine is called
283 * only from fgetc() which assures it.
284 * No attempt is made to demultiplex multiple input sources.
285 */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100286static int console_getc(int file)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100287{
288 unsigned char ret;
289
290 /* This is never called with testcdev == NULL */
Simon Glass0d1e1f72014-07-23 06:54:59 -0600291 ret = tstcdev->getc(tstcdev);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100292 tstcdev = NULL;
293 return ret;
294}
295
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100296/* Upper layer may have already called tstc(): check the saved result */
297static bool console_has_tstc(void)
298{
299 return !!tstcdev;
300}
301
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100302static int console_tstc(int file)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100303{
304 int i, ret;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200305 struct stdio_dev *dev;
Joe Hershbergerc2f39542018-07-02 20:06:48 -0500306 int prev;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100307
Joe Hershbergerc2f39542018-07-02 20:06:48 -0500308 prev = disable_ctrlc(1);
Andy Shevchenkoe29d0192021-02-11 17:09:42 +0200309 for_each_console_dev(i, file, dev) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100310 if (dev->tstc != NULL) {
Simon Glass0d1e1f72014-07-23 06:54:59 -0600311 ret = dev->tstc(dev);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100312 if (ret > 0) {
313 tstcdev = dev;
Joe Hershbergerc2f39542018-07-02 20:06:48 -0500314 disable_ctrlc(prev);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100315 return ret;
316 }
317 }
318 }
Joe Hershbergerc2f39542018-07-02 20:06:48 -0500319 disable_ctrlc(prev);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100320
321 return 0;
322}
323
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100324static void console_putc(int file, const char c)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100325{
326 int i;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200327 struct stdio_dev *dev;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100328
Andy Shevchenkoe29d0192021-02-11 17:09:42 +0200329 for_each_console_dev(i, file, dev) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100330 if (dev->putc != NULL)
Simon Glass0d1e1f72014-07-23 06:54:59 -0600331 dev->putc(dev, c);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100332 }
333}
334
Simon Glass66ee8172020-07-02 21:12:13 -0600335/**
336 * console_puts_select() - Output a string to all console devices
337 *
338 * @file: File number to output to (e,g, stdout, see stdio.h)
339 * @serial_only: true to output only to serial, false to output to everything
340 * else
341 * @s: String to output
342 */
343static void console_puts_select(int file, bool serial_only, const char *s)
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200344{
345 int i;
346 struct stdio_dev *dev;
347
Andy Shevchenkoe29d0192021-02-11 17:09:42 +0200348 for_each_console_dev(i, file, dev) {
349 bool is_serial = console_dev_is_serial(dev);
Simon Glass66ee8172020-07-02 21:12:13 -0600350
Simon Glass66ee8172020-07-02 21:12:13 -0600351 if (dev->puts && serial_only == is_serial)
Hans de Goedee355da02015-05-05 13:13:36 +0200352 dev->puts(dev, s);
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200353 }
354}
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200355
Simon Glass66ee8172020-07-02 21:12:13 -0600356void console_puts_select_stderr(bool serial_only, const char *s)
357{
Simon Glassc7ba6c82021-11-19 13:23:47 -0700358 if (gd->flags & GD_FLG_DEVINIT)
359 console_puts_select(stderr, serial_only, s);
Simon Glass66ee8172020-07-02 21:12:13 -0600360}
361
Simon Glass43000672025-04-02 06:29:32 +1300362int console_printf_select_stderr(bool serial_only, const char *fmt, ...)
363{
364 char buf[CONFIG_SYS_PBSIZE];
365 va_list args;
366 int ret;
367
368 va_start(args, fmt);
369
370 /* For this to work, buf must be larger than anything we ever want to
371 * print.
372 */
373 ret = vscnprintf(buf, sizeof(buf), fmt, args);
374 va_end(args);
375 console_puts_select_stderr(serial_only, buf);
376
377 return ret;
378}
379
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100380static void console_puts(int file, const char *s)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100381{
382 int i;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200383 struct stdio_dev *dev;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100384
Andy Shevchenkoe29d0192021-02-11 17:09:42 +0200385 for_each_console_dev(i, file, dev) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100386 if (dev->puts != NULL)
Simon Glass0d1e1f72014-07-23 06:54:59 -0600387 dev->puts(dev, s);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100388 }
389}
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100390
Pali Rohár5aceb262022-09-05 11:31:17 +0200391#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
392static void console_flush(int file)
393{
394 int i;
395 struct stdio_dev *dev;
396
397 for_each_console_dev(i, file, dev) {
398 if (dev->flush != NULL)
399 dev->flush(dev);
400 }
401}
402#endif
403
Tom Rinid30aeb12019-10-30 09:18:43 -0400404#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200405static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100406{
407 iomux_doenv(file, dev->name);
408}
Tom Rinid30aeb12019-10-30 09:18:43 -0400409#endif
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100410#else
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100411
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +0200412static void console_devices_set(int file, struct stdio_dev *dev)
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100413{
414}
415
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200416static inline bool console_needs_start_stop(int file, struct stdio_dev *sdev)
417{
418 return true;
419}
420
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100421static inline int console_getc(int file)
422{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600423 return stdio_devices[file]->getc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100424}
425
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100426static bool console_has_tstc(void)
427{
428 return false;
429}
430
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100431static inline int console_tstc(int file)
432{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600433 return stdio_devices[file]->tstc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100434}
435
436static inline void console_putc(int file, const char c)
437{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600438 stdio_devices[file]->putc(stdio_devices[file], c);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100439}
440
Simon Glass66ee8172020-07-02 21:12:13 -0600441void console_puts_select(int file, bool serial_only, const char *s)
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200442{
Simon Glassc7ba6c82021-11-19 13:23:47 -0700443 if ((gd->flags & GD_FLG_DEVINIT) &&
444 serial_only == console_dev_is_serial(stdio_devices[file]))
Hans de Goedee355da02015-05-05 13:13:36 +0200445 stdio_devices[file]->puts(stdio_devices[file], s);
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200446}
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200447
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100448static inline void console_puts(int file, const char *s)
449{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600450 stdio_devices[file]->puts(stdio_devices[file], s);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100451}
Pali Rohár5aceb262022-09-05 11:31:17 +0200452
453#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
454static inline void console_flush(int file)
455{
456 if (stdio_devices[file]->flush)
457 stdio_devices[file]->flush(stdio_devices[file]);
458}
459#endif
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100460
Tom Rinid30aeb12019-10-30 09:18:43 -0400461#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200462static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100463{
464 console_setfile(file, dev);
465}
Tom Rinid30aeb12019-10-30 09:18:43 -0400466#endif
Simon Glassdfc25352017-01-16 07:03:26 -0700467#endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100468
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +0200469static void __maybe_unused console_setfile_and_devices(int file, struct stdio_dev *dev)
470{
471 console_setfile(file, dev);
472 console_devices_set(file, dev);
473}
474
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200475int console_start(int file, struct stdio_dev *sdev)
476{
477 int error;
478
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200479 if (!console_needs_start_stop(file, sdev))
480 return 0;
481
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200482 /* Start new device */
483 if (sdev->start) {
484 error = sdev->start(sdev);
485 /* If it's not started don't use it */
486 if (error < 0)
487 return error;
488 }
489 return 0;
490}
491
492void console_stop(int file, struct stdio_dev *sdev)
493{
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200494 if (!console_needs_start_stop(file, sdev))
495 return;
496
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200497 if (sdev->stop)
498 sdev->stop(sdev);
499}
500
wdenk47d1a6e2002-11-03 00:01:44 +0000501/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
502
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200503int serial_printf(const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000504{
505 va_list args;
506 uint i;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200507 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000508
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100509 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000510
511 /* For this to work, printbuffer must be larger than
512 * anything we ever want to print.
513 */
Sonny Rao2813a212011-10-10 09:22:31 +0000514 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100515 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000516
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100517 serial_puts(printbuffer);
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200518 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000519}
520
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100521int fgetc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000522{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200523 if ((unsigned int)file < MAX_FILES) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100524 /*
525 * Effectively poll for input wherever it may be available.
526 */
527 for (;;) {
Stefan Roese80877fa2022-09-02 14:10:46 +0200528 schedule();
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100529 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
530 /*
531 * Upper layer may have already called tstc() so
532 * check for that first.
533 */
534 if (console_has_tstc())
535 return console_getc(file);
536 console_tstc(file);
537 } else {
538 if (console_tstc(file))
539 return console_getc(file);
540 }
541
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100542 /*
543 * If the watchdog must be rate-limited then it should
544 * already be handled in board-specific code.
545 */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100546 if (IS_ENABLED(CONFIG_WATCHDOG))
547 udelay(1);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100548 }
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100549 }
wdenk47d1a6e2002-11-03 00:01:44 +0000550
551 return -1;
552}
553
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100554int ftstc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000555{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200556 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100557 return console_tstc(file);
wdenk47d1a6e2002-11-03 00:01:44 +0000558
559 return -1;
560}
561
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100562void fputc(int file, const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000563{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200564 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100565 console_putc(file, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000566}
567
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100568void fputs(int file, const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000569{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200570 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100571 console_puts(file, s);
wdenk47d1a6e2002-11-03 00:01:44 +0000572}
573
Pali Rohár5aceb262022-09-05 11:31:17 +0200574#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
575void fflush(int file)
576{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200577 if ((unsigned int)file < MAX_FILES)
Pali Rohár5aceb262022-09-05 11:31:17 +0200578 console_flush(file);
579}
580#endif
581
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200582int fprintf(int file, const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000583{
584 va_list args;
585 uint i;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200586 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000587
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100588 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000589
590 /* For this to work, printbuffer must be larger than
591 * anything we ever want to print.
592 */
Sonny Rao2813a212011-10-10 09:22:31 +0000593 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100594 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000595
596 /* Send to desired file */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100597 fputs(file, printbuffer);
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200598 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000599}
600
601/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
602
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200603int getchar(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000604{
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100605 int ch;
606
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100607 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100608 return 0;
Mark Jackson5de56212008-08-25 19:21:30 +0100609
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600610 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ70600b02011-08-29 02:14:05 +0000611 return 0;
612
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100613 ch = console_record_getc();
614 if (ch != -1)
615 return ch;
Simon Glass1bb49232015-11-08 23:47:48 -0700616
wdenk47d1a6e2002-11-03 00:01:44 +0000617 if (gd->flags & GD_FLG_DEVINIT) {
618 /* Get from the standard input */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100619 return fgetc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000620 }
621
622 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100623 return serial_getc();
wdenk47d1a6e2002-11-03 00:01:44 +0000624}
625
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100626int tstc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000627{
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100628 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100629 return 0;
Mark Jackson5de56212008-08-25 19:21:30 +0100630
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600631 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ70600b02011-08-29 02:14:05 +0000632 return 0;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100633
634 if (console_record_tstc())
635 return 1;
636
wdenk47d1a6e2002-11-03 00:01:44 +0000637 if (gd->flags & GD_FLG_DEVINIT) {
638 /* Test the standard input */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100639 return ftstc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000640 }
641
642 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100643 return serial_tstc();
wdenk47d1a6e2002-11-03 00:01:44 +0000644}
645
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200646#define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0
647#define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1
648
Simon Glasse304a5e2016-10-17 20:12:36 -0600649#if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200650#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_VAL(PRE_CON_BUF_SZ))
Graeme Russ3c28f482011-09-01 00:48:27 +0000651
652static void pre_console_putc(const char c)
653{
Simon Glass46aaad02017-06-15 21:37:52 -0600654 char *buffer;
655
Rasmus Villemoese406a612022-05-03 15:13:27 +0200656 if (gd->precon_buf_idx < 0)
657 return;
658
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200659 buffer = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
Graeme Russ3c28f482011-09-01 00:48:27 +0000660
661 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
Simon Glass46aaad02017-06-15 21:37:52 -0600662
663 unmap_sysmem(buffer);
Graeme Russ3c28f482011-09-01 00:48:27 +0000664}
665
Soeren Moch54619bb2017-11-04 16:14:09 +0100666static void pre_console_puts(const char *s)
667{
Rasmus Villemoese406a612022-05-03 15:13:27 +0200668 if (gd->precon_buf_idx < 0)
669 return;
670
Soeren Moch54619bb2017-11-04 16:14:09 +0100671 while (*s)
672 pre_console_putc(*s++);
673}
674
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200675static void print_pre_console_buffer(int flushpoint)
Graeme Russ3c28f482011-09-01 00:48:27 +0000676{
Rasmus Villemoese406a612022-05-03 15:13:27 +0200677 long in = 0, out = 0;
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200678 char buf_out[CONFIG_VAL(PRE_CON_BUF_SZ) + 1];
Simon Glass46aaad02017-06-15 21:37:52 -0600679 char *buf_in;
Graeme Russ3c28f482011-09-01 00:48:27 +0000680
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100681 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200682 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200683
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200684 buf_in = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
685 if (gd->precon_buf_idx > CONFIG_VAL(PRE_CON_BUF_SZ))
686 in = gd->precon_buf_idx - CONFIG_VAL(PRE_CON_BUF_SZ);
Graeme Russ3c28f482011-09-01 00:48:27 +0000687
Hans de Goedee355da02015-05-05 13:13:36 +0200688 while (in < gd->precon_buf_idx)
689 buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)];
Simon Glass46aaad02017-06-15 21:37:52 -0600690 unmap_sysmem(buf_in);
Hans de Goedee355da02015-05-05 13:13:36 +0200691
692 buf_out[out] = 0;
693
Rasmus Villemoese406a612022-05-03 15:13:27 +0200694 gd->precon_buf_idx = -1;
Hans de Goedee355da02015-05-05 13:13:36 +0200695 switch (flushpoint) {
696 case PRE_CONSOLE_FLUSHPOINT1_SERIAL:
697 puts(buf_out);
698 break;
699 case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL:
Simon Glass66ee8172020-07-02 21:12:13 -0600700 console_puts_select(stdout, false, buf_out);
Hans de Goedee355da02015-05-05 13:13:36 +0200701 break;
702 }
Rasmus Villemoese406a612022-05-03 15:13:27 +0200703 gd->precon_buf_idx = in;
Graeme Russ3c28f482011-09-01 00:48:27 +0000704}
705#else
706static inline void pre_console_putc(const char c) {}
Soeren Moch54619bb2017-11-04 16:14:09 +0100707static inline void pre_console_puts(const char *s) {}
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200708static inline void print_pre_console_buffer(int flushpoint) {}
Graeme Russ3c28f482011-09-01 00:48:27 +0000709#endif
710
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100711void putc(const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000712{
Patrick Delaunay8f14b402020-11-27 11:20:56 +0100713 if (!gd)
714 return;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100715
716 console_record_putc(c);
717
Simon Glass16e3d7c2017-12-04 13:48:19 -0700718 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100719 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass16e3d7c2017-12-04 13:48:19 -0700720 os_putc(c);
721 return;
722 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100723
Simon Glass7dd27e02015-06-23 15:38:33 -0600724 /* if we don't have a console yet, use the debug UART */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100725 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass7dd27e02015-06-23 15:38:33 -0600726 printch(c);
727 return;
728 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100729
730 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200731 if (!(gd->flags & GD_FLG_DEVINIT))
732 pre_console_putc(c);
wdenk927034e2004-02-08 19:38:38 +0000733 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200734 }
wdenk4b6e9052004-02-06 21:48:22 +0000735
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100736 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100737 return;
Mark Jackson5de56212008-08-25 19:21:30 +0100738
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600739 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ3c28f482011-09-01 00:48:27 +0000740 return pre_console_putc(c);
Graeme Russ70600b02011-08-29 02:14:05 +0000741
wdenk47d1a6e2002-11-03 00:01:44 +0000742 if (gd->flags & GD_FLG_DEVINIT) {
743 /* Send to the standard output */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100744 fputc(stdout, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000745 } else {
746 /* Send directly to the handler */
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200747 pre_console_putc(c);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100748 serial_putc(c);
wdenk47d1a6e2002-11-03 00:01:44 +0000749 }
750}
751
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100752void puts(const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000753{
Patrick Delaunay8f14b402020-11-27 11:20:56 +0100754 if (!gd)
755 return;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100756
757 console_record_puts(s);
758
Simon Glassbf5c4862018-11-15 18:44:04 -0700759 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100760 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glassbf5c4862018-11-15 18:44:04 -0700761 os_puts(s);
762 return;
763 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100764
765 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Kever Yang2a40bd62024-11-08 16:36:23 +0800766 printascii(s);
Soeren Moch54619bb2017-11-04 16:14:09 +0100767 return;
768 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100769
770 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200771 if (!(gd->flags & GD_FLG_DEVINIT))
772 pre_console_puts(s);
Soeren Moch54619bb2017-11-04 16:14:09 +0100773 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200774 }
Soeren Moch54619bb2017-11-04 16:14:09 +0100775
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100776 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Soeren Moch54619bb2017-11-04 16:14:09 +0100777 return;
Soeren Moch54619bb2017-11-04 16:14:09 +0100778
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600779 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Soeren Moch54619bb2017-11-04 16:14:09 +0100780 return pre_console_puts(s);
781
782 if (gd->flags & GD_FLG_DEVINIT) {
783 /* Send to the standard output */
784 fputs(stdout, s);
785 } else {
786 /* Send directly to the handler */
787 pre_console_puts(s);
788 serial_puts(s);
789 }
wdenk47d1a6e2002-11-03 00:01:44 +0000790}
Pali Rohár5aceb262022-09-05 11:31:17 +0200791
792#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
793void flush(void)
794{
795 if (!gd)
796 return;
797
798 /* sandbox can send characters to stdout before it has a console */
799 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
800 os_flush();
801 return;
802 }
803
804 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY))
805 return;
806
807 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
808 return;
809
810 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
811 return;
812
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600813 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Pali Rohár5aceb262022-09-05 11:31:17 +0200814 return;
815
816 if (gd->flags & GD_FLG_DEVINIT) {
817 /* Send to the standard output */
818 fflush(stdout);
Pali Rohára48a24f2022-09-05 11:31:19 +0200819 } else {
820 /* Send directly to the handler */
821 serial_flush();
Pali Rohár5aceb262022-09-05 11:31:17 +0200822 }
823}
824#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000825
Simon Glass1bb49232015-11-08 23:47:48 -0700826#ifdef CONFIG_CONSOLE_RECORD
827int console_record_init(void)
828{
829 int ret;
830
Simon Glassf7e87f92025-03-18 16:20:44 +0100831 ret = membuf_new((struct membuf *)&gd->console_out,
Simon Glassceefc782025-03-18 16:20:42 +0100832 gd->flags & GD_FLG_RELOC ?
833 CONFIG_CONSOLE_RECORD_OUT_SIZE :
834 CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
Simon Glass1bb49232015-11-08 23:47:48 -0700835 if (ret)
836 return ret;
Simon Glassf7e87f92025-03-18 16:20:44 +0100837 ret = membuf_new((struct membuf *)&gd->console_in,
Simon Glassceefc782025-03-18 16:20:42 +0100838 CONFIG_CONSOLE_RECORD_IN_SIZE);
Simon Glass1bb49232015-11-08 23:47:48 -0700839
Ion Agorriac0b0de42024-01-05 09:22:09 +0200840 /* Start recording from the beginning */
841 gd->flags |= GD_FLG_RECORD;
842
Simon Glass1bb49232015-11-08 23:47:48 -0700843 return ret;
844}
845
846void console_record_reset(void)
847{
Simon Glassf7e87f92025-03-18 16:20:44 +0100848 membuf_purge((struct membuf *)&gd->console_out);
849 membuf_purge((struct membuf *)&gd->console_in);
Simon Glassd6ed4af2021-05-08 06:59:56 -0600850 gd->flags &= ~GD_FLG_RECORD_OVF;
Simon Glass1bb49232015-11-08 23:47:48 -0700851}
852
Simon Glassdc357ef2020-07-28 19:41:11 -0600853int console_record_reset_enable(void)
Simon Glass1bb49232015-11-08 23:47:48 -0700854{
855 console_record_reset();
856 gd->flags |= GD_FLG_RECORD;
Simon Glassdc357ef2020-07-28 19:41:11 -0600857
858 return 0;
Simon Glass1bb49232015-11-08 23:47:48 -0700859}
Simon Glassb17c1582020-01-27 08:49:54 -0700860
861int console_record_readline(char *str, int maxlen)
862{
Simon Glassd6ed4af2021-05-08 06:59:56 -0600863 if (gd->flags & GD_FLG_RECORD_OVF)
864 return -ENOSPC;
Simon Glassc2e59eb2024-08-22 07:57:47 -0600865 if (console_record_isempty())
866 return -ENOENT;
Simon Glassd6ed4af2021-05-08 06:59:56 -0600867
Simon Glassf7e87f92025-03-18 16:20:44 +0100868 return membuf_readline((struct membuf *)&gd->console_out, str,
Ion Agorria7e06c1f2024-01-05 09:22:10 +0200869 maxlen, '\0', false);
Simon Glassb17c1582020-01-27 08:49:54 -0700870}
871
872int console_record_avail(void)
873{
Simon Glassf7e87f92025-03-18 16:20:44 +0100874 return membuf_avail((struct membuf *)&gd->console_out);
Simon Glassb17c1582020-01-27 08:49:54 -0700875}
876
Ion Agorria15f6d6a2024-01-05 09:22:08 +0200877bool console_record_isempty(void)
878{
Simon Glassf7e87f92025-03-18 16:20:44 +0100879 return membuf_isempty((struct membuf *)&gd->console_out);
Ion Agorria15f6d6a2024-01-05 09:22:08 +0200880}
881
Steffen Jaeckele1788f92021-07-08 15:57:40 +0200882int console_in_puts(const char *str)
883{
Simon Glassf7e87f92025-03-18 16:20:44 +0100884 return membuf_put((struct membuf *)&gd->console_in, str, strlen(str));
Steffen Jaeckele1788f92021-07-08 15:57:40 +0200885}
886
Simon Glass1bb49232015-11-08 23:47:48 -0700887#endif
888
wdenk47d1a6e2002-11-03 00:01:44 +0000889/* test if ctrl-c was pressed */
890static int ctrlc_disabled = 0; /* see disable_ctrl() */
891static int ctrlc_was_pressed = 0;
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100892int ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000893{
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600894 if (!ctrlc_disabled && (gd->flags & GD_FLG_HAVE_CONSOLE)) {
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100895 if (tstc()) {
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200896 switch (getchar()) {
wdenk47d1a6e2002-11-03 00:01:44 +0000897 case 0x03: /* ^C - Control C */
898 ctrlc_was_pressed = 1;
899 return 1;
900 default:
901 break;
902 }
903 }
904 }
Simon Glass28c5ce72014-09-14 12:40:15 -0600905
wdenk47d1a6e2002-11-03 00:01:44 +0000906 return 0;
907}
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200908/* Reads user's confirmation.
909 Returns 1 if user's input is "y", "Y", "yes" or "YES"
910*/
911int confirm_yesno(void)
912{
913 int i;
914 char str_input[5];
wdenk47d1a6e2002-11-03 00:01:44 +0000915
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200916 /* Flush input */
917 while (tstc())
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200918 getchar();
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200919 i = 0;
920 while (i < sizeof(str_input)) {
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200921 str_input[i] = getchar();
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200922 putc(str_input[i]);
923 if (str_input[i] == '\r')
924 break;
925 i++;
926 }
927 putc('\n');
928 if (strncmp(str_input, "y\r", 2) == 0 ||
929 strncmp(str_input, "Y\r", 2) == 0 ||
930 strncmp(str_input, "yes\r", 4) == 0 ||
931 strncmp(str_input, "YES\r", 4) == 0)
932 return 1;
933 return 0;
934}
wdenk47d1a6e2002-11-03 00:01:44 +0000935/* pass 1 to disable ctrlc() checking, 0 to enable.
936 * returns previous state
937 */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100938int disable_ctrlc(int disable)
wdenk47d1a6e2002-11-03 00:01:44 +0000939{
940 int prev = ctrlc_disabled; /* save previous state */
941
942 ctrlc_disabled = disable;
943 return prev;
944}
945
946int had_ctrlc (void)
947{
948 return ctrlc_was_pressed;
949}
950
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100951void clear_ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000952{
953 ctrlc_was_pressed = 0;
954}
955
wdenk47d1a6e2002-11-03 00:01:44 +0000956/** U-Boot INIT FUNCTIONS *************************************************/
957
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200958struct stdio_dev *console_search_dev(int flags, const char *name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200959{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200960 struct stdio_dev *dev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200961
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200962 dev = stdio_get_by_name(name);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100963 if (dev && (dev->flags & flags))
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200964 return dev;
965
966 return NULL;
967}
968
Mike Frysingere3d55722010-10-20 07:18:03 -0400969int console_assign(int file, const char *devname)
wdenk47d1a6e2002-11-03 00:01:44 +0000970{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200971 int flag;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200972 struct stdio_dev *dev;
wdenk47d1a6e2002-11-03 00:01:44 +0000973
974 /* Check for valid file */
Andy Shevchenko59f324c2021-02-11 17:09:37 +0200975 flag = stdio_file_to_flags(file);
976 if (flag < 0)
977 return flag;
wdenk47d1a6e2002-11-03 00:01:44 +0000978
979 /* Check for valid device name */
980
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200981 dev = console_search_dev(flag, devname);
wdenk47d1a6e2002-11-03 00:01:44 +0000982
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100983 if (dev)
984 return console_setfile(file, dev);
wdenk47d1a6e2002-11-03 00:01:44 +0000985
986 return -1;
987}
988
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200989/* return true if the 'silent' flag is removed */
990static bool console_update_silent(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000991{
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100992 unsigned long flags = gd->flags;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200993
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100994 if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
995 return false;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200996
Harald Seiler6d09df82022-07-06 13:19:10 +0200997 if (IS_ENABLED(CONFIG_SILENT_CONSOLE_UNTIL_ENV) && !(gd->flags & GD_FLG_ENV_READY)) {
998 gd->flags |= GD_FLG_SILENT;
999 return false;
1000 }
1001
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001002 if (env_get("silent")) {
1003 gd->flags |= GD_FLG_SILENT;
1004 return false;
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001005 }
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001006
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001007 gd->flags &= ~GD_FLG_SILENT;
1008
1009 return !!(flags & GD_FLG_SILENT);
Simon Glassc9c5c9f2017-06-15 21:37:50 -06001010}
1011
1012int console_announce_r(void)
1013{
1014#if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
1015 char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
1016
1017 display_options_get_banner(false, buf, sizeof(buf));
1018
Simon Glass66ee8172020-07-02 21:12:13 -06001019 console_puts_select(stdout, false, buf);
Simon Glassc9c5c9f2017-06-15 21:37:50 -06001020#endif
1021
1022 return 0;
Chris Packhamfab806d2016-09-23 15:59:43 +12001023}
1024
1025/* Called before relocation - use serial functions */
1026int console_init_f(void)
1027{
Simon Glassd4b0fdb2024-08-21 10:19:04 -06001028 gd->flags |= GD_FLG_HAVE_CONSOLE;
Chris Packhamfab806d2016-09-23 15:59:43 +12001029
1030 console_update_silent();
wdenk808532a2003-10-10 10:05:42 +00001031
Siarhei Siamashka616d03e2015-01-08 09:02:31 +02001032 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
Graeme Russ3c28f482011-09-01 00:48:27 +00001033
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001034 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001035}
1036
Simon Glassffafbe32023-10-01 19:15:23 -06001037int console_clear(void)
1038{
1039 /*
1040 * Send clear screen and home
1041 *
1042 * FIXME(Heinrich Schuchardt <xypron.glpk@gmx.de>): This should go
1043 * through an API and only be written to serial terminals, not video
1044 * displays
1045 */
1046 printf(CSI "2J" CSI "1;1H");
1047 if (IS_ENABLED(CONFIG_VIDEO_ANSI))
1048 return 0;
1049
1050 if (IS_ENABLED(CONFIG_VIDEO)) {
1051 struct udevice *dev;
1052 int ret;
1053
1054 ret = uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev);
1055 if (ret)
1056 return ret;
1057 ret = vidconsole_clear_and_reset(dev);
1058 if (ret)
1059 return ret;
1060 }
1061
1062 return 0;
1063}
1064
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001065static char *get_stdio(const u8 std)
1066{
1067 return stdio_devices[std] ? stdio_devices[std]->name : "No devices available!";
1068}
1069
Bin Meng13186892023-07-23 12:40:35 +08001070static void stdio_print_current_devices(void)
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001071{
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001072 char *stdinname = NULL;
1073 char *stdoutname = NULL;
1074 char *stderrname = NULL;
Bin Menga6a83502023-07-23 12:40:36 +08001075
Bin Mengd61be5b2023-07-23 12:40:37 +08001076 if (CONFIG_IS_ENABLED(CONSOLE_MUX) &&
1077 CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)) {
1078 /* stdin stdout and stderr are in environment */
1079 stdinname = env_get("stdin");
1080 stdoutname = env_get("stdout");
1081 stderrname = env_get("stderr");
Bin Mengd61be5b2023-07-23 12:40:37 +08001082 }
Bin Menga6a83502023-07-23 12:40:36 +08001083
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001084 stdinname = stdinname ? : get_stdio(stdin);
1085 stdoutname = stdoutname ? : get_stdio(stdout);
1086 stderrname = stderrname ? : get_stdio(stderr);
1087
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001088 /* Print information */
1089 puts("In: ");
Bin Menga6a83502023-07-23 12:40:36 +08001090 printf("%s\n", stdinname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001091
1092 puts("Out: ");
Bin Menga6a83502023-07-23 12:40:36 +08001093 printf("%s\n", stdoutname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001094
1095 puts("Err: ");
Bin Menga6a83502023-07-23 12:40:36 +08001096 printf("%s\n", stderrname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001097}
1098
Simon Glassdfc25352017-01-16 07:03:26 -07001099#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
wdenk47d1a6e2002-11-03 00:01:44 +00001100/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001101int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +00001102{
1103 char *stdinname, *stdoutname, *stderrname;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001104 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
wdenk05939202004-04-18 17:39:38 +00001105 int i;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001106 int iomux_err = 0;
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001107 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +00001108
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001109 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001110 if (console_update_silent())
1111 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
1112 else
1113 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001114
wdenk47d1a6e2002-11-03 00:01:44 +00001115 /* set default handlers at first */
Martin Dorwigcb2c2862015-01-26 15:22:54 -07001116 gd->jt->getc = serial_getc;
1117 gd->jt->tstc = serial_tstc;
1118 gd->jt->putc = serial_putc;
1119 gd->jt->puts = serial_puts;
1120 gd->jt->printf = serial_printf;
wdenk47d1a6e2002-11-03 00:01:44 +00001121
1122 /* stdin stdout and stderr are in environment */
1123 /* scan for it */
Simon Glass64b723f2017-08-03 12:22:12 -06001124 stdinname = env_get("stdin");
1125 stdoutname = env_get("stdout");
1126 stderrname = env_get("stderr");
wdenk47d1a6e2002-11-03 00:01:44 +00001127
Wolfgang Denka1be4762008-05-20 16:00:29 +02001128 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001129 inputdev = console_search_dev(DEV_FLAGS_INPUT, stdinname);
1130 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, stdoutname);
1131 errdev = console_search_dev(DEV_FLAGS_OUTPUT, stderrname);
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001132 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
1133 iomux_err = iomux_doenv(stdin, stdinname);
1134 iomux_err += iomux_doenv(stdout, stdoutname);
1135 iomux_err += iomux_doenv(stderr, stderrname);
1136 if (!iomux_err)
1137 /* Successful, so skip all the code below. */
1138 goto done;
1139 }
wdenk47d1a6e2002-11-03 00:01:44 +00001140 }
1141 /* if the devices are overwritten or not found, use default device */
1142 if (inputdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001143 inputdev = console_search_dev(DEV_FLAGS_INPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001144 }
1145 if (outputdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001146 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001147 }
1148 if (errdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001149 errdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001150 }
1151 /* Initializes output console first */
1152 if (outputdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001153 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001154 console_doenv(stdout, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001155 }
1156 if (errdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001157 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001158 console_doenv(stderr, errdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001159 }
1160 if (inputdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001161 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001162 console_doenv(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001163 }
1164
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001165done:
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001166
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001167 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1168 stdio_print_current_devices();
1169
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001170 if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
1171 /* set the environment variables (will overwrite previous env settings) */
1172 for (i = 0; i < MAX_FILES; i++)
1173 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +00001174 }
wdenk47d1a6e2002-11-03 00:01:44 +00001175
Joe Hershbergera46f7702012-12-11 22:16:19 -06001176 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1177
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001178 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001179 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001180}
1181
Simon Glassdfc25352017-01-16 07:03:26 -07001182#else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
wdenk47d1a6e2002-11-03 00:01:44 +00001183
1184/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001185int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +00001186{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001187 struct stdio_dev *inputdev = NULL, *outputdev = NULL;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001188 int i;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001189 struct list_head *list = stdio_get_list();
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001190 struct list_head *pos;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001191 struct stdio_dev *dev;
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001192 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +00001193
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001194 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001195 if (console_update_silent())
1196 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
1197 else
1198 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Chris Packhamfab806d2016-09-23 15:59:43 +12001199
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001200 /*
1201 * suppress all output if splash screen is enabled and we have
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001202 * a bmp to display. We redirect the output from frame buffer
1203 * console to serial console in this case or suppress it if
1204 * "silent" mode was requested.
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001205 */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001206 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001207 if (!(gd->flags & GD_FLG_SILENT))
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001208 outputdev = console_search_dev (DEV_FLAGS_OUTPUT, "serial");
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001209 }
wdenk808532a2003-10-10 10:05:42 +00001210
wdenk47d1a6e2002-11-03 00:01:44 +00001211 /* Scan devices looking for input and output devices */
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001212 list_for_each(pos, list) {
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001213 dev = list_entry(pos, struct stdio_dev, list);
wdenk47d1a6e2002-11-03 00:01:44 +00001214
1215 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
1216 inputdev = dev;
1217 }
1218 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
1219 outputdev = dev;
1220 }
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001221 if(inputdev && outputdev)
1222 break;
wdenk47d1a6e2002-11-03 00:01:44 +00001223 }
1224
1225 /* Initializes output console first */
1226 if (outputdev != NULL) {
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +02001227 console_setfile_and_devices(stdout, outputdev);
1228 console_setfile_and_devices(stderr, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001229 }
1230
1231 /* Initializes input console */
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +02001232 if (inputdev != NULL)
1233 console_setfile_and_devices(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001234
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001235 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1236 stdio_print_current_devices();
wdenk47d1a6e2002-11-03 00:01:44 +00001237
1238 /* Setting environment variables */
Tom Rini66c4d712018-05-03 09:12:26 -04001239 for (i = 0; i < MAX_FILES; i++) {
Simon Glass6a38e412017-08-03 12:22:09 -06001240 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +00001241 }
1242
Joe Hershbergera46f7702012-12-11 22:16:19 -06001243 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1244
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001245 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001246 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001247}
1248
Simon Glassdfc25352017-01-16 07:03:26 -07001249#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
Simon Glass1880b8a2024-09-01 16:26:20 -06001250
1251int console_remove_by_name(const char *name)
1252{
1253 int err = 0;
1254
1255#if CONFIG_IS_ENABLED(CONSOLE_MUX)
1256 int fnum;
1257
1258 log_debug("removing console device %s\n", name);
1259 for (fnum = 0; fnum < MAX_FILES; fnum++) {
1260 struct stdio_dev **src, **dest;
1261 int i;
1262
1263 log_debug("file %d: %d devices: ", fnum, cd_count[fnum]);
1264 src = console_devices[fnum];
1265 dest = src;
1266 for (i = 0; i < cd_count[fnum]; i++, src++) {
1267 struct stdio_dev *sdev = *src;
1268 int ret = 0;
1269
1270 if (!strcmp(sdev->name, name))
1271 ret = stdio_deregister_dev(sdev, true);
1272 else
1273 *dest++ = *src;
1274 if (ret && !err)
1275 err = ret;
1276 }
1277 cd_count[fnum] = dest - console_devices[fnum];
1278 log_debug("now %d\n", cd_count[fnum]);
1279 }
1280#endif /* CONSOLE_MUX */
1281
1282 return err;
1283}