aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/init.c2
-rw-r--r--apps/window.c11
-rw-r--r--apps/wm.c12
-rw-r--r--kernel/features/mm.c89
-rw-r--r--kernel/features/syscall.c50
-rw-r--r--kernel/inc/mm.h4
-rw-r--r--libc/inc/sys.h14
-rw-r--r--libc/sys.c11
-rw-r--r--libgui/gui.c1
-rw-r--r--libgui/inc/msg.h1
-rw-r--r--libgui/msg.c3
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;
}
diff --git a/apps/wm.c b/apps/wm.c
index e445528..10f13d3 100644
--- a/apps/wm.c
+++ b/apps/wm.c
@@ -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)
diff --git a/libc/sys.c b/libc/sys.c
index aac2d1e..db31f37 100644
--- a/libc/sys.c
+++ b/libc/sys.c
@@ -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);