Files
jsix_import/src/user/drv.uefi_fb/main.cpp
Justin C. Miller fc16ed54b3 [kernel] Change VMA syscall addr param to inout
This change allows the `vma_map` and `vma_create_map` syscalls to map to
addresses other than the one specified, and therefore makes the address
parameter to those syscalls `inout` in order to return the mapped
address.

Also add the `exact` flag for specifying that mapping needs to be done
at the exact address given. If the mapping collides with another, the
new `j6_err_collision` error is returned.
2023-08-31 19:40:02 -07:00

136 lines
3.5 KiB
C++

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <bootproto/devices/framebuffer.h>
#include <j6/init.h>
#include <j6/errors.h>
#include <j6/flags.h>
#include <j6/syscalls.h>
#include <j6/syslog.hh>
#include <j6/types.h>
#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("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<const uefi_fb*>(init->args[0]);
if (!fb || !fb->framebuffer) {
j6::syslog("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_first_handle(j6_object_type_system);
if (sys == j6_handle_invalid)
return 1;
uintptr_t lfb_addr = reinterpret_cast<uintptr_t>(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<void*>(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("fb driver got error from get_log, quitting");
return s;
}
if (size > 0) {
j6_log_entry *e = reinterpret_cast<j6_log_entry*>(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("fb driver done, exiting");
return 0;
}