summaryrefslogtreecommitdiffstats
path: root/syscall/handler.c
blob: 6ac71da1945b214a464927ae29a974dc2f147939 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "syscall.h"
#include "object.h"
#include "handles.h"
#include "device/processor.h"
#include "print.h"
#include "error.h"
#include "lock.h"
#include "memory.h"
#include <stdint.h>
#include <stddef.h>

extern int _syscall_handler_arch(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at);

static inline int
s_invoke_release(
        objdir_t *root_dir, 
        objdir_entry_t *target, 
        uint8_t *payload,
        size_t payload_at,
        int (*invoke)(objdir_t*, objdir_entry_t*, uint8_t*, size_t))
{
    int e = invoke(root_dir, target, payload, payload_at);
    return e;
}

static int
s_syscall_handle_invoke(objdir_t *root_dir, uint8_t *payload)
{
    size_t payload_at = 0;
    size_t target_pathw;
    objdir_entry_t *target_entry;
    SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, target_pathw, target_entry);

    switch(target_entry->type) {
        case KO_NONE:
            return -KE_BADOBJ;
        case KO_OBJECT_DIRECTORY:
            return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_objdir);
        case KO_MEMORY_UNTYPED:
            return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_untyped);
        case KO_MEMORY_MAPPING:
            return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_mapping);
        default:
            return _syscall_handler_arch(root_dir, target_entry, payload, payload_at);
    }
}

int
_syscall_handler(uintmax_t argsi, int calli)
{
    objdir_t *root_dir = ((processor_t*)processor_current())->odir;
    objdir_entry_t *payload_entry = objdir_seek(root_dir, (uint8_t*)&argsi, sizeof(uintmax_t));

    if(payload_entry->type != KO_MESSAGE) {
        klogf("Tried to invoke syscall %i with invalid object %x\n", calli, argsi);
        return -KE_BADMSG;
    }
    mtx_acquire(&payload_entry->lock);
    uint8_t *payload = ko_entry_data(payload_entry);

    switch(calli) {
        case SYSCALL_INVOKE: {
            int e = s_syscall_handle_invoke(root_dir, payload);
            mtx_release(&payload_entry->lock);
            return e;
                             }
        case SYSCALL_DEBUG_PUTC:
            kprintf("%c", (char)payload[0]);
            mtx_release(&payload_entry->lock);
            return 0;
        default:
            klogf("Invalid syscall %i caught! Failing.\n", calli);
            mtx_release(&payload_entry->lock);
            return -KE_BADCALL;
    }
}