xref: /openbmc/u-boot/common/console.c (revision e4430779)
1 /*
2  * (C) Copyright 2000
3  * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 #include <stdarg.h>
26 #include <malloc.h>
27 #include <console.h>
28 #include <exports.h>
29 
30 DECLARE_GLOBAL_DATA_PTR;
31 
32 #ifdef CONFIG_AMIGAONEG3SE
33 int console_changed = 0;
34 #endif
35 
36 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
37 /*
38  * if overwrite_console returns 1, the stdin, stderr and stdout
39  * are switched to the serial port, else the settings in the
40  * environment are used
41  */
42 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
43 extern int overwrite_console (void);
44 #define OVERWRITE_CONSOLE overwrite_console ()
45 #else
46 #define OVERWRITE_CONSOLE 0
47 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */
48 
49 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
50 
51 static int console_setfile (int file, device_t * dev)
52 {
53 	int error = 0;
54 
55 	if (dev == NULL)
56 		return -1;
57 
58 	switch (file) {
59 	case stdin:
60 	case stdout:
61 	case stderr:
62 		/* Start new device */
63 		if (dev->start) {
64 			error = dev->start ();
65 			/* If it's not started dont use it */
66 			if (error < 0)
67 				break;
68 		}
69 
70 		/* Assign the new device (leaving the existing one started) */
71 		stdio_devices[file] = dev;
72 
73 		/*
74 		 * Update monitor functions
75 		 * (to use the console stuff by other applications)
76 		 */
77 		switch (file) {
78 		case stdin:
79 			gd->jt[XF_getc] = dev->getc;
80 			gd->jt[XF_tstc] = dev->tstc;
81 			break;
82 		case stdout:
83 			gd->jt[XF_putc] = dev->putc;
84 			gd->jt[XF_puts] = dev->puts;
85 			gd->jt[XF_printf] = printf;
86 			break;
87 		}
88 		break;
89 
90 	default:		/* Invalid file ID */
91 		error = -1;
92 	}
93 	return error;
94 }
95 
96 #if defined(CONFIG_CONSOLE_MUX)
97 /** Console I/O multiplexing *******************************************/
98 
99 static device_t *tstcdev;
100 device_t **console_devices[MAX_FILES];
101 int cd_count[MAX_FILES];
102 
103 /*
104  * This depends on tstc() always being called before getc().
105  * This is guaranteed to be true because this routine is called
106  * only from fgetc() which assures it.
107  * No attempt is made to demultiplex multiple input sources.
108  */
109 static int iomux_getc(void)
110 {
111 	unsigned char ret;
112 
113 	/* This is never called with testcdev == NULL */
114 	ret = tstcdev->getc();
115 	tstcdev = NULL;
116 	return ret;
117 }
118 
119 static int iomux_tstc(int file)
120 {
121 	int i, ret;
122 	device_t *dev;
123 
124 	disable_ctrlc(1);
125 	for (i = 0; i < cd_count[file]; i++) {
126 		dev = console_devices[file][i];
127 		if (dev->tstc != NULL) {
128 			ret = dev->tstc();
129 			if (ret > 0) {
130 				tstcdev = dev;
131 				disable_ctrlc(0);
132 				return ret;
133 			}
134 		}
135 	}
136 	disable_ctrlc(0);
137 
138 	return 0;
139 }
140 
141 static void iomux_putc(int file, const char c)
142 {
143 	int i;
144 	device_t *dev;
145 
146 	for (i = 0; i < cd_count[file]; i++) {
147 		dev = console_devices[file][i];
148 		if (dev->putc != NULL)
149 			dev->putc(c);
150 	}
151 }
152 
153 static void iomux_puts(int file, const char *s)
154 {
155 	int i;
156 	device_t *dev;
157 
158 	for (i = 0; i < cd_count[file]; i++) {
159 		dev = console_devices[file][i];
160 		if (dev->puts != NULL)
161 			dev->puts(s);
162 	}
163 }
164 #endif /* defined(CONFIG_CONSOLE_MUX) */
165 
166 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/
167 
168 void serial_printf (const char *fmt, ...)
169 {
170 	va_list args;
171 	uint i;
172 	char printbuffer[CONFIG_SYS_PBSIZE];
173 
174 	va_start (args, fmt);
175 
176 	/* For this to work, printbuffer must be larger than
177 	 * anything we ever want to print.
178 	 */
179 	i = vsprintf (printbuffer, fmt, args);
180 	va_end (args);
181 
182 	serial_puts (printbuffer);
183 }
184 
185 int fgetc (int file)
186 {
187 	if (file < MAX_FILES) {
188 #if defined(CONFIG_CONSOLE_MUX)
189 		/*
190 		 * Effectively poll for input wherever it may be available.
191 		 */
192 		for (;;) {
193 			/*
194 			 * Upper layer may have already called tstc() so
195 			 * check for that first.
196 			 */
197 			if (tstcdev != NULL)
198 				return iomux_getc();
199 			iomux_tstc(file);
200 #ifdef CONFIG_WATCHDOG
201 			/*
202 			 * If the watchdog must be rate-limited then it should
203 			 * already be handled in board-specific code.
204 			 */
205 			 udelay(1);
206 #endif
207 		}
208 #else
209 		return stdio_devices[file]->getc ();
210 #endif
211 	}
212 
213 	return -1;
214 }
215 
216 int ftstc (int file)
217 {
218 	if (file < MAX_FILES)
219 #if defined(CONFIG_CONSOLE_MUX)
220 		return iomux_tstc(file);
221 #else
222 		return stdio_devices[file]->tstc ();
223 #endif
224 
225 	return -1;
226 }
227 
228 void fputc (int file, const char c)
229 {
230 	if (file < MAX_FILES)
231 #if defined(CONFIG_CONSOLE_MUX)
232 		iomux_putc(file, c);
233 #else
234 		stdio_devices[file]->putc (c);
235 #endif
236 }
237 
238 void fputs (int file, const char *s)
239 {
240 	if (file < MAX_FILES)
241 #if defined(CONFIG_CONSOLE_MUX)
242 		iomux_puts(file, s);
243 #else
244 		stdio_devices[file]->puts (s);
245 #endif
246 }
247 
248 void fprintf (int file, const char *fmt, ...)
249 {
250 	va_list args;
251 	uint i;
252 	char printbuffer[CONFIG_SYS_PBSIZE];
253 
254 	va_start (args, fmt);
255 
256 	/* For this to work, printbuffer must be larger than
257 	 * anything we ever want to print.
258 	 */
259 	i = vsprintf (printbuffer, fmt, args);
260 	va_end (args);
261 
262 	/* Send to desired file */
263 	fputs (file, printbuffer);
264 }
265 
266 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
267 
268 int getc (void)
269 {
270 #ifdef CONFIG_DISABLE_CONSOLE
271 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
272 		return 0;
273 #endif
274 
275 	if (gd->flags & GD_FLG_DEVINIT) {
276 		/* Get from the standard input */
277 		return fgetc (stdin);
278 	}
279 
280 	/* Send directly to the handler */
281 	return serial_getc ();
282 }
283 
284 int tstc (void)
285 {
286 #ifdef CONFIG_DISABLE_CONSOLE
287 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
288 		return 0;
289 #endif
290 
291 	if (gd->flags & GD_FLG_DEVINIT) {
292 		/* Test the standard input */
293 		return ftstc (stdin);
294 	}
295 
296 	/* Send directly to the handler */
297 	return serial_tstc ();
298 }
299 
300 void putc (const char c)
301 {
302 #ifdef CONFIG_SILENT_CONSOLE
303 	if (gd->flags & GD_FLG_SILENT)
304 		return;
305 #endif
306 
307 #ifdef CONFIG_DISABLE_CONSOLE
308 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
309 		return;
310 #endif
311 
312 	if (gd->flags & GD_FLG_DEVINIT) {
313 		/* Send to the standard output */
314 		fputc (stdout, c);
315 	} else {
316 		/* Send directly to the handler */
317 		serial_putc (c);
318 	}
319 }
320 
321 void puts (const char *s)
322 {
323 #ifdef CONFIG_SILENT_CONSOLE
324 	if (gd->flags & GD_FLG_SILENT)
325 		return;
326 #endif
327 
328 #ifdef CONFIG_DISABLE_CONSOLE
329 	if (gd->flags & GD_FLG_DISABLE_CONSOLE)
330 		return;
331 #endif
332 
333 	if (gd->flags & GD_FLG_DEVINIT) {
334 		/* Send to the standard output */
335 		fputs (stdout, s);
336 	} else {
337 		/* Send directly to the handler */
338 		serial_puts (s);
339 	}
340 }
341 
342 void printf (const char *fmt, ...)
343 {
344 	va_list args;
345 	uint i;
346 	char printbuffer[CONFIG_SYS_PBSIZE];
347 
348 	va_start (args, fmt);
349 
350 	/* For this to work, printbuffer must be larger than
351 	 * anything we ever want to print.
352 	 */
353 	i = vsprintf (printbuffer, fmt, args);
354 	va_end (args);
355 
356 	/* Print the string */
357 	puts (printbuffer);
358 }
359 
360 void vprintf (const char *fmt, va_list args)
361 {
362 	uint i;
363 	char printbuffer[CONFIG_SYS_PBSIZE];
364 
365 	/* For this to work, printbuffer must be larger than
366 	 * anything we ever want to print.
367 	 */
368 	i = vsprintf (printbuffer, fmt, args);
369 
370 	/* Print the string */
371 	puts (printbuffer);
372 }
373 
374 /* test if ctrl-c was pressed */
375 static int ctrlc_disabled = 0;	/* see disable_ctrl() */
376 static int ctrlc_was_pressed = 0;
377 int ctrlc (void)
378 {
379 	if (!ctrlc_disabled && gd->have_console) {
380 		if (tstc ()) {
381 			switch (getc ()) {
382 			case 0x03:		/* ^C - Control C */
383 				ctrlc_was_pressed = 1;
384 				return 1;
385 			default:
386 				break;
387 			}
388 		}
389 	}
390 	return 0;
391 }
392 
393 /* pass 1 to disable ctrlc() checking, 0 to enable.
394  * returns previous state
395  */
396 int disable_ctrlc (int disable)
397 {
398 	int prev = ctrlc_disabled;	/* save previous state */
399 
400 	ctrlc_disabled = disable;
401 	return prev;
402 }
403 
404 int had_ctrlc (void)
405 {
406 	return ctrlc_was_pressed;
407 }
408 
409 void clear_ctrlc (void)
410 {
411 	ctrlc_was_pressed = 0;
412 }
413 
414 #ifdef CONFIG_MODEM_SUPPORT_DEBUG
415 char	screen[1024];
416 char *cursor = screen;
417 int once = 0;
418 inline void dbg(const char *fmt, ...)
419 {
420 	va_list	args;
421 	uint	i;
422 	char	printbuffer[CONFIG_SYS_PBSIZE];
423 
424 	if (!once) {
425 		memset(screen, 0, sizeof(screen));
426 		once++;
427 	}
428 
429 	va_start(args, fmt);
430 
431 	/* For this to work, printbuffer must be larger than
432 	 * anything we ever want to print.
433 	 */
434 	i = vsprintf(printbuffer, fmt, args);
435 	va_end(args);
436 
437 	if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) {
438 		memset(screen, 0, sizeof(screen));
439 		cursor = screen;
440 	}
441 	sprintf(cursor, printbuffer);
442 	cursor += strlen(printbuffer);
443 
444 }
445 #else
446 inline void dbg(const char *fmt, ...)
447 {
448 }
449 #endif
450 
451 /** U-Boot INIT FUNCTIONS *************************************************/
452 
453 device_t *search_device (int flags, char *name)
454 {
455 	device_t *dev;
456 
457 	dev = device_get_by_name(name);
458 
459 	if(dev && (dev->flags & flags))
460 		return dev;
461 
462 	return NULL;
463 }
464 
465 int console_assign (int file, char *devname)
466 {
467 	int flag;
468 	device_t *dev;
469 
470 	/* Check for valid file */
471 	switch (file) {
472 	case stdin:
473 		flag = DEV_FLAGS_INPUT;
474 		break;
475 	case stdout:
476 	case stderr:
477 		flag = DEV_FLAGS_OUTPUT;
478 		break;
479 	default:
480 		return -1;
481 	}
482 
483 	/* Check for valid device name */
484 
485 	dev = search_device(flag, devname);
486 
487 	if(dev)
488 		return console_setfile (file, dev);
489 
490 	return -1;
491 }
492 
493 /* Called before relocation - use serial functions */
494 int console_init_f (void)
495 {
496 	gd->have_console = 1;
497 
498 #ifdef CONFIG_SILENT_CONSOLE
499 	if (getenv("silent") != NULL)
500 		gd->flags |= GD_FLG_SILENT;
501 #endif
502 
503 	return (0);
504 }
505 
506 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV
507 /* Called after the relocation - use desired console functions */
508 int console_init_r (void)
509 {
510 	char *stdinname, *stdoutname, *stderrname;
511 	device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL;
512 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
513 	int i;
514 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
515 #ifdef CONFIG_CONSOLE_MUX
516 	int iomux_err = 0;
517 #endif
518 
519 	/* set default handlers at first */
520 	gd->jt[XF_getc] = serial_getc;
521 	gd->jt[XF_tstc] = serial_tstc;
522 	gd->jt[XF_putc] = serial_putc;
523 	gd->jt[XF_puts] = serial_puts;
524 	gd->jt[XF_printf] = serial_printf;
525 
526 	/* stdin stdout and stderr are in environment */
527 	/* scan for it */
528 	stdinname  = getenv ("stdin");
529 	stdoutname = getenv ("stdout");
530 	stderrname = getenv ("stderr");
531 
532 	if (OVERWRITE_CONSOLE == 0) {	/* if not overwritten by config switch */
533 		inputdev  = search_device (DEV_FLAGS_INPUT,  stdinname);
534 		outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname);
535 		errdev    = search_device (DEV_FLAGS_OUTPUT, stderrname);
536 #ifdef CONFIG_CONSOLE_MUX
537 		iomux_err = iomux_doenv(stdin, stdinname);
538 		iomux_err += iomux_doenv(stdout, stdoutname);
539 		iomux_err += iomux_doenv(stderr, stderrname);
540 		if (!iomux_err)
541 			/* Successful, so skip all the code below. */
542 			goto done;
543 #endif
544 	}
545 	/* if the devices are overwritten or not found, use default device */
546 	if (inputdev == NULL) {
547 		inputdev  = search_device (DEV_FLAGS_INPUT,  "serial");
548 	}
549 	if (outputdev == NULL) {
550 		outputdev = search_device (DEV_FLAGS_OUTPUT, "serial");
551 	}
552 	if (errdev == NULL) {
553 		errdev    = search_device (DEV_FLAGS_OUTPUT, "serial");
554 	}
555 	/* Initializes output console first */
556 	if (outputdev != NULL) {
557 #ifdef CONFIG_CONSOLE_MUX
558 		/* need to set a console if not done above. */
559 		iomux_doenv(stdout, outputdev->name);
560 #else
561 		console_setfile (stdout, outputdev);
562 #endif
563 	}
564 	if (errdev != NULL) {
565 #ifdef CONFIG_CONSOLE_MUX
566 		/* need to set a console if not done above. */
567 		iomux_doenv(stderr, errdev->name);
568 #else
569 		console_setfile (stderr, errdev);
570 #endif
571 	}
572 	if (inputdev != NULL) {
573 #ifdef CONFIG_CONSOLE_MUX
574 		/* need to set a console if not done above. */
575 		iomux_doenv(stdin, inputdev->name);
576 #else
577 		console_setfile (stdin, inputdev);
578 #endif
579 	}
580 
581 #ifdef CONFIG_CONSOLE_MUX
582 done:
583 #endif
584 
585 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
586 
587 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
588 	/* Print information */
589 	puts ("In:    ");
590 	if (stdio_devices[stdin] == NULL) {
591 		puts ("No input devices available!\n");
592 	} else {
593 #ifdef CONFIG_CONSOLE_MUX
594 		iomux_printdevs(stdin);
595 #else
596 		printf ("%s\n", stdio_devices[stdin]->name);
597 #endif
598 	}
599 
600 	puts ("Out:   ");
601 	if (stdio_devices[stdout] == NULL) {
602 		puts ("No output devices available!\n");
603 	} else {
604 #ifdef CONFIG_CONSOLE_MUX
605 		iomux_printdevs(stdout);
606 #else
607 		printf ("%s\n", stdio_devices[stdout]->name);
608 #endif
609 	}
610 
611 	puts ("Err:   ");
612 	if (stdio_devices[stderr] == NULL) {
613 		puts ("No error devices available!\n");
614 	} else {
615 #ifdef CONFIG_CONSOLE_MUX
616 		iomux_printdevs(stderr);
617 #else
618 		printf ("%s\n", stdio_devices[stderr]->name);
619 #endif
620 	}
621 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
622 
623 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE
624 	/* set the environment variables (will overwrite previous env settings) */
625 	for (i = 0; i < 3; i++) {
626 		setenv (stdio_names[i], stdio_devices[i]->name);
627 	}
628 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */
629 
630 #if 0
631 	/* If nothing usable installed, use only the initial console */
632 	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
633 		return (0);
634 #endif
635 	return (0);
636 }
637 
638 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
639 
640 /* Called after the relocation - use desired console functions */
641 int console_init_r (void)
642 {
643 	device_t *inputdev = NULL, *outputdev = NULL;
644 	int i;
645 	struct list_head *list = device_get_list();
646 	struct list_head *pos;
647 	device_t *dev;
648 
649 #ifdef CONFIG_SPLASH_SCREEN
650 	/* suppress all output if splash screen is enabled and we have
651 	   a bmp to display                                            */
652 	if (getenv("splashimage") != NULL)
653 		gd->flags |= GD_FLG_SILENT;
654 #endif
655 
656 	/* Scan devices looking for input and output devices */
657 	list_for_each(pos, list) {
658 		dev = list_entry(pos, device_t, list);
659 
660 		if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) {
661 			inputdev = dev;
662 		}
663 		if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) {
664 			outputdev = dev;
665 		}
666 		if(inputdev && outputdev)
667 			break;
668 	}
669 
670 	/* Initializes output console first */
671 	if (outputdev != NULL) {
672 		console_setfile (stdout, outputdev);
673 		console_setfile (stderr, outputdev);
674 #ifdef CONFIG_CONSOLE_MUX
675 		console_devices[stdout][0] = outputdev;
676 		console_devices[stderr][0] = outputdev;
677 #endif
678 	}
679 
680 	/* Initializes input console */
681 	if (inputdev != NULL) {
682 		console_setfile (stdin, inputdev);
683 #ifdef CONFIG_CONSOLE_MUX
684 		console_devices[stdin][0] = inputdev;
685 #endif
686 	}
687 
688 	gd->flags |= GD_FLG_DEVINIT;	/* device initialization completed */
689 
690 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET
691 	/* Print information */
692 	puts ("In:    ");
693 	if (stdio_devices[stdin] == NULL) {
694 		puts ("No input devices available!\n");
695 	} else {
696 		printf ("%s\n", stdio_devices[stdin]->name);
697 	}
698 
699 	puts ("Out:   ");
700 	if (stdio_devices[stdout] == NULL) {
701 		puts ("No output devices available!\n");
702 	} else {
703 		printf ("%s\n", stdio_devices[stdout]->name);
704 	}
705 
706 	puts ("Err:   ");
707 	if (stdio_devices[stderr] == NULL) {
708 		puts ("No error devices available!\n");
709 	} else {
710 		printf ("%s\n", stdio_devices[stderr]->name);
711 	}
712 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */
713 
714 	/* Setting environment variables */
715 	for (i = 0; i < 3; i++) {
716 		setenv (stdio_names[i], stdio_devices[i]->name);
717 	}
718 
719 #if 0
720 	/* If nothing usable installed, use only the initial console */
721 	if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL))
722 		return (0);
723 #endif
724 
725 	return (0);
726 }
727 
728 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */
729