blob: 22224701e451b318e084965dcdfb2dfbf5ef2e0f [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 &&
104 !membuff_putbyte((struct membuff *)&gd->console_out, c))
105 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
115 if (membuff_put((struct membuff *)&gd->console_out, s, len) !=
116 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
128 return membuff_getbyte((struct membuff *)&gd->console_in);
129}
130
131static int console_record_tstc(void)
132{
133 if (!(gd->flags & GD_FLG_RECORD))
134 return 0;
135 if (gd->console_in.start) {
136 if (membuff_peekbyte((struct membuff *)&gd->console_in) != -1)
137 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 }
211 break;
Simon Glass8a0417f2024-08-21 10:19:24 -0600212#endif
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
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100362static void console_puts(int file, const char *s)
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100363{
364 int i;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200365 struct stdio_dev *dev;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100366
Andy Shevchenkoe29d0192021-02-11 17:09:42 +0200367 for_each_console_dev(i, file, dev) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100368 if (dev->puts != NULL)
Simon Glass0d1e1f72014-07-23 06:54:59 -0600369 dev->puts(dev, s);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100370 }
371}
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100372
Pali Rohár5aceb262022-09-05 11:31:17 +0200373#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
374static void console_flush(int file)
375{
376 int i;
377 struct stdio_dev *dev;
378
379 for_each_console_dev(i, file, dev) {
380 if (dev->flush != NULL)
381 dev->flush(dev);
382 }
383}
384#endif
385
Tom Rinid30aeb12019-10-30 09:18:43 -0400386#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200387static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100388{
389 iomux_doenv(file, dev->name);
390}
Tom Rinid30aeb12019-10-30 09:18:43 -0400391#endif
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100392#else
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100393
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +0200394static void console_devices_set(int file, struct stdio_dev *dev)
Patrick Delaunay7c5f6ed2020-12-18 12:46:44 +0100395{
396}
397
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200398static inline bool console_needs_start_stop(int file, struct stdio_dev *sdev)
399{
400 return true;
401}
402
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100403static inline int console_getc(int file)
404{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600405 return stdio_devices[file]->getc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100406}
407
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100408static bool console_has_tstc(void)
409{
410 return false;
411}
412
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100413static inline int console_tstc(int file)
414{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600415 return stdio_devices[file]->tstc(stdio_devices[file]);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100416}
417
418static inline void console_putc(int file, const char c)
419{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600420 stdio_devices[file]->putc(stdio_devices[file], c);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100421}
422
Simon Glass66ee8172020-07-02 21:12:13 -0600423void console_puts_select(int file, bool serial_only, const char *s)
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200424{
Simon Glassc7ba6c82021-11-19 13:23:47 -0700425 if ((gd->flags & GD_FLG_DEVINIT) &&
426 serial_only == console_dev_is_serial(stdio_devices[file]))
Hans de Goedee355da02015-05-05 13:13:36 +0200427 stdio_devices[file]->puts(stdio_devices[file], s);
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200428}
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200429
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100430static inline void console_puts(int file, const char *s)
431{
Simon Glass0d1e1f72014-07-23 06:54:59 -0600432 stdio_devices[file]->puts(stdio_devices[file], s);
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100433}
Pali Rohár5aceb262022-09-05 11:31:17 +0200434
435#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
436static inline void console_flush(int file)
437{
438 if (stdio_devices[file]->flush)
439 stdio_devices[file]->flush(stdio_devices[file]);
440}
441#endif
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100442
Tom Rinid30aeb12019-10-30 09:18:43 -0400443#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200444static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100445{
446 console_setfile(file, dev);
447}
Tom Rinid30aeb12019-10-30 09:18:43 -0400448#endif
Simon Glassdfc25352017-01-16 07:03:26 -0700449#endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100450
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +0200451static void __maybe_unused console_setfile_and_devices(int file, struct stdio_dev *dev)
452{
453 console_setfile(file, dev);
454 console_devices_set(file, dev);
455}
456
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200457int console_start(int file, struct stdio_dev *sdev)
458{
459 int error;
460
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200461 if (!console_needs_start_stop(file, sdev))
462 return 0;
463
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200464 /* Start new device */
465 if (sdev->start) {
466 error = sdev->start(sdev);
467 /* If it's not started don't use it */
468 if (error < 0)
469 return error;
470 }
471 return 0;
472}
473
474void console_stop(int file, struct stdio_dev *sdev)
475{
Andy Shevchenkobdb0d4c2020-12-21 14:30:01 +0200476 if (!console_needs_start_stop(file, sdev))
477 return;
478
Andy Shevchenko2bce0212020-12-21 14:30:00 +0200479 if (sdev->stop)
480 sdev->stop(sdev);
481}
482
wdenk47d1a6e2002-11-03 00:01:44 +0000483/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
484
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200485int serial_printf(const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000486{
487 va_list args;
488 uint i;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200489 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000490
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100491 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000492
493 /* For this to work, printbuffer must be larger than
494 * anything we ever want to print.
495 */
Sonny Rao2813a212011-10-10 09:22:31 +0000496 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100497 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000498
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100499 serial_puts(printbuffer);
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200500 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000501}
502
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100503int fgetc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000504{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200505 if ((unsigned int)file < MAX_FILES) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100506 /*
507 * Effectively poll for input wherever it may be available.
508 */
509 for (;;) {
Stefan Roese80877fa2022-09-02 14:10:46 +0200510 schedule();
Patrick Delaunay4e8d61f2020-12-18 12:46:46 +0100511 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
512 /*
513 * Upper layer may have already called tstc() so
514 * check for that first.
515 */
516 if (console_has_tstc())
517 return console_getc(file);
518 console_tstc(file);
519 } else {
520 if (console_tstc(file))
521 return console_getc(file);
522 }
523
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100524 /*
525 * If the watchdog must be rate-limited then it should
526 * already be handled in board-specific code.
527 */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100528 if (IS_ENABLED(CONFIG_WATCHDOG))
529 udelay(1);
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100530 }
Gary Jennejohnc6dc7552008-11-06 15:04:23 +0100531 }
wdenk47d1a6e2002-11-03 00:01:44 +0000532
533 return -1;
534}
535
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100536int ftstc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000537{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200538 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100539 return console_tstc(file);
wdenk47d1a6e2002-11-03 00:01:44 +0000540
541 return -1;
542}
543
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100544void fputc(int file, const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000545{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200546 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100547 console_putc(file, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000548}
549
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100550void fputs(int file, const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000551{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200552 if ((unsigned int)file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +0100553 console_puts(file, s);
wdenk47d1a6e2002-11-03 00:01:44 +0000554}
555
Pali Rohár5aceb262022-09-05 11:31:17 +0200556#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
557void fflush(int file)
558{
Heinrich Schuchardt1bc421b2022-10-22 11:32:34 +0200559 if ((unsigned int)file < MAX_FILES)
Pali Rohár5aceb262022-09-05 11:31:17 +0200560 console_flush(file);
561}
562#endif
563
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200564int fprintf(int file, const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000565{
566 va_list args;
567 uint i;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200568 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000569
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100570 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000571
572 /* For this to work, printbuffer must be larger than
573 * anything we ever want to print.
574 */
Sonny Rao2813a212011-10-10 09:22:31 +0000575 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100576 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000577
578 /* Send to desired file */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100579 fputs(file, printbuffer);
Wolfgang Denk318ef5c2010-06-20 17:14:14 +0200580 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000581}
582
583/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
584
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200585int getchar(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000586{
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100587 int ch;
588
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100589 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100590 return 0;
Mark Jackson5de56212008-08-25 19:21:30 +0100591
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600592 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ70600b02011-08-29 02:14:05 +0000593 return 0;
594
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100595 ch = console_record_getc();
596 if (ch != -1)
597 return ch;
Simon Glass1bb49232015-11-08 23:47:48 -0700598
wdenk47d1a6e2002-11-03 00:01:44 +0000599 if (gd->flags & GD_FLG_DEVINIT) {
600 /* Get from the standard input */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100601 return fgetc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000602 }
603
604 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100605 return serial_getc();
wdenk47d1a6e2002-11-03 00:01:44 +0000606}
607
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100608int tstc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000609{
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100610 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100611 return 0;
Mark Jackson5de56212008-08-25 19:21:30 +0100612
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600613 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ70600b02011-08-29 02:14:05 +0000614 return 0;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100615
616 if (console_record_tstc())
617 return 1;
618
wdenk47d1a6e2002-11-03 00:01:44 +0000619 if (gd->flags & GD_FLG_DEVINIT) {
620 /* Test the standard input */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100621 return ftstc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000622 }
623
624 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100625 return serial_tstc();
wdenk47d1a6e2002-11-03 00:01:44 +0000626}
627
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200628#define PRE_CONSOLE_FLUSHPOINT1_SERIAL 0
629#define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL 1
630
Simon Glasse304a5e2016-10-17 20:12:36 -0600631#if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200632#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_VAL(PRE_CON_BUF_SZ))
Graeme Russ3c28f482011-09-01 00:48:27 +0000633
634static void pre_console_putc(const char c)
635{
Simon Glass46aaad02017-06-15 21:37:52 -0600636 char *buffer;
637
Rasmus Villemoese406a612022-05-03 15:13:27 +0200638 if (gd->precon_buf_idx < 0)
639 return;
640
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200641 buffer = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
Graeme Russ3c28f482011-09-01 00:48:27 +0000642
643 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
Simon Glass46aaad02017-06-15 21:37:52 -0600644
645 unmap_sysmem(buffer);
Graeme Russ3c28f482011-09-01 00:48:27 +0000646}
647
Soeren Moch54619bb2017-11-04 16:14:09 +0100648static void pre_console_puts(const char *s)
649{
Rasmus Villemoese406a612022-05-03 15:13:27 +0200650 if (gd->precon_buf_idx < 0)
651 return;
652
Soeren Moch54619bb2017-11-04 16:14:09 +0100653 while (*s)
654 pre_console_putc(*s++);
655}
656
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200657static void print_pre_console_buffer(int flushpoint)
Graeme Russ3c28f482011-09-01 00:48:27 +0000658{
Rasmus Villemoese406a612022-05-03 15:13:27 +0200659 long in = 0, out = 0;
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200660 char buf_out[CONFIG_VAL(PRE_CON_BUF_SZ) + 1];
Simon Glass46aaad02017-06-15 21:37:52 -0600661 char *buf_in;
Graeme Russ3c28f482011-09-01 00:48:27 +0000662
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100663 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200664 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200665
Rasmus Villemoesfb35fff2022-05-03 14:37:39 +0200666 buf_in = map_sysmem(CONFIG_VAL(PRE_CON_BUF_ADDR), CONFIG_VAL(PRE_CON_BUF_SZ));
667 if (gd->precon_buf_idx > CONFIG_VAL(PRE_CON_BUF_SZ))
668 in = gd->precon_buf_idx - CONFIG_VAL(PRE_CON_BUF_SZ);
Graeme Russ3c28f482011-09-01 00:48:27 +0000669
Hans de Goedee355da02015-05-05 13:13:36 +0200670 while (in < gd->precon_buf_idx)
671 buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)];
Simon Glass46aaad02017-06-15 21:37:52 -0600672 unmap_sysmem(buf_in);
Hans de Goedee355da02015-05-05 13:13:36 +0200673
674 buf_out[out] = 0;
675
Rasmus Villemoese406a612022-05-03 15:13:27 +0200676 gd->precon_buf_idx = -1;
Hans de Goedee355da02015-05-05 13:13:36 +0200677 switch (flushpoint) {
678 case PRE_CONSOLE_FLUSHPOINT1_SERIAL:
679 puts(buf_out);
680 break;
681 case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL:
Simon Glass66ee8172020-07-02 21:12:13 -0600682 console_puts_select(stdout, false, buf_out);
Hans de Goedee355da02015-05-05 13:13:36 +0200683 break;
684 }
Rasmus Villemoese406a612022-05-03 15:13:27 +0200685 gd->precon_buf_idx = in;
Graeme Russ3c28f482011-09-01 00:48:27 +0000686}
687#else
688static inline void pre_console_putc(const char c) {}
Soeren Moch54619bb2017-11-04 16:14:09 +0100689static inline void pre_console_puts(const char *s) {}
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200690static inline void print_pre_console_buffer(int flushpoint) {}
Graeme Russ3c28f482011-09-01 00:48:27 +0000691#endif
692
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100693void putc(const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000694{
Patrick Delaunay8f14b402020-11-27 11:20:56 +0100695 if (!gd)
696 return;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100697
698 console_record_putc(c);
699
Simon Glass16e3d7c2017-12-04 13:48:19 -0700700 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100701 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass16e3d7c2017-12-04 13:48:19 -0700702 os_putc(c);
703 return;
704 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100705
Simon Glass7dd27e02015-06-23 15:38:33 -0600706 /* if we don't have a console yet, use the debug UART */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100707 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glass7dd27e02015-06-23 15:38:33 -0600708 printch(c);
709 return;
710 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100711
712 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200713 if (!(gd->flags & GD_FLG_DEVINIT))
714 pre_console_putc(c);
wdenk927034e2004-02-08 19:38:38 +0000715 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200716 }
wdenk4b6e9052004-02-06 21:48:22 +0000717
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100718 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Mark Jackson5de56212008-08-25 19:21:30 +0100719 return;
Mark Jackson5de56212008-08-25 19:21:30 +0100720
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600721 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Graeme Russ3c28f482011-09-01 00:48:27 +0000722 return pre_console_putc(c);
Graeme Russ70600b02011-08-29 02:14:05 +0000723
wdenk47d1a6e2002-11-03 00:01:44 +0000724 if (gd->flags & GD_FLG_DEVINIT) {
725 /* Send to the standard output */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100726 fputc(stdout, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000727 } else {
728 /* Send directly to the handler */
Siarhei Siamashka616d03e2015-01-08 09:02:31 +0200729 pre_console_putc(c);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100730 serial_putc(c);
wdenk47d1a6e2002-11-03 00:01:44 +0000731 }
732}
733
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100734void puts(const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000735{
Patrick Delaunay8f14b402020-11-27 11:20:56 +0100736 if (!gd)
737 return;
Patrick Delaunayc20847f2020-12-18 12:46:45 +0100738
739 console_record_puts(s);
740
Simon Glassbf5c4862018-11-15 18:44:04 -0700741 /* sandbox can send characters to stdout before it has a console */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100742 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Simon Glassbf5c4862018-11-15 18:44:04 -0700743 os_puts(s);
744 return;
745 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100746
747 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
Soeren Moch54619bb2017-11-04 16:14:09 +0100748 while (*s) {
749 int ch = *s++;
750
751 printch(ch);
752 }
753 return;
754 }
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100755
756 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT)) {
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200757 if (!(gd->flags & GD_FLG_DEVINIT))
758 pre_console_puts(s);
Soeren Moch54619bb2017-11-04 16:14:09 +0100759 return;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200760 }
Soeren Moch54619bb2017-11-04 16:14:09 +0100761
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100762 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
Soeren Moch54619bb2017-11-04 16:14:09 +0100763 return;
Soeren Moch54619bb2017-11-04 16:14:09 +0100764
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600765 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Soeren Moch54619bb2017-11-04 16:14:09 +0100766 return pre_console_puts(s);
767
768 if (gd->flags & GD_FLG_DEVINIT) {
769 /* Send to the standard output */
770 fputs(stdout, s);
771 } else {
772 /* Send directly to the handler */
773 pre_console_puts(s);
774 serial_puts(s);
775 }
wdenk47d1a6e2002-11-03 00:01:44 +0000776}
Pali Rohár5aceb262022-09-05 11:31:17 +0200777
778#ifdef CONFIG_CONSOLE_FLUSH_SUPPORT
779void flush(void)
780{
781 if (!gd)
782 return;
783
784 /* sandbox can send characters to stdout before it has a console */
785 if (IS_ENABLED(CONFIG_SANDBOX) && !(gd->flags & GD_FLG_SERIAL_READY)) {
786 os_flush();
787 return;
788 }
789
790 if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY))
791 return;
792
793 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && (gd->flags & GD_FLG_SILENT))
794 return;
795
796 if (IS_ENABLED(CONFIG_DISABLE_CONSOLE) && (gd->flags & GD_FLG_DISABLE_CONSOLE))
797 return;
798
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600799 if (!(gd->flags & GD_FLG_HAVE_CONSOLE))
Pali Rohár5aceb262022-09-05 11:31:17 +0200800 return;
801
802 if (gd->flags & GD_FLG_DEVINIT) {
803 /* Send to the standard output */
804 fflush(stdout);
Pali Rohára48a24f2022-09-05 11:31:19 +0200805 } else {
806 /* Send directly to the handler */
807 serial_flush();
Pali Rohár5aceb262022-09-05 11:31:17 +0200808 }
809}
810#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000811
Simon Glass1bb49232015-11-08 23:47:48 -0700812#ifdef CONFIG_CONSOLE_RECORD
813int console_record_init(void)
814{
815 int ret;
816
Heinrich Schuchardt3b05a262020-02-12 18:23:49 +0100817 ret = membuff_new((struct membuff *)&gd->console_out,
Simon Glass9803ddf2021-10-23 17:26:03 -0600818 gd->flags & GD_FLG_RELOC ?
819 CONFIG_CONSOLE_RECORD_OUT_SIZE :
820 CONFIG_CONSOLE_RECORD_OUT_SIZE_F);
Simon Glass1bb49232015-11-08 23:47:48 -0700821 if (ret)
822 return ret;
Heinrich Schuchardt3b05a262020-02-12 18:23:49 +0100823 ret = membuff_new((struct membuff *)&gd->console_in,
824 CONFIG_CONSOLE_RECORD_IN_SIZE);
Simon Glass1bb49232015-11-08 23:47:48 -0700825
Ion Agorriac0b0de42024-01-05 09:22:09 +0200826 /* Start recording from the beginning */
827 gd->flags |= GD_FLG_RECORD;
828
Simon Glass1bb49232015-11-08 23:47:48 -0700829 return ret;
830}
831
832void console_record_reset(void)
833{
Heinrich Schuchardt3b05a262020-02-12 18:23:49 +0100834 membuff_purge((struct membuff *)&gd->console_out);
835 membuff_purge((struct membuff *)&gd->console_in);
Simon Glassd6ed4af2021-05-08 06:59:56 -0600836 gd->flags &= ~GD_FLG_RECORD_OVF;
Simon Glass1bb49232015-11-08 23:47:48 -0700837}
838
Simon Glassdc357ef2020-07-28 19:41:11 -0600839int console_record_reset_enable(void)
Simon Glass1bb49232015-11-08 23:47:48 -0700840{
841 console_record_reset();
842 gd->flags |= GD_FLG_RECORD;
Simon Glassdc357ef2020-07-28 19:41:11 -0600843
844 return 0;
Simon Glass1bb49232015-11-08 23:47:48 -0700845}
Simon Glassb17c1582020-01-27 08:49:54 -0700846
847int console_record_readline(char *str, int maxlen)
848{
Simon Glassd6ed4af2021-05-08 06:59:56 -0600849 if (gd->flags & GD_FLG_RECORD_OVF)
850 return -ENOSPC;
Simon Glassc2e59eb2024-08-22 07:57:47 -0600851 if (console_record_isempty())
852 return -ENOENT;
Simon Glassd6ed4af2021-05-08 06:59:56 -0600853
Heinrich Schuchardt3b05a262020-02-12 18:23:49 +0100854 return membuff_readline((struct membuff *)&gd->console_out, str,
Ion Agorria7e06c1f2024-01-05 09:22:10 +0200855 maxlen, '\0', false);
Simon Glassb17c1582020-01-27 08:49:54 -0700856}
857
858int console_record_avail(void)
859{
Heinrich Schuchardt3b05a262020-02-12 18:23:49 +0100860 return membuff_avail((struct membuff *)&gd->console_out);
Simon Glassb17c1582020-01-27 08:49:54 -0700861}
862
Ion Agorria15f6d6a2024-01-05 09:22:08 +0200863bool console_record_isempty(void)
864{
865 return membuff_isempty((struct membuff *)&gd->console_out);
866}
867
Steffen Jaeckele1788f92021-07-08 15:57:40 +0200868int console_in_puts(const char *str)
869{
870 return membuff_put((struct membuff *)&gd->console_in, str, strlen(str));
871}
872
Simon Glass1bb49232015-11-08 23:47:48 -0700873#endif
874
wdenk47d1a6e2002-11-03 00:01:44 +0000875/* test if ctrl-c was pressed */
876static int ctrlc_disabled = 0; /* see disable_ctrl() */
877static int ctrlc_was_pressed = 0;
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100878int ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000879{
Simon Glassd4b0fdb2024-08-21 10:19:04 -0600880 if (!ctrlc_disabled && (gd->flags & GD_FLG_HAVE_CONSOLE)) {
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100881 if (tstc()) {
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200882 switch (getchar()) {
wdenk47d1a6e2002-11-03 00:01:44 +0000883 case 0x03: /* ^C - Control C */
884 ctrlc_was_pressed = 1;
885 return 1;
886 default:
887 break;
888 }
889 }
890 }
Simon Glass28c5ce72014-09-14 12:40:15 -0600891
wdenk47d1a6e2002-11-03 00:01:44 +0000892 return 0;
893}
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200894/* Reads user's confirmation.
895 Returns 1 if user's input is "y", "Y", "yes" or "YES"
896*/
897int confirm_yesno(void)
898{
899 int i;
900 char str_input[5];
wdenk47d1a6e2002-11-03 00:01:44 +0000901
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200902 /* Flush input */
903 while (tstc())
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200904 getchar();
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200905 i = 0;
906 while (i < sizeof(str_input)) {
Heinrich Schuchardtc4954fb2020-10-07 18:11:48 +0200907 str_input[i] = getchar();
Pierre Aubert5fef9d32014-04-24 10:30:07 +0200908 putc(str_input[i]);
909 if (str_input[i] == '\r')
910 break;
911 i++;
912 }
913 putc('\n');
914 if (strncmp(str_input, "y\r", 2) == 0 ||
915 strncmp(str_input, "Y\r", 2) == 0 ||
916 strncmp(str_input, "yes\r", 4) == 0 ||
917 strncmp(str_input, "YES\r", 4) == 0)
918 return 1;
919 return 0;
920}
wdenk47d1a6e2002-11-03 00:01:44 +0000921/* pass 1 to disable ctrlc() checking, 0 to enable.
922 * returns previous state
923 */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100924int disable_ctrlc(int disable)
wdenk47d1a6e2002-11-03 00:01:44 +0000925{
926 int prev = ctrlc_disabled; /* save previous state */
927
928 ctrlc_disabled = disable;
929 return prev;
930}
931
932int had_ctrlc (void)
933{
934 return ctrlc_was_pressed;
935}
936
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100937void clear_ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000938{
939 ctrlc_was_pressed = 0;
940}
941
wdenk47d1a6e2002-11-03 00:01:44 +0000942/** U-Boot INIT FUNCTIONS *************************************************/
943
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200944struct stdio_dev *console_search_dev(int flags, const char *name)
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200945{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200946 struct stdio_dev *dev;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200947
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200948 dev = stdio_get_by_name(name);
Simon Glass86f07462016-02-06 14:31:37 -0700949#ifdef CONFIG_VIDCONSOLE_AS_LCD
Patrick Delaunay60b92242020-07-01 14:56:10 +0200950 if (!dev && !strcmp(name, CONFIG_VIDCONSOLE_AS_NAME))
Simon Glass86f07462016-02-06 14:31:37 -0700951 dev = stdio_get_by_name("vidconsole");
952#endif
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200953
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100954 if (dev && (dev->flags & flags))
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200955 return dev;
956
957 return NULL;
958}
959
Mike Frysingere3d55722010-10-20 07:18:03 -0400960int console_assign(int file, const char *devname)
wdenk47d1a6e2002-11-03 00:01:44 +0000961{
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +0200962 int flag;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200963 struct stdio_dev *dev;
wdenk47d1a6e2002-11-03 00:01:44 +0000964
965 /* Check for valid file */
Andy Shevchenko59f324c2021-02-11 17:09:37 +0200966 flag = stdio_file_to_flags(file);
967 if (flag < 0)
968 return flag;
wdenk47d1a6e2002-11-03 00:01:44 +0000969
970 /* Check for valid device name */
971
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +0200972 dev = console_search_dev(flag, devname);
wdenk47d1a6e2002-11-03 00:01:44 +0000973
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +0100974 if (dev)
975 return console_setfile(file, dev);
wdenk47d1a6e2002-11-03 00:01:44 +0000976
977 return -1;
978}
979
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200980/* return true if the 'silent' flag is removed */
981static bool console_update_silent(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000982{
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100983 unsigned long flags = gd->flags;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200984
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100985 if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
986 return false;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200987
Harald Seiler6d09df82022-07-06 13:19:10 +0200988 if (IS_ENABLED(CONFIG_SILENT_CONSOLE_UNTIL_ENV) && !(gd->flags & GD_FLG_ENV_READY)) {
989 gd->flags |= GD_FLG_SILENT;
990 return false;
991 }
992
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100993 if (env_get("silent")) {
994 gd->flags |= GD_FLG_SILENT;
995 return false;
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200996 }
Patrick Delaunayb39862f2019-08-02 14:58:10 +0200997
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +0100998 gd->flags &= ~GD_FLG_SILENT;
999
1000 return !!(flags & GD_FLG_SILENT);
Simon Glassc9c5c9f2017-06-15 21:37:50 -06001001}
1002
1003int console_announce_r(void)
1004{
1005#if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
1006 char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
1007
1008 display_options_get_banner(false, buf, sizeof(buf));
1009
Simon Glass66ee8172020-07-02 21:12:13 -06001010 console_puts_select(stdout, false, buf);
Simon Glassc9c5c9f2017-06-15 21:37:50 -06001011#endif
1012
1013 return 0;
Chris Packhamfab806d2016-09-23 15:59:43 +12001014}
1015
1016/* Called before relocation - use serial functions */
1017int console_init_f(void)
1018{
Simon Glassd4b0fdb2024-08-21 10:19:04 -06001019 gd->flags |= GD_FLG_HAVE_CONSOLE;
Chris Packhamfab806d2016-09-23 15:59:43 +12001020
1021 console_update_silent();
wdenk808532a2003-10-10 10:05:42 +00001022
Siarhei Siamashka616d03e2015-01-08 09:02:31 +02001023 print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
Graeme Russ3c28f482011-09-01 00:48:27 +00001024
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001025 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001026}
1027
Simon Glassffafbe32023-10-01 19:15:23 -06001028int console_clear(void)
1029{
1030 /*
1031 * Send clear screen and home
1032 *
1033 * FIXME(Heinrich Schuchardt <xypron.glpk@gmx.de>): This should go
1034 * through an API and only be written to serial terminals, not video
1035 * displays
1036 */
1037 printf(CSI "2J" CSI "1;1H");
1038 if (IS_ENABLED(CONFIG_VIDEO_ANSI))
1039 return 0;
1040
1041 if (IS_ENABLED(CONFIG_VIDEO)) {
1042 struct udevice *dev;
1043 int ret;
1044
1045 ret = uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev);
1046 if (ret)
1047 return ret;
1048 ret = vidconsole_clear_and_reset(dev);
1049 if (ret)
1050 return ret;
1051 }
1052
1053 return 0;
1054}
1055
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001056static char *get_stdio(const u8 std)
1057{
1058 return stdio_devices[std] ? stdio_devices[std]->name : "No devices available!";
1059}
1060
Bin Meng13186892023-07-23 12:40:35 +08001061static void stdio_print_current_devices(void)
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001062{
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001063 char *stdinname = NULL;
1064 char *stdoutname = NULL;
1065 char *stderrname = NULL;
Bin Menga6a83502023-07-23 12:40:36 +08001066
Bin Mengd61be5b2023-07-23 12:40:37 +08001067 if (CONFIG_IS_ENABLED(CONSOLE_MUX) &&
1068 CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)) {
1069 /* stdin stdout and stderr are in environment */
1070 stdinname = env_get("stdin");
1071 stdoutname = env_get("stdout");
1072 stderrname = env_get("stderr");
Bin Mengd61be5b2023-07-23 12:40:37 +08001073 }
Bin Menga6a83502023-07-23 12:40:36 +08001074
Patrice Chotardcc82bae2024-01-17 13:37:13 +01001075 stdinname = stdinname ? : get_stdio(stdin);
1076 stdoutname = stdoutname ? : get_stdio(stdout);
1077 stderrname = stderrname ? : get_stdio(stderr);
1078
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001079 /* Print information */
1080 puts("In: ");
Bin Menga6a83502023-07-23 12:40:36 +08001081 printf("%s\n", stdinname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001082
1083 puts("Out: ");
Bin Menga6a83502023-07-23 12:40:36 +08001084 printf("%s\n", stdoutname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001085
1086 puts("Err: ");
Bin Menga6a83502023-07-23 12:40:36 +08001087 printf("%s\n", stderrname);
Jean-Christophe PLAGNIOL-VILLARD5a309362009-05-16 12:14:55 +02001088}
1089
Simon Glassdfc25352017-01-16 07:03:26 -07001090#if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
wdenk47d1a6e2002-11-03 00:01:44 +00001091/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001092int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +00001093{
1094 char *stdinname, *stdoutname, *stderrname;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001095 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
wdenk05939202004-04-18 17:39:38 +00001096 int i;
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001097 int iomux_err = 0;
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001098 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +00001099
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001100 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001101 if (console_update_silent())
1102 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
1103 else
1104 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001105
wdenk47d1a6e2002-11-03 00:01:44 +00001106 /* set default handlers at first */
Martin Dorwigcb2c2862015-01-26 15:22:54 -07001107 gd->jt->getc = serial_getc;
1108 gd->jt->tstc = serial_tstc;
1109 gd->jt->putc = serial_putc;
1110 gd->jt->puts = serial_puts;
1111 gd->jt->printf = serial_printf;
wdenk47d1a6e2002-11-03 00:01:44 +00001112
1113 /* stdin stdout and stderr are in environment */
1114 /* scan for it */
Simon Glass64b723f2017-08-03 12:22:12 -06001115 stdinname = env_get("stdin");
1116 stdoutname = env_get("stdout");
1117 stderrname = env_get("stderr");
wdenk47d1a6e2002-11-03 00:01:44 +00001118
Wolfgang Denka1be4762008-05-20 16:00:29 +02001119 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001120 inputdev = console_search_dev(DEV_FLAGS_INPUT, stdinname);
1121 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, stdoutname);
1122 errdev = console_search_dev(DEV_FLAGS_OUTPUT, stderrname);
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001123 if (CONFIG_IS_ENABLED(CONSOLE_MUX)) {
1124 iomux_err = iomux_doenv(stdin, stdinname);
1125 iomux_err += iomux_doenv(stdout, stdoutname);
1126 iomux_err += iomux_doenv(stderr, stderrname);
1127 if (!iomux_err)
1128 /* Successful, so skip all the code below. */
1129 goto done;
1130 }
wdenk47d1a6e2002-11-03 00:01:44 +00001131 }
1132 /* if the devices are overwritten or not found, use default device */
1133 if (inputdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001134 inputdev = console_search_dev(DEV_FLAGS_INPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001135 }
1136 if (outputdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001137 outputdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001138 }
1139 if (errdev == NULL) {
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001140 errdev = console_search_dev(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +00001141 }
1142 /* Initializes output console first */
1143 if (outputdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001144 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001145 console_doenv(stdout, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001146 }
1147 if (errdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001148 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001149 console_doenv(stderr, errdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001150 }
1151 if (inputdev != NULL) {
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001152 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD63331a02009-02-01 17:07:52 +01001153 console_doenv(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001154 }
1155
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001156done:
Gary Jennejohnc6dc7552008-11-06 15:04:23 +01001157
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001158 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1159 stdio_print_current_devices();
1160
Simon Glass86f07462016-02-06 14:31:37 -07001161#ifdef CONFIG_VIDCONSOLE_AS_LCD
Patrick Delaunay60b92242020-07-01 14:56:10 +02001162 if (strstr(stdoutname, CONFIG_VIDCONSOLE_AS_NAME))
Anatolij Gustschin47020642020-05-23 17:11:20 +02001163 printf("Warning: Please change '%s' to 'vidconsole' in stdout/stderr environment vars\n",
Patrick Delaunay60b92242020-07-01 14:56:10 +02001164 CONFIG_VIDCONSOLE_AS_NAME);
Simon Glass86f07462016-02-06 14:31:37 -07001165#endif
wdenk47d1a6e2002-11-03 00:01:44 +00001166
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001167 if (IS_ENABLED(CONFIG_SYS_CONSOLE_ENV_OVERWRITE)) {
1168 /* set the environment variables (will overwrite previous env settings) */
1169 for (i = 0; i < MAX_FILES; i++)
1170 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +00001171 }
wdenk47d1a6e2002-11-03 00:01:44 +00001172
Joe Hershbergera46f7702012-12-11 22:16:19 -06001173 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1174
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001175 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001176 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001177}
1178
Simon Glassdfc25352017-01-16 07:03:26 -07001179#else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
wdenk47d1a6e2002-11-03 00:01:44 +00001180
1181/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001182int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +00001183{
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001184 struct stdio_dev *inputdev = NULL, *outputdev = NULL;
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001185 int i;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001186 struct list_head *list = stdio_get_list();
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001187 struct list_head *pos;
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001188 struct stdio_dev *dev;
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001189 int flushpoint;
wdenk47d1a6e2002-11-03 00:01:44 +00001190
Patrick Delaunay46b610d2019-08-02 14:58:09 +02001191 /* update silent for env loaded from flash (initr_env) */
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001192 if (console_update_silent())
1193 flushpoint = PRE_CONSOLE_FLUSHPOINT1_SERIAL;
1194 else
1195 flushpoint = PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL;
Chris Packhamfab806d2016-09-23 15:59:43 +12001196
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001197 /*
1198 * suppress all output if splash screen is enabled and we have
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001199 * a bmp to display. We redirect the output from frame buffer
1200 * console to serial console in this case or suppress it if
1201 * "silent" mode was requested.
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001202 */
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001203 if (IS_ENABLED(CONFIG_SPLASH_SCREEN) && env_get("splashimage")) {
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001204 if (!(gd->flags & GD_FLG_SILENT))
Andy Shevchenkocfaed7f2020-12-21 14:30:03 +02001205 outputdev = console_search_dev (DEV_FLAGS_OUTPUT, "serial");
Anatolij Gustschinec8744a2010-03-16 15:29:33 +01001206 }
wdenk808532a2003-10-10 10:05:42 +00001207
wdenk47d1a6e2002-11-03 00:01:44 +00001208 /* Scan devices looking for input and output devices */
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001209 list_for_each(pos, list) {
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +02001210 dev = list_entry(pos, struct stdio_dev, list);
wdenk47d1a6e2002-11-03 00:01:44 +00001211
1212 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
1213 inputdev = dev;
1214 }
1215 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
1216 outputdev = dev;
1217 }
Jean-Christophe PLAGNIOL-VILLARD8a4a7842008-08-31 04:24:55 +02001218 if(inputdev && outputdev)
1219 break;
wdenk47d1a6e2002-11-03 00:01:44 +00001220 }
1221
1222 /* Initializes output console first */
1223 if (outputdev != NULL) {
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +02001224 console_setfile_and_devices(stdout, outputdev);
1225 console_setfile_and_devices(stderr, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001226 }
1227
1228 /* Initializes input console */
Andy Shevchenkoba69b2c2021-02-11 17:09:39 +02001229 if (inputdev != NULL)
1230 console_setfile_and_devices(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +00001231
Patrick Delaunay4b0b56f2020-12-18 12:46:43 +01001232 if (!IS_ENABLED(CONFIG_SYS_CONSOLE_INFO_QUIET))
1233 stdio_print_current_devices();
wdenk47d1a6e2002-11-03 00:01:44 +00001234
1235 /* Setting environment variables */
Tom Rini66c4d712018-05-03 09:12:26 -04001236 for (i = 0; i < MAX_FILES; i++) {
Simon Glass6a38e412017-08-03 12:22:09 -06001237 env_set(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +00001238 }
1239
Joe Hershbergera46f7702012-12-11 22:16:19 -06001240 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
1241
Patrick Delaunayb39862f2019-08-02 14:58:10 +02001242 print_pre_console_buffer(flushpoint);
Jean-Christophe PLAGNIOL-VILLARDc7dc6722009-02-01 17:07:51 +01001243 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +00001244}
1245
Simon Glassdfc25352017-01-16 07:03:26 -07001246#endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
Simon Glass1880b8a2024-09-01 16:26:20 -06001247
1248int console_remove_by_name(const char *name)
1249{
1250 int err = 0;
1251
1252#if CONFIG_IS_ENABLED(CONSOLE_MUX)
1253 int fnum;
1254
1255 log_debug("removing console device %s\n", name);
1256 for (fnum = 0; fnum < MAX_FILES; fnum++) {
1257 struct stdio_dev **src, **dest;
1258 int i;
1259
1260 log_debug("file %d: %d devices: ", fnum, cd_count[fnum]);
1261 src = console_devices[fnum];
1262 dest = src;
1263 for (i = 0; i < cd_count[fnum]; i++, src++) {
1264 struct stdio_dev *sdev = *src;
1265 int ret = 0;
1266
1267 if (!strcmp(sdev->name, name))
1268 ret = stdio_deregister_dev(sdev, true);
1269 else
1270 *dest++ = *src;
1271 if (ret && !err)
1272 err = ret;
1273 }
1274 cd_count[fnum] = dest - console_devices[fnum];
1275 log_debug("now %d\n", cd_count[fnum]);
1276 }
1277#endif /* CONSOLE_MUX */
1278
1279 return err;
1280}