blob: cc55068c7cd823c138c4f90d1657a899621da0bf [file] [log] [blame]
wdenk47d1a6e2002-11-03 00:01:44 +00001/*
2 * (C) Copyright 2000
3 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk47d1a6e2002-11-03 00:01:44 +00006 */
7
8#include <common.h>
9#include <stdarg.h>
10#include <malloc.h>
Joe Hershberger849d5d92012-12-11 22:16:29 -060011#include <serial.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020012#include <stdio_dev.h>
wdenk27b207f2003-07-24 23:38:38 +000013#include <exports.h>
Joe Hershberger849d5d92012-12-11 22:16:29 -060014#include <environment.h>
wdenk47d1a6e2002-11-03 00:01:44 +000015
Wolfgang Denkd87080b2006-03-31 18:32:53 +020016DECLARE_GLOBAL_DATA_PTR;
17
Joe Hershberger849d5d92012-12-11 22:16:29 -060018static int on_console(const char *name, const char *value, enum env_op op,
19 int flags)
20{
21 int console = -1;
22
23 /* Check for console redirection */
24 if (strcmp(name, "stdin") == 0)
25 console = stdin;
26 else if (strcmp(name, "stdout") == 0)
27 console = stdout;
28 else if (strcmp(name, "stderr") == 0)
29 console = stderr;
30
31 /* if not actually setting a console variable, we don't care */
32 if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0)
33 return 0;
34
35 switch (op) {
36 case env_op_create:
37 case env_op_overwrite:
38
39#ifdef CONFIG_CONSOLE_MUX
40 if (iomux_doenv(console, value))
41 return 1;
42#else
43 /* Try assigning specified device */
44 if (console_assign(console, value) < 0)
45 return 1;
46#endif /* CONFIG_CONSOLE_MUX */
47 return 0;
48
49 case env_op_delete:
50 if ((flags & H_FORCE) == 0)
51 printf("Can't delete \"%s\"\n", name);
52 return 1;
53
54 default:
55 return 0;
56 }
57}
58U_BOOT_ENV_CALLBACK(console, on_console);
59
Joe Hershbergere080d542012-12-11 22:16:30 -060060#ifdef CONFIG_SILENT_CONSOLE
61static int on_silent(const char *name, const char *value, enum env_op op,
62 int flags)
63{
64#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_SET
65 if (flags & H_INTERACTIVE)
66 return 0;
67#endif
68#ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC
69 if ((flags & H_INTERACTIVE) == 0)
70 return 0;
71#endif
72
73 if (value != NULL)
74 gd->flags |= GD_FLG_SILENT;
75 else
76 gd->flags &= ~GD_FLG_SILENT;
77
78 return 0;
79}
80U_BOOT_ENV_CALLBACK(silent, on_silent);
81#endif
82
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020083#ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
wdenk47d1a6e2002-11-03 00:01:44 +000084/*
85 * if overwrite_console returns 1, the stdin, stderr and stdout
86 * are switched to the serial port, else the settings in the
87 * environment are used
88 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020089#ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +010090extern int overwrite_console(void);
91#define OVERWRITE_CONSOLE overwrite_console()
wdenk47d1a6e2002-11-03 00:01:44 +000092#else
wdenk83e40ba2005-03-31 18:42:15 +000093#define OVERWRITE_CONSOLE 0
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020094#endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
wdenk47d1a6e2002-11-03 00:01:44 +000095
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020096#endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
wdenk47d1a6e2002-11-03 00:01:44 +000097
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020098static int console_setfile(int file, struct stdio_dev * dev)
wdenk47d1a6e2002-11-03 00:01:44 +000099{
100 int error = 0;
101
102 if (dev == NULL)
103 return -1;
104
105 switch (file) {
106 case stdin:
107 case stdout:
108 case stderr:
109 /* Start new device */
110 if (dev->start) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100111 error = dev->start();
wdenk47d1a6e2002-11-03 00:01:44 +0000112 /* If it's not started dont use it */
113 if (error < 0)
114 break;
115 }
116
117 /* Assign the new device (leaving the existing one started) */
118 stdio_devices[file] = dev;
119
120 /*
121 * Update monitor functions
122 * (to use the console stuff by other applications)
123 */
124 switch (file) {
125 case stdin:
wdenk27b207f2003-07-24 23:38:38 +0000126 gd->jt[XF_getc] = dev->getc;
127 gd->jt[XF_tstc] = dev->tstc;
wdenk47d1a6e2002-11-03 00:01:44 +0000128 break;
129 case stdout:
wdenk27b207f2003-07-24 23:38:38 +0000130 gd->jt[XF_putc] = dev->putc;
131 gd->jt[XF_puts] = dev->puts;
132 gd->jt[XF_printf] = printf;
wdenk47d1a6e2002-11-03 00:01:44 +0000133 break;
134 }
135 break;
136
137 default: /* Invalid file ID */
138 error = -1;
139 }
140 return error;
141}
142
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100143#if defined(CONFIG_CONSOLE_MUX)
144/** Console I/O multiplexing *******************************************/
145
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200146static struct stdio_dev *tstcdev;
147struct stdio_dev **console_devices[MAX_FILES];
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100148int cd_count[MAX_FILES];
149
150/*
151 * This depends on tstc() always being called before getc().
152 * This is guaranteed to be true because this routine is called
153 * only from fgetc() which assures it.
154 * No attempt is made to demultiplex multiple input sources.
155 */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100156static int console_getc(int file)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100157{
158 unsigned char ret;
159
160 /* This is never called with testcdev == NULL */
161 ret = tstcdev->getc();
162 tstcdev = NULL;
163 return ret;
164}
165
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100166static int console_tstc(int file)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100167{
168 int i, ret;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200169 struct stdio_dev *dev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100170
171 disable_ctrlc(1);
172 for (i = 0; i < cd_count[file]; i++) {
173 dev = console_devices[file][i];
174 if (dev->tstc != NULL) {
175 ret = dev->tstc();
176 if (ret > 0) {
177 tstcdev = dev;
178 disable_ctrlc(0);
179 return ret;
180 }
181 }
182 }
183 disable_ctrlc(0);
184
185 return 0;
186}
187
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100188static void console_putc(int file, const char c)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100189{
190 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200191 struct stdio_dev *dev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100192
193 for (i = 0; i < cd_count[file]; i++) {
194 dev = console_devices[file][i];
195 if (dev->putc != NULL)
196 dev->putc(c);
197 }
198}
199
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100200static void console_puts(int file, const char *s)
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100201{
202 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200203 struct stdio_dev *dev;
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100204
205 for (i = 0; i < cd_count[file]; i++) {
206 dev = console_devices[file][i];
207 if (dev->puts != NULL)
208 dev->puts(s);
209 }
210}
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100211
212static inline void console_printdevs(int file)
213{
214 iomux_printdevs(file);
215}
216
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200217static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100218{
219 iomux_doenv(file, dev->name);
220}
221#else
222static inline int console_getc(int file)
223{
224 return stdio_devices[file]->getc();
225}
226
227static inline int console_tstc(int file)
228{
229 return stdio_devices[file]->tstc();
230}
231
232static inline void console_putc(int file, const char c)
233{
234 stdio_devices[file]->putc(c);
235}
236
237static inline void console_puts(int file, const char *s)
238{
239 stdio_devices[file]->puts(s);
240}
241
242static inline void console_printdevs(int file)
243{
244 printf("%s\n", stdio_devices[file]->name);
245}
246
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200247static inline void console_doenv(int file, struct stdio_dev *dev)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100248{
249 console_setfile(file, dev);
250}
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100251#endif /* defined(CONFIG_CONSOLE_MUX) */
252
wdenk47d1a6e2002-11-03 00:01:44 +0000253/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
254
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200255int serial_printf(const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000256{
257 va_list args;
258 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200259 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000260
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100261 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000262
263 /* For this to work, printbuffer must be larger than
264 * anything we ever want to print.
265 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000266 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100267 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000268
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100269 serial_puts(printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200270 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000271}
272
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100273int fgetc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000274{
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100275 if (file < MAX_FILES) {
276#if defined(CONFIG_CONSOLE_MUX)
277 /*
278 * Effectively poll for input wherever it may be available.
279 */
280 for (;;) {
281 /*
282 * Upper layer may have already called tstc() so
283 * check for that first.
284 */
285 if (tstcdev != NULL)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100286 return console_getc(file);
287 console_tstc(file);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100288#ifdef CONFIG_WATCHDOG
289 /*
290 * If the watchdog must be rate-limited then it should
291 * already be handled in board-specific code.
292 */
293 udelay(1);
294#endif
295 }
296#else
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100297 return console_getc(file);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100298#endif
299 }
wdenk47d1a6e2002-11-03 00:01:44 +0000300
301 return -1;
302}
303
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100304int ftstc(int file)
wdenk47d1a6e2002-11-03 00:01:44 +0000305{
306 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100307 return console_tstc(file);
wdenk47d1a6e2002-11-03 00:01:44 +0000308
309 return -1;
310}
311
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100312void fputc(int file, const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000313{
314 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100315 console_putc(file, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000316}
317
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100318void fputs(int file, const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000319{
320 if (file < MAX_FILES)
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100321 console_puts(file, s);
wdenk47d1a6e2002-11-03 00:01:44 +0000322}
323
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200324int fprintf(int file, const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000325{
326 va_list args;
327 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200328 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000329
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100330 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000331
332 /* For this to work, printbuffer must be larger than
333 * anything we ever want to print.
334 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000335 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100336 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000337
338 /* Send to desired file */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100339 fputs(file, printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200340 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000341}
342
343/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
344
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100345int getc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000346{
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100347#ifdef CONFIG_DISABLE_CONSOLE
348 if (gd->flags & GD_FLG_DISABLE_CONSOLE)
349 return 0;
350#endif
351
Graeme Russe3e454c2011-08-29 02:14:05 +0000352 if (!gd->have_console)
353 return 0;
354
wdenk47d1a6e2002-11-03 00:01:44 +0000355 if (gd->flags & GD_FLG_DEVINIT) {
356 /* Get from the standard input */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100357 return fgetc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000358 }
359
360 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100361 return serial_getc();
wdenk47d1a6e2002-11-03 00:01:44 +0000362}
363
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100364int tstc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000365{
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100366#ifdef CONFIG_DISABLE_CONSOLE
367 if (gd->flags & GD_FLG_DISABLE_CONSOLE)
368 return 0;
369#endif
370
Graeme Russe3e454c2011-08-29 02:14:05 +0000371 if (!gd->have_console)
372 return 0;
373
wdenk47d1a6e2002-11-03 00:01:44 +0000374 if (gd->flags & GD_FLG_DEVINIT) {
375 /* Test the standard input */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100376 return ftstc(stdin);
wdenk47d1a6e2002-11-03 00:01:44 +0000377 }
378
379 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100380 return serial_tstc();
wdenk47d1a6e2002-11-03 00:01:44 +0000381}
382
Simon Glass3fa49772012-03-19 21:59:14 -0700383#ifdef CONFIG_PRE_CONSOLE_BUFFER
Graeme Russ9558b482011-09-01 00:48:27 +0000384#define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ)
385
386static void pre_console_putc(const char c)
387{
388 char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR;
389
390 buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c;
391}
392
393static void pre_console_puts(const char *s)
394{
395 while (*s)
396 pre_console_putc(*s++);
397}
398
399static void print_pre_console_buffer(void)
400{
401 unsigned long i = 0;
402 char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR;
403
404 if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ)
405 i = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ;
406
407 while (i < gd->precon_buf_idx)
408 putc(buffer[CIRC_BUF_IDX(i++)]);
409}
410#else
411static inline void pre_console_putc(const char c) {}
412static inline void pre_console_puts(const char *s) {}
413static inline void print_pre_console_buffer(void) {}
414#endif
415
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100416void putc(const char c)
wdenk47d1a6e2002-11-03 00:01:44 +0000417{
wdenka6cccae2004-02-06 21:48:22 +0000418#ifdef CONFIG_SILENT_CONSOLE
419 if (gd->flags & GD_FLG_SILENT)
wdenkf6e20fc2004-02-08 19:38:38 +0000420 return;
wdenka6cccae2004-02-06 21:48:22 +0000421#endif
422
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100423#ifdef CONFIG_DISABLE_CONSOLE
424 if (gd->flags & GD_FLG_DISABLE_CONSOLE)
425 return;
426#endif
427
Graeme Russe3e454c2011-08-29 02:14:05 +0000428 if (!gd->have_console)
Graeme Russ9558b482011-09-01 00:48:27 +0000429 return pre_console_putc(c);
Graeme Russe3e454c2011-08-29 02:14:05 +0000430
wdenk47d1a6e2002-11-03 00:01:44 +0000431 if (gd->flags & GD_FLG_DEVINIT) {
432 /* Send to the standard output */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100433 fputc(stdout, c);
wdenk47d1a6e2002-11-03 00:01:44 +0000434 } else {
435 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100436 serial_putc(c);
wdenk47d1a6e2002-11-03 00:01:44 +0000437 }
438}
439
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100440void puts(const char *s)
wdenk47d1a6e2002-11-03 00:01:44 +0000441{
wdenka6cccae2004-02-06 21:48:22 +0000442#ifdef CONFIG_SILENT_CONSOLE
443 if (gd->flags & GD_FLG_SILENT)
444 return;
445#endif
446
Mark Jacksonf5c3ba72008-08-25 19:21:30 +0100447#ifdef CONFIG_DISABLE_CONSOLE
448 if (gd->flags & GD_FLG_DISABLE_CONSOLE)
449 return;
450#endif
451
Graeme Russe3e454c2011-08-29 02:14:05 +0000452 if (!gd->have_console)
Graeme Russ9558b482011-09-01 00:48:27 +0000453 return pre_console_puts(s);
Graeme Russe3e454c2011-08-29 02:14:05 +0000454
wdenk47d1a6e2002-11-03 00:01:44 +0000455 if (gd->flags & GD_FLG_DEVINIT) {
456 /* Send to the standard output */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100457 fputs(stdout, s);
wdenk47d1a6e2002-11-03 00:01:44 +0000458 } else {
459 /* Send directly to the handler */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100460 serial_puts(s);
wdenk47d1a6e2002-11-03 00:01:44 +0000461 }
462}
463
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200464int printf(const char *fmt, ...)
wdenk47d1a6e2002-11-03 00:01:44 +0000465{
466 va_list args;
467 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200468 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000469
Graeme Russ9558b482011-09-01 00:48:27 +0000470#ifndef CONFIG_PRE_CONSOLE_BUFFER
Graeme Russe3e454c2011-08-29 02:14:05 +0000471 if (!gd->have_console)
472 return 0;
Graeme Russ9558b482011-09-01 00:48:27 +0000473#endif
Graeme Russe3e454c2011-08-29 02:14:05 +0000474
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100475 va_start(args, fmt);
wdenk47d1a6e2002-11-03 00:01:44 +0000476
477 /* For this to work, printbuffer must be larger than
478 * anything we ever want to print.
479 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000480 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100481 va_end(args);
wdenk47d1a6e2002-11-03 00:01:44 +0000482
483 /* Print the string */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100484 puts(printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200485 return i;
wdenk47d1a6e2002-11-03 00:01:44 +0000486}
487
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200488int vprintf(const char *fmt, va_list args)
wdenk6dd652f2003-06-19 23:40:20 +0000489{
490 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200491 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk6dd652f2003-06-19 23:40:20 +0000492
Graeme Russ9558b482011-09-01 00:48:27 +0000493#ifndef CONFIG_PRE_CONSOLE_BUFFER
Graeme Russe3e454c2011-08-29 02:14:05 +0000494 if (!gd->have_console)
495 return 0;
Graeme Russ9558b482011-09-01 00:48:27 +0000496#endif
Graeme Russe3e454c2011-08-29 02:14:05 +0000497
wdenk6dd652f2003-06-19 23:40:20 +0000498 /* For this to work, printbuffer must be larger than
499 * anything we ever want to print.
500 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000501 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args);
wdenk6dd652f2003-06-19 23:40:20 +0000502
503 /* Print the string */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100504 puts(printbuffer);
Wolfgang Denkd9c27252010-06-20 17:14:14 +0200505 return i;
wdenk6dd652f2003-06-19 23:40:20 +0000506}
507
wdenk47d1a6e2002-11-03 00:01:44 +0000508/* test if ctrl-c was pressed */
509static int ctrlc_disabled = 0; /* see disable_ctrl() */
510static int ctrlc_was_pressed = 0;
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100511int ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000512{
wdenk47d1a6e2002-11-03 00:01:44 +0000513 if (!ctrlc_disabled && gd->have_console) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100514 if (tstc()) {
515 switch (getc()) {
wdenk47d1a6e2002-11-03 00:01:44 +0000516 case 0x03: /* ^C - Control C */
517 ctrlc_was_pressed = 1;
518 return 1;
519 default:
520 break;
521 }
522 }
523 }
524 return 0;
525}
526
527/* pass 1 to disable ctrlc() checking, 0 to enable.
528 * returns previous state
529 */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100530int disable_ctrlc(int disable)
wdenk47d1a6e2002-11-03 00:01:44 +0000531{
532 int prev = ctrlc_disabled; /* save previous state */
533
534 ctrlc_disabled = disable;
535 return prev;
536}
537
538int had_ctrlc (void)
539{
540 return ctrlc_was_pressed;
541}
542
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100543void clear_ctrlc(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000544{
545 ctrlc_was_pressed = 0;
546}
547
548#ifdef CONFIG_MODEM_SUPPORT_DEBUG
549char screen[1024];
550char *cursor = screen;
551int once = 0;
552inline void dbg(const char *fmt, ...)
553{
554 va_list args;
555 uint i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200556 char printbuffer[CONFIG_SYS_PBSIZE];
wdenk47d1a6e2002-11-03 00:01:44 +0000557
558 if (!once) {
559 memset(screen, 0, sizeof(screen));
560 once++;
561 }
562
563 va_start(args, fmt);
564
565 /* For this to work, printbuffer must be larger than
566 * anything we ever want to print.
567 */
Sonny Rao068af6f2011-10-10 09:22:31 +0000568 i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
wdenk47d1a6e2002-11-03 00:01:44 +0000569 va_end(args);
570
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100571 if ((screen + sizeof(screen) - 1 - cursor)
572 < strlen(printbuffer) + 1) {
wdenk47d1a6e2002-11-03 00:01:44 +0000573 memset(screen, 0, sizeof(screen));
574 cursor = screen;
575 }
576 sprintf(cursor, printbuffer);
577 cursor += strlen(printbuffer);
578
579}
580#else
581inline void dbg(const char *fmt, ...)
582{
583}
584#endif
585
586/** U-Boot INIT FUNCTIONS *************************************************/
587
Mike Frysingerd7be3052010-10-20 07:18:03 -0400588struct stdio_dev *search_device(int flags, const char *name)
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200589{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200590 struct stdio_dev *dev;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200591
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200592 dev = stdio_get_by_name(name);
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200593
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100594 if (dev && (dev->flags & flags))
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200595 return dev;
596
597 return NULL;
598}
599
Mike Frysingerd7be3052010-10-20 07:18:03 -0400600int console_assign(int file, const char *devname)
wdenk47d1a6e2002-11-03 00:01:44 +0000601{
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200602 int flag;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200603 struct stdio_dev *dev;
wdenk47d1a6e2002-11-03 00:01:44 +0000604
605 /* Check for valid file */
606 switch (file) {
607 case stdin:
608 flag = DEV_FLAGS_INPUT;
609 break;
610 case stdout:
611 case stderr:
612 flag = DEV_FLAGS_OUTPUT;
613 break;
614 default:
615 return -1;
616 }
617
618 /* Check for valid device name */
619
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200620 dev = search_device(flag, devname);
wdenk47d1a6e2002-11-03 00:01:44 +0000621
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100622 if (dev)
623 return console_setfile(file, dev);
wdenk47d1a6e2002-11-03 00:01:44 +0000624
625 return -1;
626}
627
628/* Called before relocation - use serial functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100629int console_init_f(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000630{
wdenk47d1a6e2002-11-03 00:01:44 +0000631 gd->have_console = 1;
wdenkf72da342003-10-10 10:05:42 +0000632
633#ifdef CONFIG_SILENT_CONSOLE
634 if (getenv("silent") != NULL)
635 gd->flags |= GD_FLG_SILENT;
636#endif
637
Graeme Russ9558b482011-09-01 00:48:27 +0000638 print_pre_console_buffer();
639
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100640 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000641}
642
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200643void stdio_print_current_devices(void)
644{
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200645 /* Print information */
646 puts("In: ");
647 if (stdio_devices[stdin] == NULL) {
648 puts("No input devices available!\n");
649 } else {
650 printf ("%s\n", stdio_devices[stdin]->name);
651 }
652
653 puts("Out: ");
654 if (stdio_devices[stdout] == NULL) {
655 puts("No output devices available!\n");
656 } else {
657 printf ("%s\n", stdio_devices[stdout]->name);
658 }
659
660 puts("Err: ");
661 if (stdio_devices[stderr] == NULL) {
662 puts("No error devices available!\n");
663 } else {
664 printf ("%s\n", stdio_devices[stderr]->name);
665 }
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200666}
667
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200668#ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
wdenk47d1a6e2002-11-03 00:01:44 +0000669/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100670int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000671{
672 char *stdinname, *stdoutname, *stderrname;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200673 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200674#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
wdenk6e592382004-04-18 17:39:38 +0000675 int i;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200676#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100677#ifdef CONFIG_CONSOLE_MUX
678 int iomux_err = 0;
679#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000680
681 /* set default handlers at first */
wdenk27b207f2003-07-24 23:38:38 +0000682 gd->jt[XF_getc] = serial_getc;
683 gd->jt[XF_tstc] = serial_tstc;
684 gd->jt[XF_putc] = serial_putc;
685 gd->jt[XF_puts] = serial_puts;
686 gd->jt[XF_printf] = serial_printf;
wdenk47d1a6e2002-11-03 00:01:44 +0000687
688 /* stdin stdout and stderr are in environment */
689 /* scan for it */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100690 stdinname = getenv("stdin");
691 stdoutname = getenv("stdout");
692 stderrname = getenv("stderr");
wdenk47d1a6e2002-11-03 00:01:44 +0000693
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200694 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100695 inputdev = search_device(DEV_FLAGS_INPUT, stdinname);
696 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname);
697 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100698#ifdef CONFIG_CONSOLE_MUX
699 iomux_err = iomux_doenv(stdin, stdinname);
700 iomux_err += iomux_doenv(stdout, stdoutname);
701 iomux_err += iomux_doenv(stderr, stderrname);
702 if (!iomux_err)
703 /* Successful, so skip all the code below. */
704 goto done;
705#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000706 }
707 /* if the devices are overwritten or not found, use default device */
708 if (inputdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100709 inputdev = search_device(DEV_FLAGS_INPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000710 }
711 if (outputdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100712 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000713 }
714 if (errdev == NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100715 errdev = search_device(DEV_FLAGS_OUTPUT, "serial");
wdenk47d1a6e2002-11-03 00:01:44 +0000716 }
717 /* Initializes output console first */
718 if (outputdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100719 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100720 console_doenv(stdout, outputdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000721 }
722 if (errdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100723 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100724 console_doenv(stderr, errdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000725 }
726 if (inputdev != NULL) {
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100727 /* need to set a console if not done above. */
Jean-Christophe PLAGNIOL-VILLARD5f032012009-02-01 17:07:52 +0100728 console_doenv(stdin, inputdev);
wdenk47d1a6e2002-11-03 00:01:44 +0000729 }
730
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100731#ifdef CONFIG_CONSOLE_MUX
732done:
733#endif
734
Simon Glass78c112c2012-12-05 14:46:43 +0000735#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200736 stdio_print_current_devices();
Simon Glass78c112c2012-12-05 14:46:43 +0000737#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
wdenk47d1a6e2002-11-03 00:01:44 +0000738
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200739#ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
wdenk47d1a6e2002-11-03 00:01:44 +0000740 /* set the environment variables (will overwrite previous env settings) */
741 for (i = 0; i < 3; i++) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100742 setenv(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +0000743 }
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200744#endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
wdenk47d1a6e2002-11-03 00:01:44 +0000745
Joe Hershbergerc4e00572012-12-11 22:16:19 -0600746 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
747
wdenk47d1a6e2002-11-03 00:01:44 +0000748#if 0
749 /* If nothing usable installed, use only the initial console */
750 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100751 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000752#endif
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100753 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000754}
755
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200756#else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
wdenk47d1a6e2002-11-03 00:01:44 +0000757
758/* Called after the relocation - use desired console functions */
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100759int console_init_r(void)
wdenk47d1a6e2002-11-03 00:01:44 +0000760{
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200761 struct stdio_dev *inputdev = NULL, *outputdev = NULL;
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200762 int i;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200763 struct list_head *list = stdio_get_list();
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200764 struct list_head *pos;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200765 struct stdio_dev *dev;
wdenk47d1a6e2002-11-03 00:01:44 +0000766
wdenkd791b1d2003-04-20 14:04:18 +0000767#ifdef CONFIG_SPLASH_SCREEN
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100768 /*
769 * suppress all output if splash screen is enabled and we have
Anatolij Gustschina7490812010-03-16 15:29:33 +0100770 * a bmp to display. We redirect the output from frame buffer
771 * console to serial console in this case or suppress it if
772 * "silent" mode was requested.
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100773 */
Anatolij Gustschina7490812010-03-16 15:29:33 +0100774 if (getenv("splashimage") != NULL) {
775 if (!(gd->flags & GD_FLG_SILENT))
776 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
777 }
wdenkf72da342003-10-10 10:05:42 +0000778#endif
779
wdenk47d1a6e2002-11-03 00:01:44 +0000780 /* Scan devices looking for input and output devices */
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200781 list_for_each(pos, list) {
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200782 dev = list_entry(pos, struct stdio_dev, list);
wdenk47d1a6e2002-11-03 00:01:44 +0000783
784 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
785 inputdev = dev;
786 }
787 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
788 outputdev = dev;
789 }
Jean-Christophe PLAGNIOL-VILLARDc1de7a62008-08-31 04:24:55 +0200790 if(inputdev && outputdev)
791 break;
wdenk47d1a6e2002-11-03 00:01:44 +0000792 }
793
794 /* Initializes output console first */
795 if (outputdev != NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100796 console_setfile(stdout, outputdev);
797 console_setfile(stderr, outputdev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100798#ifdef CONFIG_CONSOLE_MUX
799 console_devices[stdout][0] = outputdev;
800 console_devices[stderr][0] = outputdev;
801#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000802 }
803
804 /* Initializes input console */
805 if (inputdev != NULL) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100806 console_setfile(stdin, inputdev);
Gary Jennejohn16a28ef2008-11-06 15:04:23 +0100807#ifdef CONFIG_CONSOLE_MUX
808 console_devices[stdin][0] = inputdev;
809#endif
wdenk47d1a6e2002-11-03 00:01:44 +0000810 }
811
Simon Glass78c112c2012-12-05 14:46:43 +0000812#ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
Jean-Christophe PLAGNIOL-VILLARD7e3be7c2009-05-16 12:14:55 +0200813 stdio_print_current_devices();
Simon Glass78c112c2012-12-05 14:46:43 +0000814#endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
wdenk47d1a6e2002-11-03 00:01:44 +0000815
816 /* Setting environment variables */
817 for (i = 0; i < 3; i++) {
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100818 setenv(stdio_names[i], stdio_devices[i]->name);
wdenk47d1a6e2002-11-03 00:01:44 +0000819 }
820
Joe Hershbergerc4e00572012-12-11 22:16:19 -0600821 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
822
wdenk47d1a6e2002-11-03 00:01:44 +0000823#if 0
824 /* If nothing usable installed, use only the initial console */
825 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100826 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000827#endif
828
Jean-Christophe PLAGNIOL-VILLARDec6f1492009-02-01 17:07:51 +0100829 return 0;
wdenk47d1a6e2002-11-03 00:01:44 +0000830}
831
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200832#endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */