mirror of
https://github.com/ivoszbg/uniLoader.git
synced 2026-08-15 05:18:32 +00:00
For a while now, both simple-framebuffer and uart were hard-wired to the debug library. You could alternate between each or have both running, but the implementation was really ugly - ifdefs based on whether uart/simplefb are compiled in or not. As uniLoader has advanced enough to feature a sane-ish probing system for drivers, we can start experimenting with things like: - multiple framebuffers / UART devices - support for more complex peripherals (USB, storage) - multiple boot paths Hence registering output sinks as console devices, just like how u-boot and linux do, is a feature we should've had a long while ago. So let's begin working on that by decoupling framebuffer and uart from the "debug" interface in uni and rather allowing the registering of such sinks as "console" devices. With that, make the simple-framebuffer driver handle the debug level colors as well as the message assembling and writing to the framebuffer. That fully detaches it from the debug interface, as all that is required now is to invoke console_register() with the appropriate struct passed as an argument. As the drivers for output sinks are now responsible for the formatting of the messages, their set-up and writing, UART can be implemented as a sole driver as well. However, drivers register late in the boot process (after assembly, board early_initand other drivers with higher priority). With that in mind and all the leftover UART puts/c code in board files for several of the currently supported devices, introduce an early console path dedicated for debugging via UART. Looking at the currently supported devices, the only one requiring set-up before being able to output to UART is lucky7. For ease of use, make early_console_init weak, allowing it to be overrided by board files such as board-lucky7. Lastly, debug -> console, as that more correctly addresses the purpose of the library now.
100 lines
2.4 KiB
C
100 lines
2.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2022, Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <lib/console.h>
|
|
#include <lib/debug.h>
|
|
|
|
#define NANOPRINTF_IMPLEMENTATION
|
|
#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
|
|
#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
|
|
#define NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS 0
|
|
#define NANOPRINTF_USE_SMALL_FORMAT_SPECIFIERS 1
|
|
#define NANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS 0
|
|
#define NANOPRINTF_USE_BINARY_FORMAT_SPECIFIERS 1
|
|
#define NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS 1
|
|
#define NANOPRINTF_USE_ALT_FORM_FLAG 1
|
|
#include <lib/nanoprintf.h>
|
|
|
|
#define PRINTK_BUFFER_SIZE 256
|
|
|
|
/* earlycon (usually uart) + fb; bump if a third sink appears. */
|
|
#define MAX_CONSOLES 2
|
|
|
|
static const struct console *consoles[MAX_CONSOLES];
|
|
static unsigned int n_consoles;
|
|
|
|
void console_register(const struct console *con)
|
|
{
|
|
if (con && n_consoles < MAX_CONSOLES)
|
|
consoles[n_consoles++] = con;
|
|
}
|
|
|
|
static const char *log_prefix(int level)
|
|
{
|
|
static const char *const prefix[] = {
|
|
[KERN_EMERG] = "[EMERG] ",
|
|
[KERN_ALERT] = "[ALERT] ",
|
|
[KERN_CRIT] = "[CRIT] ",
|
|
[KERN_ERR] = "[ERROR] ",
|
|
[KERN_WARNING] = "[WARN] ",
|
|
[KERN_NOTICE] = "[NOTICE] ",
|
|
[KERN_INFO] = "[INFO] ",
|
|
[KERN_DEBUG] = "[DEBUG] ",
|
|
};
|
|
|
|
return (level >= 0 && level < (int)(sizeof(prefix) / sizeof(prefix[0]))) ?
|
|
prefix[level] : "[UNKNOWN] ";
|
|
}
|
|
|
|
#ifdef CONFIG_UART_DEBUG
|
|
extern void uart_puts(const char *s);
|
|
|
|
static void earlycon_write(int level, const char *prefix, const char *msg)
|
|
{
|
|
(void)level; /* unused */
|
|
uart_puts(prefix);
|
|
uart_puts(msg);
|
|
uart_puts("\r");
|
|
}
|
|
|
|
static const struct console earlycon = {
|
|
.write = earlycon_write,
|
|
};
|
|
|
|
void earlycon_register(void)
|
|
{
|
|
console_register(&earlycon);
|
|
}
|
|
#else
|
|
void earlycon_register(void) {}
|
|
#endif
|
|
|
|
/* no set-up console for early debugging w/ uart; overridable in board files */
|
|
__attribute__((weak)) void early_console_init(void)
|
|
{
|
|
earlycon_register();
|
|
}
|
|
|
|
void printk(int log_level, const char *fmt, ...)
|
|
{
|
|
if (log_level > CONFIG_LOGLEVEL || !n_consoles)
|
|
return;
|
|
|
|
va_list args;
|
|
static char print_buffer[PRINTK_BUFFER_SIZE];
|
|
|
|
va_start(args, fmt);
|
|
npf_vsnprintf(print_buffer, sizeof(print_buffer), fmt, args);
|
|
va_end(args);
|
|
|
|
const char *prefix = log_prefix(log_level);
|
|
|
|
for (unsigned int i = 0; i < n_consoles; i++)
|
|
consoles[i]->write(log_level, prefix, print_buffer);
|
|
}
|