xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/console/multi_console.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park 
9*54fd6939SJiyong Park #include <drivers/console.h>
10*54fd6939SJiyong Park 
11*54fd6939SJiyong Park console_t *console_list;
12*54fd6939SJiyong Park uint8_t console_state = CONSOLE_FLAG_BOOT;
13*54fd6939SJiyong Park 
IMPORT_SYM(console_t *,__STACKS_START__,stacks_start)14*54fd6939SJiyong Park IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
15*54fd6939SJiyong Park IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
16*54fd6939SJiyong Park 
17*54fd6939SJiyong Park int console_register(console_t *console)
18*54fd6939SJiyong Park {
19*54fd6939SJiyong Park 	/* Assert that the struct is not on the stack (common mistake). */
20*54fd6939SJiyong Park 	assert((console < stacks_start) || (console >= stacks_end));
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park 	/* Check that we won't make a circle in the list. */
23*54fd6939SJiyong Park 	if (console_is_registered(console) == 1)
24*54fd6939SJiyong Park 		return 1;
25*54fd6939SJiyong Park 
26*54fd6939SJiyong Park 	console->next = console_list;
27*54fd6939SJiyong Park 	console_list = console;
28*54fd6939SJiyong Park 
29*54fd6939SJiyong Park 	/* Return 1 for convenient tail-calling from console_xxx_register(). */
30*54fd6939SJiyong Park 	return 1;
31*54fd6939SJiyong Park }
32*54fd6939SJiyong Park 
console_unregister(console_t * to_be_deleted)33*54fd6939SJiyong Park console_t *console_unregister(console_t *to_be_deleted)
34*54fd6939SJiyong Park {
35*54fd6939SJiyong Park 	console_t **ptr;
36*54fd6939SJiyong Park 
37*54fd6939SJiyong Park 	assert(to_be_deleted != NULL);
38*54fd6939SJiyong Park 
39*54fd6939SJiyong Park 	for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
40*54fd6939SJiyong Park 		if (*ptr == to_be_deleted) {
41*54fd6939SJiyong Park 			*ptr = (*ptr)->next;
42*54fd6939SJiyong Park 			return to_be_deleted;
43*54fd6939SJiyong Park 		}
44*54fd6939SJiyong Park 
45*54fd6939SJiyong Park 	return NULL;
46*54fd6939SJiyong Park }
47*54fd6939SJiyong Park 
console_is_registered(console_t * to_find)48*54fd6939SJiyong Park int console_is_registered(console_t *to_find)
49*54fd6939SJiyong Park {
50*54fd6939SJiyong Park 	console_t *console;
51*54fd6939SJiyong Park 
52*54fd6939SJiyong Park 	assert(to_find != NULL);
53*54fd6939SJiyong Park 
54*54fd6939SJiyong Park 	for (console = console_list; console != NULL; console = console->next)
55*54fd6939SJiyong Park 		if (console == to_find)
56*54fd6939SJiyong Park 			return 1;
57*54fd6939SJiyong Park 
58*54fd6939SJiyong Park 	return 0;
59*54fd6939SJiyong Park }
60*54fd6939SJiyong Park 
console_switch_state(unsigned int new_state)61*54fd6939SJiyong Park void console_switch_state(unsigned int new_state)
62*54fd6939SJiyong Park {
63*54fd6939SJiyong Park 	console_state = new_state;
64*54fd6939SJiyong Park }
65*54fd6939SJiyong Park 
console_set_scope(console_t * console,unsigned int scope)66*54fd6939SJiyong Park void console_set_scope(console_t *console, unsigned int scope)
67*54fd6939SJiyong Park {
68*54fd6939SJiyong Park 	assert(console != NULL);
69*54fd6939SJiyong Park 
70*54fd6939SJiyong Park 	console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
71*54fd6939SJiyong Park }
72*54fd6939SJiyong Park 
do_putc(int c,console_t * console)73*54fd6939SJiyong Park static int do_putc(int c, console_t *console)
74*54fd6939SJiyong Park {
75*54fd6939SJiyong Park 	int ret;
76*54fd6939SJiyong Park 
77*54fd6939SJiyong Park 	if ((c == '\n') &&
78*54fd6939SJiyong Park 	    ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
79*54fd6939SJiyong Park 		ret = console->putc('\r', console);
80*54fd6939SJiyong Park 		if (ret < 0)
81*54fd6939SJiyong Park 			return ret;
82*54fd6939SJiyong Park 	}
83*54fd6939SJiyong Park 
84*54fd6939SJiyong Park 	return console->putc(c, console);
85*54fd6939SJiyong Park }
86*54fd6939SJiyong Park 
console_putc(int c)87*54fd6939SJiyong Park int console_putc(int c)
88*54fd6939SJiyong Park {
89*54fd6939SJiyong Park 	int err = ERROR_NO_VALID_CONSOLE;
90*54fd6939SJiyong Park 	console_t *console;
91*54fd6939SJiyong Park 
92*54fd6939SJiyong Park 	for (console = console_list; console != NULL; console = console->next)
93*54fd6939SJiyong Park 		if ((console->flags & console_state) && (console->putc != NULL)) {
94*54fd6939SJiyong Park 			int ret = do_putc(c, console);
95*54fd6939SJiyong Park 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
96*54fd6939SJiyong Park 				err = ret;
97*54fd6939SJiyong Park 		}
98*54fd6939SJiyong Park 
99*54fd6939SJiyong Park 	return err;
100*54fd6939SJiyong Park }
101*54fd6939SJiyong Park 
console_getc(void)102*54fd6939SJiyong Park int console_getc(void)
103*54fd6939SJiyong Park {
104*54fd6939SJiyong Park 	int err = ERROR_NO_VALID_CONSOLE;
105*54fd6939SJiyong Park 	console_t *console;
106*54fd6939SJiyong Park 
107*54fd6939SJiyong Park 	do {	/* Keep polling while at least one console works correctly. */
108*54fd6939SJiyong Park 		for (console = console_list; console != NULL;
109*54fd6939SJiyong Park 		     console = console->next)
110*54fd6939SJiyong Park 			if ((console->flags & console_state) && (console->getc != NULL)) {
111*54fd6939SJiyong Park 				int ret = console->getc(console);
112*54fd6939SJiyong Park 				if (ret >= 0)
113*54fd6939SJiyong Park 					return ret;
114*54fd6939SJiyong Park 				if (err != ERROR_NO_PENDING_CHAR)
115*54fd6939SJiyong Park 					err = ret;
116*54fd6939SJiyong Park 			}
117*54fd6939SJiyong Park 	} while (err == ERROR_NO_PENDING_CHAR);
118*54fd6939SJiyong Park 
119*54fd6939SJiyong Park 	return err;
120*54fd6939SJiyong Park }
121*54fd6939SJiyong Park 
console_flush(void)122*54fd6939SJiyong Park void console_flush(void)
123*54fd6939SJiyong Park {
124*54fd6939SJiyong Park 	console_t *console;
125*54fd6939SJiyong Park 
126*54fd6939SJiyong Park 	for (console = console_list; console != NULL; console = console->next)
127*54fd6939SJiyong Park 		if ((console->flags & console_state) && (console->flush != NULL)) {
128*54fd6939SJiyong Park 			console->flush(console);
129*54fd6939SJiyong Park 		}
130*54fd6939SJiyong Park }
131