mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-19 11:04:20 +00:00

And from crash_console_flush. We ignore the error information return by console_flush in _every_ place where we call it, and casting the return type to void does not work around the MISRA violation that this causes. Instead, we collect the error information from the driver (to avoid changing that API), and don't return it to the caller. Change-Id: I1e35afe01764d5c8f0efd04f8949d333ffb688c1 Signed-off-by: Jimmy Brisson <jimmy.brisson@arm.com>
130 lines
2.8 KiB
C
130 lines
2.8 KiB
C
/*
|
|
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <assert.h>
|
|
|
|
#include <drivers/console.h>
|
|
|
|
console_t *console_list;
|
|
uint8_t console_state = CONSOLE_FLAG_BOOT;
|
|
|
|
IMPORT_SYM(console_t *, __STACKS_START__, stacks_start)
|
|
IMPORT_SYM(console_t *, __STACKS_END__, stacks_end)
|
|
|
|
int console_register(console_t *console)
|
|
{
|
|
/* Assert that the struct is not on the stack (common mistake). */
|
|
assert((console < stacks_start) || (console >= stacks_end));
|
|
|
|
/* Check that we won't make a circle in the list. */
|
|
if (console_is_registered(console) == 1)
|
|
return 1;
|
|
|
|
console->next = console_list;
|
|
console_list = console;
|
|
|
|
/* Return 1 for convenient tail-calling from console_xxx_register(). */
|
|
return 1;
|
|
}
|
|
|
|
console_t *console_unregister(console_t *to_be_deleted)
|
|
{
|
|
console_t **ptr;
|
|
|
|
assert(to_be_deleted != NULL);
|
|
|
|
for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next)
|
|
if (*ptr == to_be_deleted) {
|
|
*ptr = (*ptr)->next;
|
|
return to_be_deleted;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int console_is_registered(console_t *to_find)
|
|
{
|
|
console_t *console;
|
|
|
|
assert(to_find != NULL);
|
|
|
|
for (console = console_list; console != NULL; console = console->next)
|
|
if (console == to_find)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void console_switch_state(unsigned int new_state)
|
|
{
|
|
console_state = new_state;
|
|
}
|
|
|
|
void console_set_scope(console_t *console, unsigned int scope)
|
|
{
|
|
assert(console != NULL);
|
|
|
|
console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope;
|
|
}
|
|
|
|
static int do_putc(int c, console_t *console)
|
|
{
|
|
int ret;
|
|
|
|
if ((c == '\n') &&
|
|
((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) {
|
|
ret = console->putc('\r', console);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
return console->putc(c, console);
|
|
}
|
|
|
|
int console_putc(int c)
|
|
{
|
|
int err = ERROR_NO_VALID_CONSOLE;
|
|
console_t *console;
|
|
|
|
for (console = console_list; console != NULL; console = console->next)
|
|
if ((console->flags & console_state) && (console->putc != NULL)) {
|
|
int ret = do_putc(c, console);
|
|
if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
|
|
err = ret;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int console_getc(void)
|
|
{
|
|
int err = ERROR_NO_VALID_CONSOLE;
|
|
console_t *console;
|
|
|
|
do { /* Keep polling while at least one console works correctly. */
|
|
for (console = console_list; console != NULL;
|
|
console = console->next)
|
|
if ((console->flags & console_state) && (console->getc != NULL)) {
|
|
int ret = console->getc(console);
|
|
if (ret >= 0)
|
|
return ret;
|
|
if (err != ERROR_NO_PENDING_CHAR)
|
|
err = ret;
|
|
}
|
|
} while (err == ERROR_NO_PENDING_CHAR);
|
|
|
|
return err;
|
|
}
|
|
|
|
void console_flush(void)
|
|
{
|
|
console_t *console;
|
|
|
|
for (console = console_list; console != NULL; console = console->next)
|
|
if ((console->flags & console_state) && (console->flush != NULL)) {
|
|
console->flush(console);
|
|
}
|
|
}
|