xref: /openbmc/u-boot/common/console.c (revision 6b21502229035779059493b2193fd790448fe85e)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
247d1a6e1Swdenk /*
347d1a6e1Swdenk  * (C) Copyright 2000
447d1a6e1Swdenk  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
547d1a6e1Swdenk  */
647d1a6e1Swdenk 
747d1a6e1Swdenk #include <common.h>
824b852a7SSimon Glass #include <console.h>
9d6ea5307SSimon Glass #include <debug_uart.h>
107b3c4c3aSSimon Glass #include <dm.h>
1147d1a6e1Swdenk #include <stdarg.h>
12482f4691SJeroen Hofstee #include <iomux.h>
1347d1a6e1Swdenk #include <malloc.h>
144e6bafa5SSimon Glass #include <mapmem.h>
1591b136c7SSimon Glass #include <os.h>
16849d5d9cSJoe Hershberger #include <serial.h>
1752cb4d4fSJean-Christophe PLAGNIOL-VILLARD #include <stdio_dev.h>
1827b207fdSwdenk #include <exports.h>
19849d5d9cSJoe Hershberger #include <environment.h>
2064407467SAndreas J. Reichel #include <watchdog.h>
2147d1a6e1Swdenk 
22d87080b7SWolfgang Denk DECLARE_GLOBAL_DATA_PTR;
23d87080b7SWolfgang Denk 
on_console(const char * name,const char * value,enum env_op op,int flags)24849d5d9cSJoe Hershberger static int on_console(const char *name, const char *value, enum env_op op,
25849d5d9cSJoe Hershberger 	int flags)
26849d5d9cSJoe Hershberger {
27849d5d9cSJoe Hershberger 	int console = -1;
28849d5d9cSJoe Hershberger 
29849d5d9cSJoe Hershberger 	/* Check for console redirection */
30849d5d9cSJoe Hershberger 	if (strcmp(name, "stdin") == 0)
31849d5d9cSJoe Hershberger 		console = stdin;
32849d5d9cSJoe Hershberger 	else if (strcmp(name, "stdout") == 0)
33849d5d9cSJoe Hershberger 		console = stdout;
34849d5d9cSJoe Hershberger 	else if (strcmp(name, "stderr") == 0)
35849d5d9cSJoe Hershberger 		console = stderr;
36849d5d9cSJoe Hershberger 
37849d5d9cSJoe Hershberger 	/* if not actually setting a console variable, we don't care */
38849d5d9cSJoe Hershberger 	if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0)
39849d5d9cSJoe Hershberger 		return 0;
40849d5d9cSJoe Hershberger 
41849d5d9cSJoe Hershberger 	switch (op) {
42849d5d9cSJoe Hershberger 	case env_op_create:
43849d5d9cSJoe Hershberger 	case env_op_overwrite:
44849d5d9cSJoe Hershberger 
45b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
46849d5d9cSJoe Hershberger 		if (iomux_doenv(console, value))
47849d5d9cSJoe Hershberger 			return 1;
48849d5d9cSJoe Hershberger #else
49849d5d9cSJoe Hershberger 		/* Try assigning specified device */
50849d5d9cSJoe Hershberger 		if (console_assign(console, value) < 0)
51849d5d9cSJoe Hershberger 			return 1;
52b0265429SSimon Glass #endif
53849d5d9cSJoe Hershberger 		return 0;
54849d5d9cSJoe Hershberger 
55849d5d9cSJoe Hershberger 	case env_op_delete:
56849d5d9cSJoe Hershberger 		if ((flags & H_FORCE) == 0)
57849d5d9cSJoe Hershberger 			printf("Can't delete \"%s\"\n", name);
58849d5d9cSJoe Hershberger 		return 1;
59849d5d9cSJoe Hershberger 
60849d5d9cSJoe Hershberger 	default:
61849d5d9cSJoe Hershberger 		return 0;
62849d5d9cSJoe Hershberger 	}
63849d5d9cSJoe Hershberger }
64849d5d9cSJoe Hershberger U_BOOT_ENV_CALLBACK(console, on_console);
65849d5d9cSJoe Hershberger 
66e080d545SJoe Hershberger #ifdef CONFIG_SILENT_CONSOLE
on_silent(const char * name,const char * value,enum env_op op,int flags)67e080d545SJoe Hershberger static int on_silent(const char *name, const char *value, enum env_op op,
68e080d545SJoe Hershberger 	int flags)
69e080d545SJoe Hershberger {
705daf6e56SWilson Lee #if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_SET)
71e080d545SJoe Hershberger 	if (flags & H_INTERACTIVE)
72e080d545SJoe Hershberger 		return 0;
73e080d545SJoe Hershberger #endif
745daf6e56SWilson Lee #if !CONFIG_IS_ENABLED(SILENT_CONSOLE_UPDATE_ON_RELOC)
75e080d545SJoe Hershberger 	if ((flags & H_INTERACTIVE) == 0)
76e080d545SJoe Hershberger 		return 0;
77e080d545SJoe Hershberger #endif
78e080d545SJoe Hershberger 
79e080d545SJoe Hershberger 	if (value != NULL)
80e080d545SJoe Hershberger 		gd->flags |= GD_FLG_SILENT;
81e080d545SJoe Hershberger 	else
82e080d545SJoe Hershberger 		gd->flags &= ~GD_FLG_SILENT;
83e080d545SJoe Hershberger 
84e080d545SJoe Hershberger 	return 0;
85e080d545SJoe Hershberger }
86e080d545SJoe Hershberger U_BOOT_ENV_CALLBACK(silent, on_silent);
87e080d545SJoe Hershberger #endif
88e080d545SJoe Hershberger 
89b0265429SSimon Glass #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
9047d1a6e1Swdenk /*
9147d1a6e1Swdenk  * if overwrite_console returns 1, the stdin, stderr and stdout
9247d1a6e1Swdenk  * are switched to the serial port, else the settings in the
9347d1a6e1Swdenk  * environment are used
9447d1a6e1Swdenk  */
956d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
9647d1a6e1Swdenk extern int overwrite_console(void);
9783e40ba7Swdenk #define OVERWRITE_CONSOLE overwrite_console()
9847d1a6e1Swdenk #else
9983e40ba7Swdenk #define OVERWRITE_CONSOLE 0
1006d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
10147d1a6e1Swdenk 
102b0265429SSimon Glass #endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
10347d1a6e1Swdenk 
console_setfile(int file,struct stdio_dev * dev)10452cb4d4fSJean-Christophe PLAGNIOL-VILLARD static int console_setfile(int file, struct stdio_dev * dev)
10547d1a6e1Swdenk {
10647d1a6e1Swdenk 	int error = 0;
10747d1a6e1Swdenk 
10847d1a6e1Swdenk 	if (dev == NULL)
10947d1a6e1Swdenk 		return -1;
11047d1a6e1Swdenk 
11147d1a6e1Swdenk 	switch (file) {
11247d1a6e1Swdenk 	case stdin:
11347d1a6e1Swdenk 	case stdout:
11447d1a6e1Swdenk 	case stderr:
11547d1a6e1Swdenk 		/* Start new device */
11647d1a6e1Swdenk 		if (dev->start) {
117709ea543SSimon Glass 			error = dev->start(dev);
11847d1a6e1Swdenk 			/* If it's not started dont use it */
11947d1a6e1Swdenk 			if (error < 0)
12047d1a6e1Swdenk 				break;
12147d1a6e1Swdenk 		}
12247d1a6e1Swdenk 
12347d1a6e1Swdenk 		/* Assign the new device (leaving the existing one started) */
12447d1a6e1Swdenk 		stdio_devices[file] = dev;
12547d1a6e1Swdenk 
12647d1a6e1Swdenk 		/*
12747d1a6e1Swdenk 		 * Update monitor functions
12847d1a6e1Swdenk 		 * (to use the console stuff by other applications)
12947d1a6e1Swdenk 		 */
13047d1a6e1Swdenk 		switch (file) {
13147d1a6e1Swdenk 		case stdin:
13249cad547SMartin Dorwig 			gd->jt->getc = getc;
13349cad547SMartin Dorwig 			gd->jt->tstc = tstc;
13447d1a6e1Swdenk 			break;
13547d1a6e1Swdenk 		case stdout:
13649cad547SMartin Dorwig 			gd->jt->putc  = putc;
13749cad547SMartin Dorwig 			gd->jt->puts  = puts;
13849cad547SMartin Dorwig 			gd->jt->printf = printf;
13947d1a6e1Swdenk 			break;
14047d1a6e1Swdenk 		}
14147d1a6e1Swdenk 		break;
14247d1a6e1Swdenk 
14347d1a6e1Swdenk 	default:		/* Invalid file ID */
14447d1a6e1Swdenk 		error = -1;
14547d1a6e1Swdenk 	}
14647d1a6e1Swdenk 	return error;
14747d1a6e1Swdenk }
14847d1a6e1Swdenk 
14942f9f915SSimon Glass /**
15042f9f915SSimon Glass  * console_dev_is_serial() - Check if a stdio device is a serial device
15142f9f915SSimon Glass  *
15242f9f915SSimon Glass  * @sdev: Device to check
1537b3c4c3aSSimon Glass  * @return true if this device is in the serial uclass (or for pre-driver-model,
1547b3c4c3aSSimon Glass  * whether it is called "serial".
15542f9f915SSimon Glass  */
console_dev_is_serial(struct stdio_dev * sdev)15642f9f915SSimon Glass static bool console_dev_is_serial(struct stdio_dev *sdev)
15742f9f915SSimon Glass {
15842f9f915SSimon Glass 	bool is_serial;
15942f9f915SSimon Glass 
1607b3c4c3aSSimon Glass #ifdef CONFIG_DM_SERIAL
1617b3c4c3aSSimon Glass 	if (sdev->flags & DEV_FLAGS_DM) {
1627b3c4c3aSSimon Glass 		struct udevice *dev = sdev->priv;
1637b3c4c3aSSimon Glass 
1647b3c4c3aSSimon Glass 		is_serial = device_get_uclass_id(dev) == UCLASS_SERIAL;
1657b3c4c3aSSimon Glass 	} else
1667b3c4c3aSSimon Glass #endif
16742f9f915SSimon Glass 	is_serial = !strcmp(sdev->name, "serial");
16842f9f915SSimon Glass 
16942f9f915SSimon Glass 	return is_serial;
17042f9f915SSimon Glass }
17142f9f915SSimon Glass 
172b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
17316a28ef2SGary Jennejohn /** Console I/O multiplexing *******************************************/
17416a28ef2SGary Jennejohn 
17552cb4d4fSJean-Christophe PLAGNIOL-VILLARD static struct stdio_dev *tstcdev;
17652cb4d4fSJean-Christophe PLAGNIOL-VILLARD struct stdio_dev **console_devices[MAX_FILES];
17716a28ef2SGary Jennejohn int cd_count[MAX_FILES];
17816a28ef2SGary Jennejohn 
17916a28ef2SGary Jennejohn /*
18016a28ef2SGary Jennejohn  * This depends on tstc() always being called before getc().
18116a28ef2SGary Jennejohn  * This is guaranteed to be true because this routine is called
18216a28ef2SGary Jennejohn  * only from fgetc() which assures it.
18316a28ef2SGary Jennejohn  * No attempt is made to demultiplex multiple input sources.
18416a28ef2SGary Jennejohn  */
console_getc(int file)1855f032010SJean-Christophe PLAGNIOL-VILLARD static int console_getc(int file)
18616a28ef2SGary Jennejohn {
18716a28ef2SGary Jennejohn 	unsigned char ret;
18816a28ef2SGary Jennejohn 
18916a28ef2SGary Jennejohn 	/* This is never called with testcdev == NULL */
190709ea543SSimon Glass 	ret = tstcdev->getc(tstcdev);
19116a28ef2SGary Jennejohn 	tstcdev = NULL;
19216a28ef2SGary Jennejohn 	return ret;
19316a28ef2SGary Jennejohn }
19416a28ef2SGary Jennejohn 
console_tstc(int file)1955f032010SJean-Christophe PLAGNIOL-VILLARD static int console_tstc(int file)
19616a28ef2SGary Jennejohn {
19716a28ef2SGary Jennejohn 	int i, ret;
19852cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
199b2f58d8eSJoe Hershberger 	int prev;
20016a28ef2SGary Jennejohn 
201b2f58d8eSJoe Hershberger 	prev = disable_ctrlc(1);
20216a28ef2SGary Jennejohn 	for (i = 0; i < cd_count[file]; i++) {
20316a28ef2SGary Jennejohn 		dev = console_devices[file][i];
20416a28ef2SGary Jennejohn 		if (dev->tstc != NULL) {
205709ea543SSimon Glass 			ret = dev->tstc(dev);
20616a28ef2SGary Jennejohn 			if (ret > 0) {
20716a28ef2SGary Jennejohn 				tstcdev = dev;
208b2f58d8eSJoe Hershberger 				disable_ctrlc(prev);
20916a28ef2SGary Jennejohn 				return ret;
21016a28ef2SGary Jennejohn 			}
21116a28ef2SGary Jennejohn 		}
21216a28ef2SGary Jennejohn 	}
213b2f58d8eSJoe Hershberger 	disable_ctrlc(prev);
21416a28ef2SGary Jennejohn 
21516a28ef2SGary Jennejohn 	return 0;
21616a28ef2SGary Jennejohn }
21716a28ef2SGary Jennejohn 
console_putc(int file,const char c)2185f032010SJean-Christophe PLAGNIOL-VILLARD static void console_putc(int file, const char c)
21916a28ef2SGary Jennejohn {
22016a28ef2SGary Jennejohn 	int i;
22152cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
22216a28ef2SGary Jennejohn 
22316a28ef2SGary Jennejohn 	for (i = 0; i < cd_count[file]; i++) {
22416a28ef2SGary Jennejohn 		dev = console_devices[file][i];
22516a28ef2SGary Jennejohn 		if (dev->putc != NULL)
226709ea543SSimon Glass 			dev->putc(dev, c);
22716a28ef2SGary Jennejohn 	}
22816a28ef2SGary Jennejohn }
22916a28ef2SGary Jennejohn 
console_puts_noserial(int file,const char * s)230a8552c7cSHans de Goede static void console_puts_noserial(int file, const char *s)
23127669667SSiarhei Siamashka {
23227669667SSiarhei Siamashka 	int i;
23327669667SSiarhei Siamashka 	struct stdio_dev *dev;
23427669667SSiarhei Siamashka 
23527669667SSiarhei Siamashka 	for (i = 0; i < cd_count[file]; i++) {
23627669667SSiarhei Siamashka 		dev = console_devices[file][i];
23742f9f915SSimon Glass 		if (dev->puts != NULL && !console_dev_is_serial(dev))
238a8552c7cSHans de Goede 			dev->puts(dev, s);
23927669667SSiarhei Siamashka 	}
24027669667SSiarhei Siamashka }
24127669667SSiarhei Siamashka 
console_puts(int file,const char * s)2425f032010SJean-Christophe PLAGNIOL-VILLARD static void console_puts(int file, const char *s)
24316a28ef2SGary Jennejohn {
24416a28ef2SGary Jennejohn 	int i;
24552cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
24616a28ef2SGary Jennejohn 
24716a28ef2SGary Jennejohn 	for (i = 0; i < cd_count[file]; i++) {
24816a28ef2SGary Jennejohn 		dev = console_devices[file][i];
24916a28ef2SGary Jennejohn 		if (dev->puts != NULL)
250709ea543SSimon Glass 			dev->puts(dev, s);
25116a28ef2SGary Jennejohn 	}
25216a28ef2SGary Jennejohn }
2535f032010SJean-Christophe PLAGNIOL-VILLARD 
console_doenv(int file,struct stdio_dev * dev)25452cb4d4fSJean-Christophe PLAGNIOL-VILLARD static inline void console_doenv(int file, struct stdio_dev *dev)
2555f032010SJean-Christophe PLAGNIOL-VILLARD {
2565f032010SJean-Christophe PLAGNIOL-VILLARD 	iomux_doenv(file, dev->name);
2575f032010SJean-Christophe PLAGNIOL-VILLARD }
2585f032010SJean-Christophe PLAGNIOL-VILLARD #else
console_getc(int file)2595f032010SJean-Christophe PLAGNIOL-VILLARD static inline int console_getc(int file)
2605f032010SJean-Christophe PLAGNIOL-VILLARD {
261709ea543SSimon Glass 	return stdio_devices[file]->getc(stdio_devices[file]);
2625f032010SJean-Christophe PLAGNIOL-VILLARD }
2635f032010SJean-Christophe PLAGNIOL-VILLARD 
console_tstc(int file)2645f032010SJean-Christophe PLAGNIOL-VILLARD static inline int console_tstc(int file)
2655f032010SJean-Christophe PLAGNIOL-VILLARD {
266709ea543SSimon Glass 	return stdio_devices[file]->tstc(stdio_devices[file]);
2675f032010SJean-Christophe PLAGNIOL-VILLARD }
2685f032010SJean-Christophe PLAGNIOL-VILLARD 
console_putc(int file,const char c)2695f032010SJean-Christophe PLAGNIOL-VILLARD static inline void console_putc(int file, const char c)
2705f032010SJean-Christophe PLAGNIOL-VILLARD {
271709ea543SSimon Glass 	stdio_devices[file]->putc(stdio_devices[file], c);
2725f032010SJean-Christophe PLAGNIOL-VILLARD }
2735f032010SJean-Christophe PLAGNIOL-VILLARD 
console_puts_noserial(int file,const char * s)274a8552c7cSHans de Goede static inline void console_puts_noserial(int file, const char *s)
27527669667SSiarhei Siamashka {
27642f9f915SSimon Glass 	if (!console_dev_is_serial(stdio_devices[file]))
277a8552c7cSHans de Goede 		stdio_devices[file]->puts(stdio_devices[file], s);
27827669667SSiarhei Siamashka }
27927669667SSiarhei Siamashka 
console_puts(int file,const char * s)2805f032010SJean-Christophe PLAGNIOL-VILLARD static inline void console_puts(int file, const char *s)
2815f032010SJean-Christophe PLAGNIOL-VILLARD {
282709ea543SSimon Glass 	stdio_devices[file]->puts(stdio_devices[file], s);
2835f032010SJean-Christophe PLAGNIOL-VILLARD }
2845f032010SJean-Christophe PLAGNIOL-VILLARD 
console_doenv(int file,struct stdio_dev * dev)28552cb4d4fSJean-Christophe PLAGNIOL-VILLARD static inline void console_doenv(int file, struct stdio_dev *dev)
2865f032010SJean-Christophe PLAGNIOL-VILLARD {
2875f032010SJean-Christophe PLAGNIOL-VILLARD 	console_setfile(file, dev);
2885f032010SJean-Christophe PLAGNIOL-VILLARD }
289b0265429SSimon Glass #endif /* CONIFIG_IS_ENABLED(CONSOLE_MUX) */
29016a28ef2SGary Jennejohn 
29147d1a6e1Swdenk /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
29247d1a6e1Swdenk 
serial_printf(const char * fmt,...)293d9c27253SWolfgang Denk int serial_printf(const char *fmt, ...)
29447d1a6e1Swdenk {
29547d1a6e1Swdenk 	va_list args;
29647d1a6e1Swdenk 	uint i;
2976d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	char printbuffer[CONFIG_SYS_PBSIZE];
29847d1a6e1Swdenk 
29947d1a6e1Swdenk 	va_start(args, fmt);
30047d1a6e1Swdenk 
30147d1a6e1Swdenk 	/* For this to work, printbuffer must be larger than
30247d1a6e1Swdenk 	 * anything we ever want to print.
30347d1a6e1Swdenk 	 */
304068af6f8SSonny Rao 	i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
30547d1a6e1Swdenk 	va_end(args);
30647d1a6e1Swdenk 
30747d1a6e1Swdenk 	serial_puts(printbuffer);
308d9c27253SWolfgang Denk 	return i;
30947d1a6e1Swdenk }
31047d1a6e1Swdenk 
fgetc(int file)31147d1a6e1Swdenk int fgetc(int file)
31247d1a6e1Swdenk {
31316a28ef2SGary Jennejohn 	if (file < MAX_FILES) {
31416a28ef2SGary Jennejohn 		/*
31516a28ef2SGary Jennejohn 		 * Effectively poll for input wherever it may be available.
31616a28ef2SGary Jennejohn 		 */
31716a28ef2SGary Jennejohn 		for (;;) {
31864407467SAndreas J. Reichel 			WATCHDOG_RESET();
319273a1252SPatrick Delaunay #if CONFIG_IS_ENABLED(CONSOLE_MUX)
32016a28ef2SGary Jennejohn 			/*
32116a28ef2SGary Jennejohn 			 * Upper layer may have already called tstc() so
32216a28ef2SGary Jennejohn 			 * check for that first.
32316a28ef2SGary Jennejohn 			 */
32416a28ef2SGary Jennejohn 			if (tstcdev != NULL)
3255f032010SJean-Christophe PLAGNIOL-VILLARD 				return console_getc(file);
3265f032010SJean-Christophe PLAGNIOL-VILLARD 			console_tstc(file);
327273a1252SPatrick Delaunay #else
328273a1252SPatrick Delaunay 			if (console_tstc(file))
329273a1252SPatrick Delaunay 				return console_getc(file);
330273a1252SPatrick Delaunay #endif
33116a28ef2SGary Jennejohn #ifdef CONFIG_WATCHDOG
33216a28ef2SGary Jennejohn 			/*
33316a28ef2SGary Jennejohn 			 * If the watchdog must be rate-limited then it should
33416a28ef2SGary Jennejohn 			 * already be handled in board-specific code.
33516a28ef2SGary Jennejohn 			 */
33616a28ef2SGary Jennejohn 			 udelay(1);
33716a28ef2SGary Jennejohn #endif
33816a28ef2SGary Jennejohn 		}
33916a28ef2SGary Jennejohn 	}
34047d1a6e1Swdenk 
34147d1a6e1Swdenk 	return -1;
34247d1a6e1Swdenk }
34347d1a6e1Swdenk 
ftstc(int file)34447d1a6e1Swdenk int ftstc(int file)
34547d1a6e1Swdenk {
34647d1a6e1Swdenk 	if (file < MAX_FILES)
3475f032010SJean-Christophe PLAGNIOL-VILLARD 		return console_tstc(file);
34847d1a6e1Swdenk 
34947d1a6e1Swdenk 	return -1;
35047d1a6e1Swdenk }
35147d1a6e1Swdenk 
fputc(int file,const char c)35247d1a6e1Swdenk void fputc(int file, const char c)
35347d1a6e1Swdenk {
35447d1a6e1Swdenk 	if (file < MAX_FILES)
3555f032010SJean-Christophe PLAGNIOL-VILLARD 		console_putc(file, c);
35647d1a6e1Swdenk }
35747d1a6e1Swdenk 
fputs(int file,const char * s)35847d1a6e1Swdenk void fputs(int file, const char *s)
35947d1a6e1Swdenk {
36047d1a6e1Swdenk 	if (file < MAX_FILES)
3615f032010SJean-Christophe PLAGNIOL-VILLARD 		console_puts(file, s);
36247d1a6e1Swdenk }
36347d1a6e1Swdenk 
fprintf(int file,const char * fmt,...)364d9c27253SWolfgang Denk int fprintf(int file, const char *fmt, ...)
36547d1a6e1Swdenk {
36647d1a6e1Swdenk 	va_list args;
36747d1a6e1Swdenk 	uint i;
3686d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	char printbuffer[CONFIG_SYS_PBSIZE];
36947d1a6e1Swdenk 
37047d1a6e1Swdenk 	va_start(args, fmt);
37147d1a6e1Swdenk 
37247d1a6e1Swdenk 	/* For this to work, printbuffer must be larger than
37347d1a6e1Swdenk 	 * anything we ever want to print.
37447d1a6e1Swdenk 	 */
375068af6f8SSonny Rao 	i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
37647d1a6e1Swdenk 	va_end(args);
37747d1a6e1Swdenk 
37847d1a6e1Swdenk 	/* Send to desired file */
37947d1a6e1Swdenk 	fputs(file, printbuffer);
380d9c27253SWolfgang Denk 	return i;
38147d1a6e1Swdenk }
38247d1a6e1Swdenk 
38347d1a6e1Swdenk /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
38447d1a6e1Swdenk 
getc(void)38547d1a6e1Swdenk int getc(void)
38647d1a6e1Swdenk {
387f5c3ba79SMark Jackson #ifdef CONFIG_DISABLE_CONSOLE
388f5c3ba79SMark Jackson 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
389f5c3ba79SMark Jackson 		return 0;
390f5c3ba79SMark Jackson #endif
391f5c3ba79SMark Jackson 
392e3e454cdSGraeme Russ 	if (!gd->have_console)
393e3e454cdSGraeme Russ 		return 0;
394e3e454cdSGraeme Russ 
3959854a874SSimon Glass #ifdef CONFIG_CONSOLE_RECORD
3969854a874SSimon Glass 	if (gd->console_in.start) {
3979854a874SSimon Glass 		int ch;
3989854a874SSimon Glass 
3999854a874SSimon Glass 		ch = membuff_getbyte(&gd->console_in);
4009854a874SSimon Glass 		if (ch != -1)
4019854a874SSimon Glass 			return 1;
4029854a874SSimon Glass 	}
4039854a874SSimon Glass #endif
40447d1a6e1Swdenk 	if (gd->flags & GD_FLG_DEVINIT) {
40547d1a6e1Swdenk 		/* Get from the standard input */
40647d1a6e1Swdenk 		return fgetc(stdin);
40747d1a6e1Swdenk 	}
40847d1a6e1Swdenk 
40947d1a6e1Swdenk 	/* Send directly to the handler */
41047d1a6e1Swdenk 	return serial_getc();
41147d1a6e1Swdenk }
41247d1a6e1Swdenk 
tstc(void)41347d1a6e1Swdenk int tstc(void)
41447d1a6e1Swdenk {
415f5c3ba79SMark Jackson #ifdef CONFIG_DISABLE_CONSOLE
416f5c3ba79SMark Jackson 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
417f5c3ba79SMark Jackson 		return 0;
418f5c3ba79SMark Jackson #endif
419f5c3ba79SMark Jackson 
420e3e454cdSGraeme Russ 	if (!gd->have_console)
421e3e454cdSGraeme Russ 		return 0;
4229854a874SSimon Glass #ifdef CONFIG_CONSOLE_RECORD
4239854a874SSimon Glass 	if (gd->console_in.start) {
4249854a874SSimon Glass 		if (membuff_peekbyte(&gd->console_in) != -1)
4259854a874SSimon Glass 			return 1;
4269854a874SSimon Glass 	}
4279854a874SSimon Glass #endif
42847d1a6e1Swdenk 	if (gd->flags & GD_FLG_DEVINIT) {
42947d1a6e1Swdenk 		/* Test the standard input */
43047d1a6e1Swdenk 		return ftstc(stdin);
43147d1a6e1Swdenk 	}
43247d1a6e1Swdenk 
43347d1a6e1Swdenk 	/* Send directly to the handler */
43447d1a6e1Swdenk 	return serial_tstc();
43547d1a6e1Swdenk }
43647d1a6e1Swdenk 
43727669667SSiarhei Siamashka #define PRE_CONSOLE_FLUSHPOINT1_SERIAL			0
43827669667SSiarhei Siamashka #define PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL	1
43927669667SSiarhei Siamashka 
4408f925584SSimon Glass #if CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
4419558b48aSGraeme Russ #define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ)
4429558b48aSGraeme Russ 
pre_console_putc(const char c)4439558b48aSGraeme Russ static void pre_console_putc(const char c)
4449558b48aSGraeme Russ {
4454e6bafa5SSimon Glass 	char *buffer;
4464e6bafa5SSimon Glass 
4474e6bafa5SSimon Glass 	buffer = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
4489558b48aSGraeme Russ 
4499558b48aSGraeme Russ 	buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
4504e6bafa5SSimon Glass 
4514e6bafa5SSimon Glass 	unmap_sysmem(buffer);
4529558b48aSGraeme Russ }
4539558b48aSGraeme Russ 
pre_console_puts(const char * s)454be135cc5SSoeren Moch static void pre_console_puts(const char *s)
455be135cc5SSoeren Moch {
456be135cc5SSoeren Moch 	while (*s)
457be135cc5SSoeren Moch 		pre_console_putc(*s++);
458be135cc5SSoeren Moch }
459be135cc5SSoeren Moch 
print_pre_console_buffer(int flushpoint)46027669667SSiarhei Siamashka static void print_pre_console_buffer(int flushpoint)
4619558b48aSGraeme Russ {
462a8552c7cSHans de Goede 	unsigned long in = 0, out = 0;
463a8552c7cSHans de Goede 	char buf_out[CONFIG_PRE_CON_BUF_SZ + 1];
4644e6bafa5SSimon Glass 	char *buf_in;
4659558b48aSGraeme Russ 
4664e6bafa5SSimon Glass 	buf_in = map_sysmem(CONFIG_PRE_CON_BUF_ADDR, CONFIG_PRE_CON_BUF_SZ);
4679558b48aSGraeme Russ 	if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
468a8552c7cSHans de Goede 		in = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ;
4699558b48aSGraeme Russ 
470a8552c7cSHans de Goede 	while (in < gd->precon_buf_idx)
471a8552c7cSHans de Goede 		buf_out[out++] = buf_in[CIRC_BUF_IDX(in++)];
4724e6bafa5SSimon Glass 	unmap_sysmem(buf_in);
473a8552c7cSHans de Goede 
474a8552c7cSHans de Goede 	buf_out[out] = 0;
475a8552c7cSHans de Goede 
47627669667SSiarhei Siamashka 	switch (flushpoint) {
47727669667SSiarhei Siamashka 	case PRE_CONSOLE_FLUSHPOINT1_SERIAL:
478a8552c7cSHans de Goede 		puts(buf_out);
47927669667SSiarhei Siamashka 		break;
48027669667SSiarhei Siamashka 	case PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL:
481a8552c7cSHans de Goede 		console_puts_noserial(stdout, buf_out);
48227669667SSiarhei Siamashka 		break;
48327669667SSiarhei Siamashka 	}
4849558b48aSGraeme Russ }
4859558b48aSGraeme Russ #else
pre_console_putc(const char c)4869558b48aSGraeme Russ static inline void pre_console_putc(const char c) {}
pre_console_puts(const char * s)487be135cc5SSoeren Moch static inline void pre_console_puts(const char *s) {}
print_pre_console_buffer(int flushpoint)48827669667SSiarhei Siamashka static inline void print_pre_console_buffer(int flushpoint) {}
4899558b48aSGraeme Russ #endif
4909558b48aSGraeme Russ 
putc(const char c)49147d1a6e1Swdenk void putc(const char c)
49247d1a6e1Swdenk {
49364e9b4f3SSimon Glass #ifdef CONFIG_SANDBOX
49464e9b4f3SSimon Glass 	/* sandbox can send characters to stdout before it has a console */
49564e9b4f3SSimon Glass 	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
49664e9b4f3SSimon Glass 		os_putc(c);
49764e9b4f3SSimon Glass 		return;
49864e9b4f3SSimon Glass 	}
49964e9b4f3SSimon Glass #endif
500d6ea5307SSimon Glass #ifdef CONFIG_DEBUG_UART
501d6ea5307SSimon Glass 	/* if we don't have a console yet, use the debug UART */
502d6ea5307SSimon Glass 	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
503d6ea5307SSimon Glass 		printch(c);
504d6ea5307SSimon Glass 		return;
505d6ea5307SSimon Glass 	}
506d6ea5307SSimon Glass #endif
507af880e24SSimon Glass 	if (!gd)
508af880e24SSimon Glass 		return;
5099854a874SSimon Glass #ifdef CONFIG_CONSOLE_RECORD
510af880e24SSimon Glass 	if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
5119854a874SSimon Glass 		membuff_putbyte(&gd->console_out, c);
5129854a874SSimon Glass #endif
513a6cccaeaSwdenk #ifdef CONFIG_SILENT_CONSOLE
514a6cccaeaSwdenk 	if (gd->flags & GD_FLG_SILENT)
515f6e20fc6Swdenk 		return;
516a6cccaeaSwdenk #endif
517a6cccaeaSwdenk 
518f5c3ba79SMark Jackson #ifdef CONFIG_DISABLE_CONSOLE
519f5c3ba79SMark Jackson 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
520f5c3ba79SMark Jackson 		return;
521f5c3ba79SMark Jackson #endif
522f5c3ba79SMark Jackson 
523e3e454cdSGraeme Russ 	if (!gd->have_console)
5249558b48aSGraeme Russ 		return pre_console_putc(c);
525e3e454cdSGraeme Russ 
52647d1a6e1Swdenk 	if (gd->flags & GD_FLG_DEVINIT) {
52747d1a6e1Swdenk 		/* Send to the standard output */
52847d1a6e1Swdenk 		fputc(stdout, c);
52947d1a6e1Swdenk 	} else {
53047d1a6e1Swdenk 		/* Send directly to the handler */
53127669667SSiarhei Siamashka 		pre_console_putc(c);
53247d1a6e1Swdenk 		serial_putc(c);
53347d1a6e1Swdenk 	}
53447d1a6e1Swdenk }
53547d1a6e1Swdenk 
puts(const char * s)53647d1a6e1Swdenk void puts(const char *s)
53747d1a6e1Swdenk {
538*36bcea62SSimon Glass #ifdef CONFIG_SANDBOX
539*36bcea62SSimon Glass 	/* sandbox can send characters to stdout before it has a console */
540*36bcea62SSimon Glass 	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
541*36bcea62SSimon Glass 		os_puts(s);
542*36bcea62SSimon Glass 		return;
543*36bcea62SSimon Glass 	}
544*36bcea62SSimon Glass #endif
545be135cc5SSoeren Moch #ifdef CONFIG_DEBUG_UART
546be135cc5SSoeren Moch 	if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) {
547be135cc5SSoeren Moch 		while (*s) {
548be135cc5SSoeren Moch 			int ch = *s++;
549be135cc5SSoeren Moch 
550be135cc5SSoeren Moch 			printch(ch);
551be135cc5SSoeren Moch 		}
552be135cc5SSoeren Moch 		return;
553be135cc5SSoeren Moch 	}
554be135cc5SSoeren Moch #endif
555af880e24SSimon Glass 	if (!gd)
556af880e24SSimon Glass 		return;
557be135cc5SSoeren Moch #ifdef CONFIG_CONSOLE_RECORD
558af880e24SSimon Glass 	if ((gd->flags & GD_FLG_RECORD) && gd->console_out.start)
559be135cc5SSoeren Moch 		membuff_put(&gd->console_out, s, strlen(s));
560be135cc5SSoeren Moch #endif
561be135cc5SSoeren Moch #ifdef CONFIG_SILENT_CONSOLE
562be135cc5SSoeren Moch 	if (gd->flags & GD_FLG_SILENT)
563be135cc5SSoeren Moch 		return;
564be135cc5SSoeren Moch #endif
565be135cc5SSoeren Moch 
566be135cc5SSoeren Moch #ifdef CONFIG_DISABLE_CONSOLE
567be135cc5SSoeren Moch 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
568be135cc5SSoeren Moch 		return;
569be135cc5SSoeren Moch #endif
570be135cc5SSoeren Moch 
571be135cc5SSoeren Moch 	if (!gd->have_console)
572be135cc5SSoeren Moch 		return pre_console_puts(s);
573be135cc5SSoeren Moch 
574be135cc5SSoeren Moch 	if (gd->flags & GD_FLG_DEVINIT) {
575be135cc5SSoeren Moch 		/* Send to the standard output */
576be135cc5SSoeren Moch 		fputs(stdout, s);
577be135cc5SSoeren Moch 	} else {
578be135cc5SSoeren Moch 		/* Send directly to the handler */
579be135cc5SSoeren Moch 		pre_console_puts(s);
580be135cc5SSoeren Moch 		serial_puts(s);
581be135cc5SSoeren Moch 	}
58247d1a6e1Swdenk }
58347d1a6e1Swdenk 
5849854a874SSimon Glass #ifdef CONFIG_CONSOLE_RECORD
console_record_init(void)5859854a874SSimon Glass int console_record_init(void)
5869854a874SSimon Glass {
5879854a874SSimon Glass 	int ret;
5889854a874SSimon Glass 
5899854a874SSimon Glass 	ret = membuff_new(&gd->console_out, CONFIG_CONSOLE_RECORD_OUT_SIZE);
5909854a874SSimon Glass 	if (ret)
5919854a874SSimon Glass 		return ret;
5929854a874SSimon Glass 	ret = membuff_new(&gd->console_in, CONFIG_CONSOLE_RECORD_IN_SIZE);
5939854a874SSimon Glass 
5949854a874SSimon Glass 	return ret;
5959854a874SSimon Glass }
5969854a874SSimon Glass 
console_record_reset(void)5979854a874SSimon Glass void console_record_reset(void)
5989854a874SSimon Glass {
5999854a874SSimon Glass 	membuff_purge(&gd->console_out);
6009854a874SSimon Glass 	membuff_purge(&gd->console_in);
6019854a874SSimon Glass }
6029854a874SSimon Glass 
console_record_reset_enable(void)6039854a874SSimon Glass void console_record_reset_enable(void)
6049854a874SSimon Glass {
6059854a874SSimon Glass 	console_record_reset();
6069854a874SSimon Glass 	gd->flags |= GD_FLG_RECORD;
6079854a874SSimon Glass }
6089854a874SSimon Glass #endif
6099854a874SSimon Glass 
61047d1a6e1Swdenk /* test if ctrl-c was pressed */
61147d1a6e1Swdenk static int ctrlc_disabled = 0;	/* see disable_ctrl() */
61247d1a6e1Swdenk static int ctrlc_was_pressed = 0;
ctrlc(void)61347d1a6e1Swdenk int ctrlc(void)
61447d1a6e1Swdenk {
61547d1a6e1Swdenk 	if (!ctrlc_disabled && gd->have_console) {
61647d1a6e1Swdenk 		if (tstc()) {
61747d1a6e1Swdenk 			switch (getc()) {
61847d1a6e1Swdenk 			case 0x03:		/* ^C - Control C */
61947d1a6e1Swdenk 				ctrlc_was_pressed = 1;
62047d1a6e1Swdenk 				return 1;
62147d1a6e1Swdenk 			default:
62247d1a6e1Swdenk 				break;
62347d1a6e1Swdenk 			}
62447d1a6e1Swdenk 		}
62547d1a6e1Swdenk 	}
6268969ea3eSSimon Glass 
62747d1a6e1Swdenk 	return 0;
62847d1a6e1Swdenk }
629a5dffa4bSPierre Aubert /* Reads user's confirmation.
630a5dffa4bSPierre Aubert    Returns 1 if user's input is "y", "Y", "yes" or "YES"
631a5dffa4bSPierre Aubert */
confirm_yesno(void)632a5dffa4bSPierre Aubert int confirm_yesno(void)
633a5dffa4bSPierre Aubert {
634a5dffa4bSPierre Aubert 	int i;
635a5dffa4bSPierre Aubert 	char str_input[5];
63647d1a6e1Swdenk 
637a5dffa4bSPierre Aubert 	/* Flush input */
638a5dffa4bSPierre Aubert 	while (tstc())
639a5dffa4bSPierre Aubert 		getc();
640a5dffa4bSPierre Aubert 	i = 0;
641a5dffa4bSPierre Aubert 	while (i < sizeof(str_input)) {
642a5dffa4bSPierre Aubert 		str_input[i] = getc();
643a5dffa4bSPierre Aubert 		putc(str_input[i]);
644a5dffa4bSPierre Aubert 		if (str_input[i] == '\r')
645a5dffa4bSPierre Aubert 			break;
646a5dffa4bSPierre Aubert 		i++;
647a5dffa4bSPierre Aubert 	}
648a5dffa4bSPierre Aubert 	putc('\n');
649a5dffa4bSPierre Aubert 	if (strncmp(str_input, "y\r", 2) == 0 ||
650a5dffa4bSPierre Aubert 	    strncmp(str_input, "Y\r", 2) == 0 ||
651a5dffa4bSPierre Aubert 	    strncmp(str_input, "yes\r", 4) == 0 ||
652a5dffa4bSPierre Aubert 	    strncmp(str_input, "YES\r", 4) == 0)
653a5dffa4bSPierre Aubert 		return 1;
654a5dffa4bSPierre Aubert 	return 0;
655a5dffa4bSPierre Aubert }
65647d1a6e1Swdenk /* pass 1 to disable ctrlc() checking, 0 to enable.
65747d1a6e1Swdenk  * returns previous state
65847d1a6e1Swdenk  */
disable_ctrlc(int disable)65947d1a6e1Swdenk int disable_ctrlc(int disable)
66047d1a6e1Swdenk {
66147d1a6e1Swdenk 	int prev = ctrlc_disabled;	/* save previous state */
66247d1a6e1Swdenk 
66347d1a6e1Swdenk 	ctrlc_disabled = disable;
66447d1a6e1Swdenk 	return prev;
66547d1a6e1Swdenk }
66647d1a6e1Swdenk 
had_ctrlc(void)66747d1a6e1Swdenk int had_ctrlc (void)
66847d1a6e1Swdenk {
66947d1a6e1Swdenk 	return ctrlc_was_pressed;
67047d1a6e1Swdenk }
67147d1a6e1Swdenk 
clear_ctrlc(void)67247d1a6e1Swdenk void clear_ctrlc(void)
67347d1a6e1Swdenk {
67447d1a6e1Swdenk 	ctrlc_was_pressed = 0;
67547d1a6e1Swdenk }
67647d1a6e1Swdenk 
67747d1a6e1Swdenk /** U-Boot INIT FUNCTIONS *************************************************/
67847d1a6e1Swdenk 
search_device(int flags,const char * name)679d7be3056SMike Frysinger struct stdio_dev *search_device(int flags, const char *name)
680c1de7a6dSJean-Christophe PLAGNIOL-VILLARD {
68152cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
682c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 
68352cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	dev = stdio_get_by_name(name);
684a2931b30SSimon Glass #ifdef CONFIG_VIDCONSOLE_AS_LCD
685a2931b30SSimon Glass 	if (!dev && !strcmp(name, "lcd"))
686a2931b30SSimon Glass 		dev = stdio_get_by_name("vidconsole");
687a2931b30SSimon Glass #endif
688c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 
689c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	if (dev && (dev->flags & flags))
690c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 		return dev;
691c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 
692c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	return NULL;
693c1de7a6dSJean-Christophe PLAGNIOL-VILLARD }
694c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 
console_assign(int file,const char * devname)695d7be3056SMike Frysinger int console_assign(int file, const char *devname)
69647d1a6e1Swdenk {
697c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	int flag;
69852cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
69947d1a6e1Swdenk 
70047d1a6e1Swdenk 	/* Check for valid file */
70147d1a6e1Swdenk 	switch (file) {
70247d1a6e1Swdenk 	case stdin:
70347d1a6e1Swdenk 		flag = DEV_FLAGS_INPUT;
70447d1a6e1Swdenk 		break;
70547d1a6e1Swdenk 	case stdout:
70647d1a6e1Swdenk 	case stderr:
70747d1a6e1Swdenk 		flag = DEV_FLAGS_OUTPUT;
70847d1a6e1Swdenk 		break;
70947d1a6e1Swdenk 	default:
71047d1a6e1Swdenk 		return -1;
71147d1a6e1Swdenk 	}
71247d1a6e1Swdenk 
71347d1a6e1Swdenk 	/* Check for valid device name */
71447d1a6e1Swdenk 
715c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	dev = search_device(flag, devname);
71647d1a6e1Swdenk 
717c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	if (dev)
71847d1a6e1Swdenk 		return console_setfile(file, dev);
71947d1a6e1Swdenk 
72047d1a6e1Swdenk 	return -1;
72147d1a6e1Swdenk }
72247d1a6e1Swdenk 
console_update_silent(void)72343e0a3deSChris Packham static void console_update_silent(void)
72443e0a3deSChris Packham {
72543e0a3deSChris Packham #ifdef CONFIG_SILENT_CONSOLE
72600caae6dSSimon Glass 	if (env_get("silent") != NULL)
72743e0a3deSChris Packham 		gd->flags |= GD_FLG_SILENT;
72843e0a3deSChris Packham 	else
72943e0a3deSChris Packham 		gd->flags &= ~GD_FLG_SILENT;
73043e0a3deSChris Packham #endif
73143e0a3deSChris Packham }
73243e0a3deSChris Packham 
console_announce_r(void)733b0895384SSimon Glass int console_announce_r(void)
734b0895384SSimon Glass {
735b0895384SSimon Glass #if !CONFIG_IS_ENABLED(PRE_CONSOLE_BUFFER)
736b0895384SSimon Glass 	char buf[DISPLAY_OPTIONS_BANNER_LENGTH];
737b0895384SSimon Glass 
738b0895384SSimon Glass 	display_options_get_banner(false, buf, sizeof(buf));
739b0895384SSimon Glass 
740b0895384SSimon Glass 	console_puts_noserial(stdout, buf);
741b0895384SSimon Glass #endif
742b0895384SSimon Glass 
743b0895384SSimon Glass 	return 0;
744b0895384SSimon Glass }
745b0895384SSimon Glass 
74647d1a6e1Swdenk /* Called before relocation - use serial functions */
console_init_f(void)74747d1a6e1Swdenk int console_init_f(void)
74847d1a6e1Swdenk {
74947d1a6e1Swdenk 	gd->have_console = 1;
750f72da340Swdenk 
75143e0a3deSChris Packham 	console_update_silent();
752f72da340Swdenk 
75327669667SSiarhei Siamashka 	print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
7549558b48aSGraeme Russ 
755ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	return 0;
75647d1a6e1Swdenk }
75747d1a6e1Swdenk 
stdio_print_current_devices(void)7587e3be7cfSJean-Christophe PLAGNIOL-VILLARD void stdio_print_current_devices(void)
7597e3be7cfSJean-Christophe PLAGNIOL-VILLARD {
7607e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	/* Print information */
7617e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	puts("In:    ");
7627e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	if (stdio_devices[stdin] == NULL) {
7637e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		puts("No input devices available!\n");
7647e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	} else {
7657e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s\n", stdio_devices[stdin]->name);
7667e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	}
7677e3be7cfSJean-Christophe PLAGNIOL-VILLARD 
7687e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	puts("Out:   ");
7697e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	if (stdio_devices[stdout] == NULL) {
7707e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		puts("No output devices available!\n");
7717e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	} else {
7727e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s\n", stdio_devices[stdout]->name);
7737e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	}
7747e3be7cfSJean-Christophe PLAGNIOL-VILLARD 
7757e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	puts("Err:   ");
7767e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	if (stdio_devices[stderr] == NULL) {
7777e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		puts("No error devices available!\n");
7787e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	} else {
7797e3be7cfSJean-Christophe PLAGNIOL-VILLARD 		printf ("%s\n", stdio_devices[stderr]->name);
7807e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	}
7817e3be7cfSJean-Christophe PLAGNIOL-VILLARD }
7827e3be7cfSJean-Christophe PLAGNIOL-VILLARD 
783b0265429SSimon Glass #if CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV)
78447d1a6e1Swdenk /* Called after the relocation - use desired console functions */
console_init_r(void)78547d1a6e1Swdenk int console_init_r(void)
78647d1a6e1Swdenk {
78747d1a6e1Swdenk 	char *stdinname, *stdoutname, *stderrname;
78852cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
7896d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
7906e592385Swdenk 	int i;
7916d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
792b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
79316a28ef2SGary Jennejohn 	int iomux_err = 0;
79416a28ef2SGary Jennejohn #endif
79547d1a6e1Swdenk 
79647d1a6e1Swdenk 	/* set default handlers at first */
79749cad547SMartin Dorwig 	gd->jt->getc  = serial_getc;
79849cad547SMartin Dorwig 	gd->jt->tstc  = serial_tstc;
79949cad547SMartin Dorwig 	gd->jt->putc  = serial_putc;
80049cad547SMartin Dorwig 	gd->jt->puts  = serial_puts;
80149cad547SMartin Dorwig 	gd->jt->printf = serial_printf;
80247d1a6e1Swdenk 
80347d1a6e1Swdenk 	/* stdin stdout and stderr are in environment */
80447d1a6e1Swdenk 	/* scan for it */
80500caae6dSSimon Glass 	stdinname  = env_get("stdin");
80600caae6dSSimon Glass 	stdoutname = env_get("stdout");
80700caae6dSSimon Glass 	stderrname = env_get("stderr");
80847d1a6e1Swdenk 
80983e40ba7Swdenk 	if (OVERWRITE_CONSOLE == 0) {	/* if not overwritten by config switch */
81047d1a6e1Swdenk 		inputdev  = search_device(DEV_FLAGS_INPUT,  stdinname);
81147d1a6e1Swdenk 		outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
81247d1a6e1Swdenk 		errdev    = search_device(DEV_FLAGS_OUTPUT, stderrname);
813b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
81416a28ef2SGary Jennejohn 		iomux_err = iomux_doenv(stdin, stdinname);
81516a28ef2SGary Jennejohn 		iomux_err += iomux_doenv(stdout, stdoutname);
81616a28ef2SGary Jennejohn 		iomux_err += iomux_doenv(stderr, stderrname);
81716a28ef2SGary Jennejohn 		if (!iomux_err)
81816a28ef2SGary Jennejohn 			/* Successful, so skip all the code below. */
81916a28ef2SGary Jennejohn 			goto done;
82016a28ef2SGary Jennejohn #endif
82147d1a6e1Swdenk 	}
82247d1a6e1Swdenk 	/* if the devices are overwritten or not found, use default device */
82347d1a6e1Swdenk 	if (inputdev == NULL) {
82447d1a6e1Swdenk 		inputdev  = search_device(DEV_FLAGS_INPUT,  "serial");
82547d1a6e1Swdenk 	}
82647d1a6e1Swdenk 	if (outputdev == NULL) {
82747d1a6e1Swdenk 		outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
82847d1a6e1Swdenk 	}
82947d1a6e1Swdenk 	if (errdev == NULL) {
83047d1a6e1Swdenk 		errdev    = search_device(DEV_FLAGS_OUTPUT, "serial");
83147d1a6e1Swdenk 	}
83247d1a6e1Swdenk 	/* Initializes output console first */
83347d1a6e1Swdenk 	if (outputdev != NULL) {
83416a28ef2SGary Jennejohn 		/* need to set a console if not done above. */
8355f032010SJean-Christophe PLAGNIOL-VILLARD 		console_doenv(stdout, outputdev);
83647d1a6e1Swdenk 	}
83747d1a6e1Swdenk 	if (errdev != NULL) {
83816a28ef2SGary Jennejohn 		/* need to set a console if not done above. */
8395f032010SJean-Christophe PLAGNIOL-VILLARD 		console_doenv(stderr, errdev);
84047d1a6e1Swdenk 	}
84147d1a6e1Swdenk 	if (inputdev != NULL) {
84216a28ef2SGary Jennejohn 		/* need to set a console if not done above. */
8435f032010SJean-Christophe PLAGNIOL-VILLARD 		console_doenv(stdin, inputdev);
84447d1a6e1Swdenk 	}
84547d1a6e1Swdenk 
846b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
84716a28ef2SGary Jennejohn done:
84816a28ef2SGary Jennejohn #endif
84916a28ef2SGary Jennejohn 
85078c112c9SSimon Glass #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
8517e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	stdio_print_current_devices();
85278c112c9SSimon Glass #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
853a2931b30SSimon Glass #ifdef CONFIG_VIDCONSOLE_AS_LCD
854a2931b30SSimon Glass 	if (strstr(stdoutname, "lcd"))
855a2931b30SSimon Glass 		printf("Warning: Please change 'lcd' to 'vidconsole' in stdout/stderr environment vars\n");
856a2931b30SSimon Glass #endif
85747d1a6e1Swdenk 
8586d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
85947d1a6e1Swdenk 	/* set the environment variables (will overwrite previous env settings) */
86027b4225bSTom Rini 	for (i = 0; i < MAX_FILES; i++) {
861382bee57SSimon Glass 		env_set(stdio_names[i], stdio_devices[i]->name);
86247d1a6e1Swdenk 	}
8636d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
86447d1a6e1Swdenk 
865c4e0057fSJoe Hershberger 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
866c4e0057fSJoe Hershberger 
86747d1a6e1Swdenk #if 0
86847d1a6e1Swdenk 	/* If nothing usable installed, use only the initial console */
86947d1a6e1Swdenk 	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
870ec6f1499SJean-Christophe PLAGNIOL-VILLARD 		return 0;
87147d1a6e1Swdenk #endif
87227669667SSiarhei Siamashka 	print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL);
873ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	return 0;
87447d1a6e1Swdenk }
87547d1a6e1Swdenk 
876b0265429SSimon Glass #else /* !CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
87747d1a6e1Swdenk 
87847d1a6e1Swdenk /* Called after the relocation - use desired console functions */
console_init_r(void)87947d1a6e1Swdenk int console_init_r(void)
88047d1a6e1Swdenk {
88152cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *inputdev = NULL, *outputdev = NULL;
882c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	int i;
88352cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct list_head *list = stdio_get_list();
884c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	struct list_head *pos;
88552cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
88647d1a6e1Swdenk 
88743e0a3deSChris Packham 	console_update_silent();
88843e0a3deSChris Packham 
889d791b1dcSwdenk #ifdef CONFIG_SPLASH_SCREEN
890ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	/*
891ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	 * suppress all output if splash screen is enabled and we have
892a7490816SAnatolij Gustschin 	 * a bmp to display. We redirect the output from frame buffer
893a7490816SAnatolij Gustschin 	 * console to serial console in this case or suppress it if
894a7490816SAnatolij Gustschin 	 * "silent" mode was requested.
895ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	 */
89600caae6dSSimon Glass 	if (env_get("splashimage") != NULL) {
897a7490816SAnatolij Gustschin 		if (!(gd->flags & GD_FLG_SILENT))
898a7490816SAnatolij Gustschin 			outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
899a7490816SAnatolij Gustschin 	}
900f72da340Swdenk #endif
901f72da340Swdenk 
90247d1a6e1Swdenk 	/* Scan devices looking for input and output devices */
903c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 	list_for_each(pos, list) {
90452cb4d4fSJean-Christophe PLAGNIOL-VILLARD 		dev = list_entry(pos, struct stdio_dev, list);
90547d1a6e1Swdenk 
90647d1a6e1Swdenk 		if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
90747d1a6e1Swdenk 			inputdev = dev;
90847d1a6e1Swdenk 		}
90947d1a6e1Swdenk 		if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
91047d1a6e1Swdenk 			outputdev = dev;
91147d1a6e1Swdenk 		}
912c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 		if(inputdev && outputdev)
913c1de7a6dSJean-Christophe PLAGNIOL-VILLARD 			break;
91447d1a6e1Swdenk 	}
91547d1a6e1Swdenk 
91647d1a6e1Swdenk 	/* Initializes output console first */
91747d1a6e1Swdenk 	if (outputdev != NULL) {
91847d1a6e1Swdenk 		console_setfile(stdout, outputdev);
91947d1a6e1Swdenk 		console_setfile(stderr, outputdev);
920b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
92116a28ef2SGary Jennejohn 		console_devices[stdout][0] = outputdev;
92216a28ef2SGary Jennejohn 		console_devices[stderr][0] = outputdev;
92316a28ef2SGary Jennejohn #endif
92447d1a6e1Swdenk 	}
92547d1a6e1Swdenk 
92647d1a6e1Swdenk 	/* Initializes input console */
92747d1a6e1Swdenk 	if (inputdev != NULL) {
92847d1a6e1Swdenk 		console_setfile(stdin, inputdev);
929b0265429SSimon Glass #if CONFIG_IS_ENABLED(CONSOLE_MUX)
93016a28ef2SGary Jennejohn 		console_devices[stdin][0] = inputdev;
93116a28ef2SGary Jennejohn #endif
93247d1a6e1Swdenk 	}
93347d1a6e1Swdenk 
93478c112c9SSimon Glass #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
9357e3be7cfSJean-Christophe PLAGNIOL-VILLARD 	stdio_print_current_devices();
93678c112c9SSimon Glass #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
93747d1a6e1Swdenk 
93847d1a6e1Swdenk 	/* Setting environment variables */
93927b4225bSTom Rini 	for (i = 0; i < MAX_FILES; i++) {
940382bee57SSimon Glass 		env_set(stdio_names[i], stdio_devices[i]->name);
94147d1a6e1Swdenk 	}
94247d1a6e1Swdenk 
943c4e0057fSJoe Hershberger 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
944c4e0057fSJoe Hershberger 
94547d1a6e1Swdenk #if 0
94647d1a6e1Swdenk 	/* If nothing usable installed, use only the initial console */
94747d1a6e1Swdenk 	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
948ec6f1499SJean-Christophe PLAGNIOL-VILLARD 		return 0;
94947d1a6e1Swdenk #endif
95027669667SSiarhei Siamashka 	print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT2_EVERYTHING_BUT_SERIAL);
951ec6f1499SJean-Christophe PLAGNIOL-VILLARD 	return 0;
95247d1a6e1Swdenk }
95347d1a6e1Swdenk 
954b0265429SSimon Glass #endif /* CONFIG_IS_ENABLED(SYS_CONSOLE_IS_IN_ENV) */
955