console: Add loglevel prefix to interactive consoles

In an attempt to make loglevels more visible (and therefore useful,
hopefully), this patch adds a prefix indicating the log level to every
line sent to an "interactive" console (such as a UART). If the code
contains a `printk(BIOS_DEBUG, "This is a debug message!\n"), it will
now show up as

  [DEBUG]  This is a debug message!

on the UART output.

"Stored" consoles (such as in CBMEM) will get a similar but more
space-efficient feature in a later CL.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: Ic83413475400821f8097ef1819a293ee8926bb0b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/61306
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
Julius Werner 2022-01-21 15:15:29 -08:00 committed by Felix Held
parent 1ee6e4ab6c
commit 7cd8ba6eda
4 changed files with 70 additions and 9 deletions

View File

@ -157,4 +157,27 @@
#define BIOS_NEVER 9 #define BIOS_NEVER 9
/** @} */ /** @} */
#ifndef __ASSEMBLER__
/*
* When printing logs, lines should be printed with the following prefixes in
* front of them according to the BIOS_LOG_PREFIX_PATTERN printf() pattern.
*/
#define BIOS_LOG_PREFIX_PATTERN "[%.5s] "
#define BIOS_LOG_PREFIX_MAX_LEVEL BIOS_SPEW
static const char bios_log_prefix[BIOS_LOG_PREFIX_MAX_LEVEL + 1][5] = {
/* Note: These strings are *not* null-terminated to save space. */
[BIOS_EMERG] = "EMERG",
[BIOS_ALERT] = "ALERT",
[BIOS_CRIT] = "CRIT ",
[BIOS_ERR] = "ERROR",
[BIOS_WARNING] = "WARN ",
[BIOS_NOTICE] = "NOTE ",
[BIOS_INFO] = "INFO ",
[BIOS_DEBUG] = "DEBUG",
[BIOS_SPEW] = "SPEW ",
};
#endif /* __ASSEMBLER__ */
#endif /* LOGLEVEL_H */ #endif /* LOGLEVEL_H */

View File

@ -25,28 +25,35 @@ void console_hw_init(void)
__system76_ec_init(); __system76_ec_init();
} }
void console_tx_byte(unsigned char byte) void console_interactive_tx_byte(unsigned char byte, void *data_unused)
{ {
__cbmemc_tx_byte(byte);
__spkmodem_tx_byte(byte);
__qemu_debugcon_tx_byte(byte);
/* Some consoles want newline conversion
* to keep terminals happy.
*/
if (byte == '\n') { if (byte == '\n') {
/* Some consoles want newline conversion to keep terminals happy. */
__uart_tx_byte('\r'); __uart_tx_byte('\r');
__usb_tx_byte('\r'); __usb_tx_byte('\r');
} }
__spkmodem_tx_byte(byte);
__qemu_debugcon_tx_byte(byte);
__uart_tx_byte(byte); __uart_tx_byte(byte);
__ne2k_tx_byte(byte); __ne2k_tx_byte(byte);
__usb_tx_byte(byte); __usb_tx_byte(byte);
__spiconsole_tx_byte(byte); __spiconsole_tx_byte(byte);
__flashconsole_tx_byte(byte);
__system76_ec_tx_byte(byte); __system76_ec_tx_byte(byte);
} }
void console_stored_tx_byte(unsigned char byte, void *data_unused)
{
__flashconsole_tx_byte(byte);
__cbmemc_tx_byte(byte);
}
void console_tx_byte(unsigned char byte)
{
console_interactive_tx_byte(byte, NULL);
console_stored_tx_byte(byte, NULL);
}
void console_tx_flush(void) void console_tx_flush(void)
{ {
__uart_tx_flush(); __uart_tx_flush();

View File

@ -67,9 +67,35 @@ union log_state {
}; };
}; };
static void wrap_interactive_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vtxprintf(console_interactive_tx_byte, fmt, args, NULL);
}
static void line_start(union log_state state)
{
if (state.level > BIOS_LOG_PREFIX_MAX_LEVEL)
return;
if (state.speed == CONSOLE_LOG_FAST)
return;
/* Interactive consoles get a `[DEBUG] ` style readable prefix. */
wrap_interactive_printf(BIOS_LOG_PREFIX_PATTERN, bios_log_prefix[state.level]);
}
static void wrap_putchar(unsigned char byte, void *data) static void wrap_putchar(unsigned char byte, void *data)
{ {
union log_state state = { .as_ptr = data }; union log_state state = { .as_ptr = data };
static bool line_started = false;
if (byte == '\n') {
line_started = false;
} else if (!line_started) {
line_start(state);
line_started = true;
}
if (state.speed == CONSOLE_LOG_FAST) if (state.speed == CONSOLE_LOG_FAST)
__cbmemc_tx_byte(byte); __cbmemc_tx_byte(byte);

View File

@ -10,6 +10,11 @@ void console_hw_init(void);
void console_tx_byte(unsigned char byte); void console_tx_byte(unsigned char byte);
void console_tx_flush(void); void console_tx_flush(void);
/* Interactive consoles that are usually displayed in real time on a terminal. */
void console_interactive_tx_byte(unsigned char byte, void *data_unused);
/* Consoles that store logs on some medium for later retrieval. */
void console_stored_tx_byte(unsigned char byte, void *data_unused);
/* /*
* Write number_of_bytes data bytes from buffer to the serial device. * Write number_of_bytes data bytes from buffer to the serial device.
* If number_of_bytes is zero, wait until all serial data is output. * If number_of_bytes is zero, wait until all serial data is output.