aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/drivers/ide.c4
-rw-r--r--kernel/drivers/interrupts.c11
-rw-r--r--kernel/drivers/keyboard.c41
-rw-r--r--kernel/drivers/mouse.c147
-rw-r--r--kernel/features/event.c61
-rw-r--r--kernel/features/fs.c171
-rw-r--r--kernel/features/load.c26
-rw-r--r--kernel/features/proc.c182
-rw-r--r--kernel/features/syscall.c36
-rw-r--r--kernel/inc/event.h19
-rw-r--r--kernel/inc/fs.h33
-rw-r--r--kernel/inc/keyboard.h1
-rw-r--r--kernel/inc/load.h55
-rw-r--r--kernel/inc/proc.h25
-rw-r--r--kernel/main.c1
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();