i think it works
This commit is contained in:
commit
0e1479b168
167 files changed
+27008
No files matched your search
@@ -0,0 +1,377 @@
|
||||
// ke_syscall.c - syscall dispatch
|
||||
//
|
||||
// KeSyscallEntry (MASM64) pushes all arguments onto the kernel stack and
|
||||
// calls KeSyscallDispatch. We read them from the stack frame.
|
||||
//#include "ke_syscall.h"
|
||||
#include "ke_thread.h"
|
||||
#include "ke_sched.h"
|
||||
#include "ke_process.h"
|
||||
#include "ke_mutex.h"
|
||||
#include "ke_semaphore.h"
|
||||
#include "ke_event.h"
|
||||
#include "ke_queue.h"
|
||||
#include "ke_debug.h"
|
||||
#include "mm_virt.h"
|
||||
#include "syscall_nr.h"
|
||||
#include "hal_api.h"
|
||||
#include "io_file.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// hal pointer set at boot
|
||||
static const HAL_API* gHal;
|
||||
void KeSyscallSetHal(const HAL_API* hal) { gHal = hal; }
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Individual syscall handlers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static uint64_t SyscallExitThread(uint64_t code, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
KeExitThread(KeCurrentThread(), (int)code);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallExitProcess(uint64_t code, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* t = KeCurrentThread();
|
||||
if (t && t->Owner) KeExitProcess(t->Owner, (int)code);
|
||||
KeExitThread(t, (int)code);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
KeYield();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallSleep(uint64_t ms, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
// Simple busy-wait sleep via HAL timer.
|
||||
if (gHal) {
|
||||
uint64_t start = gHal->Timer.QueryTicks();
|
||||
while (gHal->Timer.QueryTicks() - start < ms) KeYield();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallAlloc(uint64_t size, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return (uint64_t)MmAllocateUserMemory((size_t)size);
|
||||
}
|
||||
|
||||
static uint64_t SyscallFree(uint64_t ptr, uint64_t size, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
MmFreeUserMemory((void *)ptr, (size_t)size);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallCreateThread(uint64_t entry, uint64_t arg,
|
||||
uint64_t priority, uint64_t a3,
|
||||
uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return (uint64_t)STATUS_FAILURE;
|
||||
THREAD* newThread;
|
||||
KSTATUS s = KeCreateThread(cur->Owner, entry, arg,
|
||||
(THREAD_PRIORITY)priority, &newThread);
|
||||
if (!KSUCCESS(s)) return (uint64_t)s;
|
||||
uint32_t handle;
|
||||
KeAllocateHandle(cur->Owner, &newThread->Header, &handle);
|
||||
return (uint64_t)handle;
|
||||
}
|
||||
|
||||
static uint64_t SyscallCloseHandle(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
KeCloseHandle(cur->Owner, (uint32_t)handle);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallDbgPrint(uint64_t strPtr, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
const char* s = (const char *)(uintptr_t)strPtr;
|
||||
DbgPrint(s);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
MUTEX* m; if (!KSUCCESS(MutexCreate(&m))) return 0;
|
||||
uint32_t h; KeAllocateHandle(cur->Owner, &m->Header, &h);
|
||||
ObDereferenceObject(&m->Header); // handle holds the ref
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint64_t SyscallMutexAcquire(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KSTATUS s = KeAcquireMutex((MUTEX *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallMutexRelease(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KeReleaseMutex((MUTEX *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallSemCreate(uint64_t initial, uint64_t max, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
SEMAPHORE* s; if (!KSUCCESS(SemaphoreCreate((int32_t)initial,(int32_t)max,&s))) return 0;
|
||||
uint32_t h; KeAllocateHandle(cur->Owner, &s->Header, &h);
|
||||
ObDereferenceObject(&s->Header);
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint64_t SyscallSemWait(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KSTATUS s = KeWaitSemaphore((SEMAPHORE *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallSemSignal(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KeSignalSemaphore((SEMAPHORE *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallEventCreate(uint64_t manualReset, uint64_t initial,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
EVENT* e;
|
||||
EVENT_TYPE t = manualReset ? EventManualReset : EventAutoReset;
|
||||
if (!KSUCCESS(KeEventCreate(t, (uint32_t)initial, &e))) return 0;
|
||||
uint32_t h; KeAllocateHandle(cur->Owner, &e->Header, &h);
|
||||
ObDereferenceObject(&e->Header);
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint64_t SyscallEventSet(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KeSignalEvent((EVENT *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallEventWait(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KSTATUS s = KeWaitForEvent((EVENT *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
QUEUE* q; if (!KSUCCESS(QueueCreate(&q))) return 0;
|
||||
uint32_t h; KeAllocateHandle(cur->Owner, &q->Header, &h);
|
||||
ObDereferenceObject(&q->Header);
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint64_t SyscallQueueSend(uint64_t handle, uint64_t msgPtr,
|
||||
uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KSTATUS s = KeSendMessage((QUEUE *)obj, (const QUEUE_MESSAGE *)msgPtr, (bool)blocking);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallQueueRecv(uint64_t handle, uint64_t msgPtr,
|
||||
uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; }
|
||||
KSTATUS s = KeReceiveMessage((QUEUE *)obj, (QUEUE_MESSAGE *)msgPtr, (bool)blocking);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallScreenBlit(uint64_t x, uint64_t y, uint64_t w,
|
||||
uint64_t h, uint64_t pixels, uint64_t a5) {
|
||||
(void)a5;
|
||||
if (gHal) {
|
||||
gHal->Screen.Blit((int)x, (int)y, (int)w, (int)h, (const uint32_t *)pixels);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
DbgPrint("!! SyscallScreenBlit: what?\n");
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
return gHal ? gHal->Timer.QueryTicks() : 0;
|
||||
}
|
||||
|
||||
static uint64_t SyscallOpen(uint64_t pathPtr, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
|
||||
FILE_OBJECT* f;
|
||||
KSTATUS s = IoOpenFile((const char *)pathPtr, &f);
|
||||
if (!KSUCCESS(s)) return 0;
|
||||
|
||||
uint32_t handle;
|
||||
s = KeAllocateHandle(cur->Owner, &f->Header, &handle);
|
||||
ObDereferenceObject(&f->Header); // handle holds the ref now
|
||||
if (!KSUCCESS(s)) return 0;
|
||||
return (uint64_t)handle;
|
||||
}
|
||||
|
||||
static uint64_t SyscallRead(uint64_t handle, uint64_t bufPtr, uint64_t size,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj) return 0;
|
||||
// FILE_OBJECT reuses ObjectTypeQueue slot - check it holds a Fs pointer.
|
||||
FILE_OBJECT* f = (FILE_OBJECT *)obj;
|
||||
size_t bytesRead = 0;
|
||||
IoReadFile(f, (void *)bufPtr, (size_t)size, &bytesRead);
|
||||
ObDereferenceObject(obj);
|
||||
return (uint64_t)bytesRead;
|
||||
}
|
||||
|
||||
static uint64_t SyscallFClose(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
KeCloseHandle(cur->Owner, (uint32_t)handle);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t SyscallFSeek(uint64_t handle, uint64_t offset, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return STATUS_FAILURE;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj) return STATUS_NOT_FOUND;
|
||||
KSTATUS s = IoSeekFile((FILE_OBJECT *)obj, offset);
|
||||
ObDereferenceObject(obj);
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint64_t SyscallFSize(uint64_t handle, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5;
|
||||
THREAD* cur = KeCurrentThread();
|
||||
if (!cur || !cur->Owner) return 0;
|
||||
OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle);
|
||||
if (!obj) return 0;
|
||||
uint64_t sz = IoGetFileSize((FILE_OBJECT *)obj);
|
||||
ObDereferenceObject(obj);
|
||||
return sz;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dispatch table
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef uint64_t (*SYSCALL_FN)(uint64_t, uint64_t, uint64_t,
|
||||
uint64_t, uint64_t, uint64_t);
|
||||
|
||||
static const SYSCALL_FN gSyscallTable[SYS_MAX] = {
|
||||
[SYS_EXIT_THREAD] = SyscallExitThread,
|
||||
[SYS_EXIT_PROCESS] = SyscallExitProcess,
|
||||
[SYS_SPAWN] = (SYSCALL_FN)0, // TODO: process spawn
|
||||
[SYS_SLEEP] = SyscallSleep,
|
||||
[SYS_YIELD] = SyscallYield,
|
||||
[SYS_ALLOC] = SyscallAlloc,
|
||||
[SYS_FREE] = SyscallFree,
|
||||
[SYS_CREATE_THREAD]= SyscallCreateThread,
|
||||
[SYS_OPEN_HANDLE] = (SYSCALL_FN)0, // TODO
|
||||
[SYS_CLOSE_HANDLE] = SyscallCloseHandle,
|
||||
[SYS_DBG_PRINT] = SyscallDbgPrint,
|
||||
[SYS_MUTEX_CREATE] = SyscallMutexCreate,
|
||||
[SYS_MUTEX_ACQUIRE]= SyscallMutexAcquire,
|
||||
[SYS_MUTEX_RELEASE]= SyscallMutexRelease,
|
||||
[SYS_SEM_CREATE] = SyscallSemCreate,
|
||||
[SYS_SEM_WAIT] = SyscallSemWait,
|
||||
[SYS_SEM_SIGNAL] = SyscallSemSignal,
|
||||
[SYS_EVENT_CREATE] = SyscallEventCreate,
|
||||
[SYS_EVENT_SET] = SyscallEventSet,
|
||||
[SYS_EVENT_WAIT] = SyscallEventWait,
|
||||
[SYS_QUEUE_CREATE] = SyscallQueueCreate,
|
||||
[SYS_QUEUE_SEND] = SyscallQueueSend,
|
||||
[SYS_QUEUE_RECV] = SyscallQueueRecv,
|
||||
[SYS_SCREEN_BLIT] = SyscallScreenBlit,
|
||||
[SYS_GET_TICK] = SyscallGetTick,
|
||||
[SYS_OPEN] = SyscallOpen,
|
||||
[SYS_READ] = SyscallRead,
|
||||
[SYS_FCLOSE] = SyscallFClose,
|
||||
[SYS_FSEEK] = SyscallFSeek,
|
||||
[SYS_FSIZE] = SyscallFSize,
|
||||
};
|
||||
|
||||
// Called from ke_syscall.asm - args already on the stack in order.
|
||||
uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1,
|
||||
uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
if (nr >= SYS_MAX || !gSyscallTable[nr]) return (uint64_t)STATUS_NOT_SUPPORTED;
|
||||
return gSyscallTable[nr](a0, a1, a2, a3, a4, a5);
|
||||
}
|
||||
Reference in new issue
Block a user