From f7e5b5ba6760f9efd1fbf1af9b5bab9648ac405f Mon Sep 17 00:00:00 2001 From: Matheus Date: Sat, 20 Aug 2022 14:16:26 -0300 Subject: [PATCH] proper limine terminal interface --- src/arch/x86_64/main.c | 17 ++--- src/include/kernel/liminetty.h | 16 ++++ src/include/kernel/vmm.h | 1 + src/video/liminetty.c | 130 +++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 src/include/kernel/liminetty.h create mode 100644 src/video/liminetty.c diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index 85dba4c8..4068fd5c 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -18,6 +18,8 @@ #include #include +/* + static volatile struct limine_terminal_request liminettyr = { .id = LIMINE_TERMINAL_REQUEST, .revision = 0 @@ -43,15 +45,12 @@ void liminewrite(char* str, size_t c){ } -void kmain(){ - if(!liminettyr.response) - return; +*/ + +void kmain(){ + + liminetty_init(); - liminetty = liminettyr.response; - liminetty->write += 0xFFFF800000000000; - - console_setwritehook(liminewrite); - bsp_setcls(); gdt_init(); @@ -65,7 +64,7 @@ void kmain(){ vmm_init(); - liminettyctx = arch_getcls()->context; + liminetty_setcontext(arch_getcls()->context); alloc_init(); diff --git a/src/include/kernel/liminetty.h b/src/include/kernel/liminetty.h new file mode 100644 index 00000000..c97d2fc5 --- /dev/null +++ b/src/include/kernel/liminetty.h @@ -0,0 +1,16 @@ +#ifndef _LIMINETTY_H_INCLUDE +#define _LIMINETTY_H_INCLUDE + +#include +#include + +void liminetty_write(int tty, const char* str, size_t len); +struct limine_framebuffer* liminetty_getfb(int tty); +void liminetty_setcallback(int tty, limine_terminal_callback callback); +struct limine_terminal* liminetty_get(int tty); +size_t liminetty_ttycount(); +void liminetty_setcontext(vmm_context* ctx); +void liminetty_writeuser(const char* str, size_t len); +void liminetty_writekernel(const char* str, size_t len); + +#endif diff --git a/src/include/kernel/vmm.h b/src/include/kernel/vmm.h index b2b9c3bb..604ac7a2 100644 --- a/src/include/kernel/vmm.h +++ b/src/include/kernel/vmm.h @@ -64,4 +64,5 @@ bool vmm_setfree(void* addr, size_t pagec); bool vmm_allocnowat(void* addr, size_t mmuflags, size_t size); void* vmm_allocfrom(void* addr, size_t mmuflags, size_t size); vmm_context* vmm_newcontext(); +void vmm_switchcontext(vmm_context*); #endif diff --git a/src/video/liminetty.c b/src/video/liminetty.c new file mode 100644 index 00000000..08c44452 --- /dev/null +++ b/src/video/liminetty.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include + +static struct limine_terminal** ttys; +static size_t ttycount; +static int usertty; // accessed by /dev/console +static int kerneltty; // libc and kernel logs +static limine_terminal_write writetty; +static bool shared = false; +static int lock; // for shared access between user and kernel +static vmm_context* liminectx = NULL; +static limine_terminal_callback* callbacks = NULL; + + +static void callbackhandler(struct limine_terminal *terminal, uint64_t type, uint64_t arg1, uint64_t arg2, uint64_t arg3){ + uintmax_t tty = 0; + for(;tty < ttycount; ++tty){ + if(ttys[tty] == terminal) + break; + } + + if(callbacks == NULL || tty == ttycount || callbacks[tty] == NULL); + return; + + callbacks[tty](terminal, type, arg1, arg2, arg3); + +} + +static volatile struct limine_terminal_request req = { + .id = LIMINE_TERMINAL_REQUEST, + .revision = 0, + .callback = callbackhandler +}; + +void liminetty_setcontext(vmm_context* ctx){ + liminectx = ctx; +} + +void liminetty_setcallback(int tty, limine_terminal_callback callback){ + if(!callbacks){ // allocate space for the callbacks + callbacks = alloc(sizeof(limine_terminal_callback)*ttycount); + if(!callbacks) + _panic("Failed to allocate callbacks", 0); + } + + if(tty >= ttycount) + return; + + callbacks[tty] = callback; + +} + +struct limine_terminal* liminetty_get(int tty){ + if(tty >= ttycount) + return NULL; + + return ttys[tty]; + +} + +size_t liminetty_ttycount(){ + return ttycount; +} + +void liminetty_write(int tty, const char* str, size_t len){ + if(tty >= ttycount) return; + vmm_context* old = arch_getcls()->context; + + if(liminectx) + vmm_switchcontext(liminectx); + + writetty(ttys[usertty], str, len); + + if(liminectx) + vmm_switchcontext(old); + +} + +struct limine_framebuffer* liminetty_getfb(int tty){ + if(tty >= ttycount) return NULL; + + return ttys[tty]->framebuffer; + +} + +void liminetty_writeuser(const char* str, size_t len){ + + if(shared) + spinlock_acquire(&lock); + + liminetty_write(usertty, str, len); + + if(shared) + spinlock_release(&lock); + +} + +void liminetty_writekernel(const char* str, size_t len){ + if(shared) + spinlock_acquire(&lock); + + liminetty_write(kerneltty, str, len); + + if(shared) + spinlock_release(&lock); +} + + +void liminetty_init(){ + if(!req.response) + for(;;); // not a lot that can be done I guess + + struct limine_terminal_response* r = req.response; + + ttys = r->terminals; + + ttycount = r->terminal_count; + + usertty = 0; + shared = ttycount == 1; + kerneltty = shared ? 0 : 1; + writetty = r->write; + + console_setwritehook(liminetty_writekernel); + +}