From 554b13ac50e0eff5117b8c4a862209cb12a5eb14 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 18 Apr 2025 01:19:59 +0300 Subject: [PATCH] Kernel: Restructure terminal initialization This is still very ugly and will be rewritten in the future :D --- kernel/CMakeLists.txt | 1 + .../kernel/Terminal/FramebufferTerminal.h | 12 ++++-- .../include/kernel/Terminal/TerminalDriver.h | 18 ++++----- kernel/include/kernel/Terminal/VirtualTTY.h | 6 +-- kernel/kernel/Debug.cpp | 1 - kernel/kernel/Device/FramebufferDevice.cpp | 10 ++--- kernel/kernel/Processor.cpp | 2 - .../kernel/Terminal/FramebufferTerminal.cpp | 39 ++++++++++--------- kernel/kernel/Terminal/TerminalDriver.cpp | 25 ++++++++++++ kernel/kernel/Terminal/VirtualTTY.cpp | 10 ++++- kernel/kernel/kernel.cpp | 14 ++----- 11 files changed, 85 insertions(+), 53 deletions(-) create mode 100644 kernel/kernel/Terminal/TerminalDriver.cpp diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index daf5b738..b03718ad 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -89,6 +89,7 @@ set(KERNEL_SOURCES kernel/Terminal/FramebufferTerminal.cpp kernel/Terminal/PseudoTerminal.cpp kernel/Terminal/Serial.cpp + kernel/Terminal/TerminalDriver.cpp kernel/Terminal/TTY.cpp kernel/Terminal/VirtualTTY.cpp kernel/Thread.cpp diff --git a/kernel/include/kernel/Terminal/FramebufferTerminal.h b/kernel/include/kernel/Terminal/FramebufferTerminal.h index 582fafa8..4c54f4dc 100644 --- a/kernel/include/kernel/Terminal/FramebufferTerminal.h +++ b/kernel/include/kernel/Terminal/FramebufferTerminal.h @@ -9,10 +9,10 @@ namespace Kernel class FramebufferTerminalDriver final : public TerminalDriver { public: - static FramebufferTerminalDriver* create(BAN::RefPtr); + static BAN::ErrorOr> create(BAN::RefPtr); - virtual uint32_t width() const override { return m_framebuffer_device->width() / font().width(); } - virtual uint32_t height() const override { return m_framebuffer_device->height() / font().height(); } + virtual uint32_t width() const override { return m_framebuffer_device->width() / m_font.width(); } + virtual uint32_t height() const override { return m_framebuffer_device->height() / m_font.height(); } virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) override; virtual bool scroll(Color) override; @@ -20,6 +20,11 @@ namespace Kernel virtual void set_cursor_position(uint32_t, uint32_t) override; + virtual bool has_font() const override { return true; } + + virtual void set_font(const LibFont::Font& font) override { m_font = font; }; + virtual const LibFont::Font& font() const override { return m_font; }; + private: FramebufferTerminalDriver(BAN::RefPtr framebuffer_device) : m_framebuffer_device(framebuffer_device) @@ -27,6 +32,7 @@ namespace Kernel private: BAN::RefPtr m_framebuffer_device; + LibFont::Font m_font; static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE; }; diff --git a/kernel/include/kernel/Terminal/TerminalDriver.h b/kernel/include/kernel/Terminal/TerminalDriver.h index ab9a5fa9..e38a2401 100644 --- a/kernel/include/kernel/Terminal/TerminalDriver.h +++ b/kernel/include/kernel/Terminal/TerminalDriver.h @@ -1,13 +1,13 @@ #pragma once -#include +#include -#include +#include namespace Kernel { - class TerminalDriver + class TerminalDriver : public BAN::RefCounted { public: struct Color @@ -25,7 +25,7 @@ namespace Kernel }; public: - TerminalDriver() : m_font(MUST(LibFont::Font::prefs())) {} + static BAN::ErrorOr initialize_from_boot_info(); virtual ~TerminalDriver() {} virtual uint32_t width() const = 0; virtual uint32_t height() const = 0; @@ -36,13 +36,13 @@ namespace Kernel virtual void set_cursor_position(uint32_t, uint32_t) = 0; - void set_font(const LibFont::Font& font) { m_font = font; }; - const LibFont::Font& font() const { return m_font; } - - private: - LibFont::Font m_font; + virtual bool has_font() const { return false; } + virtual void set_font(const LibFont::Font&) { ASSERT_NOT_REACHED(); }; + virtual const LibFont::Font& font() const { ASSERT_NOT_REACHED(); }; }; + extern BAN::RefPtr g_terminal_driver; + namespace TerminalColor { static constexpr TerminalDriver::Color BLACK = 0x000000; diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index 37b9f774..d480e9e1 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -12,7 +12,7 @@ namespace Kernel class VirtualTTY : public TTY { public: - static BAN::ErrorOr> create(TerminalDriver*); + static BAN::ErrorOr> create(BAN::RefPtr); virtual void set_font(const LibFont::Font&) override; @@ -26,7 +26,7 @@ namespace Kernel virtual void putchar_impl(uint8_t ch) override; private: - VirtualTTY(TerminalDriver*); + VirtualTTY(BAN::RefPtr); void reset_ansi(); void handle_ansi_csi(uint8_t ch); @@ -84,7 +84,7 @@ namespace Kernel Cell* m_buffer { nullptr }; bool m_show_cursor { true }; - TerminalDriver* m_terminal_driver { nullptr }; + BAN::RefPtr m_terminal_driver; }; } diff --git a/kernel/kernel/Debug.cpp b/kernel/kernel/Debug.cpp index 0d9189eb..1eb0a58c 100644 --- a/kernel/kernel/Debug.cpp +++ b/kernel/kernel/Debug.cpp @@ -9,7 +9,6 @@ #include bool g_disable_debug = false; -extern Kernel::TerminalDriver* g_terminal_driver; namespace Debug { diff --git a/kernel/kernel/Device/FramebufferDevice.cpp b/kernel/kernel/Device/FramebufferDevice.cpp index 32a64076..892235a7 100644 --- a/kernel/kernel/Device/FramebufferDevice.cpp +++ b/kernel/kernel/Device/FramebufferDevice.cpp @@ -3,14 +3,12 @@ #include #include #include -#include +#include #include #include #include -extern Kernel::TerminalDriver* g_terminal_driver; - namespace Kernel { @@ -22,8 +20,7 @@ namespace Kernel BAN::ErrorOr> FramebufferDevice::create_from_boot_framebuffer() { - if (g_boot_info.framebuffer.type != FramebufferInfo::Type::RGB) - return BAN::Error::from_errno(ENODEV); + ASSERT(g_boot_info.framebuffer.type == FramebufferInfo::Type::RGB); if (g_boot_info.framebuffer.bpp != 24 && g_boot_info.framebuffer.bpp != 32) return BAN::Error::from_errno(ENOTSUP); auto* device_ptr = new FramebufferDevice( @@ -39,6 +36,7 @@ namespace Kernel return BAN::Error::from_errno(ENOMEM); auto device = BAN::RefPtr::adopt(device_ptr); TRY(device->initialize()); + DevFileSystem::get().add_device(device); return device; } @@ -315,6 +313,8 @@ namespace Kernel const uint32_t fb_width = m_framebuffer->width(); + // If we are here (in FramebufferMemoryRegion), our terminal driver is FramebufferTerminalDriver + ASSERT(g_terminal_driver->has_font()); const auto& font = g_terminal_driver->font(); const uint32_t x = first_pixel % fb_width; diff --git a/kernel/kernel/Processor.cpp b/kernel/kernel/Processor.cpp index c0a6fdfb..ae6dc1a4 100644 --- a/kernel/kernel/Processor.cpp +++ b/kernel/kernel/Processor.cpp @@ -5,8 +5,6 @@ #include #include -extern Kernel::TerminalDriver* g_terminal_driver; - namespace Kernel { diff --git a/kernel/kernel/Terminal/FramebufferTerminal.cpp b/kernel/kernel/Terminal/FramebufferTerminal.cpp index fe1d4b47..38ed6550 100644 --- a/kernel/kernel/Terminal/FramebufferTerminal.cpp +++ b/kernel/kernel/Terminal/FramebufferTerminal.cpp @@ -3,39 +3,42 @@ namespace Kernel { - FramebufferTerminalDriver* FramebufferTerminalDriver::create(BAN::RefPtr framebuffer_device) + BAN::ErrorOr> FramebufferTerminalDriver::create(BAN::RefPtr framebuffer_device) { + auto font = TRY(LibFont::Font::prefs());; + auto* driver = new FramebufferTerminalDriver(framebuffer_device); if (driver == nullptr) - return nullptr; + return BAN::Error::from_errno(ENOMEM); + driver->m_font = BAN::move(font); driver->set_cursor_position(0, 0); driver->clear(TerminalColor::BLACK); - return driver; + return BAN::RefPtr::adopt(driver); } void FramebufferTerminalDriver::putchar_at(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) { - const uint8_t* glyph = font().has_glyph(ch) ? font().glyph(ch) : font().glyph('?'); + const uint8_t* glyph = m_font.has_glyph(ch) ? m_font.glyph(ch) : m_font.glyph('?'); - x *= font().width(); - y *= font().height(); + x *= m_font.width(); + y *= m_font.height(); - for (uint32_t dy = 0; dy < font().height() && y + dy < m_framebuffer_device->height(); dy++) + for (uint32_t dy = 0; dy < m_font.height() && y + dy < m_framebuffer_device->height(); dy++) { - for (uint32_t dx = 0; dx < font().width() && x + dx < m_framebuffer_device->width(); dx++) + for (uint32_t dx = 0; dx < m_font.width() && x + dx < m_framebuffer_device->width(); dx++) { - const uint8_t bitmask = 1 << (font().width() - dx - 1); - const auto color = glyph[dy * font().pitch()] & bitmask ? fg : bg; + const uint8_t bitmask = 1 << (m_font.width() - dx - 1); + const auto color = glyph[dy * m_font.pitch()] & bitmask ? fg : bg; m_framebuffer_device->set_pixel(x + dx, y + dy, color.rgb); } } - m_framebuffer_device->sync_pixels_rectangle(x, y, font().width(), font().height()); + m_framebuffer_device->sync_pixels_rectangle(x, y, m_font.width(), m_font.height()); } bool FramebufferTerminalDriver::scroll(Color color) { - m_framebuffer_device->scroll(font().height(), color.rgb); + m_framebuffer_device->scroll(m_font.height(), color.rgb); m_framebuffer_device->sync_pixels_full(); return true; } @@ -50,16 +53,16 @@ namespace Kernel void FramebufferTerminalDriver::set_cursor_position(uint32_t x, uint32_t y) { - const uint32_t cursor_h = font().height() / 8; - const uint32_t cursor_top = font().height() * 13 / 16; + const uint32_t cursor_h = m_font.height() / 8; + const uint32_t cursor_top = m_font.height() * 13 / 16; - x *= font().width(); - y *= font().height(); + x *= m_font.width(); + y *= m_font.height(); for (uint32_t dy = 0; dy < cursor_h; dy++) - for (uint32_t dx = 0; dx < font().width(); dx++) + for (uint32_t dx = 0; dx < m_font.width(); dx++) m_framebuffer_device->set_pixel(x + dx, y + cursor_top + dy, s_cursor_color.rgb); - m_framebuffer_device->sync_pixels_rectangle(x, y + cursor_top, font().width(), cursor_h); + m_framebuffer_device->sync_pixels_rectangle(x, y + cursor_top, m_font.width(), cursor_h); } } diff --git a/kernel/kernel/Terminal/TerminalDriver.cpp b/kernel/kernel/Terminal/TerminalDriver.cpp new file mode 100644 index 00000000..799469d7 --- /dev/null +++ b/kernel/kernel/Terminal/TerminalDriver.cpp @@ -0,0 +1,25 @@ +#include +#include + +namespace Kernel +{ + + BAN::RefPtr g_terminal_driver; + + BAN::ErrorOr TerminalDriver::initialize_from_boot_info() + { + switch (g_boot_info.framebuffer.type) + { + case FramebufferInfo::Type::None: + case FramebufferInfo::Type::Unknown: + return BAN::Error::from_errno(ENODEV); + case FramebufferInfo::Type::RGB: + g_terminal_driver = TRY(FramebufferTerminalDriver::create( + TRY(FramebufferDevice::create_from_boot_framebuffer()) + )); + break; + } + return {}; + } + +} diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 42f993ab..fc374c3e 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -25,7 +25,7 @@ namespace Kernel static BAN::Atomic s_next_tty_number = 0; - BAN::ErrorOr> VirtualTTY::create(TerminalDriver* driver) + BAN::ErrorOr> VirtualTTY::create(BAN::RefPtr driver) { auto* tty_ptr = new VirtualTTY(driver); ASSERT(tty_ptr); @@ -35,7 +35,7 @@ namespace Kernel return tty; } - VirtualTTY::VirtualTTY(TerminalDriver* driver) + VirtualTTY::VirtualTTY(BAN::RefPtr driver) : TTY(0600, 0, 0) , m_name(MUST(BAN::String::formatted("tty{}", s_next_tty_number++))) , m_terminal_driver(driver) @@ -59,6 +59,12 @@ namespace Kernel { SpinLockGuard _(m_write_lock); + if (!m_terminal_driver->has_font()) + { + dwarnln("terminal driver does not have a font"); + return; + } + m_terminal_driver->set_font(font); uint32_t new_width = m_terminal_driver->width(); diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index b75a7409..bd37dd9e 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -107,8 +107,6 @@ static void parse_command_line() } } -Kernel::TerminalDriver* g_terminal_driver = nullptr; - static void init2(void*); extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) @@ -163,14 +161,10 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) DevFileSystem::initialize(); dprintln("devfs initialized"); - auto framebuffer_device = FramebufferDevice::create_from_boot_framebuffer(); - if (!framebuffer_device.is_error()) - { - DevFileSystem::get().add_device(framebuffer_device.value()); - g_terminal_driver = FramebufferTerminalDriver::create(framebuffer_device.value()); - } - if (g_terminal_driver) - dprintln("Framebuffer terminal initialized"); + if (auto ret = TerminalDriver::initialize_from_boot_info(); ret.is_error()) + dprintln("failed to initialize terminal driver: {}", ret.error()); + else + dprintln("terminal driver initialized"); if (!cmdline.disable_smp) InterruptController::get().initialize_multiprocessor();