[fb] Create fb driver

Create a new framebuffer driver. Also hackily passing frame buffer size
in the list of init handles to all processes and mapping the framebuffer
into all processes. Changed bootloader passing frame buffer as a module
to its own struct.
This commit is contained in:
2020-12-27 18:49:38 -08:00
parent 7bdde2d359
commit 5787aff866
15 changed files with 170 additions and 71 deletions

View File

@@ -87,6 +87,16 @@ modules:
- src/drivers/nulldrv/main.s
- src/drivers/nulldrv/serial.cpp
fb:
kind: exe
target: user
output: fb.elf
deps:
- libc
source:
- src/drivers/fb/main.cpp
- src/drivers/fb/main.s
kutil:
kind: lib
output: libkutil.a

View File

@@ -190,6 +190,9 @@ build $builddir/fatroot/efi/boot/bootx64.efi : cp $builddir/boot/boot.efi
build $builddir/fatroot/nulldrv.elf : cp $builddir/user/nulldrv.elf
name = null driver to FAT image
build $builddir/fatroot/fb.elf : cp $builddir/user/fb.elf
name = fb driver to FAT image
build $builddir/fatroot/terminal.elf : cp $builddir/user/nulldrv.elf
name = terminal driver to FAT image
@@ -198,6 +201,7 @@ build ${builddir}/fatroot/symbol_table.dat : makest ${builddir}/jsix.elf
build $builddir/jsix.img : makefat | $
$builddir/fatroot/symbol_table.dat $
$builddir/fatroot/nulldrv.elf $
$builddir/fatroot/fb.elf $
$builddir/fatroot/terminal.elf $
$builddir/fatroot/jsix.elf $
$builddir/fatroot/efi/boot/bootx64.efi

View File

@@ -49,9 +49,10 @@ wstrlen(const wchar_t *s)
console::console(uefi::boot_services *bs, uefi::protos::simple_text_output *out) :
m_rows(0),
m_cols(0),
m_out(out)
m_rows {0},
m_cols {0},
m_out {out},
m_fb {0, 0}
{
pick_mode(bs);
@@ -93,7 +94,7 @@ console::pick_mode(uefi::boot_services *bs)
(uefi::graphics_output_mode_info *)gfx_out_proto->mode;
uint32_t res = info->horizontal_resolution * info->vertical_resolution;
int is_fb = info->pixel_format != uefi::pixel_format::blt_only;
int pixmode = static_cast<int>(info->pixel_format);
for (uint32_t i = 0; i < modes; ++i) {
size_t size = 0;
@@ -107,17 +108,27 @@ console::pick_mode(uefi::boot_services *bs)
#endif
const uint32_t new_res = info->horizontal_resolution * info->vertical_resolution;
const int new_is_fb = info->pixel_format != uefi::pixel_format::blt_only;
int new_pixmode = static_cast<int>(info->pixel_format);
if (new_is_fb > is_fb && new_res >= res) {
if (new_pixmode <= pixmode && new_res >= res) {
best = i;
res = new_res;
pixmode = new_pixmode;
}
}
try_or_raise(
gfx_out_proto->set_mode(best),
L"Failed to set graphics mode");
if (pixmode <= static_cast<int>(uefi::pixel_format::bgr8)) {
m_fb.phys_addr = gfx_out_proto->mode->frame_buffer_base;
m_fb.size = gfx_out_proto->mode->frame_buffer_size;
m_fb.vertical = gfx_out_proto->mode->info->vertical_resolution;
m_fb.horizontal = gfx_out_proto->mode->info->horizontal_resolution;
m_fb.scanline = gfx_out_proto->mode->info->pixels_per_scanline;
m_fb.type = static_cast<kernel::args::fb_type>(pixmode);
}
}
size_t
@@ -387,61 +398,4 @@ status_line::finish()
print_status_tag();
}
/*
uefi::status
con_get_framebuffer(
EFI_BOOT_SERVICES *bootsvc,
void **buffer,
size_t *buffer_size,
uint32_t *hres,
uint32_t *vres,
uint32_t *rmask,
uint32_t *gmask,
uint32_t *bmask)
{
uefi::status status;
uefi::protos::graphics_output *gop;
status = bootsvc->LocateProtocol(&guid_gfx_out, NULL, (void **)&gop);
if (status != EFI_NOT_FOUND) {
CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx");
*buffer = (void *)gop->Mode->FrameBufferBase;
*buffer_size = gop->Mode->FrameBufferSize;
*hres = gop->Mode->Info->horizontal_resolution;
*vres = gop->Mode->Info->vertical_resolution;
switch (gop->Mode->Info->PixelFormat) {
case PixelRedGreenBlueReserved8BitPerColor:
*rmask = 0x0000ff;
*gmask = 0x00ff00;
*bmask = 0xff0000;
return EFI_SUCCESS;
case PixelBlueGreenRedReserved8BitPerColor:
*bmask = 0x0000ff;
*gmask = 0x00ff00;
*rmask = 0xff0000;
return EFI_SUCCESS;
case PixelBitMask:
*rmask = gop->Mode->Info->PixelInformation.RedMask;
*gmask = gop->Mode->Info->PixelInformation.GreenMask;
*bmask = gop->Mode->Info->PixelInformation.BlueMask;
return EFI_SUCCESS;
default:
// Not a framebuffer, fall through to zeroing out
// values below.
break;
}
}
*buffer = NULL;
*buffer_size = *hres = *vres = 0;
*rmask = *gmask = *bmask = 0;
return EFI_SUCCESS;
}
*/
} // namespace boot

View File

@@ -5,6 +5,8 @@
#include <stddef.h>
#include <uefi/boot_services.h>
#include <uefi/protos/simple_text_output.h>
#include "kernel_args.h"
#include "types.h"
namespace boot {
@@ -12,6 +14,8 @@ namespace boot {
class console
{
public:
using framebuffer = kernel::args::framebuffer;
console(uefi::boot_services *bs, uefi::protos::simple_text_output *out);
size_t print_hex(uint32_t n) const;
@@ -20,6 +24,8 @@ public:
size_t print_long_dec(uint64_t n) const;
size_t printf(const wchar_t *fmt, ...) const;
const framebuffer & fb() const { return m_fb; };
static console & get() { return *s_console; }
static size_t print(const wchar_t *fmt, ...);
@@ -31,6 +37,7 @@ private:
size_t m_rows, m_cols;
uefi::protos::simple_text_output *m_out;
framebuffer m_fb;
static console *s_console;
};

View File

@@ -37,6 +37,7 @@ struct program_desc
const program_desc program_list[] = {
{L"kernel", L"jsix.elf"},
{L"null driver", L"nulldrv.elf"},
{L"fb driver", L"fb.elf"},
//{L"terminal driver", L"terminal.elf"},
};
@@ -127,6 +128,8 @@ bootloader_main_uefi(
memory::module_type);
add_module(args, args::mod_type::symbol_table, symbols);
args->video = con.fb();
for (auto &desc : program_list) {
buffer buf = loader::load_file(disk, desc.name, desc.path);
args::program &program = args->programs[args->num_programs++];

41
src/drivers/fb/main.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include <stdint.h>
#include <stdlib.h>
#include "j6/types.h"
#include "j6/errors.h"
#include "j6/signals.h"
#include <j6libc/syscalls.h>
extern "C" {
void _init_libc(j6_process_init *);
int main(int, const char **);
}
j6_handle_t sys = j6_handle_invalid;
size_t size = 0;
void
_init_libc(j6_process_init *init)
{
sys = init->handles[0];
size = reinterpret_cast<size_t>(init->handles[1]);
}
int
main(int argc, const char **argv)
{
_syscall_system_log("fb driver starting");
if (size == 0)
return 1;
uint32_t *fb = reinterpret_cast<uint32_t*>(0x100000000);
for (size_t i=0; i < size/4; ++i) {
fb[i] = 0xff;
}
_syscall_system_log("fb driver done, exiting");
return 0;
}

24
src/drivers/fb/main.s Normal file
View File

@@ -0,0 +1,24 @@
section .bss
mymessage:
resq 1024
extern main
extern _init_libc
extern exit
section .text
global _start
_start:
mov rbp, rsp
mov rdi, rsp
call _init_libc
mov rdi, 0
mov rsi, 0
call main
mov rdi, rax
call exit

View File

@@ -11,8 +11,7 @@ constexpr uint32_t magic = 0x600dda7a;
constexpr uint16_t version = 1;
enum class mod_type : uint32_t {
symbol_table,
framebuffer
symbol_table
};
struct module {
@@ -21,6 +20,20 @@ struct module {
mod_type type;
};
enum class fb_type : uint16_t {
rgb8,
bgr8
};
struct framebuffer {
uintptr_t phys_addr;
size_t size;
uint32_t vertical;
uint32_t horizontal;
uint16_t scanline;
fb_type type;
};
struct program {
uintptr_t phys_addr;
uintptr_t virt_addr;
@@ -74,6 +87,8 @@ struct header {
void *runtime_services;
void *acpi_table;
framebuffer video;
}
__attribute__((aligned(alignof(max_align_t))));

View File

@@ -17,6 +17,7 @@
#include "log.h"
#include "objects/channel.h"
#include "objects/event.h"
#include "objects/thread.h"
#include "scheduler.h"
#include "serial.h"
#include "symbol_table.h"
@@ -44,6 +45,10 @@ run_constructors()
extern void __kernel_assert(const char *, unsigned, const char *);
/// TODO: not this. this is awful.
uintptr_t fb_loc = 0;
size_t fb_size = 0;
/// Bootstrap the memory managers.
void memory_initialize_pre_ctors(kernel::args::header *kargs);
void memory_initialize_post_ctors(kernel::args::header *kargs);
@@ -131,6 +136,11 @@ kernel_main(args::header *header)
}
}
if (header->video.size > 0) {
fb_size = header->video.size;
fb_loc = header->video.phys_addr;
}
log::debug(logs::boot, " jsix header is at: %016lx", header);
log::debug(logs::boot, " Memory map is at: %016lx", header->mem_map);
log::debug(logs::boot, "ACPI root table is at: %016lx", header->acpi_table);
@@ -176,7 +186,10 @@ kernel_main(args::header *header)
// Skip program 0, which is the kernel itself
for (size_t i = 1; i < header->num_programs; ++i) {
args::program &prog = header->programs[i];
sched->load_process(prog.phys_addr, prog.virt_addr, prog.size, prog.entrypoint);
thread *th = sched->load_process(prog.phys_addr, prog.virt_addr, prog.size, prog.entrypoint);
if (i == 2) {
th->set_state(thread::state::constant);
}
}
sched->create_kernel_task(logger_task, scheduler::max_priority-1, true);

View File

@@ -28,6 +28,8 @@ enum class vm_flags : uint32_t
large_pages = 0x00000100,
huge_pages = 0x00000200,
mmio = 0x00010000,
user_mask = 0x0000ffff ///< flags allowed via syscall
};

View File

@@ -22,6 +22,9 @@
scheduler *scheduler::s_instance = nullptr;
extern uintptr_t fb_loc;
extern size_t fb_size;
const uint64_t rflags_noint = 0x002;
const uint64_t rflags_int = 0x202;
@@ -87,6 +90,12 @@ load_process_image(uintptr_t phys, uintptr_t virt, size_t bytes, TCB *tcb)
init->handles[1] = j6_handle_invalid;
init->handles[2] = j6_handle_invalid;
// Crazypants framebuffer part
init->handles[1] = reinterpret_cast<j6_handle_t>(fb_size);
vma = new vm_area_open(fb_size, space, vm_flags::write|vm_flags::mmio);
space.add(0x100000000, vma);
vma->commit(fb_loc, 0, memory::page_count(fb_size));
thread::current().clear_state(thread::state::loading);
return tcb->rsp3;
}
@@ -107,7 +116,7 @@ scheduler::create_process(bool user)
return th;
}
void
thread *
scheduler::load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t entry)
{
@@ -145,6 +154,8 @@ scheduler::load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t e
log::debug(logs::task, " RSP %016lx", tcb->rsp);
log::debug(logs::task, " RSP0 %016lx", tcb->rsp0);
log::debug(logs::task, " PML4 %016lx", tcb->pml4);
return th;
}
void

View File

@@ -45,7 +45,8 @@ public:
/// \arg virt Virtual address of the loaded program image
/// \arg size Size of the program image, in bytes
/// \arg entry Virtual address of the program entrypoint
void load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t entry);
/// \returns The main thread of the loaded process
thread * load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t entry);
/// Create a new kernel task
/// \arg proc Function to run as a kernel task

View File

@@ -30,6 +30,14 @@ vm_mapper_single::unmap(uintptr_t offset, size_t count)
m_space.clear(m_area, offset, count, true);
}
void
vm_mapper_single::remove(vm_space *space)
{
size_t count = memory::page_count(m_area.size());
bool keep = m_area.flags() && vm_flags::mmio;
m_space.clear(m_area, 0, count, !keep);
}
vm_mapper_multi::vm_mapper_multi(vm_area &area) :
@@ -88,11 +96,13 @@ void
vm_mapper_multi::remove(vm_space *space)
{
size_t count = memory::page_count(m_area.size());
bool keep = m_area.flags() && vm_flags::mmio;
for (int i = 0; i < m_spaces.count(); ++i) {
if (m_spaces[i] == space) {
m_spaces.remove_swap_at(i);
space->clear(m_area, 0, count, m_spaces.count() == 0);
keep &= m_spaces.count() > 0;
space->clear(m_area, 0, count, !keep);
}
}
}

View File

@@ -54,6 +54,8 @@ public:
vm_space & space() { return m_space; }
virtual void remove(vm_space *space) override;
private:
vm_area &m_area;
vm_space &m_space;

View File

@@ -175,8 +175,10 @@ vm_space::page_in(const vm_area &vma, uintptr_t offset, uintptr_t phys, size_t c
page_table::iterator it {virt, m_pml4};
for (size_t i = 0; i < count; ++i) {
it.entry(page_table::level::pt) =
(phys + i * frame_size) | flags;
uint64_t &entry = it.entry(page_table::level::pt);
entry = (phys + i * frame_size) | flags;
log::debug(logs::paging, "Setting entry for %016llx: %016llx [%04llx]",
it.vaddress(), (phys + i * frame_size), flags);
++it;
}
}