#include #include #include #include #include #include #include #include #include #include #include "font.h" #include "screen.h" #include "scrollback.h" extern "C" { void _get_init(size_t *initc, struct j6_init_value **initv); } int main(int argc, const char **argv, const char **env) { j6::syslog(j6::logs::srv, j6::log_level::info, "fb driver starting"); using bootproto::devices::uefi_fb; using bootproto::devices::video_mode; using bootproto::devices::fb_layout; const j6_init_args *init = j6_get_init_args(); const uefi_fb *fb = reinterpret_cast(init->argv[0]); if (!fb || !fb->framebuffer) { j6::syslog(j6::logs::srv, j6::log_level::error, "fb driver didn't find a framebuffer, exiting"); return 1; } util::buffer lfb = fb->framebuffer; const video_mode &mode = fb->mode; j6_handle_t fb_handle = j6_handle_invalid; uint32_t flags = j6_vm_flag_write | j6_vm_flag_write_combine | j6_vm_flag_mmio; j6_handle_t sys = j6_find_init_handle(0); if (sys == j6_handle_invalid) return 1; uintptr_t lfb_addr = reinterpret_cast(lfb.pointer); j6_status_t s = j6_system_map_phys( sys, &fb_handle, lfb_addr, lfb.count, flags); if (s != j6_status_ok) { return s; } s = j6_vma_map(fb_handle, 0, &lfb_addr, j6_vm_flag_exact); if (s != j6_status_ok) { return s; } const screen::pixel_order order = (mode.layout == fb_layout::bgr8) ? screen::pixel_order::bgr8 : screen::pixel_order::rgb8; screen scr( reinterpret_cast(lfb.pointer), mode.horizontal, mode.vertical, mode.scanline, order); font fnt; screen::pixel_t fg = scr.color(0xb0, 0xb0, 0xb0); screen::pixel_t bg = scr.color(49, 79, 128); scr.fill(bg); scr.update(); constexpr int margin = 2; const unsigned xstride = (margin + fnt.width()); const unsigned ystride = (margin + fnt.height()); const unsigned rows = (scr.height() - margin) / ystride; const unsigned cols = (scr.width() - margin) / xstride; scrollback scroll(rows, cols); int pending = 0; static constexpr int pending_threshold = 0; size_t buffer_size = 0; void *message_buffer = nullptr; uint64_t seen = 0; while (true) { size_t size = buffer_size; j6_status_t s = j6_system_get_log(sys, seen, message_buffer, &size); if (s == j6_err_insufficient) { free(message_buffer); message_buffer = malloc(size * 2); buffer_size = size; continue; } else if (s != j6_status_ok) { j6::syslog(j6::logs::srv, j6::log_level::error, "fb driver got error from get_log, quitting"); return s; } if (size > 0) { j6_log_entry *e = reinterpret_cast(message_buffer); size_t eom = e->bytes - sizeof(j6_log_entry); e->message[eom] = 0; seen = e->id; scroll.add_line(e->message, eom); if (++pending > pending_threshold) { scroll.render(scr, fnt); scr.update(); pending = 0; } } else { if (pending) { scroll.render(scr, fnt); scr.update(); pending = 0; } } } j6::syslog(j6::logs::srv, j6::log_level::info, "fb driver done, exiting"); return 0; }