[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
committed by Justin C. Miller
parent e70eb5a926
commit 19cbf1ca67
15 changed files with 170 additions and 71 deletions

View File

@@ -87,6 +87,16 @@ modules:
- src/drivers/nulldrv/main.s - src/drivers/nulldrv/main.s
- src/drivers/nulldrv/serial.cpp - 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: kutil:
kind: lib kind: lib
output: libkutil.a 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 build $builddir/fatroot/nulldrv.elf : cp $builddir/user/nulldrv.elf
name = null driver to FAT image 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 build $builddir/fatroot/terminal.elf : cp $builddir/user/nulldrv.elf
name = terminal driver to FAT image 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 | $ build $builddir/jsix.img : makefat | $
$builddir/fatroot/symbol_table.dat $ $builddir/fatroot/symbol_table.dat $
$builddir/fatroot/nulldrv.elf $ $builddir/fatroot/nulldrv.elf $
$builddir/fatroot/fb.elf $
$builddir/fatroot/terminal.elf $ $builddir/fatroot/terminal.elf $
$builddir/fatroot/jsix.elf $ $builddir/fatroot/jsix.elf $
$builddir/fatroot/efi/boot/bootx64.efi $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) : console::console(uefi::boot_services *bs, uefi::protos::simple_text_output *out) :
m_rows(0), m_rows {0},
m_cols(0), m_cols {0},
m_out(out) m_out {out},
m_fb {0, 0}
{ {
pick_mode(bs); pick_mode(bs);
@@ -93,7 +94,7 @@ console::pick_mode(uefi::boot_services *bs)
(uefi::graphics_output_mode_info *)gfx_out_proto->mode; (uefi::graphics_output_mode_info *)gfx_out_proto->mode;
uint32_t res = info->horizontal_resolution * info->vertical_resolution; 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) { for (uint32_t i = 0; i < modes; ++i) {
size_t size = 0; size_t size = 0;
@@ -107,17 +108,27 @@ console::pick_mode(uefi::boot_services *bs)
#endif #endif
const uint32_t new_res = info->horizontal_resolution * info->vertical_resolution; 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; best = i;
res = new_res; res = new_res;
pixmode = new_pixmode;
} }
} }
try_or_raise( try_or_raise(
gfx_out_proto->set_mode(best), gfx_out_proto->set_mode(best),
L"Failed to set graphics mode"); 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 size_t
@@ -387,61 +398,4 @@ status_line::finish()
print_status_tag(); 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 } // namespace boot

View File

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

View File

@@ -37,6 +37,7 @@ struct program_desc
const program_desc program_list[] = { const program_desc program_list[] = {
{L"kernel", L"jsix.elf"}, {L"kernel", L"jsix.elf"},
{L"null driver", L"nulldrv.elf"}, {L"null driver", L"nulldrv.elf"},
{L"fb driver", L"fb.elf"},
//{L"terminal driver", L"terminal.elf"}, //{L"terminal driver", L"terminal.elf"},
}; };
@@ -127,6 +128,8 @@ bootloader_main_uefi(
memory::module_type); memory::module_type);
add_module(args, args::mod_type::symbol_table, symbols); add_module(args, args::mod_type::symbol_table, symbols);
args->video = con.fb();
for (auto &desc : program_list) { for (auto &desc : program_list) {
buffer buf = loader::load_file(disk, desc.name, desc.path); buffer buf = loader::load_file(disk, desc.name, desc.path);
args::program &program = args->programs[args->num_programs++]; 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; constexpr uint16_t version = 1;
enum class mod_type : uint32_t { enum class mod_type : uint32_t {
symbol_table, symbol_table
framebuffer
}; };
struct module { struct module {
@@ -21,6 +20,20 @@ struct module {
mod_type type; 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 { struct program {
uintptr_t phys_addr; uintptr_t phys_addr;
uintptr_t virt_addr; uintptr_t virt_addr;
@@ -74,6 +87,8 @@ struct header {
void *runtime_services; void *runtime_services;
void *acpi_table; void *acpi_table;
framebuffer video;
} }
__attribute__((aligned(alignof(max_align_t)))); __attribute__((aligned(alignof(max_align_t))));

View File

@@ -17,6 +17,7 @@
#include "log.h" #include "log.h"
#include "objects/channel.h" #include "objects/channel.h"
#include "objects/event.h" #include "objects/event.h"
#include "objects/thread.h"
#include "scheduler.h" #include "scheduler.h"
#include "serial.h" #include "serial.h"
#include "symbol_table.h" #include "symbol_table.h"
@@ -44,6 +45,10 @@ run_constructors()
extern void __kernel_assert(const char *, unsigned, const char *); 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. /// Bootstrap the memory managers.
void memory_initialize_pre_ctors(kernel::args::header *kargs); void memory_initialize_pre_ctors(kernel::args::header *kargs);
void memory_initialize_post_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, " jsix header is at: %016lx", header);
log::debug(logs::boot, " Memory map is at: %016lx", header->mem_map); 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); 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 // Skip program 0, which is the kernel itself
for (size_t i = 1; i < header->num_programs; ++i) { for (size_t i = 1; i < header->num_programs; ++i) {
args::program &prog = header->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); 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, large_pages = 0x00000100,
huge_pages = 0x00000200, huge_pages = 0x00000200,
mmio = 0x00010000,
user_mask = 0x0000ffff ///< flags allowed via syscall user_mask = 0x0000ffff ///< flags allowed via syscall
}; };

View File

@@ -22,6 +22,9 @@
scheduler *scheduler::s_instance = nullptr; 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_noint = 0x002;
const uint64_t rflags_int = 0x202; 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[1] = j6_handle_invalid;
init->handles[2] = 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); thread::current().clear_state(thread::state::loading);
return tcb->rsp3; return tcb->rsp3;
} }
@@ -107,7 +116,7 @@ scheduler::create_process(bool user)
return th; return th;
} }
void thread *
scheduler::load_process(uintptr_t phys, uintptr_t virt, size_t size, uintptr_t entry) 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, " RSP %016lx", tcb->rsp);
log::debug(logs::task, " RSP0 %016lx", tcb->rsp0); log::debug(logs::task, " RSP0 %016lx", tcb->rsp0);
log::debug(logs::task, " PML4 %016lx", tcb->pml4); log::debug(logs::task, " PML4 %016lx", tcb->pml4);
return th;
} }
void void

View File

@@ -45,7 +45,8 @@ public:
/// \arg virt Virtual address of the loaded program image /// \arg virt Virtual address of the loaded program image
/// \arg size Size of the program image, in bytes /// \arg size Size of the program image, in bytes
/// \arg entry Virtual address of the program entrypoint /// \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 /// Create a new kernel task
/// \arg proc Function to run as a 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); 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) : vm_mapper_multi::vm_mapper_multi(vm_area &area) :
@@ -88,11 +96,13 @@ void
vm_mapper_multi::remove(vm_space *space) vm_mapper_multi::remove(vm_space *space)
{ {
size_t count = memory::page_count(m_area.size()); 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) { for (int i = 0; i < m_spaces.count(); ++i) {
if (m_spaces[i] == space) { if (m_spaces[i] == space) {
m_spaces.remove_swap_at(i); 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; } vm_space & space() { return m_space; }
virtual void remove(vm_space *space) override;
private: private:
vm_area &m_area; vm_area &m_area;
vm_space &m_space; 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}; page_table::iterator it {virt, m_pml4};
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
it.entry(page_table::level::pt) = uint64_t &entry = it.entry(page_table::level::pt);
(phys + i * frame_size) | flags; entry = (phys + i * frame_size) | flags;
log::debug(logs::paging, "Setting entry for %016llx: %016llx [%04llx]",
it.vaddress(), (phys + i * frame_size), flags);
++it; ++it;
} }
} }