From 714118709607c32f450f9ce7c649ddebfc1d79ad Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sat, 7 Feb 2026 20:13:26 -0300 Subject: [PATCH] kernel: add console subsystem and kprintf (uart+vga) --- include/console.h | 18 ++++ src/arch/x86/arch_platform.c | 4 +- src/kernel/console.c | 192 +++++++++++++++++++++++++++++++++++ src/kernel/main.c | 14 +-- 4 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 include/console.h create mode 100644 src/kernel/console.c diff --git a/include/console.h b/include/console.h new file mode 100644 index 0000000..4f61e25 --- /dev/null +++ b/include/console.h @@ -0,0 +1,18 @@ +#ifndef CONSOLE_H +#define CONSOLE_H + +#include +#include + +void console_init(void); +void console_enable_uart(int enabled); +void console_enable_vga(int enabled); + +void console_write(const char* s); + +int kvsnprintf(char* out, size_t out_size, const char* fmt, va_list ap); +int ksnprintf(char* out, size_t out_size, const char* fmt, ...); + +void kprintf(const char* fmt, ...); + +#endif diff --git a/src/arch/x86/arch_platform.c b/src/arch/x86/arch_platform.c index 98fb466..0999272 100644 --- a/src/arch/x86/arch_platform.c +++ b/src/arch/x86/arch_platform.c @@ -6,6 +6,7 @@ #include "syscall.h" #include "timer.h" #include "uart_console.h" +#include "console.h" #include "uaccess.h" #include "vga_console.h" #include "vmm.h" @@ -72,7 +73,8 @@ int arch_platform_setup(const struct boot_info* bi) { vga_init(); vga_set_color(0x0A, 0x00); - vga_print("[AdrOS] Kernel Initialized (VGA).\n"); + console_enable_vga(1); + kprintf("[AdrOS] Kernel Initialized (VGA).\n"); syscall_init(); keyboard_init(); diff --git a/src/kernel/console.c b/src/kernel/console.c new file mode 100644 index 0000000..089211a --- /dev/null +++ b/src/kernel/console.c @@ -0,0 +1,192 @@ +#include +#include +#include + +#include "console.h" + +#include "spinlock.h" +#include "uart_console.h" +#include "vga_console.h" + +static spinlock_t g_console_lock = {0}; +static int g_console_uart_enabled = 1; +static int g_console_vga_enabled = 0; + +void console_init(void) { + spinlock_init(&g_console_lock); + g_console_uart_enabled = 1; + g_console_vga_enabled = 0; +} + +void console_enable_uart(int enabled) { + uintptr_t flags = spin_lock_irqsave(&g_console_lock); + g_console_uart_enabled = enabled ? 1 : 0; + spin_unlock_irqrestore(&g_console_lock, flags); +} + +void console_enable_vga(int enabled) { + uintptr_t flags = spin_lock_irqsave(&g_console_lock); + g_console_vga_enabled = enabled ? 1 : 0; + spin_unlock_irqrestore(&g_console_lock, flags); +} + +void console_write(const char* s) { + if (!s) return; + + uintptr_t flags = spin_lock_irqsave(&g_console_lock); + + if (g_console_uart_enabled) { + uart_print(s); + } + if (g_console_vga_enabled) { + vga_print(s); + } + + spin_unlock_irqrestore(&g_console_lock, flags); +} + +static void out_char(char** dst, size_t* rem, int* total, char c) { + (*total)++; + if (*rem == 0) return; + **dst = c; + (*dst)++; + (*rem)--; +} + +static void out_str(char** dst, size_t* rem, int* total, const char* s) { + if (!s) s = "(null)"; + for (size_t i = 0; s[i] != 0; i++) { + out_char(dst, rem, total, s[i]); + } +} + +static void out_uint_base_u32(char** dst, size_t* rem, int* total, uint32_t v, unsigned base, int upper) { + char tmp[32]; + size_t n = 0; + + if (base < 2 || base > 16) base = 10; + + if (v == 0) { + tmp[n++] = '0'; + } else { + while (v != 0 && n < sizeof(tmp)) { + unsigned d = (unsigned)(v % (uint32_t)base); + if (d < 10) tmp[n++] = (char)('0' + d); + else tmp[n++] = (char)((upper ? 'A' : 'a') + (d - 10)); + v /= (uint32_t)base; + } + } + + while (n > 0) { + out_char(dst, rem, total, tmp[--n]); + } +} + +static void out_uint_hex_fixed_u32(char** dst, size_t* rem, int* total, uint32_t v, int digits, int upper) { + const char* hex = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + for (int i = digits - 1; i >= 0; i--) { + unsigned nibble = (unsigned)((v >> (i * 4)) & 0xF); + out_char(dst, rem, total, hex[nibble]); + } +} + +static void out_int_i32(char** dst, size_t* rem, int* total, int32_t v) { + if (v < 0) { + out_char(dst, rem, total, '-'); + out_uint_base_u32(dst, rem, total, (uint32_t)(-v), 10, 0); + } else { + out_uint_base_u32(dst, rem, total, (uint32_t)v, 10, 0); + } +} + +int kvsnprintf(char* out, size_t out_size, const char* fmt, va_list ap) { + if (!out || out_size == 0) return 0; + if (!fmt) { + out[0] = 0; + return 0; + } + + char* dst = out; + size_t rem = out_size - 1; + int total = 0; + + for (size_t i = 0; fmt[i] != 0; i++) { + char c = fmt[i]; + if (c != '%') { + out_char(&dst, &rem, &total, c); + continue; + } + + char spec = fmt[++i]; + if (spec == 0) break; + + switch (spec) { + case '%': + out_char(&dst, &rem, &total, '%'); + break; + case 'c': { + int v = va_arg(ap, int); + out_char(&dst, &rem, &total, (char)v); + break; + } + case 's': { + const char* s = va_arg(ap, const char*); + out_str(&dst, &rem, &total, s); + break; + } + case 'd': + case 'i': { + int v = va_arg(ap, int); + out_int_i32(&dst, &rem, &total, (int32_t)v); + break; + } + case 'u': { + unsigned v = va_arg(ap, unsigned); + out_uint_base_u32(&dst, &rem, &total, (uint32_t)v, 10, 0); + break; + } + case 'x': { + unsigned v = va_arg(ap, unsigned); + out_uint_base_u32(&dst, &rem, &total, (uint32_t)v, 16, 0); + break; + } + case 'X': { + unsigned v = va_arg(ap, unsigned); + out_uint_base_u32(&dst, &rem, &total, (uint32_t)v, 16, 1); + break; + } + case 'p': { + uintptr_t v = (uintptr_t)va_arg(ap, void*); + out_str(&dst, &rem, &total, "0x"); + out_uint_hex_fixed_u32(&dst, &rem, &total, (uint32_t)v, 8, 1); + break; + } + default: + out_char(&dst, &rem, &total, '%'); + out_char(&dst, &rem, &total, spec); + break; + } + } + + *dst = 0; + return total; +} + +int ksnprintf(char* out, size_t out_size, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + int r = kvsnprintf(out, out_size, fmt, ap); + va_end(ap); + return r; +} + +void kprintf(const char* fmt, ...) { + char buf[512]; + + va_list ap; + va_start(ap, fmt); + (void)kvsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + console_write(buf); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index cf477f3..a89b560 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -1,5 +1,6 @@ #include #include +#include "console.h" #include "vga_console.h" #include "uart_console.h" #include "pmm.h" @@ -34,16 +35,17 @@ * Arguments are passed from boot.S (architecture specific) */ void kernel_main(const struct boot_info* bi) { - - uart_print("[AdrOS] Initializing PMM...\n"); + console_init(); + + kprintf("[AdrOS] Initializing PMM...\n"); // 2. Initialize Physical Memory Manager pmm_init((void*)(bi ? bi->arch_boot_info : 0)); // 3. Initialize Virtual Memory Manager - uart_print("[AdrOS] Initializing VMM...\n"); + kprintf("[AdrOS] Initializing VMM...\n"); if (arch_platform_setup(bi) < 0) { - uart_print("[WARN] VMM/IDT/Sched not implemented for this architecture yet.\n"); + kprintf("[WARN] VMM/IDT/Sched not implemented for this architecture yet.\n"); goto done; } @@ -51,7 +53,7 @@ void kernel_main(const struct boot_info* bi) { kheap_init(); // 7. Initialize Multitasking - uart_print("[AdrOS] Initializing Scheduler...\n"); + kprintf("[AdrOS] Initializing Scheduler...\n"); process_init(); // 8. Start Timer (Preemption!) - 50Hz @@ -67,7 +69,7 @@ void kernel_main(const struct boot_info* bi) { } done: - uart_print("Welcome to AdrOS (x86/ARM/RISC-V/MIPS)!\n"); + kprintf("Welcome to AdrOS (x86/ARM/RISC-V/MIPS)!\n"); // Infinite loop acting as Idle Task for(;;) { -- 2.43.0