summaryrefslogtreecommitdiff
path: root/src/kernel/Object
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/Object')
-rw-r--r--src/kernel/Object/Folder_if.c8
-rw-r--r--src/kernel/Object/Folder_if.h15
-rw-r--r--src/kernel/Object/Object.c188
-rw-r--r--src/kernel/Object/Object.h78
-rw-r--r--src/kernel/Object/VirtualFolder_cl.c96
-rw-r--r--src/kernel/Object/VirtualFolder_cl.h30
6 files changed, 415 insertions, 0 deletions
diff --git a/src/kernel/Object/Folder_if.c b/src/kernel/Object/Folder_if.c
new file mode 100644
index 0000000..81fd6ad
--- /dev/null
+++ b/src/kernel/Object/Folder_if.c
@@ -0,0 +1,8 @@
+#include "Folder_if.h"
+
+Interface FolderIface = {
+ "Folder", // name
+ 2, // method count
+ 1, // public method count
+ 0, 0 // internal
+};
diff --git a/src/kernel/Object/Folder_if.h b/src/kernel/Object/Folder_if.h
new file mode 100644
index 0000000..8f1db11
--- /dev/null
+++ b/src/kernel/Object/Folder_if.h
@@ -0,0 +1,15 @@
+#ifndef DEF_FOLDER_IF_H
+#define DEF_FOLDER_IF_H
+
+#include "Object.h"
+#include <tce/Folder_common.h>
+
+typedef struct _FolderMethods {
+ MethodPtr GetChildNameAt;
+ MethodPtr addChild;
+} FolderMethods;
+
+extern Interface FolderIface;
+
+#endif
+
diff --git a/src/kernel/Object/Object.c b/src/kernel/Object/Object.c
new file mode 100644
index 0000000..3af8fff
--- /dev/null
+++ b/src/kernel/Object/Object.c
@@ -0,0 +1,188 @@
+#include "Object.h"
+
+#include "VirtualFolder_cl.h"
+#include <task/task.h>
+#include <core/sys.h>
+#include <core/monitor.h>
+
+#include <lib/earray.h>
+
+struct earray numberedMethods;
+struct earray interfaces;
+
+void setup_object_system() {
+ numberedMethods.ref_vect_init_len = 32;
+ numberedMethods.vect_len = 256;
+ numberedMethods.data = 0;
+ earray_init(&numberedMethods);
+
+ interfaces.ref_vect_init_len = 32;
+ interfaces.vect_len = 32;
+ interfaces.data = 0;
+ earray_init(&interfaces);
+
+ Class_setup(&VirtualFolderClass);
+
+ rootObject = VirtualFolder_new();
+ deviceListObject = VirtualFolder_new();
+ VirtualFolder_addChild(rootObject, 0, ".dev", deviceListObject, 0, 0);
+}
+
+void Class_setup(Class *_class) {
+ monitor_write("\n * Setup class '");
+ monitor_write(_class->name);
+ monitor_write("'... ");
+
+ int i;
+ for (i = 0; _class->interfaces[i].interface != 0; i++) {
+ Interface_setup(_class->interfaces[i].interface);
+ }
+}
+
+void Interface_setup(Interface *iface) {
+ int i;
+
+ monitor_write("\n - Setup interface '");
+ monitor_write(iface->name);
+ monitor_write("' :");
+
+ if (iface->numberedMethods != 0) return;
+
+ earray_add(&interfaces, iface);
+
+ iface->numberedMethods = kmalloc(iface->method_count * sizeof(NumberedMethod));
+ iface->methodNumbers = kmalloc(iface->method_count * sizeof(int));
+
+ for (i = 0; i < iface->method_count; i++) {
+ iface->numberedMethods[i].iface = iface;
+ iface->numberedMethods[i].numberInIface = i;
+ iface->methodNumbers[i] = earray_add(&numberedMethods, &iface->numberedMethods[i]);
+ monitor_write(" #"); monitor_writeDec(iface->methodNumbers[i]);
+ }
+}
+
+MethodPtr *Class_getInterfaceImpl(Class *_class, Interface *iface) {
+ int i;
+ for (i = 0; _class->interfaces[i].interface != 0; i++) {
+ if (_class->interfaces[i].interface == iface) {
+ return _class->interfaces[i].methods;
+ }
+ }
+ return 0;
+}
+
+Object* Object_get(Object *parent, char *path) {
+ char* member = path;
+ Object *object = parent;
+
+ while (*path != 0 && object != 0) {
+ if (*path == '/') {
+ if (member == path) {
+ member++;
+ path++;
+ } else {
+ *path = 0;
+ if (object->_class->findChild != 0) {
+ object = object->_class->findChild(object, member);
+ } else {
+ object = 0;
+ }
+ path++;
+ member = path;
+ }
+ } else {
+ path++;
+ }
+ }
+ if (object != 0 && member != path) {
+ if (object->_class->findChild != 0) {
+ object = object->_class->findChild(object, member);
+ } else {
+ object = 0;
+ }
+ }
+
+ return object;
+}
+
+// SYSCALLS
+
+int open(char* name) {
+ ASSERT(current_process != 0);
+
+ Object *obj = Object_get(rootObject, name);
+ if (obj == 0) return E_NOT_FOUND;
+ obj->handles++;
+ return earray_add(&current_process->handles, obj);
+}
+
+int open_relative(char* name, int root_handle) {
+ ASSERT(current_process != 0);
+
+ Object *parent = read_handle(current_process, root_handle);
+ if (parent == 0) return E_BAD_HANDLE;
+ Object *obj = Object_get(parent, name);
+ if (obj == 0) return E_NOT_FOUND;
+ if (obj->_class->open != 0) {
+ int r = obj->_class->open(obj, current_process);
+ if (r != 0) return r;
+ }
+ obj->handles++;
+ return earray_add(&current_process->handles, obj);
+}
+
+void close(size_t handle) {
+ ASSERT(current_process != 0);
+
+ Object *obj = read_handle(current_process, handle);
+ if (obj == 0) return;
+ obj->handles--;
+ if (obj->_class->closed != 0) obj->_class->closed(obj);
+ earray_set(&current_process->handles, handle, 0);
+}
+
+int get_methods(char* iface_name, int* whereto) {
+ int i = 0;
+ Interface *iface = 0, *tmp;
+ for (i = 0; i < interfaces.elements; i++) {
+ tmp = earray_at(&interfaces, i);
+ if (tmp != 0) {
+ if (strcmp(tmp->name, iface_name) == 0) {
+ iface = tmp;
+ break;
+ }
+ }
+ }
+ if (iface == 0) return E_NOT_FOUND;
+ for (i = 0; i < iface->public_method_count; i++) {
+ whereto[i] = iface->methodNumbers[i];
+ }
+ return iface->public_method_count;
+}
+
+Object* read_handle(struct process *proc, size_t handle) {
+ if (proc == 0) return (Object*)handle;
+ return earray_at(&proc->handles, handle);
+}
+
+int do_method_call_2(int handle, int method, size_t a, size_t b, size_t c, size_t d) {
+ ASSERT(current_process != 0)
+
+ Object *obj = read_handle(current_process, handle);
+ if (obj == 0) return E_BAD_HANDLE;
+
+ NumberedMethod *nm = earray_at(&numberedMethods, method);
+ if (nm == 0) return E_NOT_IMPLEMENTED;
+ if (nm->numberInIface >= nm->iface->public_method_count) return E_NOT_PUBLIC;
+
+ MethodPtr* m = Class_getInterfaceImpl(obj->_class, nm->iface);
+ if (m == 0) return E_NOT_IMPLEMENTED;
+ MethodPtr p = m[nm->numberInIface];
+ ASSERT(p != 0);
+
+ return p(obj, current_process, a, b, c, d);
+}
+
+void do_method_call(struct registers *regs) {
+ regs->eax = do_method_call_2(regs->eax, regs->ebx, regs->ecx, regs->edx, regs->esi, regs->edi);
+}
diff --git a/src/kernel/Object/Object.h b/src/kernel/Object/Object.h
new file mode 100644
index 0000000..1b0daec
--- /dev/null
+++ b/src/kernel/Object/Object.h
@@ -0,0 +1,78 @@
+#ifndef DEF_INTERFACE_H
+#define DEF_INTERFACE_H
+
+#include <types.h>
+#include <task/task.h>
+
+#include <tce/Object_common.h>
+
+struct _Object;
+struct _NumberedMethod;
+
+typedef struct _Interface {
+ char* name;
+ int method_count;
+ int public_method_count;
+
+ struct _NumberedMethod *numberedMethods;
+ int *methodNumbers;
+} Interface;
+
+typedef struct _NumberedMethod {
+ Interface *iface;
+ int numberInIface;
+} NumberedMethod;
+
+typedef int (*MethodPtr)(struct _Object* object, struct process* process, size_t a, size_t b, size_t c, size_t d);
+typedef struct _Object* (*FindChildPtr)(struct _Object *object, const char* name);
+typedef int (*OpenPtr)(struct _Object *object, struct process *process);
+typedef void (*ClosedPtr)(struct _Object *object);
+typedef void (*DeletePtr)(struct _Object *object);
+
+typedef struct _InterfaceImpl {
+ Interface *interface;
+ MethodPtr *methods;
+} InterfaceImpl;
+
+// ==
+
+typedef struct _Class {
+ char *name;
+ FindChildPtr findChild;
+ OpenPtr open; // optionnal - if 0, always success
+ ClosedPtr closed; // optionnal
+ DeletePtr deleted; // optionnal but should be implemented
+ InterfaceImpl interfaces[]; // zero-terminated list
+} Class;
+
+typedef struct _Object {
+ Class *_class;
+ void *data;
+ int handles; // reference counter
+} Object;
+
+//
+
+void setup_object_system();
+
+void Class_setup(Class* _class);
+void Interface_setup(Interface* iface);
+
+MethodPtr* Class_getInterfaceImpl(Class *_class, Interface *iface);
+
+Object* Object_get(Object *parent, char *path);
+
+Object *rootObject, *deviceListObject;
+
+// syscalls
+int open(char* name);
+int open_relative(char* name, int root_handle);
+void close(size_t handle);
+int get_methods(char* iface_name, int* whereto);
+
+Object* read_handle(struct process *proc, size_t handle);
+void do_method_call(struct registers *regs);
+
+
+#endif
+
diff --git a/src/kernel/Object/VirtualFolder_cl.c b/src/kernel/Object/VirtualFolder_cl.c
new file mode 100644
index 0000000..98641dd
--- /dev/null
+++ b/src/kernel/Object/VirtualFolder_cl.c
@@ -0,0 +1,96 @@
+#include <string.h>
+
+#include <core/monitor.h>
+#include <core/sys.h>
+
+#include "VirtualFolder_cl.h"
+
+MethodPtr _VirtualFolderMethodsAsFolder[] = {
+ &VirtualFolder_GetChildNameAt,
+ &VirtualFolder_addChild,
+ 0
+ };
+Class VirtualFolderClass = {
+ "VirtualFolder",
+ VirtualFolder_findChild, 0, 0, VirtualFolder_delete,
+ {
+ { &FolderIface, &_VirtualFolderMethodsAsFolder
+ },
+ { 0, { 0 } }
+ }
+};
+
+Object *VirtualFolder_new() {
+ struct _VirtualFolder *f = kmalloc(sizeof(struct _VirtualFolder));
+ f->obj.data = f;
+ f->obj._class = &VirtualFolderClass;
+ f->obj.handles = 0;
+
+ f->children.ref_vect_init_len = 32;
+ f->children.vect_len = 64;
+ f->children.data = 0;
+ earray_init(&f->children);
+
+ struct _VirtualFolder_child *fc = kmalloc(sizeof(struct _VirtualFolder));
+ fc->name = ".";
+ fc->obj = &f->obj;
+
+ earray_add(&f->children, fc);
+ f->child_count = 1;
+
+ return &f->obj;
+}
+
+void VirtualFolder_delete(Object *o) {
+ struct _VirtualFolder *f = o->data;
+ int i;
+ for (i = 1; i < f->child_count; i++) {
+ struct _VirtualFolder_child *child = earray_at(&f->children, i);
+ if (child->obj->_class->deleted != 0) child->obj->_class->deleted(child->obj);
+ kfree(child);
+ }
+ kfree(earray_at(&f->children, 0)); // self-reference, "."
+ earray_free(&f->children);
+ kfree(f);
+}
+
+Object *VirtualFolder_findChild(Object* object, const char* name) {
+ struct _VirtualFolder *f = object->data;
+ int i;
+ for (i = 1; i < f->child_count; i++) {
+ struct _VirtualFolder_child *child = earray_at(&f->children, i);
+ if (strcmp(name, child->name) == 0) return child->obj;
+ }
+ return 0;
+}
+
+
+int VirtualFolder_GetChildNameAt(Object *object, struct process *process, size_t a, size_t b, size_t c, size_t d) {
+ struct _VirtualFolder *f = object->data;
+ if (a >= f->child_count) return E_NOT_FOUND;
+ struct _VirtualFolder_child *child = earray_at(&f->children, a);
+ strcpy((char*)b, child->name);
+ return strlen(child->name);
+}
+
+int VirtualFolder_addChild(Object *object, struct process *process, size_t a, size_t b, size_t c, size_t d) {
+ ASSERT(process == 0); // this is done in kernel land
+ struct _VirtualFolder *f = object->data;
+
+ if (b == 0) return E_INVALID;
+
+ struct _VirtualFolder_child *fc = kmalloc(sizeof(struct _VirtualFolder));
+ fc->name = strdup((char*)a);
+ fc->obj = (Object*)b;
+
+ if (strlen(fc->name) >= FILENAME_MAX_LEN) {
+ fc->name[FILENAME_MAX_LEN] = 0;
+ }
+
+ // THIS SHOULD'NT BE DONE LIKE THIS, IT'S TO CHECK OUR CODE WORKS!
+ ASSERT(earray_add(&f->children, fc) == f->child_count);
+
+ f->child_count++;
+
+ return 0;
+}
diff --git a/src/kernel/Object/VirtualFolder_cl.h b/src/kernel/Object/VirtualFolder_cl.h
new file mode 100644
index 0000000..fac697d
--- /dev/null
+++ b/src/kernel/Object/VirtualFolder_cl.h
@@ -0,0 +1,30 @@
+#ifndef DEF_VIRTUALFOLDER_CL_H
+#define DEF_VIRTUALFOLDER_CL_H
+
+#include "Folder_if.h"
+
+#include <lib/earray.h>
+
+extern Class VirtualFolderClass;
+
+struct _VirtualFolder {
+ Object obj;
+
+ int child_count;
+ struct earray children;
+};
+
+struct _VirtualFolder_child {
+ char* name;
+ Object *obj;
+};
+
+Object *VirtualFolder_new();
+void VirtualFolder_delete(Object* obj);
+
+Object* VirtualFolder_findChild(Object* object, const char* name);
+
+int VirtualFolder_GetChildNameAt(Object *object, struct process* process, size_t a, size_t b, size_t c, size_t d);
+int VirtualFolder_addChild(Object *object, struct process* process, size_t a, size_t b, size_t c, size_t d);
+
+#endif