diff options
-rw-r--r-- | apps/init.c | 2 | ||||
-rw-r--r-- | apps/window.c | 11 | ||||
-rw-r--r-- | apps/wm.c | 12 | ||||
-rw-r--r-- | kernel/features/mm.c | 89 | ||||
-rw-r--r-- | kernel/features/syscall.c | 50 | ||||
-rw-r--r-- | kernel/inc/mm.h | 4 | ||||
-rw-r--r-- | libc/inc/sys.h | 14 | ||||
-rw-r--r-- | libc/sys.c | 11 | ||||
-rw-r--r-- | libgui/gui.c | 1 | ||||
-rw-r--r-- | libgui/inc/msg.h | 1 | ||||
-rw-r--r-- | libgui/msg.c | 3 |
11 files changed, 140 insertions, 58 deletions
diff --git a/apps/init.c b/apps/init.c index 35d296b..f1fcdf6 100644 --- a/apps/init.c +++ b/apps/init.c @@ -10,7 +10,7 @@ int main(int argc, char **argv) UNUSED(argv); assert(exec("/bin/wm", "wm", NULL) == 0); - /* assert(exec("/bin/window", "test", NULL) == 0); */ + assert(exec("/bin/window", "test", NULL) == 0); return 0; } diff --git a/apps/window.c b/apps/window.c index 0f9e7d1..03a384d 100644 --- a/apps/window.c +++ b/apps/window.c @@ -8,16 +8,15 @@ int main(void) { struct gui_window win = { 0 }; assert(gui_new_window(&win) > 0); - return 0; -#if 0 - gfx_fill(win.ctx, COLOR_GREEN); + gfx_fill(&win.ctx, COLOR_GREEN); // Professional testing for (int i = 0; i < 12; i++) { - gfx_write(win.ctx, vec2(0, i * gfx_font_height(FONT_32)), FONT_32, + gfx_write(&win.ctx, vec2(0, i * gfx_font_height(FONT_32)), FONT_32, 0xff000000 + (i * 0xaf << i), "Hallo, wie geht es Ihnen denn heute?!"); } assert(gui_redraw_window(win.id) > 0); - log("%d\n", win.ctx->size.x); -#endif + log("%d\n", win.ctx.size.x); + /* while (1) */ + /* ; */ return 0; } @@ -21,6 +21,7 @@ struct client { struct window { u32 id; + u32 shid; const char *name; struct context ctx; struct client client; @@ -83,7 +84,8 @@ static struct window *window_new(struct client client, const char *name, struct if ((flags & WF_NO_FB) != 0) { win->ctx.fb = NULL; } else { - win->ctx.fb = zalloc(size.y * win->ctx.pitch); + win->shid = shalloc(size.y * win->ctx.pitch); + win->ctx.fb = shaccess(win->shid); } win->client = client; win->flags = flags; @@ -315,6 +317,7 @@ static void handle_message_new_window(struct message_new_window *msg) struct window *win = window_new((struct client){ .pid = msg->header.src }, "idk", vec2(500, 600), vec2(600, 400), 0); msg->ctx = win->ctx; + msg->shid = win->shid; msg->id = win->id; msg_send(msg->header.src, GUI_NEW_WINDOW | MSG_SUCCESS, msg, sizeof(*msg)); /* window_redraw(win); */ @@ -329,7 +332,7 @@ static void handle_message_redraw_window(struct message_redraw_window *msg) sizeof(msg->header)); return; } - msg_send(msg->header.src, GUI_REDRAW_WINDOW | MSG_SUCCESS, NULL, sizeof(msg->header)); + msg_send(msg->header.src, GUI_REDRAW_WINDOW | MSG_SUCCESS, msg, sizeof(msg->header)); window_redraw(win); } @@ -346,7 +349,7 @@ static void handle_message(void *msg) break; default: log("Message type %d not implemented!\n", header->type); - msg_send(header->src, MSG_FAILURE, NULL, sizeof(*header)); + msg_send(header->src, MSG_FAILURE, msg, sizeof(*header)); } } @@ -384,7 +387,8 @@ int main(int argc, char **argv) wallpaper = window_new(wm_client, "wallpaper", vec2(0, 0), vec2(screen.width, screen.height), WF_NO_DRAG | WF_NO_FOCUS | WF_NO_RESIZE); - cursor = window_new(wm_client, "cursor", vec2(0, 0), vec2(32, 32), + // TODO: Fix strange cursor size segfault + cursor = window_new(wm_client, "cursor", vec2(0, 0), vec2(32, 33), WF_NO_WINDOW | WF_NO_DRAG | WF_NO_FOCUS | WF_NO_RESIZE); /* gfx_write(&direct->ctx, vec2(0, 0), FONT_32, COLOR_FG, "Loading Melvix..."); */ diff --git a/kernel/features/mm.c b/kernel/features/mm.c index d14bd81..a8e7e22 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -8,6 +8,7 @@ #include <mem.h> #include <mm.h> #include <print.h> +#include <random.h> static struct page_dir kernel_dir ALIGNED(PAGE_SIZE) = { 0 }; static struct page_table kernel_tables[PAGE_KERNEL_COUNT] ALIGNED(PAGE_SIZE) = { 0 }; @@ -353,7 +354,7 @@ void *memory_alloc(struct page_dir *dir, u32 size, u32 flags) return (void *)vaddr; err: - printf("Memory allocation error!\n"); + print("Memory allocation error!\n"); return NULL; } @@ -374,10 +375,96 @@ void *memory_alloc_identity(struct page_dir *dir, u32 flags) return 0; } +#define SHARED_MEMORY_MAX 128 +struct shared_memory { + u32 id; + u32 refs; + u8 used; + struct memory_range prange; +}; +static struct shared_memory shmem[SHARED_MEMORY_MAX] = { 0 }; +u32 memory_shalloc(struct page_dir *dir, u32 size, u32 flags) +{ + u32 slot = SHARED_MEMORY_MAX + 1; + + for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) { + if (!shmem[i].used) { + slot = i; + break; + } + } + + if (slot >= SHARED_MEMORY_MAX) + return 0; + + void *addr = memory_alloc(dir, size, flags); + if (!addr) + return 0; + + // TODO: Verify that shid isn't used already + // TODO: Check for colliding prange + u32 shid = rand() + 1; + shmem[slot].id = shid; + shmem[slot].used = 1; + shmem[slot].prange = memory_range(virtual_to_physical(dir, (u32)addr), size); + + return shid; +} + +static struct shared_memory memory_shresolve_range(struct memory_range prange) +{ + for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) { + if (!shmem[i].used) + continue; + + struct memory_range shrange = shmem[i].prange; + if (prange.base < shrange.base + shrange.size && + prange.base + prange.size > shrange.base) + return shmem[i]; + } + + return (struct shared_memory){ 0, 0, 0, memory_range(0, 0) }; +} + +static struct shared_memory memory_shresolve_id(u32 shid) +{ + for (u32 i = 0; i < SHARED_MEMORY_MAX; i++) { + if (!shmem[i].used) + continue; + + if (shmem[i].id == shid) + return shmem[i]; + } + + return shmem[0]; +} + +void *memory_shaccess(struct page_dir *dir, u32 shid) +{ + struct shared_memory sh = memory_shresolve_id(shid); + struct memory_range prange = sh.prange; + if (sh.used == 0 || prange.base == 0 || prange.size == 0) + return NULL; + + sh.refs++; + + return (void *)virtual_alloc(dir, prange, MEMORY_CLEAR | MEMORY_USER).base; +} + +// TODO: Free by address instead of vrange (combine with shmem map?) void memory_free(struct page_dir *dir, struct memory_range vrange) { assert(PAGE_ALIGNED(vrange.base) && PAGE_ALIGNED(vrange.size)); + struct memory_range prange = + memory_range(virtual_to_physical(dir, vrange.base), vrange.size); + struct shared_memory sh = memory_shresolve_range(prange); + if (sh.used != 0 && sh.refs > 1) { + panic("Freeing busy memory!\n"); + return; + } + /* sh.used = 0; */ + for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) { u32 vaddr = vrange.base + i * PAGE_SIZE; if (virtual_present(dir, vaddr)) { diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 7d68d93..c59c423 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -29,10 +29,19 @@ static void syscall_handler(struct regs *r) break; } case SYS_ALLOC: { - r->eax = (u32)memory_alloc(proc_current()->page_dir, r->ebx, + r->eax = (u32)memory_alloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx), MEMORY_CLEAR | MEMORY_USER); break; } + case SYS_SHALLOC: { + r->eax = (u32)memory_shalloc(proc_current()->page_dir, PAGE_ALIGN_UP(r->ebx), + MEMORY_CLEAR | MEMORY_USER); + break; + } + case SYS_SHACCESS: { + r->eax = (u32)memory_shaccess(proc_current()->page_dir, r->ebx); + break; + } case SYS_FREE: { memory_free(proc_current()->page_dir, memory_range(r->ebx, r->ecx)); break; @@ -123,45 +132,6 @@ static void syscall_handler(struct regs *r) break; } // TODO: Reimplement network functions using VFS - case SYS_NET_OPEN: - case SYS_NET_CLOSE: - case SYS_NET_CONNECT: - case SYS_NET_SEND: - case SYS_NET_RECEIVE: -#if 0 - case SYS_NET_OPEN: { - r->eax = (int)net_open(r->ebx); - break; - } - case SYS_NET_CLOSE: { - struct socket *s = (void *)r->ebx; - int status = net_close(s); - if (!status) { - proc_yield(r); - return; - } - r->eax = net_close(s); - break; - } - case SYS_NET_CONNECT: { - struct socket *s = (void *)r->ebx; - if (s->state == S_CONNECTED) - r->eax = 1; - else if (s->state == S_FAILED || s->state == S_CLOSED) - r->eax = 0; - else if (s->state == S_OPEN) - r->eax = net_connect(s, r->ecx, r->edx); - break; - } - case SYS_NET_SEND: { - net_send((void *)r->ebx, (void *)r->ecx, r->edx); - break; - } - case SYS_NET_RECEIVE: { - r->eax = net_receive((void *)r->ebx, (void *)r->ecx, r->edx); - break; - } -#endif default: { printf("Unknown syscall %d!\n", num); break; diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index e506331..5e30be6 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -104,8 +104,10 @@ struct memory_range memory_range_around(u32 base, u32 size); void *memory_alloc(struct page_dir *dir, u32 size, u32 flags); void *memory_alloc_identity(struct page_dir *dir, u32 flags); -void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags); +u32 memory_shalloc(struct page_dir *dir, u32 size, u32 flags); +void *memory_shaccess(struct page_dir *dir, u32 shid); void memory_free(struct page_dir *dir, struct memory_range vrange); +void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 flags); void memory_switch_dir(struct page_dir *dir); void memory_backup_dir(struct page_dir **backup); diff --git a/libc/inc/sys.h b/libc/inc/sys.h index 46a5849..a06a792 100644 --- a/libc/inc/sys.h +++ b/libc/inc/sys.h @@ -16,6 +16,8 @@ enum sys { SYS_LOOP, // To infinity and beyond (debug)! SYS_ALLOC, // Allocate memory + SYS_SHALLOC, // Allocate shared memory + SYS_SHACCESS, // Access shared memory SYS_FREE, // Free memory SYS_STAT, // Get file information SYS_READ, // Read file @@ -27,11 +29,11 @@ enum sys { SYS_BOOT, // Boot functions (e.g. reboot/shutdown) SYS_YIELD, // Switch to next process SYS_TIME, // Get kernel time - SYS_NET_OPEN, // Open network socket - SYS_NET_CLOSE, // Close network socket - SYS_NET_CONNECT, // Connect to destination - SYS_NET_SEND, // Send to socket - SYS_NET_RECEIVE, // Receive data from socket + /* SYS_NET_OPEN, // Open network socket */ + /* SYS_NET_CLOSE, // Close network socket */ + /* SYS_NET_CONNECT, // Connect to destination */ + /* SYS_NET_SEND, // Send to socket */ + /* SYS_NET_RECEIVE, // Receive data from socket */ }; struct event_keyboard { @@ -76,6 +78,8 @@ s32 boot(u32 cmd); u32 time(void); void *sys_alloc(u32 size); +u32 shalloc(u32 size); +void *shaccess(u32 id); void sys_free(void *ptr, u32 size); static inline u32 getpid(void) @@ -83,6 +83,17 @@ void *sys_alloc(u32 size) return (void *)sys1(SYS_ALLOC, (int)size); } +u32 shalloc(u32 size) +{ + return (u32)sys1(SYS_SHALLOC, (int)size); +} + +void *shaccess(u32 id) +{ + return (void *)sys1(SYS_SHACCESS, (int)id); +} + +// TODO: Freeing by ptr + size could be a security risk -> only by address! void sys_free(void *ptr, u32 size) { sys2(SYS_FREE, (int)ptr, (int)size); diff --git a/libgui/gui.c b/libgui/gui.c index bc8adb1..e4800bc 100644 --- a/libgui/gui.c +++ b/libgui/gui.c @@ -15,6 +15,7 @@ s32 gui_new_window(struct gui_window *win) msg.header.type == (GUI_NEW_WINDOW | MSG_SUCCESS)) { win->id = msg.id; win->ctx = msg.ctx; + win->ctx.fb = shaccess(msg.shid); return win->id; } return -1; diff --git a/libgui/inc/msg.h b/libgui/inc/msg.h index 7cbfa2c..150c42d 100644 --- a/libgui/inc/msg.h +++ b/libgui/inc/msg.h @@ -20,6 +20,7 @@ struct message_header { struct message_new_window { struct message_header header; u32 id; + u32 shid; struct context ctx; }; diff --git a/libgui/msg.c b/libgui/msg.c index 3f58267..677ad52 100644 --- a/libgui/msg.c +++ b/libgui/msg.c @@ -1,12 +1,15 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include <assert.h> +#include <errno.h> #include <msg.h> #include <print.h> #include <sys.h> int msg_send(u32 pid, enum message_type type, void *data, u32 size) { + if (!data) + return -EFAULT; assert((signed)pid != -1 && size >= sizeof(struct message_header)); char path[32] = { 0 }; sprintf(path, "/proc/%d/msg", pid); |