diff --git a/include/crescent/dev.h b/include/crescent/dev.h new file mode 100644 index 0000000..4c44fea --- /dev/null +++ b/include/crescent/dev.h @@ -0,0 +1,18 @@ +#ifndef CRESCENT_DEV_H +#define CRESCENT_DEV_H + +typedef enum { + DEVICE_TYPE_SOUND, + DEVICE_TYPE_FB, + DEVICE_TYPE_STORAGE, + DEVICE_TYPE_MAX +} DeviceType; + +#define DEVMSG_INFO 0 + +#define DEVMSG_SND_MAP 1 + +#define DEVMSG_FB_INFO 1 +#define DEVMSG_FB_MAP 2 + +#endif \ No newline at end of file diff --git a/include/crescent/fb.h b/include/crescent/fb.h index d0f55fb..440f6d8 100644 --- a/include/crescent/fb.h +++ b/include/crescent/fb.h @@ -6,14 +6,12 @@ typedef enum { SYS_FB_FORMAT_BGRA32 } SysFramebufferFormat; -typedef struct SysFramebuffer { - void* base; +typedef struct SysFramebufferInfo { size_t width; size_t height; size_t pitch; size_t bpp; SysFramebufferFormat fmt; - bool primary; -} SysFramebuffer; +} SysFramebufferInfo; #endif diff --git a/include/crescent/sys.h b/include/crescent/sys.h index 8e4e439..bb056b7 100644 --- a/include/crescent/sys.h +++ b/include/crescent/sys.h @@ -19,7 +19,8 @@ typedef enum { #define SYS_MMAP 10 #define SYS_MUNMAP 11 #define SYS_CLOSE 12 -#define SYS_ENUMERATE_FRAMEBUFFERS 13 +#define SYS_DEVMSG 13 +#define SYS_DEVENUM 14 #define ERR_INVALID_ARG (-1) #define ERR_NO_PERMISSIONS (-2) diff --git a/src/arch/x86/con.c b/src/arch/x86/con.c index 0da4c62..0405cd8 100644 --- a/src/arch/x86/con.c +++ b/src/arch/x86/con.c @@ -4,28 +4,28 @@ #include "arch/mod.h" #include "mem/allocator.h" #include "assert.h" +#include "string.h" static volatile struct limine_framebuffer_request FB_REQUEST = { .id = LIMINE_FRAMEBUFFER_REQUEST }; -static SysFramebuffer x86_boot_fb; +static FbDev x86_boot_fb; void x86_init_con() { if (FB_REQUEST.response && FB_REQUEST.response->framebuffer_count) { struct limine_framebuffer* limine_fb = FB_REQUEST.response->framebuffers[0]; + memcpy(x86_boot_fb.generic.name, "fb#0", sizeof("fb#0")); x86_boot_fb.base = limine_fb->address; - x86_boot_fb.width = limine_fb->width; - x86_boot_fb.height = limine_fb->height; - x86_boot_fb.pitch = limine_fb->pitch; - x86_boot_fb.bpp = limine_fb->bpp; - x86_boot_fb.fmt = SYS_FB_FORMAT_BGRA32; - x86_boot_fb.primary = true; - primary_fb = &x86_boot_fb; + x86_boot_fb.info.width = limine_fb->width; + x86_boot_fb.info.height = limine_fb->height; + x86_boot_fb.info.pitch = limine_fb->pitch; + x86_boot_fb.info.bpp = limine_fb->bpp; + x86_boot_fb.info.fmt = SYS_FB_FORMAT_BGRA32; Module font_module = arch_get_module("Tamsyn8x16r.psf"); if (font_module.base) { - fbcon_init(primary_fb, font_module.base); + fbcon_init(&x86_boot_fb, font_module.base); } } } @@ -34,18 +34,28 @@ void x86_init_fbs() { if (FB_REQUEST.response) { for (usize i = 0; i < FB_REQUEST.response->framebuffer_count; ++i) { struct limine_framebuffer* limine_fb = FB_REQUEST.response->framebuffers[i]; - LinkedSysFramebuffer* fb = kmalloc(sizeof(LinkedSysFramebuffer)); + FbDev* fb = kcalloc(sizeof(FbDev)); assert(fb); - fb->next = NULL; - fb->fb.base = limine_fb->address; - fb->fb.width = limine_fb->width; - fb->fb.height = limine_fb->height; - fb->fb.pitch = limine_fb->pitch; - fb->fb.bpp = limine_fb->bpp; - fb->fb.fmt = SYS_FB_FORMAT_BGRA32; - fb->fb.primary = i == 0; - sys_fb_add(fb); + memcpy(fb->generic.name, "fb#", 3); + // todo maybe snprintf + usize num = i; + char buf[21]; + buf[20] = 0; + char* ptr = buf + 20; + do { + *--ptr = (char) ('0' + num % 10); + num /= 10; + } while (num); + memcpy(fb->generic.name + 3, ptr, buf + 21 - ptr); + + fb->base = limine_fb->address; + fb->info.width = limine_fb->width; + fb->info.height = limine_fb->height; + fb->info.pitch = limine_fb->pitch; + fb->info.bpp = limine_fb->bpp; + fb->info.fmt = SYS_FB_FORMAT_BGRA32; + dev_add(&fb->generic, DEVICE_TYPE_FB); } } } diff --git a/src/dev/fb.c b/src/dev/fb.c index 9366094..2da5439 100644 --- a/src/dev/fb.c +++ b/src/dev/fb.c @@ -3,64 +3,32 @@ #include "sched/mutex.h" #include "string.h" -void fb_set_pixel(SysFramebuffer* self, usize x, usize y, u32 color) { +void fb_set_pixel(FbDev* self, usize x, usize y, u32 color) { assert(self); assert(self->base); - assert(x < self->width); - assert(y < self->height); - if (self->fmt == SYS_FB_FORMAT_BGRA32) { - *offset(self->base, u32*, y * self->pitch + x * (self->bpp / 8)) = color; + assert(x < self->info.width); + assert(y < self->info.height); + if (self->info.fmt == SYS_FB_FORMAT_BGRA32) { + *offset(self->base, u32*, y * self->info.pitch + x * (self->info.bpp / 8)) = color; } else { return; } } -u32 fb_get_pixel(SysFramebuffer* self, usize x, usize y) { - if (self->fmt == SYS_FB_FORMAT_BGRA32) { - return *offset(self->base, u32*, y * self->pitch + x * (self->bpp / 8)); +u32 fb_get_pixel(FbDev* self, usize x, usize y) { + if (self->info.fmt == SYS_FB_FORMAT_BGRA32) { + return *offset(self->base, u32*, y * self->info.pitch + x * (self->info.bpp / 8)); } else { return 0; } } -void fb_clear(SysFramebuffer* self, u32 color) { - for (usize y = 0; y < self->height; ++y) { - for (usize x = 0; x < self->width; ++x) { +void fb_clear(FbDev* self, u32 color) { + for (usize y = 0; y < self->info.height; ++y) { + for (usize x = 0; x < self->info.width; ++x) { fb_set_pixel(self, x, y, color); } } } - -static Mutex SYS_FB_LOCK = {}; -static LinkedSysFramebuffer* SYS_FBS = NULL; -static usize SYS_FB_COUNT = 0; - -void sys_fb_add(LinkedSysFramebuffer* fb) { - mutex_lock(&SYS_FB_LOCK); - fb->next = SYS_FBS; - SYS_FBS = fb; - SYS_FB_COUNT += 1; - mutex_unlock(&SYS_FB_LOCK); -} - -void sys_fb_get(SysFramebuffer* res, usize* count) { - mutex_lock(&SYS_FB_LOCK); - - if (count) { - *count = SYS_FB_COUNT; - } - if (res) { - usize i = 0; - for (LinkedSysFramebuffer* fb = SYS_FBS; fb; fb = fb->next) { - memcpy(res + i, &fb->fb, sizeof(SysFramebuffer)); - i += 1; - } - } - - mutex_unlock(&SYS_FB_LOCK); -} - -SysFramebuffer* primary_fb = NULL; - diff --git a/src/dev/fb.h b/src/dev/fb.h index ee17d7d..ffb0309 100644 --- a/src/dev/fb.h +++ b/src/dev/fb.h @@ -1,17 +1,14 @@ #pragma once #include "types.h" #include "crescent/fb.h" +#include "sys/dev.h" -void fb_set_pixel(SysFramebuffer* self, usize x, usize y, u32 color); -u32 fb_get_pixel(SysFramebuffer* self, usize x, usize y); -void fb_clear(SysFramebuffer* self, u32 color); +typedef struct FbDev { + GenericDevice generic; + void* base; + SysFramebufferInfo info; +} FbDev; -typedef struct LinkedSysFramebuffer { - struct LinkedSysFramebuffer* next; - SysFramebuffer fb; -} LinkedSysFramebuffer; - -void sys_fb_add(LinkedSysFramebuffer* fb); -void sys_fb_get(SysFramebuffer* res, usize* count); - -extern SysFramebuffer* primary_fb; +void fb_set_pixel(FbDev* self, usize x, usize y, u32 color); +u32 fb_get_pixel(FbDev* self, usize x, usize y); +void fb_clear(FbDev* self, u32 color); diff --git a/src/dev/fbcon.c b/src/dev/fbcon.c index 752d708..87652e4 100644 --- a/src/dev/fbcon.c +++ b/src/dev/fbcon.c @@ -16,7 +16,7 @@ typedef struct { typedef struct { Con common; - SysFramebuffer* fb; + FbDev* fb; const PsfFont* font; } FbCon; @@ -35,31 +35,31 @@ static FbCon fbcon = { }; static int fbcon_write(Con* self, char c) { - FbCon* fb = container_of(self, FbCon, common); - if ((self->column + 1) * fb->font->width >= fb->fb->width) { + FbCon* con = container_of(self, FbCon, common); + if ((self->column + 1) * con->font->width >= con->fb->info.width) { self->column = 0; self->line += 1; } - if (self->line * fb->font->height >= fb->fb->height) { + if (self->line * con->font->height >= con->fb->info.height) { /* - fb_clear(fb->fb, 0); + fb_clear(con->con, 0); self->line = 0; self->column = 0;*/ return 0; // todo } - u32 bytes_per_line = (fb->font->width + 7) / 8; + u32 bytes_per_line = (con->font->width + 7) / 8; - usize offset = sizeof(PsfFont) + (usize) c * fb->font->bytes_per_glyph; - const u8* font_c = offset(fb->font, const u8*, offset); - usize init_x = self->column * fb->font->width; - usize init_y = self->line * fb->font->height; - for (usize y = 0; y < fb->font->height; ++y) { - for (usize x = 0; x < fb->font->width; ++x) { - u32 shift = fb->font->width - 1 - x; + usize offset = sizeof(PsfFont) + (usize) c * con->font->bytes_per_glyph; + const u8* font_c = offset(con->font, const u8*, offset); + usize init_x = self->column * con->font->width; + usize init_y = self->line * con->font->height; + for (usize y = 0; y < con->font->height; ++y) { + for (usize x = 0; x < con->font->width; ++x) { + u32 shift = con->font->width - 1 - x; u32 color = font_c[shift / 8] & (1 << (shift % 8)) ? self->fg : self->bg; - fb_set_pixel(fb->fb, init_x + x, init_y + y, color); + fb_set_pixel(con->fb, init_x + x, init_y + y, color); } font_c += bytes_per_line; } @@ -70,11 +70,11 @@ static int fbcon_write(Con* self, char c) { static int fbcon_write_at(Con* self, usize x, usize y, char c) { FbCon* fb = container_of(self, FbCon, common); - if ((x + 1) * fb->font->width >= fb->fb->width) { + if ((x + 1) * fb->font->width >= fb->fb->info.width) { x = 0; y += 1; } - if (y * fb->font->height >= fb->fb->height) { + if (y * fb->font->height >= fb->fb->info.height) { return 0; } @@ -96,7 +96,7 @@ static int fbcon_write_at(Con* self, usize x, usize y, char c) { return 1; } -void fbcon_init(SysFramebuffer* fb, const void* font) { +void fbcon_init(FbDev* fb, const void* font) { fbcon.fb = fb; fbcon.font = (const PsfFont*) font; kernel_con = &fbcon.common; diff --git a/src/dev/fbcon.h b/src/dev/fbcon.h index 6ac9f4f..17ee915 100644 --- a/src/dev/fbcon.h +++ b/src/dev/fbcon.h @@ -1,5 +1,5 @@ #pragma once -typedef struct SysFramebuffer SysFramebuffer; +typedef struct FbDev FbDev; -void fbcon_init(SysFramebuffer* fb, const void* font); \ No newline at end of file +void fbcon_init(FbDev* fb, const void* font); \ No newline at end of file diff --git a/src/mem/allocator.c b/src/mem/allocator.c index 0dd5ab6..fa3003f 100644 --- a/src/mem/allocator.c +++ b/src/mem/allocator.c @@ -5,6 +5,7 @@ #include "string.h" #include "utils.h" #include "vm.h" +#include "utils/math.h" typedef struct Node { struct Node* prev; @@ -166,3 +167,13 @@ void* kcalloc(usize size) { memset(mem, 0, size); return mem; } + +void* krealloc(void* ptr, usize old_size, usize new_size) { + void* new_ptr = kmalloc(new_size); + if (!new_ptr) { + return NULL; + } + memcpy(new_ptr, ptr, MIN(old_size, new_size)); + kfree(ptr, old_size); + return new_ptr; +} diff --git a/src/mem/allocator.h b/src/mem/allocator.h index 1ceb1bd..c8c7189 100644 --- a/src/mem/allocator.h +++ b/src/mem/allocator.h @@ -5,4 +5,5 @@ typedef struct Task Task; void* kmalloc(usize size); void* kcalloc(usize size); -void kfree(void* ptr, usize size); \ No newline at end of file +void kfree(void* ptr, usize size); +void* krealloc(void* ptr, usize old_size, usize new_size); diff --git a/src/sys/CMakeLists.txt b/src/sys/CMakeLists.txt index 9cfbf87..3bfdd1c 100644 --- a/src/sys/CMakeLists.txt +++ b/src/sys/CMakeLists.txt @@ -1,2 +1,3 @@ target_sources(crescent PRIVATE - syscalls.c) \ No newline at end of file + syscalls.c + dev.c) \ No newline at end of file diff --git a/src/sys/dev.c b/src/sys/dev.c new file mode 100644 index 0000000..1ef4c33 --- /dev/null +++ b/src/sys/dev.c @@ -0,0 +1,88 @@ +#include "dev.h" +#include "arch/cpu.h" +#include "crescent/sys.h" +#include "mem/allocator.h" +#include "string.h" +#include "mem/user.h" +#include "utils/math.h" + +DeviceList DEVICES[DEVICE_TYPE_MAX] = {}; + +void dev_add(GenericDevice* device, DeviceType type) { + DeviceList* list = &DEVICES[type]; + mutex_lock(&list->lock); + + if (list->len == list->cap) { + usize new_cap = list->cap < 8 ? 8 : list->cap + list->cap / 2; + list->devices = krealloc(list->devices, list->cap * sizeof(GenericDevice*), new_cap * sizeof(GenericDevice*)); + assert(list->devices); + list->cap = new_cap; + } + + list->devices[list->len++] = device; + + mutex_unlock(&list->lock); +} + +void dev_remove(GenericDevice* device, DeviceType type) { + DeviceList* list = &DEVICES[type]; + mutex_lock(&list->lock); + + for (usize i = 0; i < list->len; ++i) { + if (list->devices[i] == device) { + memmove(&list->devices[i], &list->devices[i + 1], (list->len - i - 1) * sizeof(GenericDevice*)); + break; + } + } + + mutex_unlock(&list->lock); +} + +int sys_devmsg(Handle handle, size_t msg, __user void* data) { + return ERR_INVALID_ARG; +} + +int sys_devenum(DeviceType type, __user Handle* res, __user size_t* count) { + if (type >= DEVICE_TYPE_MAX) { + return ERR_INVALID_ARG; + } + + DeviceList* list = &DEVICES[type]; + + mutex_lock(&list->lock); + if (!res) { + size_t kernel_count = list->len; + + if (!mem_copy_to_user(count, &kernel_count, sizeof(size_t))) { + mutex_unlock(&list->lock); + return ERR_FAULT; + } + return 0; + } + + size_t len; + if (!mem_copy_to_kernel(&len, count, sizeof(size_t))) { + mutex_unlock(&list->lock); + return ERR_FAULT; + } + len = MIN(len, list->len); + + Task* task = arch_get_cur_task(); + for (size_t i = 0; i < len; ++i) { + GenericDevice* ptr = list->devices[i]; + // todo support removing devices + ptr->refcount += 1; + Handle handle = handle_tab_insert(&task->process->handle_table, ptr, HANDLE_TYPE_GENERIC); + if (!mem_copy_to_user(res + i, &handle, sizeof(Handle))) { + mutex_unlock(&list->lock); + return ERR_FAULT; + } + } + + if (!mem_copy_to_user(count, &len, sizeof(size_t))) { + return ERR_FAULT; + } + + mutex_unlock(&DEVICES[type].lock); + return 0; +} diff --git a/src/sys/dev.h b/src/sys/dev.h new file mode 100644 index 0000000..d2b3b6a --- /dev/null +++ b/src/sys/dev.h @@ -0,0 +1,24 @@ +#pragma once +#include "utils/handle.h" +#include "arch/misc.h" +#include "crescent/dev.h" + +int sys_devmsg(Handle handle, size_t msg, __user void* data); +int sys_devenum(DeviceType type, __user Handle* res, __user size_t* count); + +typedef struct { + usize refcount; + char name[64]; +} GenericDevice; + +void dev_add(GenericDevice* device, DeviceType type); +void dev_remove(GenericDevice* device, DeviceType type); + +typedef struct { + GenericDevice** devices; + Mutex lock; + usize len; + usize cap; +} DeviceList; + +extern DeviceList DEVICES[DEVICE_TYPE_MAX]; diff --git a/src/sys/syscalls.c b/src/sys/syscalls.c index 620526a..5dc4177 100644 --- a/src/sys/syscalls.c +++ b/src/sys/syscalls.c @@ -27,7 +27,6 @@ bool sys_request_cap(u32 cap); void* sys_mmap(size_t size, int protection); int sys_munmap(__user void* ptr, size_t size); int sys_close(Handle handle); -int sys_enumerate_framebuffers(__user SysFramebuffer* res, __user size_t* count); __attribute__((used)) void* syscall_handlers[] = { sys_create_thread, @@ -47,7 +46,8 @@ __attribute__((used)) void* syscall_handlers[] = { sys_munmap, sys_close, - sys_enumerate_framebuffers + sys_devmsg, + sys_devenum }; __attribute__((used)) usize syscall_handler_count = sizeof(syscall_handlers) / sizeof(*syscall_handlers); @@ -322,48 +322,9 @@ int sys_close(Handle handle) { case HANDLE_TYPE_THREAD: kfree(data, sizeof(ThreadHandle)); break; + case HANDLE_TYPE_GENERIC: + break; } } return 0; } - -int sys_enumerate_framebuffers(__user SysFramebuffer* res, __user size_t* count) { - Task* self = arch_get_cur_task(); - if (!(self->caps & CAP_DIRECT_FB_ACCESS)) { - return ERR_NO_PERMISSIONS; - } - - // todo support more than one - if (primary_fb) { - if (count) { - size_t kernel_count = 1; - if (!mem_copy_to_user(count, &kernel_count, sizeof(size_t))) { - return ERR_FAULT; - } - } - if (count && res) { - usize size = primary_fb->height * primary_fb->pitch; - void* mem = vm_user_alloc(self->process, ALIGNUP(size, PAGE_SIZE) / PAGE_SIZE); - if (!mem) { - return ERR_NO_MEM; - } - for (usize i = 0; i < size; i += PAGE_SIZE) { - if (!arch_user_map_page(self->process, (usize) mem + i, to_phys(primary_fb->base) + i, PF_READ | PF_WRITE | PF_WC | PF_USER)) { - return ERR_NO_MEM; - } - } - - SysFramebuffer kernel_res = *primary_fb; - kernel_res.base = mem; - - if (!mem_copy_to_user(res, &kernel_res, sizeof(SysFramebuffer))) { - return ERR_FAULT; - } - } - } - else { - return 1; - } - - return 0; -} diff --git a/src/utils/handle.h b/src/utils/handle.h index 2757256..943c3e4 100644 --- a/src/utils/handle.h +++ b/src/utils/handle.h @@ -4,7 +4,8 @@ #include "sched/mutex.h" typedef enum { - HANDLE_TYPE_THREAD + HANDLE_TYPE_THREAD, + HANDLE_TYPE_GENERIC } HandleType; typedef struct { diff --git a/tests/user_tty.c b/tests/user_tty.c index 8a7b10c..6ae2c9b 100644 --- a/tests/user_tty.c +++ b/tests/user_tty.c @@ -1,6 +1,7 @@ #include "crescent/sys.h" #include "crescent/input.h" #include "crescent/fb.h" +#include "crescent/dev.h" #include #include @@ -81,8 +82,12 @@ int sys_close(Handle handle) { return (int) syscall1(SYS_CLOSE, handle); } -int sys_enumerate_framebuffers(SysFramebuffer* res, size_t* count) { - return (int) syscall2(SYS_ENUMERATE_FRAMEBUFFERS, (size_t) res, (size_t) count); +int sys_devmsg(Handle handle, size_t msg, void* data) { + return (int) syscall3(SYS_DEVMSG, (size_t) handle, msg, (size_t) data); +} + +int sys_devenum(DeviceType type, Handle* res, size_t* count) { + return (int) syscall3(SYS_DEVENUM, (size_t) type, (size_t) res, (size_t) count); } // clang-format off @@ -214,7 +219,7 @@ _Noreturn void _start(void*) { puts("user_tty didn't get power management access, F5 isn't going to work\n"); } - SysFramebuffer fb; + /*SysFramebuffer fb; size_t count = 1; int ret = sys_enumerate_framebuffers(&fb, &count); if (ret == 0) { @@ -231,7 +236,7 @@ _Noreturn void _start(void*) { } else if (ret == ERR_NO_PERMISSIONS) { puts("no permissions to get a framebuffer\n"); - } + }*/ // num arg0 arg1 arg2 arg3 arg4 arg5 // rdi rax rsi rdx r10 r8 r9