diff options
-rw-r--r-- | apps/wm.c | 49 | ||||
-rw-r--r-- | kernel/Makefile | 3 | ||||
-rw-r--r-- | kernel/drivers/ide.c | 4 | ||||
-rw-r--r-- | kernel/drivers/interrupts.c | 11 | ||||
-rw-r--r-- | kernel/drivers/keyboard.c | 41 | ||||
-rw-r--r-- | kernel/drivers/mouse.c | 147 | ||||
-rw-r--r-- | kernel/features/event.c | 61 | ||||
-rw-r--r-- | kernel/features/fs.c | 171 | ||||
-rw-r--r-- | kernel/features/load.c | 26 | ||||
-rw-r--r-- | kernel/features/proc.c | 182 | ||||
-rw-r--r-- | kernel/features/syscall.c | 36 | ||||
-rw-r--r-- | kernel/inc/event.h | 19 | ||||
-rw-r--r-- | kernel/inc/fs.h | 33 | ||||
-rw-r--r-- | kernel/inc/keyboard.h | 1 | ||||
-rw-r--r-- | kernel/inc/load.h | 55 | ||||
-rw-r--r-- | kernel/inc/proc.h | 25 | ||||
-rw-r--r-- | kernel/main.c | 1 | ||||
-rw-r--r-- | libc/Makefile | 1 | ||||
-rw-r--r-- | libc/inc/assert.h | 3 | ||||
-rw-r--r-- | libc/inc/mem.h | 20 | ||||
-rw-r--r-- | libc/inc/stack.h | 28 | ||||
-rw-r--r-- | libc/inc/sys.h | 38 | ||||
-rw-r--r-- | libc/mem.c | 355 | ||||
-rw-r--r-- | libc/stack.c | 125 | ||||
-rw-r--r-- | libgui/gfx.c | 8 | ||||
-rw-r--r-- | libgui/gui.c | 20 | ||||
-rw-r--r-- | libgui/inc/gfx.h | 8 | ||||
-rw-r--r-- | libgui/png.c | 8 |
28 files changed, 985 insertions, 494 deletions
@@ -88,7 +88,7 @@ static void kill_focused() { if (!focused) return; - msg_send(focused->pid, GUI_KILL, NULL); + //msg_send(focused->pid, GUI_KILL, NULL); remove_context(focused); focused = context_at(mouse_x, mouse_y); } @@ -162,7 +162,7 @@ static void handle_keyboard(struct event_keyboard *event) msg->press = event->press; msg->scancode = event->scancode; - msg_send(focused->pid, GUI_KEYBOARD, msg); + //msg_send(focused->pid, GUI_KEYBOARD, msg); } static int mouse_skip = 0; @@ -237,7 +237,7 @@ static void handle_mouse(struct event_mouse *event) focused = resized; struct gui_event_resize *msg = malloc(sizeof(*msg)); msg->new_ctx = resized; - msg_send(resized->pid, GUI_RESIZE, msg); + //msg_send(resized->pid, GUI_RESIZE, msg); redraw_all(); } } @@ -255,7 +255,7 @@ static void handle_mouse(struct event_mouse *event) msg->but1 = event->but1; msg->but2 = event->but2; msg->but3 = event->but3; - msg_send(focused->pid, GUI_MOUSE, msg); + //msg_send(focused->pid, GUI_MOUSE, msg); } // TODO: Clean this god-function @@ -285,36 +285,47 @@ int main(int argc, char **argv) gfx_load_image(&cursor, "/res/cursor.png", 0, 0); redraw_all(); - event_register(EVENT_MOUSE); - event_register(EVENT_KEYBOARD); - - struct message *msg; + struct message msg = { 0 }; + struct event_keyboard kbd_event = { 0 }; + struct event_mouse mouse_event = { 0 }; while (1) { - if (!(msg = msg_receive())) { + if (read("/dev/kbd", &kbd_event, 0, sizeof(struct event_keyboard))) + handle_keyboard(&kbd_event); + /* else if (read("/dev/mouse", &mouse_event, 0, sizeof(struct event_mouse))) */ + /* handle_mouse(&mouse_event); */ + /* else if (msg_receive(&msg)) { */ + /* handle_message(&msg); */ + /* } */ + else { yield(); continue; } - switch (msg->type) { + //if (!msg_receive(&msg)) { + yield(); + continue; + //} + + switch (msg.type) { case GFX_NEW_CONTEXT: { - struct context *ctx = msg->data; + struct context *ctx = msg.data; int width = ctx->width; int height = ctx->height; int x = ctx->x; int y = ctx->y; - ctx->pid = msg->src; - new_context(ctx, msg->src, x, y, width, height, ctx->flags); + ctx->pid = msg.src; + new_context(ctx, msg.src, x, y, width, height, ctx->flags); list_add(contexts, ctx); if (!(ctx->flags & WF_RELATIVE)) focused = ctx; redraw_all(); - msg_send(msg->src, GFX_NEW_CONTEXT, ctx); + //msg_send(msg.src, GFX_NEW_CONTEXT, ctx); // Send mouse position - struct gui_event_mouse *mouse = malloc(sizeof(*msg)); + struct gui_event_mouse *mouse = malloc(sizeof(msg)); mouse->x = mouse_x - focused->x; mouse->y = mouse_y - focused->y; - msg_send(focused->pid, GUI_MOUSE, mouse); + //msg_send(focused->pid, GUI_MOUSE, mouse); break; } case GFX_REDRAW: @@ -323,12 +334,6 @@ int main(int argc, char **argv) case GFX_REDRAW_FOCUSED: redraw_focused(); break; - case EVENT_MOUSE: - handle_mouse(msg->data); - break; - case EVENT_KEYBOARD: - handle_keyboard(msg->data); - break; default: break; } diff --git a/kernel/Makefile b/kernel/Makefile index 64b5993..492d975 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -14,8 +14,7 @@ COBJS = main.o \ features/proc.o \ features/proc_asm.o \ features/syscall.o \ - features/net.o \ - features/event.o + features/net.o CC = ccache ../cross/opt/bin/i686-elf-gcc LD = ccache ../cross/opt/bin/i686-elf-ld OC = ccache ../cross/opt/bin/i686-elf-objcopy diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c index f3d0f6e..7dd2416 100644 --- a/kernel/drivers/ide.c +++ b/kernel/drivers/ide.c @@ -106,7 +106,7 @@ u8 ata_read_one(u8 *buf, u32 lba, struct device *dev) return 1; } -u32 ata_read(void *buf, u32 lba, u32 sector_count, struct device *dev) +s32 ata_read(void *buf, u32 lba, u32 sector_count, struct device *dev) { u8 *b = buf; // I love bytes, yk for (u32 i = 0; i < sector_count; i++) { @@ -147,8 +147,10 @@ void ata_probe(void) struct vfs *vfs = malloc(sizeof(*vfs)); vfs->type = VFS_EXT2; vfs->read = ext2_read; + vfs->ready = ext2_ready; vfs->stat = ext2_stat; dev->vfs = vfs; + dev->data = data; vfs_mount(dev, "/"); } } diff --git a/kernel/drivers/interrupts.c b/kernel/drivers/interrupts.c index 29ff55d..4c5c3b7 100644 --- a/kernel/drivers/interrupts.c +++ b/kernel/drivers/interrupts.c @@ -170,11 +170,7 @@ void isr_uninstall_handler(int isr) void isr_handler(struct regs *r) { - // Execute fault handler if exists - void (*handler)(struct regs * r) = isr_routines[r->int_no]; - if (handler) { - handler(r); - } else if (r->int_no <= 32) { + if (r->int_no <= 32) { printf("%s Exception, exiting!\n", isr_exceptions[r->int_no]); struct proc *proc = proc_current(); if (proc) @@ -182,6 +178,11 @@ void isr_handler(struct regs *r) else __asm__ volatile("cli\nhlt"); proc_yield(r); + } else { + // Execute fault handler if exists + void (*handler)(struct regs * r) = isr_routines[r->int_no]; + if (handler) + handler(r); } } diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index ac97d36..0dd7219 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -2,13 +2,18 @@ #include <cpu.h> #include <def.h> -#include <event.h> +#include <fs.h> #include <interrupts.h> #include <mem.h> #include <print.h> +#include <proc.h> +#include <stack.h> +#include <str.h> #include <sys.h> static struct event_keyboard *event = NULL; +static struct stack *queue = NULL; +static u32 dev_id = 0; static int state = 0; static int merged = 0; @@ -34,10 +39,12 @@ void keyboard_handler() event->magic = KEYBOARD_MAGIC; event->press = (scancode & 0x80) == 0; event->scancode = event->press ? scancode : scancode & ~0x80; - event_trigger(EVENT_KEYBOARD, event); + stack_push_bot(queue, event); state = 0; merged = 0; + + proc_enable_waiting(dev_id); } void keyboard_acknowledge(void) @@ -53,8 +60,38 @@ void keyboard_rate(void) outb(0x60, 0x0); // Rate{00000} Delay{00} 0 } +s32 keyboard_read(void *buf, u32 offset, u32 count, struct device *dev) +{ + (void)dev; + if (stack_empty(queue)) + return -1; + + struct event *e = stack_pop(queue); + memcpy(buf, (u8 *)e + offset, count); + return count; +} + +u8 keyboard_ready(void) +{ + return !stack_empty(queue); +} + +void keyboard_reset(void) +{ + stack_clear(queue); +} + void keyboard_install(void) { //keyboard_rate(); TODO: Fix keyboard rate? irq_install_handler(1, keyboard_handler); + + queue = stack_new(); + struct device *dev = malloc(sizeof(*dev)); + dev->name = strdup("kbd"); + dev->type = DEV_CHAR; + dev->read = keyboard_read; + dev->ready = keyboard_ready; + device_add(dev); + dev_id = dev->id; } diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c index d58fbfc..2e9ceae 100644 --- a/kernel/drivers/mouse.c +++ b/kernel/drivers/mouse.c @@ -2,14 +2,18 @@ #include <boot.h> #include <cpu.h> -#include <event.h> +#include <fs.h> #include <interrupts.h> #include <mem.h> #include <print.h> +#include <stack.h> +#include <str.h> #include <sys.h> static char mouse_cycle = 0; static char mouse_byte[3] = { 0 }; +static struct stack *queue = NULL; +static u32 dev_id = 0; static struct event_mouse *event = NULL; @@ -39,7 +43,7 @@ void mouse_handler() event->but1 = mouse_byte[0] & 1; event->but2 = (mouse_byte[0] >> 1) & 1; event->but3 = (mouse_byte[0] >> 2) & 1; - event_trigger(EVENT_MOUSE, event); + stack_push_bot(queue, event); mouse_cycle = 0; break; @@ -48,7 +52,7 @@ void mouse_handler() } } -void mouse_wait(u8 a_type) +void mouse_serial_wait(u8 a_type) { u32 time_out = 100000; if (a_type == 0) { @@ -64,96 +68,121 @@ void mouse_wait(u8 a_type) } } -void mouse_write(u8 a_write) +void mouse_serial_write(u8 a_write) { - mouse_wait(1); + mouse_serial_wait(1); outb(0x64, 0xD4); - mouse_wait(1); + mouse_serial_wait(1); outb(0x60, a_write); } -u8 mouse_read(void) +u8 mouse_serial_read(void) { - mouse_wait(0); + mouse_serial_wait(0); return inb(0x60); } +u8 mouse_ready(void) +{ + return !stack_empty(queue); +} + +s32 mouse_read(void *buf, u32 offset, u32 count, struct device *dev) +{ + (void)dev; + if (stack_empty(queue)) + return -1; + + struct event *e = stack_pop(queue); + memcpy(buf, (u8 *)e + offset, count); + return count; +} + void mouse_install(void) { u8 status; // Enable auxiliary mouse device - mouse_wait(1); + mouse_serial_wait(1); outb(0x64, 0xA8); // Enable interrupts - mouse_wait(1); + mouse_serial_wait(1); outb(0x64, 0x20); - mouse_wait(0); + mouse_serial_wait(0); status = (u8)(inb(0x60) | 3); - mouse_wait(1); + mouse_serial_wait(1); outb(0x64, 0x60); - mouse_wait(1); + mouse_serial_wait(1); outb(0x60, status); // Enable mousewheel - mouse_write(0xF2); - mouse_read(); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(200); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(100); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(80); - mouse_read(); - mouse_write(0xF2); - mouse_read(); - status = (u8)mouse_read(); + mouse_serial_write(0xF2); + mouse_serial_read(); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(200); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(100); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(80); + mouse_serial_read(); + mouse_serial_write(0xF2); + mouse_serial_read(); + status = (u8)mouse_serial_read(); if (status == 3) printf("Scrollwheel support!\n"); // Activate 4th and 5th mouse buttons - mouse_write(0xF2); - mouse_read(); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(200); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(200); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(80); - mouse_read(); - mouse_write(0xF2); - mouse_read(); - status = (u8)mouse_read(); + mouse_serial_write(0xF2); + mouse_serial_read(); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(200); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(200); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(80); + mouse_serial_read(); + mouse_serial_write(0xF2); + mouse_serial_read(); + status = (u8)mouse_serial_read(); if (status == 4) printf("4th and 5th mouse button support!\n"); /* TODO: Fix mouse laggyness - mouse_write(0xE8); - mouse_read(); - mouse_write(0x03); - mouse_read(); - mouse_write(0xF3); - mouse_read(); - mouse_write(200); - mouse_read(); */ + mouse_serial_write(0xE8); + mouse_serial_read(); + mouse_serial_write(0x03); + mouse_serial_read(); + mouse_serial_write(0xF3); + mouse_serial_read(); + mouse_serial_write(200); + mouse_serial_read(); */ // Enable mouse - mouse_write(0xF4); - mouse_read(); + mouse_serial_write(0xF4); + mouse_serial_read(); // Setup the mouse handler irq_install_handler(12, mouse_handler); + + queue = stack_new(); + struct device *dev = malloc(sizeof(*dev)); + dev->name = strdup("mouse"); + dev->type = DEV_CHAR; + dev->read = mouse_read; + dev->ready = mouse_ready; + device_add(dev); + dev_id = dev->id; } diff --git a/kernel/features/event.c b/kernel/features/event.c deleted file mode 100644 index c9bd3a4..0000000 --- a/kernel/features/event.c +++ /dev/null @@ -1,61 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#include <assert.h> -#include <def.h> -#include <event.h> -#include <list.h> -#include <mem.h> -#include <proc.h> -#include <sys.h> - -static struct list *event_table[] = { [EVENT_KEYBOARD] = NULL, [EVENT_MOUSE] = NULL }; - -u32 event_register(u32 id, struct proc *proc) -{ - assert(id < sizeof(event_table) / sizeof(*event_table)); - - if (event_table[id] == NULL) - event_table[id] = (struct list *)list_new(); - - struct event_descriptor *desc = malloc(sizeof(*desc)); - desc->id = id; - desc->proc = proc; - - list_add(event_table[id], (void *)desc); - return 0; -} - -void event_unregister(u32 id, struct proc *proc) -{ - assert(id < sizeof(event_table) / sizeof(*event_table)); - - struct event_descriptor desc; - desc.id = id; - desc.proc = proc; - - struct node *iterator = event_table[id]->head; - while (iterator != NULL) { - struct event_descriptor *desc_comp = iterator->data; - if (desc_comp->id == desc.id && desc_comp->proc == desc.proc) - list_remove(event_table[id], iterator); - iterator = iterator->next; - } -} - -u32 event_trigger(u32 id, void *data) -{ - assert(id < sizeof(event_table) / sizeof(*event_table)); - - if (!event_table[id] || !event_table[id]->head) { - printf("Event %d not mapped!\n", id); - return 1; - } - - struct node *iterator = event_table[id]->head; - while (iterator != NULL) { - proc_send(kernel_proc, ((struct event_descriptor *)iterator->data)->proc, id, data); - iterator = iterator->next; - } - - return 0; -} diff --git a/kernel/features/fs.c b/kernel/features/fs.c index 14e6a9c..b59eb03 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -24,7 +24,7 @@ char *vfs_normalize_path(const char *path) return fixed; } -u32 vfs_mounted(struct device *dev, const char *path) +u8 vfs_mounted(struct device *dev, const char *path) { struct node *iterator = mount_points->head; while (iterator) { @@ -70,6 +70,8 @@ struct device *vfs_find_dev(const char *path) { assert(path[0] == '/'); struct mount_info *m = vfs_find_mount_info(path); + if (m->dev->vfs->type == VFS_DEVFS) // TODO: ? + return device_get_by_name(path + strlen(m->path) + 1); return m && m->dev ? m->dev : NULL; } @@ -100,11 +102,11 @@ void vfs_list_mounts() } } -u32 vfs_mount(struct device *dev, const char *path) +s32 vfs_mount(struct device *dev, const char *path) { // TODO: Check if already mounted if (!dev || !dev->id || vfs_mounted(dev, path)) - return 0; + return -1; char *fixed = vfs_normalize_path(path); @@ -113,14 +115,20 @@ u32 vfs_mount(struct device *dev, const char *path) m->dev = dev; list_add(mount_points, m); - return 1; + return 0; } -u32 vfs_read(const char *path, void *buf, u32 offset, u32 count) +s32 vfs_read(const char *path, void *buf, u32 offset, u32 count) { - if (count == 0 || offset > count) + if (!count) return 0; + if (offset > count) + return -1; + + while (*path == ' ') + path++; + struct mount_info *m = vfs_find_mount_info(path); assert(m && m->dev && m->dev->vfs && m->dev->vfs->read); @@ -128,22 +136,58 @@ u32 vfs_read(const char *path, void *buf, u32 offset, u32 count) if (len > 1) path += len; - struct device *dev = m->dev; - return dev->vfs->read(path, buf, offset, count, dev); + return m->dev->vfs->read(path, buf, offset, count, m->dev); +} + +s32 vfs_write(const char *path, void *buf, u32 offset, u32 count) +{ + if (!count) + return 0; + + if (offset > count) + return -1; + + while (*path == ' ') + path++; + + struct mount_info *m = vfs_find_mount_info(path); + assert(m && m->dev && m->dev->vfs && m->dev->vfs->write); + + u32 len = strlen(m->path); + if (len > 1) + path += len; + + return m->dev->vfs->write(path, buf, offset, count, m->dev); } -u32 vfs_write(const char *path, void *buf, u32 offset, u32 count) +s32 vfs_stat(const char *path, struct stat *buf) { - struct device *dev = vfs_find_dev(path); - assert(dev && dev->vfs && dev->vfs->write); - return dev->vfs->write(path, buf, offset, count, dev); + while (*path == ' ') + path++; + + struct mount_info *m = vfs_find_mount_info(path); + assert(m && m->dev && m->dev->vfs && m->dev->vfs->stat); + + u32 len = strlen(m->path); + if (len > 1) + path += len; + + return m->dev->vfs->stat(path, buf, m->dev); } -u32 vfs_stat(const char *path, struct stat *buf) +u8 vfs_ready(const char *path) { - struct device *dev = vfs_find_dev(path); - assert(dev && dev->vfs && dev->vfs->stat); - return dev->vfs->stat(path, buf, dev); + while (*path == ' ') + path++; + + struct mount_info *m = vfs_find_mount_info(path); + assert(m && m->dev && m->dev->vfs && m->dev->vfs->ready); + + u32 len = strlen(m->path); + if (len > 1) + path += len; + + return m->dev->vfs->ready(path, m->dev); } void vfs_install(void) @@ -163,7 +207,7 @@ void device_add(struct device *dev) list_add(devices, dev); } -struct device *device_get(u32 id) +struct device *device_get_by_id(u32 id) { struct node *iterator = devices->head; while (iterator) { @@ -174,25 +218,46 @@ struct device *device_get(u32 id) return NULL; } -u32 devfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +struct device *device_get_by_name(const char *name) +{ + struct node *iterator = devices->head; + while (iterator) { + if (!strcmp(((struct device *)iterator->data)->name, name)) + return iterator->data; + iterator = iterator->next; + } + return NULL; +} + +s32 devfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +{ + struct device *target = device_get_by_name(path + 1); + if (!target || !target->read) + return 0; + return target->read(buf, offset, count, dev); +} + +u8 devfs_ready(const char *path, struct device *dev) { - assert(dev && dev->read); - printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev); - return dev->read(buf, offset, count, dev); + (void)dev; + + struct device *target = device_get_by_name(path + 1); + if (!target || !target->ready) + return 0; + return target->ready(); } void device_install(void) { devices = list_new(); - struct vfs *vfs; - struct device *dev; - - vfs = malloc(sizeof(*vfs)); + struct vfs *vfs = malloc(sizeof(*vfs)); vfs->type = VFS_DEVFS; vfs->read = devfs_read; - dev = malloc(sizeof(*dev)); + vfs->ready = devfs_ready; + struct device *dev = malloc(sizeof(*dev)); dev->name = "dev"; + dev->type = DEV_CHAR; dev->vfs = vfs; device_add(dev); vfs_mount(dev, "/dev/"); @@ -204,6 +269,7 @@ void device_install(void) * EXT2 */ +// TODO: Remove malloc from buffer_read (attempt in #56cd63f199) void *buffer_read(u32 block, struct device *dev) { void *buf = malloc(BLOCK_SIZE); @@ -215,8 +281,7 @@ struct ext2_superblock *get_superblock(struct device *dev) { struct ext2_superblock *sb = buffer_read(EXT2_SUPER, dev); - if (sb->magic != EXT2_MAGIC) - return NULL; + assert(sb->magic == EXT2_MAGIC); return sb; } @@ -237,31 +302,38 @@ struct ext2_inode *get_inode(u32 i, struct device *dev) u32 block = (index * EXT2_INODE_SIZE) / BLOCK_SIZE; b += block_group; - u32 *data = buffer_read(b->inode_table + block, dev); + u32 *buf = buffer_read(b->inode_table + block, dev); struct ext2_inode *in = - (struct ext2_inode *)((u32)data + + (struct ext2_inode *)((u32)buf + (index % (BLOCK_SIZE / EXT2_INODE_SIZE)) * EXT2_INODE_SIZE); + + free(buf); + free(s); + free(b - block_group); + return in; } u32 read_indirect(u32 indirect, u32 block_num, struct device *dev) { char *data = buffer_read(indirect, dev); - return *(u32 *)((u32)data + block_num * sizeof(u32)); + u32 ind = *(u32 *)((u32)data + block_num * sizeof(u32)); + free(data); + return ind; } -u32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct device *dev) +s32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct device *dev) { // TODO: Support read offset (void)offset; if (!in || !buf) - return 0; + return -1; u32 num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE); if (!num_blocks) - return 0; + return -1; // TODO: memcpy block chunks until count is copied while (BLOCK_SIZE * num_blocks > count) @@ -269,28 +341,25 @@ u32 read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, struct d u32 indirect = 0; u32 blocknum = 0; - char *data = 0; // TODO: Support triply indirect pointers // TODO: This can be heavily optimized by saving the indirect block lists for (u32 i = 0; i < num_blocks; i++) { if (i < 12) { blocknum = in->block[i]; - data = buffer_read(blocknum, dev); - memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE); } else if (i < BLOCK_COUNT + 12) { indirect = in->block[12]; blocknum = read_indirect(indirect, i - 12, dev); - data = buffer_read(blocknum, dev); - memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE); } else { indirect = in->block[13]; blocknum = read_indirect(indirect, (i - (BLOCK_COUNT + 12)) / BLOCK_COUNT, dev); blocknum = read_indirect(blocknum, (i - (BLOCK_COUNT + 12)) % BLOCK_COUNT, dev); - data = buffer_read(blocknum, dev); - memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE); } + + char *data = buffer_read(blocknum, dev); + memcpy((u32 *)((u32)buf + i * BLOCK_SIZE), data, BLOCK_SIZE); + free(data); /* printf("Loaded %d of %d\n", i + 1, num_blocks); */ } @@ -310,6 +379,7 @@ u32 find_inode(const char *name, u32 dir_inode, struct device *dev) for (u32 q = 0; q < i->blocks / 2; q++) { char *data = buffer_read(i->block[q], dev); memcpy((u32 *)((u32)buf + q * BLOCK_SIZE), data, BLOCK_SIZE); + free(data); } struct ext2_dirent *d = (struct ext2_dirent *)buf; @@ -341,7 +411,7 @@ struct ext2_inode *find_inode_by_path(const char *path, struct device *dev) path_cp++; u32 current_inode = EXT2_ROOT; - int i = 0; + u32 i = 0; while (1) { for (i = 0; path_cp[i] != '/' && path_cp[i] != '\0'; i++) ; @@ -369,23 +439,23 @@ struct ext2_inode *find_inode_by_path(const char *path, struct device *dev) return get_inode(inode, dev); } -u32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +s32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) { struct ext2_inode *in = find_inode_by_path(path, dev); if (in) return read_inode(in, buf, offset, count, dev); else - return 0; + return -1; } -u32 ext2_stat(const char *path, struct stat *buf, struct device *dev) +s32 ext2_stat(const char *path, struct stat *buf, struct device *dev) { if (!buf) - return 1; + return -1; struct ext2_inode *in = find_inode_by_path(path, dev); if (!in) - return 1; + return -1; u32 num_blocks = in->blocks / (BLOCK_SIZE / SECTOR_SIZE); u32 sz = BLOCK_SIZE * num_blocks; @@ -395,3 +465,10 @@ u32 ext2_stat(const char *path, struct stat *buf, struct device *dev) return 0; } + +u8 ext2_ready(const char *path, struct device *dev) +{ + (void)path; + (void)dev; + return 1; +} diff --git a/kernel/features/load.c b/kernel/features/load.c index 1eb34d3..3e1ea8e 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -1,28 +1,30 @@ // MIT License, Copyright (c) 2020 Marvin Borner -#include <assert.h> -#include <cpu.h> -#include <def.h> #include <fs.h> #include <load.h> #include <mem.h> -#include <proc.h> #include <str.h> +void proc_load(struct proc *proc, void *data) +{ + u32 stack = (u32)malloc(0x2000) + 0x1000; + + proc->regs.ebp = (u32)stack; + proc->regs.useresp = (u32)stack; + proc->regs.eip = (u32)data; +} + int bin_load(char *path, struct proc *proc) { // TODO: Remove hardcoded filesize struct stat s = { 0 }; vfs_stat(path, &s); char *data = malloc(s.size); - vfs_read(path, data, 0, s.size); - - u32 stack = (u32)malloc(0x2000) + 0x1000; + if (!vfs_read(path, data, 0, s.size)) + return 1; - proc->regs.ebp = (u32)stack; - proc->regs.useresp = (u32)stack; - proc->regs.eip = (u32)data; - strcpy(proc->name, path + 1); + strcpy(proc->name, path); + proc_load(proc, data); - return data ? 0 : 1; + return 0; } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index d76312c..bec48fa 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -3,12 +3,12 @@ #include <assert.h> #include <boot.h> #include <cpu.h> -#include <interrupts.h> -#include <list.h> +#include <fs.h> #include <load.h> #include <mem.h> #include <print.h> #include <proc.h> +#include <stack.h> #include <str.h> #include <timer.h> @@ -16,6 +16,7 @@ u32 current_pid = 0; u32 quantum = 0; struct proc *priority_proc; struct list *proc_list; +struct node *idle_proc; struct node *current; // TODO: Use less memcpy and only copy relevant registers @@ -44,8 +45,7 @@ void scheduler(struct regs *regs) } else if (((struct proc *)proc_list->head->data)->state == PROC_RUNNING) { current = proc_list->head; } else { - print("TODO: All processes are sleeping!\n"); // TODO! - /* loop(); */ + current = idle_proc; } memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); @@ -63,6 +63,12 @@ void scheduler(struct regs *regs) /* printf("{%d}", ((struct proc *)current->data)->pid); */ } +void kernel_idle() +{ + while (1) + ; +} + void proc_print(void) { struct node *node = proc_list->head; @@ -82,33 +88,6 @@ struct proc *proc_current(void) return current && current->data ? current->data : NULL; } -void proc_send(struct proc *src, struct proc *dest, u32 type, void *data) -{ - // TODO: Use unique key instead of pid for IPC - if (!src || !dest) - return; - struct proc_message *msg = malloc(sizeof(*msg)); - msg->src = src; - msg->dest = dest; - msg->msg = malloc(sizeof(struct message)); - msg->msg->src = (int)src->pid; - msg->msg->type = (int)type; - msg->msg->data = data; - list_add(dest->messages, msg); - priority_proc = dest; -} - -struct proc_message *proc_receive(struct proc *proc) -{ - if (proc->messages && proc->messages->head) { - struct proc_message *msg = proc->messages->head->data; - list_remove(proc->messages, proc->messages->head); - return msg; - } else { - return NULL; - } -} - struct proc *proc_from_pid(u32 pid) { struct node *iterator = proc_list->head; @@ -120,13 +99,18 @@ struct proc *proc_from_pid(u32 pid) return NULL; } +void proc_clear_quantum() +{ + quantum = 0; +} + void proc_exit(struct proc *proc, int status) { assert(proc); int res = 0; struct node *iterator = proc_list->head; - while (iterator != NULL) { + while (iterator) { if (iterator->data == proc) { res = 1; list_remove(proc_list, iterator); @@ -141,20 +125,38 @@ void proc_exit(struct proc *proc, int status) if (res) printf("Process %s exited with status %d\n", proc->name, status); - quantum = 0; // TODO: Add quantum to each process struct? + proc_clear_quantum(); // TODO: Add quantum to each process struct? + sti(); + hlt(); } void proc_yield(struct regs *r) { - quantum = 0; + proc_clear_quantum(); scheduler(r); } +void proc_enable_waiting(u32 dev_id) +{ + struct node *iterator = proc_list->head; + while (iterator) { + struct proc *p = iterator->data; + struct proc_wait *w = &p->wait; + if (p && w && w->id == dev_id) { + struct regs *r = &p->regs; + r->eax = (u32)w->func((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); + memset(&p->wait, 0, sizeof(p->wait)); + p->state = PROC_RUNNING; + } + iterator = iterator->next; + } +} + struct proc *proc_make(void) { struct proc *proc = malloc(sizeof(*proc)); proc->pid = current_pid++; - proc->messages = list_new(); + proc->messages = stack_new(); proc->state = PROC_RUNNING; if (current) @@ -163,6 +165,94 @@ struct proc *proc_make(void) return proc; } +s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +{ + while (*path == '/') + path++; + + int pid = 0; + while (path[0] >= '0' && path[0] <= '9') { + pid = pid * 10 + (path[0] - '0'); + path++; + } + + if (!pid && !memcmp(path, "self/", 5)) { + pid = proc_current()->pid; + path += 4; + } + + if (pid) { + struct proc *p = proc_from_pid(pid); + if (!p || path[0] != '/') + return -1; + + path++; + if (!memcmp(path, "msg", 4)) { + stack_push_bot(p->messages, buf); + return count; + } + } + + printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev); + return -1; +} + +s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +{ + (void)dev; + + while (*path == '/') + path++; + + int pid = 0; + while (path[0] >= '0' && path[0] <= '9') { + pid = pid * 10 + (path[0] - '0'); + path++; + } + + if (!pid && !memcmp(path, "self/", 5)) { + pid = proc_current()->pid; + path += 4; + } + + if (pid) { + struct proc *p = proc_from_pid(pid); + if (!p || path[0] != '/') + return -1; + + path++; + if (!memcmp(path, "pid", 4)) { + //memcpy(buf, ((u8 *)p->pid) + offset, count); + *(u32 *)buf = p->pid; + return count; + } else if (!memcmp(path, "name", 5)) { + memcpy(buf, p->name + offset, count); + return count; + } else if (!memcmp(path, "status", 7)) { + const char *status = p->state == PROC_RUNNING ? "running" : "sleeping"; + memcpy(buf, status + offset, count); + return count; + } else if (!memcmp(path, "msg", 4)) { + if (stack_empty(p->messages)) { + return 0; + } else { + u8 *msg = stack_pop(p->messages); + memcpy(buf, msg + offset, count); + return count; + } + } + } + + return -1; +} + +u8 procfs_ready(const char *path, struct device *dev) +{ + (void)path; + (void)dev; + return 1; +} + extern void proc_jump_userspace(void); u32 _esp, _eip; @@ -175,7 +265,27 @@ void proc_init(void) scheduler_enable(); proc_list = list_new(); - kernel_proc = proc_make(); + // Procfs + struct vfs *vfs = malloc(sizeof(*vfs)); + vfs->type = VFS_PROCFS; + vfs->read = procfs_read; + vfs->write = procfs_write; + vfs->ready = procfs_ready; + vfs->data = NULL; + struct device *dev = malloc(sizeof(*dev)); + dev->name = "proc"; + dev->type = DEV_CHAR; + dev->vfs = vfs; + device_add(dev); + vfs_mount(dev, "/proc/"); + + // Idle proc + struct proc *kernel_proc = proc_make(); + void (*func)() = kernel_idle; + proc_load(kernel_proc, *(void **)&func); + strcpy(kernel_proc->name, "idle"); + kernel_proc->state = PROC_SLEEPING; + idle_proc = list_add(proc_list, kernel_proc); struct node *new = list_add(proc_list, proc_make()); bin_load((char *)"/bin/init", new->data); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index e2df79a..d980317 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -1,7 +1,6 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <cpu.h> -#include <event.h> #include <fs.h> #include <interrupts.h> #include <load.h> @@ -38,7 +37,18 @@ void syscall_handler(struct regs *r) break; } case SYS_READ: { - r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); + if (vfs_ready((char *)r->ebx)) { + r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); + } else { + struct proc *p = proc_current(); + p->state = PROC_SLEEPING; + p->wait.id = vfs_find_dev((char *)r->ebx)->id; + p->wait.func = vfs_read; + proc_yield(r); + sti(); + while (1) + hlt(); + } break; } case SYS_WRITE: { @@ -74,28 +84,6 @@ void syscall_handler(struct regs *r) r->eax = timer_get(); break; } - case SYS_REGISTER: { - event_register(r->ebx, proc_current()); - break; - } - case SYS_UNREGISTER: { - event_unregister(r->ebx, proc_current()); - break; - } - case SYS_SEND: { - proc_send(proc_current(), proc_from_pid(r->ebx), r->ecx, (void *)r->edx); - proc_yield(r); - break; - } - case SYS_RECEIVE: { - struct proc_message *msg = proc_receive(proc_current()); - r->eax = (u32)(msg ? msg->msg : NULL); - break; - } - case SYS_GETPID: { - r->eax = proc_current()->pid; - break; - } case SYS_NET_OPEN: { r->eax = (int)net_open(r->ebx); break; diff --git a/kernel/inc/event.h b/kernel/inc/event.h deleted file mode 100644 index 59a0df1..0000000 --- a/kernel/inc/event.h +++ /dev/null @@ -1,19 +0,0 @@ -// MIT License, Copyright (c) 2020 Marvin Borner - -#ifndef EVENT_H -#define EVENT_H - -#include <def.h> -#include <proc.h> -#include <sys.h> - -struct event_descriptor { - u32 id; - struct proc *proc; -}; - -u32 event_register(u32 id, struct proc *proc); -void event_unregister(u32 id, struct proc *proc); -u32 event_trigger(u32 id, void *data); - -#endif diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h index ff14361..64f3970 100644 --- a/kernel/inc/fs.h +++ b/kernel/inc/fs.h @@ -18,8 +18,9 @@ struct device { enum dev_type type; struct vfs *vfs; void *data; - u32 (*read)(void *buf, u32 offset, u32 count, struct device *dev); - u32 (*write)(void *buf, u32 offset, u32 count, struct device *dev); + s32 (*read)(void *buf, u32 offset, u32 count, struct device *dev); + s32 (*write)(void *buf, u32 offset, u32 count, struct device *dev); + u8 (*ready)(); }; void device_install(void); @@ -35,9 +36,11 @@ enum vfs_type { VFS_DEVFS, VFS_TMPFS, VFS_PROCFS, VFS_EXT2 }; struct vfs { enum vfs_type type; int flags; - u32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); - u32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); - u32 (*stat)(const char *path, struct stat *buf, struct device *dev); + void *data; + s32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); + s32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev); + s32 (*stat)(const char *path, struct stat *buf, struct device *dev); + u8 (*ready)(const char *path, struct device *dev); }; struct mount_info { @@ -47,12 +50,17 @@ struct mount_info { void vfs_install(void); -u32 vfs_mounted(struct device *dev, const char *path); -u32 vfs_mount(struct device *dev, const char *path); +u8 vfs_mounted(struct device *dev, const char *path); +s32 vfs_mount(struct device *dev, const char *path); + +struct device *vfs_find_dev(const char *path); + +s32 vfs_read(const char *path, void *buf, u32 offset, u32 count); +s32 vfs_write(const char *path, void *buf, u32 offset, u32 count); +s32 vfs_stat(const char *path, struct stat *buf); +u8 vfs_ready(const char *path); -u32 vfs_read(const char *path, void *buf, u32 offset, u32 count); -u32 vfs_write(const char *path, void *buf, u32 offset, u32 count); -u32 vfs_stat(const char *path, struct stat *buf); +struct device *device_get_by_name(const char *name); /** * EXT2 @@ -145,7 +153,8 @@ struct ext2_file { u32 curr_block_pos; }; -u32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev); -u32 ext2_stat(const char *path, struct stat *buf, struct device *dev); +s32 ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev); +s32 ext2_stat(const char *path, struct stat *buf, struct device *dev); +u8 ext2_ready(const char *path, struct device *dev); #endif diff --git a/kernel/inc/keyboard.h b/kernel/inc/keyboard.h index 32168f4..22120e5 100644 --- a/kernel/inc/keyboard.h +++ b/kernel/inc/keyboard.h @@ -4,5 +4,6 @@ #define KEYBOARD_H void keyboard_install(void); +void keyboard_reset(void); #endif diff --git a/kernel/inc/load.h b/kernel/inc/load.h index 43c941c..422a28c 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -5,60 +5,7 @@ #include <proc.h> -#define ELF_MAG 0x7F // 0 -#define ELF_32 (1) // 4: 32-bit Architecture -#define ELF_LITTLE (1) // 5: Little Endian -#define ELF_CURRENT (1) // 6: ELF Current Version -#define ELF_386 (3) // header->machine x86 machine type - -#define ET_NONE 0 // Unkown type -#define ET_REL 1 // Relocatable file -#define ET_EXEC 2 // Executable file - -#define PT_LOAD 1 - -struct elf_header { - u8 ident[16]; - u16 type; - u16 machine; - u32 version; - u32 entry; - u32 phoff; - u32 shoff; - u32 flags; - u16 ehsize; - u16 phentsize; - u16 phnum; - u16 shentsize; - u16 shnum; - u16 shstrndx; -}; - -struct elf_section_header { - u32 name; - u32 type; - u32 flags; - u32 addr; - u32 offset; - u32 size; - u32 link; - u32 info; - u32 addralign; - u32 entsize; -}; - -struct elf_program_header { - u32 type; - u32 offset; - u32 vaddr; - u32 paddr; - u32 filesz; - u32 memsz; - u32 flags; - u32 align; -}; - +void proc_load(struct proc *proc, void *data); int bin_load(char *path, struct proc *proc); -void elf_load(char *path, struct proc *proc); #endif diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 5fc217c..6be7da3 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -4,12 +4,12 @@ #define PROC_H #include <def.h> -#include <event.h> #include <interrupts.h> #include <list.h> +#include <stack.h> #include <sys.h> -#define PROC_QUANTUM 100 // Milliseconds or something // TODO +#define PROC_QUANTUM 42 // Milliseconds or something // TODO #define EFLAGS_ALWAYS 0x2 // Always one #define EFLAGS_INTERRUPTS 0x200 // Enable interrupts @@ -19,32 +19,29 @@ enum proc_state { PROC_RUNNING, PROC_SLEEPING }; +struct proc_wait { + u32 id; // dev_id + s32 (*func)(); +}; + struct proc { u32 pid; char name[32]; struct regs regs; - struct regs regs_backup; + struct proc_wait wait; // dev_id enum proc_state state; - struct list *messages; + struct stack *messages; }; -struct proc_message { - struct proc *src; - struct proc *dest; - struct message *msg; -}; - -struct proc *kernel_proc; - void scheduler(struct regs *regs); void proc_init(void); void proc_print(void); struct proc *proc_current(void); -void proc_send(struct proc *src, struct proc *dest, u32 type, void *data); -struct proc_message *proc_receive(struct proc *proc); struct proc *proc_from_pid(u32 pid); void proc_exit(struct proc *proc, int status); void proc_yield(struct regs *r); +void proc_clear_quantum(); +void proc_enable_waiting(u32 dev_id); struct proc *proc_make(void); #endif diff --git a/kernel/main.c b/kernel/main.c index 563cae7..7466f5d 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -40,6 +40,7 @@ void kernel_main(struct vid_info *vid_info) // Enable drivers sti(); + keyboard_reset(); syscall_init(); proc_init(); diff --git a/libc/Makefile b/libc/Makefile index 1a8e0f0..a3d1300 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -10,6 +10,7 @@ COBJS = str.o \ cpu.o \ sys.o \ list.o \ + stack.o \ random.o CC = ccache ../cross/opt/bin/i686-elf-gcc LD = ccache ../cross/opt/bin/i686-elf-ld diff --git a/libc/inc/assert.h b/libc/inc/assert.h index 3e45f44..e42fc5a 100644 --- a/libc/inc/assert.h +++ b/libc/inc/assert.h @@ -9,7 +9,8 @@ #include <proc.h> #define assert(exp) \ if (!(exp)) { \ - printf("%s:%d: %s: Assertion '%s' failed\n", __FILE__, __LINE__, __func__, #exp); \ + printf("%s:%d: %s: Kernel assertion '%s' failed\n", __FILE__, __LINE__, __func__, \ + #exp); \ struct proc *assert_proc = proc_current(); \ if (assert_proc) \ proc_exit(assert_proc, 1); \ diff --git a/libc/inc/mem.h b/libc/inc/mem.h index 15505fd..e35ee62 100644 --- a/libc/inc/mem.h +++ b/libc/inc/mem.h @@ -5,16 +5,21 @@ #include <def.h> -// Huh +int malloc_allocated; + +void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp); +void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp); +#define malloc(size) malloc_debug(size, __FILE__, __LINE__, __func__, #size) +#define free(ptr) free_debug(ptr, __FILE__, __LINE__, __func__, #ptr) + +/* void *_malloc(u32 size); */ +/* void _free(void *ptr); */ +/* #define malloc(size) _malloc(size) */ +/* #define free(ptr) _free(ptr) */ + #ifdef kernel -#define HEAP_SIZE 0x10000 -#define HEAP_MAGIC 0x42 void heap_init(u32 start); -void *malloc(u32 size); -void free(void *ptr); #elif defined(userspace) -void *malloc(u32 size); -void free(void *ptr); #else #error "No lib target specified. Please use -Dkernel or -Duserspace" #endif @@ -23,5 +28,6 @@ void *memcpy(void *dest, const void *src, u32 n); void *memset(void *dest, int val, u32 n); void *memchr(void *src, int c, u32 n); int memcmp(const void *s1, const void *s2, u32 n); +int mememp(const u8 *buf, u32 n); #endif diff --git a/libc/inc/stack.h b/libc/inc/stack.h new file mode 100644 index 0000000..16725f8 --- /dev/null +++ b/libc/inc/stack.h @@ -0,0 +1,28 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#ifndef STACK_H +#define STACK_H + +#include <def.h> + +struct stack_node { + void *data; + int nonce; + struct stack_node *next; + struct stack_node *prev; +}; + +struct stack { + struct stack_node *tail; +}; + +struct stack *stack_new(); +void stack_destroy(struct stack *stack); +u32 stack_empty(struct stack *stack); +u32 stack_push_bot(struct stack *stack, void *data); +u32 stack_push(struct stack *stack, void *data); +void *stack_pop(struct stack *stack); +void *stack_peek(struct stack *stack); +void stack_clear(struct stack *stack); + +#endif diff --git a/libc/inc/sys.h b/libc/inc/sys.h index 3145432..14f83dd 100644 --- a/libc/inc/sys.h +++ b/libc/inc/sys.h @@ -20,11 +20,6 @@ enum sys { SYS_EXIT, // Exit current process // TODO: Free all memory of process SYS_YIELD, // Switch to next process SYS_TIME, // Get kernel time - SYS_REGISTER, // Register for event - SYS_UNREGISTER, // Unregister event - SYS_SEND, // Send message to process - SYS_RECEIVE, // Receive message (non-blocking/sync) - SYS_GETPID, // Get the process ID SYS_NET_OPEN, // Open network socket SYS_NET_CLOSE, // Close network socket SYS_NET_CONNECT, // Connect to destination @@ -94,22 +89,33 @@ int sysv(enum sys num, ...); #define yield() (int)sys0(SYS_YIELD) #define time() (u32) sys0(SYS_TIME) -#define event_register(id) sys1(SYS_REGISTER, (int)(id)) -#define event_unregister(id) sys1(SYS_UNREGISTER, (int)(id)) +static inline u32 getpid() +{ + u32 buf = 0; + read("/proc/self/pid", &buf, 0, sizeof(buf)); + return buf; +} -#define msg_send(pid, type, msg) sys3(SYS_SEND, (int)(pid), (int)(type), (int)(msg)) -#define msg_receive() (struct message *)sys0(SYS_RECEIVE) -#define getpid() (int)sys0(SYS_GETPID) -static inline struct message *msg_receive_loop() +// Hacky one-digit solution - TODO! +#include <mem.h> +#include <str.h> +static inline u32 pidof(const char *name) { - struct message *msg; - while (!(msg = msg_receive())) - yield(); - return msg; + u32 curr = 1; + char buf[32] = { 0 }; + char *path = (char *)"/proc/1/name"; // AAH + while (read(path, buf, 0, 32)) { + if (!strcmp(name, buf)) + return curr; + + curr++; + path[7]++; + } + + return 0; } // Simple read wrapper -#include <mem.h> static inline void *sread(const char *path) { struct stat s = { 0 }; @@ -1,5 +1,6 @@ // MIT License, Copyright (c) 2020 Marvin Borner +#include <assert.h> #include <def.h> #include <mem.h> #include <sys.h> @@ -68,126 +69,318 @@ int memcmp(const void *s1, const void *s2, u32 n) return 0; } -#define ALIGNMENT 16ul -#define ALIGN_TYPE char -#define ALIGN_INFO sizeof(ALIGN_TYPE) * 16 +int mememp(const u8 *buf, u32 n) +{ + return buf[0] == 0 && !memcmp(buf, buf + 1, n - 1); +} -#define ALIGN(ptr) \ - if (ALIGNMENT > 1) { \ - u32 diff; \ - ptr = (void *)((u32)ptr + ALIGN_INFO); \ - diff = (u32)ptr & (ALIGNMENT - 1); \ - if (diff != 0) { \ - diff = ALIGNMENT - diff; \ - ptr = (void *)((u32)ptr + diff); \ - } \ - *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)) = diff + ALIGN_INFO; \ - } +/** + * Heap allocator + */ + +#ifdef kernel -#define UNALIGN(ptr) \ - if (ALIGNMENT > 1) { \ - u32 diff = *((ALIGN_TYPE *)((u32)ptr - ALIGN_INFO)); \ - if (diff < (ALIGNMENT + ALIGN_INFO)) { \ - ptr = (void *)((u32)ptr - diff); \ - } \ +int malloc_allocated = 0; + +#define HEAP_MAGIC 0x42424242 +#define HEAP_INIT_SIZE 0xff000000 +#define HEAP_MIN_SIZE HEAP_INIT_SIZE +#define MIN_ALLOC_SZ 4 +#define BIN_COUNT 9 +#define BIN_MAX_IDX (BIN_COUNT - 1) +#define OVERHEAD (sizeof(struct h_footer) + sizeof(struct h_node)) +/* #define MIN_WILDERNESS 0x2000 */ +/* #define MAX_WILDERNESS 0x1000000 */ + +struct h_node { + u32 magic; + u32 hole; + u32 size; + struct h_node *next; + struct h_node *prev; +}; + +struct h_footer { + struct h_node *header; +}; + +struct h_bin { + struct h_node *head; +}; + +struct heap { + u32 start; + u32 end; + struct h_bin bins[BIN_COUNT]; +}; + +void node_add(struct h_bin *bin, struct h_node *node) +{ + node->magic = HEAP_MAGIC; + node->next = NULL; + node->prev = NULL; + if (!bin->head) { + bin->head = node; + return; + } + struct h_node *curr = bin->head; + struct h_node *prev = NULL; + while (curr && curr->size <= node->size) { + prev = curr; + curr = curr->next; } + if (!curr) { + prev->next = node; + node->prev = prev; + } else if (prev) { + node->next = curr; + prev->next = node; + node->prev = prev; + curr->prev = node; + } else { + node->next = bin->head; + bin->head->prev = node; + bin->head = node; + } +} -#ifdef kernel +void node_remove(struct h_bin *bin, struct h_node *node) +{ + if (!bin->head) + return; + if (bin->head == node) { + bin->head = bin->head->next; + return; + } -static u32 *heap; -static u32 index; + struct h_node *temp = bin->head->next; + while (temp) { + if (temp == node) { + if (!temp->next) { + temp->prev->next = NULL; + } else { + temp->prev->next = temp->next; + temp->next->prev = temp->prev; + } + return; + } + temp = temp->next; + } +} -void heap_init(u32 start) +struct h_node *node_best_fit(struct h_bin *bin, u32 size) { - heap = (u32 *)start; - for (int i = 0; i < HEAP_SIZE; i++) - heap[i] = 0; - heap[0] = HEAP_MAGIC; - index = 1; + if (!bin->head) + return NULL; + + struct h_node *temp = bin->head; + while (temp) { + if (temp->size >= size) + return temp; + temp = temp->next; + } + return NULL; } -int count() +struct h_node *node_last(struct h_bin *bin) { - int i = 0; - u32 *iterator = heap + 1; - do { - iterator += iterator[0] + 1; - i++; - } while (iterator[0] != 0); - return i; + struct h_node *temp = bin->head; + while (temp->next) + temp = temp->next; + return temp; } -// TODO: Identify by pid (for freeing) -void *malloc(u32 size) +struct h_footer *node_foot(struct h_node *node) { - if (size < 1) - return NULL; + return (struct h_footer *)((char *)node + sizeof(*node) + node->size); +} - size = size + ALIGNMENT + ALIGN_INFO; +void node_create_foot(struct h_node *head) +{ + struct h_footer *foot = node_foot(head); + foot->header = head; +} - heap[index] = size; - index += size + 1; +u32 bin_index(u32 sz) +{ + u32 index = 0; + sz = sz < 4 ? 4 : sz; + while (sz >>= 1) + index++; + index -= 2; + if (index > BIN_MAX_IDX) + index = BIN_MAX_IDX; + return index; +} - void *p = (void *)(heap + index - size); - ALIGN(p); +/* struct h_node *wilderness_get(struct heap *heap) */ +/* { */ +/* struct h_footer *wild_foot = (struct h_footer *)((char *)heap->end - sizeof(*wild_foot)); */ +/* return wild_foot->header; */ +/* } */ - return p; +u32 expand(struct heap *heap, u32 sz) +{ + (void)heap; + (void)sz; + return 0; } -// TODO: Implement free, realloc and find_smallest_hole -void free(void *ptr) +u32 contract(struct heap *heap, u32 sz) { - (void)ptr; - /* UNALIGN(ptr); */ + (void)heap; + (void)sz; + return 0; } -void *realloc(void *ptr, u32 size) +static struct heap heap = { 0 }; +void heap_init(u32 start) { - (void)size; - return ptr; + struct h_node *init_region = (struct h_node *)start; + init_region->hole = 1; + init_region->size = HEAP_INIT_SIZE - OVERHEAD; + node_create_foot(init_region); + node_add(&heap.bins[bin_index(init_region->size)], init_region); + heap.start = start; + heap.end = start + HEAP_INIT_SIZE; } -#elif defined(userspace) +void *_malloc(u32 size) +{ + malloc_allocated += size; + u32 index = bin_index(size); + struct h_bin *temp = (struct h_bin *)&heap.bins[index]; + struct h_node *found = node_best_fit(temp, size); -#define HEAP_SIZE 100000 + while (!found) { + assert(index + 1 < BIN_COUNT); -#define kmalloc(n) (void *)sys1(SYS_MALLOC, n) -#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr)) + temp = &heap.bins[++index]; + found = node_best_fit(temp, size); + } -/* static u32 *heap = NULL; */ -/* static u32 index = 0; */ -/* static u32 malloced = 0; */ + assert(found->magic == HEAP_MAGIC); -// TODO: Fix userspace malloc (for size > HEAP_SIZE)! -void *malloc(u32 size) -{ - return kmalloc(size); + if ((found->size - size) > (OVERHEAD + MIN_ALLOC_SZ)) { + struct h_node *split = (struct h_node *)(((char *)found + OVERHEAD) + size); + split->magic = HEAP_MAGIC; + split->size = found->size - size - OVERHEAD; + split->hole = 1; - /* if (size < 1) */ - /* return NULL; */ + node_create_foot(split); - /* size = size + ALIGNMENT + ALIGN_INFO; */ + u32 new_idx = bin_index(split->size); - /* if (!malloced || size > malloced) { */ - /* heap = kmalloc(HEAP_SIZE); */ - /* malloced = HEAP_SIZE; */ + node_add(&heap.bins[new_idx], split); + + found->size = size; + node_create_foot(found); + } + + found->hole = 0; + node_remove(&heap.bins[index], found); + + // TODO: Implement expand/contract + /* struct h_node *wild = wilderness_get(&heap); */ + /* if (wild->size < MIN_WILDERNESS) { */ + /* assert(expand(&heap, 0x1000)); */ + /* } else if (wild->size > MAX_WILDERNESS) { */ + /* assert(contract(&heap, 0x1000)); */ /* } */ - /* malloced -= size; */ - /* heap[index] = size; */ - /* index += size + 1; */ + found->prev = NULL; + found->next = NULL; + return &found->next; +} + +void _free(void *p) +{ + if (!p) + return; + + struct h_bin *list; + struct h_footer *new_foot, *old_foot; + + struct h_node *head = (struct h_node *)((char *)p - 12); + assert(head->magic == HEAP_MAGIC && head->hole == 0); + malloc_allocated -= head->size; + if (head == (struct h_node *)(u32 *)heap.start) { + head->hole = 1; + node_add(&heap.bins[bin_index(head->size)], head); + return; + } + + struct h_node *next = (struct h_node *)((char *)node_foot(head) + sizeof(struct h_footer)); + struct h_footer *f = (struct h_footer *)((char *)head - sizeof(struct h_footer)); + struct h_node *prev = f->header; + + if (prev->hole) { + list = &heap.bins[bin_index(prev->size)]; + node_remove(list, prev); + + prev->size += OVERHEAD + head->size; + new_foot = node_foot(head); + new_foot->header = prev; + + head = prev; + } + + if (next->hole) { + list = &heap.bins[bin_index(next->size)]; + node_remove(list, next); + + head->size += OVERHEAD + next->size; + + old_foot = node_foot(next); + old_foot->header = 0; + next->size = 0; + next->hole = 0; + + new_foot = node_foot(head); + new_foot->header = head; + } + + head->hole = 1; + node_add(&heap.bins[bin_index(head->size)], head); +} - /* void *p = (void *)(heap + index - size); */ - /* ALIGN(p); */ +#elif defined(userspace) + +#define kmalloc(n) (void *)sys1(SYS_MALLOC, n) +#define kfree(ptr) (void)(sys1(SYS_FREE, (int)ptr)) + +void *_malloc(u32 size) +{ + return kmalloc(size); +} - /* return p; */ +void _free(void *ptr) +{ + kfree(ptr); } -// TODO: Implement free, realloc and find_smallest_hole -void free(void *ptr) +#endif + +void *malloc_debug(u32 size, const char *file, int line, const char *func, const char *inp) { - (void)ptr; - /* UNALIGN(ptr); */ + void *ret = _malloc(size); +#ifdef kernel + printf("K"); +#else + printf("U"); +#endif + printf("MALLOC\t%s:%d: %s: 0x%x %dB (%s)\n", file, line, func, ret, size, inp); + return ret; } +void free_debug(void *ptr, const char *file, int line, const char *func, const char *inp) +{ +#ifdef kernel + printf("K"); +#else + printf("U"); #endif + printf("FREE\t%s:%d: %s: 0x%x (%s)\n", file, line, func, ptr, inp); + if (ptr) + _free(ptr); +} diff --git a/libc/stack.c b/libc/stack.c new file mode 100644 index 0000000..c47dd59 --- /dev/null +++ b/libc/stack.c @@ -0,0 +1,125 @@ +// MIT License, Copyright (c) 2020 Marvin Borner + +#include <def.h> +#include <mem.h> +#include <stack.h> + +static int nonce = 0; + +struct stack *stack_new() +{ + struct stack *stack = malloc(sizeof(*stack)); + stack->tail = NULL; + return stack; +} + +void stack_destroy(struct stack *stack) +{ + struct stack_node *iterator = stack->tail; + while (iterator) { + if (!iterator->prev) { + free(iterator); + break; + } + iterator = iterator->prev; + free(iterator->next); + } + stack->tail = NULL; + free(stack); + stack = NULL; +} + +struct stack_node *stack_new_node() +{ + struct stack_node *node = malloc(sizeof(*node)); + node->data = NULL; + node->prev = NULL; + node->next = NULL; + node->nonce = nonce++; + return node; +} + +u32 stack_push_bot_node(struct stack *stack, struct stack_node *node) +{ + if (!stack || !node) + return 0; + + if (stack->tail) { + struct stack_node *iterator = stack->tail; + while (iterator) { + if (!iterator->prev) + break; + iterator = iterator->prev; + } + iterator->prev = node; + node->next = iterator; + } else { + stack->tail = node; + } + + return 1; +} + +u32 stack_push_node(struct stack *stack, struct stack_node *node) +{ + if (!stack || !node) + return 0; + + if (stack->tail) { + stack->tail->next = node; + node->prev = stack->tail; + stack->tail = node; + } else { + stack->tail = node; + } + + return 1; +} + +u32 stack_empty(struct stack *stack) +{ + return !stack->tail; +} + +u32 stack_push_bot(struct stack *stack, void *data) +{ + struct stack_node *node = stack_new_node(); + node->data = data; + return stack_push_bot_node(stack, node); +} + +u32 stack_push(struct stack *stack, void *data) +{ + struct stack_node *node = stack_new_node(); + node->data = data; + return stack_push_node(stack, node); +} + +void *stack_pop(struct stack *stack) +{ + if (!stack || !stack->tail) + return NULL; + + struct stack_node *prev = stack->tail; + + stack->tail->prev->next = NULL; + stack->tail = stack->tail->prev; + + void *data = prev->data; + free(prev); + return data; +} + +void *stack_peek(struct stack *stack) +{ + if (!stack || !stack->tail) + return NULL; + + return stack->tail; +} + +void stack_clear(struct stack *stack) +{ + while (stack_pop(stack)) + ; +} diff --git a/libgui/gfx.c b/libgui/gfx.c index 3eb388a..986ecda 100644 --- a/libgui/gfx.c +++ b/libgui/gfx.c @@ -96,6 +96,14 @@ static void draw_rectangle(struct context *ctx, int x1, int y1, int x2, int y2, } } +struct context *gfx_new_ctx(struct context *ctx) +{ + //struct message msg = { 0 }; + //msg_send(2, GFX_NEW_CONTEXT, ctx); + //memcpy(ctx, msg_receive_loop(&msg)->data, sizeof(*ctx)); + return ctx; +} + // On-demand font loading struct font *gfx_resolve_font(enum font_type font_type) { diff --git a/libgui/gui.c b/libgui/gui.c index afbc3ba..9b49c2e 100644 --- a/libgui/gui.c +++ b/libgui/gui.c @@ -465,6 +465,7 @@ struct element *gui_add_text_input(struct element *container, int x, int y, u32 ((struct element_text_input *)text_input->data)->x = x; ((struct element_text_input *)text_input->data)->y = y; ((struct element_text_input *)text_input->data)->width = width; + ((struct element_text_input *)text_input->data)->text[0] = '\0'; ((struct element_text_input *)text_input->data)->color_fg = color_fg; ((struct element_text_input *)text_input->data)->color_bg = color_bg; ((struct element_text_input *)text_input->data)->font_type = font_type; @@ -530,28 +531,28 @@ void gui_event_loop(struct element *container) if (!container) return; - struct message *msg; + struct message msg = { 0 }; struct element *focused = NULL; while (1) { - if (!(msg = msg_receive())) { - yield(); - continue; - } + /* if (!msg_receive(&msg)) { */ + yield(); + continue; + /* } */ - switch (msg->type) { + switch (msg.type) { case GUI_KILL: { remove_all(); exit(0); } case GUI_MOUSE: { - struct gui_event_mouse *event = msg->data; + struct gui_event_mouse *event = msg.data; focused = element_at(container, event->x, event->y); if (focused && focused->event.on_click && event->but1) focused->event.on_click(event, focused); break; } case GUI_KEYBOARD: { - struct gui_event_keyboard *event = msg->data; + struct gui_event_keyboard *event = msg.data; if (focused && focused->type == GUI_TYPE_TEXT_INPUT && event->press) { char *s = ((struct element_text_input *)focused->data)->text; @@ -583,14 +584,13 @@ void gui_event_loop(struct element *container) break; } case GUI_RESIZE: { - struct gui_event_resize *event = msg->data; + struct gui_event_resize *event = msg.data; struct element *root = get_root(container->window_id); root->ctx = event->new_ctx; gui_sync_window(container->window_id); break; } } - free(msg); } exit(1); diff --git a/libgui/inc/gfx.h b/libgui/inc/gfx.h index 0f4c631..718fd28 100644 --- a/libgui/inc/gfx.h +++ b/libgui/inc/gfx.h @@ -64,6 +64,7 @@ struct context { int flags; }; +struct context *gfx_new_ctx(struct context *ctx); struct font *gfx_resolve_font(enum font_type font_type); void gfx_write_char(struct context *ctx, int x, int y, enum font_type font_type, u32 c, char ch); void gfx_write(struct context *ctx, int x, int y, enum font_type font_type, u32 c, @@ -83,9 +84,8 @@ int gfx_font_width(enum font_type); * Wrappers */ -#define gfx_new_ctx(ctx) \ - (msg_send(2, GFX_NEW_CONTEXT, (ctx)), (struct context *)msg_receive_loop()->data) -#define gfx_redraw() (msg_send(2, GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization) -#define gfx_redraw_focused() (msg_send(2, GFX_REDRAW_FOCUSED, NULL)) +#define gfx_redraw() \ + (void)42 //(msg_send(2, GFX_REDRAW, NULL)) // TODO: Partial redraw (optimization) +#define gfx_redraw_focused() (void)42 //(msg_send(2, GFX_REDRAW_FOCUSED, NULL)) #endif diff --git a/libgui/png.c b/libgui/png.c index 2db6e4d..ad65eba 100644 --- a/libgui/png.c +++ b/libgui/png.c @@ -1125,9 +1125,8 @@ static struct png *png_new(void) void png_free(struct png *png) { // Deallocate image buffer - /* if (png->buffer != NULL) { */ - /* free(png->buffer); */ - /* } */ + if (png->buffer) + free(png->buffer); // Deallocate source buffer, if necessary png_free_source(png); @@ -1167,7 +1166,7 @@ struct bmp *png_load(const char *path) return NULL; void *buf = sread(path); - if (!png) { + if (!buf) { SET_ERROR(png, PNG_ENOTFOUND); png_free(png); return NULL; @@ -1190,7 +1189,6 @@ struct bmp *png_load(const char *path) bmp->pitch = png->width * (bmp->bpp >> 3); png_free(png); - free(buf); return bmp; } |