diff options
Diffstat (limited to 'src/kernel/Object')
-rw-r--r-- | src/kernel/Object/Folder_if.c | 8 | ||||
-rw-r--r-- | src/kernel/Object/Folder_if.h | 15 | ||||
-rw-r--r-- | src/kernel/Object/Object.c | 188 | ||||
-rw-r--r-- | src/kernel/Object/Object.h | 78 | ||||
-rw-r--r-- | src/kernel/Object/VirtualFolder_cl.c | 96 | ||||
-rw-r--r-- | src/kernel/Object/VirtualFolder_cl.h | 30 |
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(¤t_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(¤t_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(¤t_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 |