diff options
| author | Arseney300 <Arseney300@gmail.com> | 2026-04-23 17:02:05 +0700 |
|---|---|---|
| committer | Arseney300 <Arseney300@gmail.com> | 2026-04-23 17:02:05 +0700 |
| commit | e935c3afba9b3a492ad804726fa0fd97d437d8f5 (patch) | |
| tree | c8c26fe36ed4db1ffec4dab5f5bf3b489c064a07 /kernel/drivers/console/framebuffer.cpp | |
| parent | 496246c92dabe6757480147016490ea6ae43bb66 (diff) | |
WIP: add driver objectsWIP/add_driver_obj
Diffstat (limited to 'kernel/drivers/console/framebuffer.cpp')
| -rw-r--r-- | kernel/drivers/console/framebuffer.cpp | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/kernel/drivers/console/framebuffer.cpp b/kernel/drivers/console/framebuffer.cpp new file mode 100644 index 0000000..e7f0577 --- /dev/null +++ b/kernel/drivers/console/framebuffer.cpp @@ -0,0 +1,328 @@ +// ============================================================================ +// drivers/console/framebuffer.cpp — Framebuffer console driver + device +// +// FramebufferDevice describes the GOP framebuffer hardware (base address, +// resolution, pixel format). FramebufferConsole is the driver that renders +// text to it using a built-in 8x16 VGA bitmap font. +// +// Both are early-allocated (static storage, no heap). +// ============================================================================ + +#include <kernel/console_driver.h> +#include <kernel/early_driver.h> +#include <kernel/early_device.h> +#include <kernel/platform_bus.h> +#include <boot/boot_info.h> + +// ── Minimal 8x16 bitmap font (ASCII 32-126) ────────────────────────────── + +static constexpr int FONT_FIRST = 32; +static constexpr int FONT_LAST = 126; + +// clang-format off +static const uint8_t g_font[][16] = { + // 32: space + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 33: ! + {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 34: " + {0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 35: # + {0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, + // 36: $ + {0x00,0x10,0x10,0x7C,0xD6,0xD0,0x7C,0x16,0xD6,0x7C,0x10,0x10,0x00,0x00,0x00,0x00}, + // 37: % + {0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00}, + // 38: & + {0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + // 39: ' + {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 40: ( + {0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00}, + // 41: ) + {0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00}, + // 42: * + {0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00}, + // 43: + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, + // 44: , + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00}, + // 45: - + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 46: . + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 47: / + {0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00}, + // 48-57: 0-9 + {0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xDE,0xF6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00}, + // 58: : + {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, + // 59: ; + {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00}, + // 60: < + {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, + // 61: = + {0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 62: > + {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, + // 63: ? + {0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 64: @ + {0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0xC0,0x7C,0x00,0x00,0x00,0x00}, + // 65-90: A-Z + {0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00}, + // 91: [ + {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, + // 92: backslash + {0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00,0x00,0x00}, + // 93: ] + {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, + // 94: ^ + {0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 95: _ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, + // 96: ` + {0x00,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 97-122: a-z + {0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00}, + // 123: { + {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, + // 124: | + {0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, + // 125: } + {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, + // 126: ~ + {0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +}; +// clang-format on + +// ── FramebufferDevice ───────────────────────────────────────────────────── + +class FramebufferDevice : public Device, public EarlyDevice<FramebufferDevice> { +public: + explicit FramebufferDevice(const FramebufferInfo& fb) + : base_(fb.base), width_(fb.width), height_(fb.height) + , pitch_(fb.pitch), format_(fb.format) + {} + + const char* name() const override { return "framebuffer0"; } + + uint64_t base() const { return base_; } + uint32_t width() const { return width_; } + uint32_t height() const { return height_; } + uint32_t pitch() const { return pitch_; } + PixelFormat format() const { return format_; } + +private: + uint64_t base_; + uint32_t width_; + uint32_t height_; + uint32_t pitch_; + PixelFormat format_; +}; + +// ── FramebufferConsole driver ───────────────────────────────────────────── + +class FramebufferConsole : public ConsoleDriver, + public EarlyDriver<FramebufferConsole> { +public: + FramebufferConsole() = default; + + const char* name() const override { return "framebuffer-console"; } + + bool init() override { + auto* dev = static_cast<FramebufferDevice*>(device()); + fb_ = reinterpret_cast<uint32_t*>(dev->base()); + width_ = dev->width(); + height_ = dev->height(); + pitch_ = dev->pitch(); + is_bgr_ = (dev->format() == PixelFormat::BGR); + clear(); + return true; + } + + void shutdown() override {} + + void putchar(char c) override { + uint32_t max_cols = width_ / CHAR_W; + uint32_t max_rows = height_ / CHAR_H; + + if (c == '\n') { + col_ = 0; + row_++; + } else if (c == '\r') { + col_ = 0; + } else if (c == '\t') { + col_ = (col_ + 4) & ~3u; + } else { + render_char(col_, row_, c); + col_++; + } + + if (col_ >= max_cols) { + col_ = 0; + row_++; + } + + if (row_ >= max_rows) { + scroll(); + row_ = max_rows - 1; + } + } + + void clear() override { + for (uint32_t y = 0; y < height_; y++) { + for (uint32_t x = 0; x < width_; x++) { + put_pixel(x, y, BG_COLOR); + } + } + col_ = 0; + row_ = 0; + } + +private: + uint32_t* fb_ = nullptr; + uint32_t width_ = 0; + uint32_t height_ = 0; + uint32_t pitch_ = 0; + bool is_bgr_ = false; + uint32_t col_ = 0; + uint32_t row_ = 0; + + static constexpr uint32_t CHAR_W = 8; + static constexpr uint32_t CHAR_H = 16; + static constexpr uint32_t FG_COLOR = CONFIG_FBCON_FG_COLOR; + static constexpr uint32_t BG_COLOR = CONFIG_FBCON_BG_COLOR; + + void put_pixel(uint32_t x, uint32_t y, uint32_t rgb) { + if (x >= width_ || y >= height_) return; + + uint32_t color; + if (is_bgr_) { + color = ((rgb & 0xFF) << 16) | (rgb & 0xFF00) | ((rgb >> 16) & 0xFF); + } else { + color = rgb; + } + + auto* row = reinterpret_cast<uint32_t*>( + reinterpret_cast<uint8_t*>(fb_) + y * pitch_); + row[x] = color; + } + + void scroll() { + uint32_t row_bytes = pitch_; + uint32_t shift = CHAR_H * row_bytes; + uint32_t total = height_ * row_bytes; + + auto* fb = reinterpret_cast<uint8_t*>(fb_); + + for (uint32_t i = 0; i < total - shift; i++) { + fb[i] = fb[i + shift]; + } + for (uint32_t i = total - shift; i < total; i++) { + fb[i] = 0; + } + uint32_t start_y = height_ - CHAR_H; + for (uint32_t y = start_y; y < height_; y++) { + for (uint32_t x = 0; x < width_; x++) { + put_pixel(x, y, BG_COLOR); + } + } + } + + void render_char(uint32_t col, uint32_t row, char c) { + int idx = static_cast<int>(c) - FONT_FIRST; + if (idx < 0 || idx > (FONT_LAST - FONT_FIRST)) idx = 0; + + uint32_t px = col * CHAR_W; + uint32_t py = row * CHAR_H; + + for (uint32_t y = 0; y < CHAR_H; y++) { + uint8_t bits = g_font[idx][y]; + for (uint32_t x = 0; x < CHAR_W; x++) { + uint32_t color = (bits & (0x80 >> x)) ? FG_COLOR : BG_COLOR; + put_pixel(px + x, py + y, color); + } + } + } +}; + +// ── Driver init function ────────────────────────────────────────────────── + +namespace console { + +void init_framebuffer(const FramebufferInfo& fb) { + // Create device on the platform bus + auto* dev = FramebufferDevice::create(fb); + platform::bus().add_device(dev); + + // Create driver and bind to device + auto* drv = FramebufferConsole::create(); + drv->bind(dev); + drv->init(); + + // Register as active console + console::register_driver(drv); + console::set_active(drv); +} + +} // namespace console |
