diff options
Diffstat (limited to 'kernel')
-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 |
16 files changed, 468 insertions, 348 deletions
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(); |