diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/service/serviceSyscalls.c b/src/kernel/service/serviceSyscalls.c new file mode 100644 index 0000000..f92325a --- /dev/null +++ b/src/kernel/service/serviceSyscalls.c @@ -0,0 +1,68 @@ +#include +#include + +void handleGetServiceIdSyscall(Syscall *call) { + uint32_t i = 0; + foreach (services, Service *, service, { + if (service == call->service) { + call->returnValue = i; + } + i++; + }) + ; +} + +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + call->returnValue = listCount(service->providers); + // todo make listAdd return the new index + listAdd(&service->providers, provider); +} + +void handleRequestSyscall(Syscall *call) { + Service *service = call->service; + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); + void *data = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); + scheduleProvider(provider, data, call->parameters[3], call); + call->avoidReschedule = true; +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/service/serviceSyscalls.c b/src/kernel/service/serviceSyscalls.c new file mode 100644 index 0000000..f92325a --- /dev/null +++ b/src/kernel/service/serviceSyscalls.c @@ -0,0 +1,68 @@ +#include +#include + +void handleGetServiceIdSyscall(Syscall *call) { + uint32_t i = 0; + foreach (services, Service *, service, { + if (service == call->service) { + call->returnValue = i; + } + i++; + }) + ; +} + +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + call->returnValue = listCount(service->providers); + // todo make listAdd return the new index + listAdd(&service->providers, provider); +} + +void handleRequestSyscall(Syscall *call) { + Service *service = call->service; + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); + void *data = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); + scheduleProvider(provider, data, call->parameters[3], call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c deleted file mode 100644 index 7ac6bd6..0000000 --- a/src/kernel/service/services.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "elf.h" -#include "service.h" -#include -#include -#include - -extern void *functionsStart; -extern void *functionsEnd; -extern void(runFunction)(); - -ListElement *services, *callsToProcess; -Syscall *currentSyscall; -extern Service *hlib; - -void resume(Syscall *syscall) { - if (U32(syscall) < 0x1000) { - asm("hlt" ::"a"(syscall)); - } - currentSyscall = syscall; - runFunction(); -} - -Service *loadElf(void *elfStart, char *serviceName) { - // use this function ONLY to load the initrd/loader program(maybe also the - // ELF loader service)! - ElfHeader *header = elfStart; - ProgramHeader *programHeader = - elfStart + header->programHeaderTablePosition; - Service *service = malloc(sizeof(Service)); - memset(service, 0, sizeof(Service)); - service->pagingInfo.pageDirectory = malloc(0x1000); - service->name = serviceName; - void *current = &functionsStart; - if (hlib) { - service->pagingInfo.pageDirectory[0x3FC].pageTableID = - hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; - service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; - service->pagingInfo.pageDirectory[0x3FC].present = 1; - service->pagingInfo.pageDirectory[0x3FC].writable = 1; - } - for (uint32_t i = 0; i < 3; i++) { - // todo: make this unwritable! - sharePage(&(service->pagingInfo), current, current); - current += 0x1000; - } - for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { - if (hlib && programHeader->virtualAddress >= 0xF0000000) { - goto end; - } - for (uint32_t page = 0; page < programHeader->segmentMemorySize; - page += 0x1000) { - void *data = malloc(0x1000); - memset(data, 0, 0x1000); - memcpy(elfStart + programHeader->dataOffset, data, - MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(&service->pagingInfo, data, - PTR(programHeader->virtualAddress + page)); - } - end: - programHeader = (void *)programHeader + header->programHeaderEntrySize; - } - Provider *main = malloc(sizeof(Provider)); - main->name = "main"; - main->service = service; - main->address = PTR(header->entryPosition); - listAdd(&services, service); - listAdd(&service->providers, main); - return service; -} - -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} - -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, - Syscall *respondingTo) { - sharePage(&provider->service->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = 0; - runCall->esp = malloc(0x1000); - runCall->respondingTo = respondingTo; - runCall->cr3 = - getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); - runCall->service = provider->service; - runCall->resume = true; - sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = dataLength; - listAdd(&callsToProcess, runCall); -} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/service/serviceSyscalls.c b/src/kernel/service/serviceSyscalls.c new file mode 100644 index 0000000..f92325a --- /dev/null +++ b/src/kernel/service/serviceSyscalls.c @@ -0,0 +1,68 @@ +#include +#include + +void handleGetServiceIdSyscall(Syscall *call) { + uint32_t i = 0; + foreach (services, Service *, service, { + if (service == call->service) { + call->returnValue = i; + } + i++; + }) + ; +} + +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + call->returnValue = listCount(service->providers); + // todo make listAdd return the new index + listAdd(&service->providers, provider); +} + +void handleRequestSyscall(Syscall *call) { + Service *service = call->service; + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); + void *data = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); + scheduleProvider(provider, data, call->parameters[3], call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c deleted file mode 100644 index 7ac6bd6..0000000 --- a/src/kernel/service/services.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "elf.h" -#include "service.h" -#include -#include -#include - -extern void *functionsStart; -extern void *functionsEnd; -extern void(runFunction)(); - -ListElement *services, *callsToProcess; -Syscall *currentSyscall; -extern Service *hlib; - -void resume(Syscall *syscall) { - if (U32(syscall) < 0x1000) { - asm("hlt" ::"a"(syscall)); - } - currentSyscall = syscall; - runFunction(); -} - -Service *loadElf(void *elfStart, char *serviceName) { - // use this function ONLY to load the initrd/loader program(maybe also the - // ELF loader service)! - ElfHeader *header = elfStart; - ProgramHeader *programHeader = - elfStart + header->programHeaderTablePosition; - Service *service = malloc(sizeof(Service)); - memset(service, 0, sizeof(Service)); - service->pagingInfo.pageDirectory = malloc(0x1000); - service->name = serviceName; - void *current = &functionsStart; - if (hlib) { - service->pagingInfo.pageDirectory[0x3FC].pageTableID = - hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; - service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; - service->pagingInfo.pageDirectory[0x3FC].present = 1; - service->pagingInfo.pageDirectory[0x3FC].writable = 1; - } - for (uint32_t i = 0; i < 3; i++) { - // todo: make this unwritable! - sharePage(&(service->pagingInfo), current, current); - current += 0x1000; - } - for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { - if (hlib && programHeader->virtualAddress >= 0xF0000000) { - goto end; - } - for (uint32_t page = 0; page < programHeader->segmentMemorySize; - page += 0x1000) { - void *data = malloc(0x1000); - memset(data, 0, 0x1000); - memcpy(elfStart + programHeader->dataOffset, data, - MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(&service->pagingInfo, data, - PTR(programHeader->virtualAddress + page)); - } - end: - programHeader = (void *)programHeader + header->programHeaderEntrySize; - } - Provider *main = malloc(sizeof(Provider)); - main->name = "main"; - main->service = service; - main->address = PTR(header->entryPosition); - listAdd(&services, service); - listAdd(&service->providers, main); - return service; -} - -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} - -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, - Syscall *respondingTo) { - sharePage(&provider->service->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = 0; - runCall->esp = malloc(0x1000); - runCall->respondingTo = respondingTo; - runCall->cr3 = - getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); - runCall->service = provider->service; - runCall->resume = true; - sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = dataLength; - listAdd(&callsToProcess, runCall); -} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 6427a98..168c54b 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -17,8 +17,6 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -uint32_t n = 0; - void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3) { @@ -51,202 +49,43 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - call->returnValue = listCount(service->providers); - // todo make listAdd return the new index - listAdd(&service->providers, provider); -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -extern ListElement *services; - -void handleRequestSyscall(Syscall *call) { - Service *service = call->service; - Service *providerService = listGet(services, call->parameters[0]); - Provider *provider = - listGet(providerService->providers, call->parameters[1]); - void *data = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - scheduleProvider(provider, data, call->parameters[3], call); - call->avoidReschedule = true; -} - -void handleIOInSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("in %%dx, %%al" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 2: - asm("in %%dx, %%ax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 4: - asm("in %%dx, %%eax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - } -} - -void handleIOOutSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("out %0, %1" - : - : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 2: - asm("out %0, %1" - : - : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 4: - asm("out %0, %1" - : - : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - } -} - -extern void loadProgram(char *name, Syscall *respondingTo); - -void handleLoadFromInitrdSyscall(Syscall *call) { - Service *service = call->service; - char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - loadProgram(programName, (void *)call); - call->avoidReschedule = true; -} - -void handleGetServiceSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -void handleGetProviderSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *providerService = listGet(services, call->parameters[0]); - foreach (providerService->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -extern ListElement *interruptSubscriptions[255]; - -void handleSubscribeInterruptSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = "INTERRUPT"; - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - listAdd(&interruptSubscriptions[call->parameters[0]], provider); -} - -void handleCreateEventSyscall(Syscall *call) { - Event *event = malloc(sizeof(Provider)); - Service *service = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - event->subscriptions = NULL; - event->name = name; - call->returnValue = listCount(service->events); - listAdd(&service->events, event); -} - -void handleGetEventSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *service = listGet(services, call->parameters[0]); - foreach (service->events, Event *, event, { - if (stringEquals(event->name, name)) { - call->returnValue = i; - break; - } - i++; - }) - ; - unmapPage(name); -} - -void handleFireEventSyscall(Syscall *call) { - Service *service = call->service; - Event *event = listGet(service->events, call->parameters[0]); - foreach (event->subscriptions, Provider *, provider, - { scheduleProvider(provider, 0, 0, 0); }) - ; -} - -void handleSubscribeEventSyscall(Syscall *call) { - Service *eventService = listGet(services, call->parameters[0]); - Event *event = listGet(eventService->events, call->parameters[1]); - Provider *provider = malloc(sizeof(Provider)); - provider->name = "event subscription"; - provider->service = call->service; - provider->address = PTR(call->parameters[2]); - listAdd(&event->subscriptions, provider); -} - -void handleGetServiceIdSyscall(Syscall *call) { - uint32_t i = 0; - foreach (services, Service *, service, { - if (service == call->service) { - call->returnValue = i; - } - i++; - }) - ; -} +extern uintptr_t handleLoadFromInitrdSyscall; +extern uintptr_t handleIOInSyscall, handleIOOutSyscall; +extern uintptr_t handleGetServiceIdSyscall, handleGetProviderSyscall, + handleGetServiceSyscall, handleInstallSyscall, handleRequestSyscall; +extern uintptr_t handleCreateEventSyscall, handleGetEventSyscall, + handleFireEventSyscall, handleSubscribeEventSyscall; +extern uintptr_t handleSubscribeInterruptSyscall; void (*syscallHandlers[])(Syscall *) = { 0, - (void *)handleInstallSyscall, - (void *)handleRequestSyscall, - (void *)handleIOInSyscall, - (void *)handleIOOutSyscall, - (void *)handleLoadFromInitrdSyscall, - (void *)handleGetServiceSyscall, - (void *)handleGetProviderSyscall, - (void *)handleSubscribeInterruptSyscall, - (void *)handleCreateEventSyscall, - (void *)handleGetEventSyscall, - (void *)handleFireEventSyscall, - (void *)handleSubscribeEventSyscall, - (void *)handleGetServiceIdSyscall, + (void *)&handleInstallSyscall, + (void *)&handleRequestSyscall, + (void *)&handleIOInSyscall, + (void *)&handleIOOutSyscall, + (void *)&handleLoadFromInitrdSyscall, + (void *)&handleGetServiceSyscall, + (void *)&handleGetProviderSyscall, + (void *)&handleSubscribeInterruptSyscall, + (void *)&handleCreateEventSyscall, + (void *)&handleGetEventSyscall, + (void *)&handleFireEventSyscall, + (void *)&handleSubscribeEventSyscall, + (void *)&handleGetServiceIdSyscall, }; + +void processSyscall(Syscall *call) { + if (call->resume) { + resume(call); + free(call); + return; + } + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); + } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + } +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/service/serviceSyscalls.c b/src/kernel/service/serviceSyscalls.c new file mode 100644 index 0000000..f92325a --- /dev/null +++ b/src/kernel/service/serviceSyscalls.c @@ -0,0 +1,68 @@ +#include +#include + +void handleGetServiceIdSyscall(Syscall *call) { + uint32_t i = 0; + foreach (services, Service *, service, { + if (service == call->service) { + call->returnValue = i; + } + i++; + }) + ; +} + +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + call->returnValue = listCount(service->providers); + // todo make listAdd return the new index + listAdd(&service->providers, provider); +} + +void handleRequestSyscall(Syscall *call) { + Service *service = call->service; + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); + void *data = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); + scheduleProvider(provider, data, call->parameters[3], call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c deleted file mode 100644 index 7ac6bd6..0000000 --- a/src/kernel/service/services.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "elf.h" -#include "service.h" -#include -#include -#include - -extern void *functionsStart; -extern void *functionsEnd; -extern void(runFunction)(); - -ListElement *services, *callsToProcess; -Syscall *currentSyscall; -extern Service *hlib; - -void resume(Syscall *syscall) { - if (U32(syscall) < 0x1000) { - asm("hlt" ::"a"(syscall)); - } - currentSyscall = syscall; - runFunction(); -} - -Service *loadElf(void *elfStart, char *serviceName) { - // use this function ONLY to load the initrd/loader program(maybe also the - // ELF loader service)! - ElfHeader *header = elfStart; - ProgramHeader *programHeader = - elfStart + header->programHeaderTablePosition; - Service *service = malloc(sizeof(Service)); - memset(service, 0, sizeof(Service)); - service->pagingInfo.pageDirectory = malloc(0x1000); - service->name = serviceName; - void *current = &functionsStart; - if (hlib) { - service->pagingInfo.pageDirectory[0x3FC].pageTableID = - hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; - service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; - service->pagingInfo.pageDirectory[0x3FC].present = 1; - service->pagingInfo.pageDirectory[0x3FC].writable = 1; - } - for (uint32_t i = 0; i < 3; i++) { - // todo: make this unwritable! - sharePage(&(service->pagingInfo), current, current); - current += 0x1000; - } - for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { - if (hlib && programHeader->virtualAddress >= 0xF0000000) { - goto end; - } - for (uint32_t page = 0; page < programHeader->segmentMemorySize; - page += 0x1000) { - void *data = malloc(0x1000); - memset(data, 0, 0x1000); - memcpy(elfStart + programHeader->dataOffset, data, - MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(&service->pagingInfo, data, - PTR(programHeader->virtualAddress + page)); - } - end: - programHeader = (void *)programHeader + header->programHeaderEntrySize; - } - Provider *main = malloc(sizeof(Provider)); - main->name = "main"; - main->service = service; - main->address = PTR(header->entryPosition); - listAdd(&services, service); - listAdd(&service->providers, main); - return service; -} - -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} - -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, - Syscall *respondingTo) { - sharePage(&provider->service->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = 0; - runCall->esp = malloc(0x1000); - runCall->respondingTo = respondingTo; - runCall->cr3 = - getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); - runCall->service = provider->service; - runCall->resume = true; - sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = dataLength; - listAdd(&callsToProcess, runCall); -} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 6427a98..168c54b 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -17,8 +17,6 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -uint32_t n = 0; - void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3) { @@ -51,202 +49,43 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - call->returnValue = listCount(service->providers); - // todo make listAdd return the new index - listAdd(&service->providers, provider); -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -extern ListElement *services; - -void handleRequestSyscall(Syscall *call) { - Service *service = call->service; - Service *providerService = listGet(services, call->parameters[0]); - Provider *provider = - listGet(providerService->providers, call->parameters[1]); - void *data = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - scheduleProvider(provider, data, call->parameters[3], call); - call->avoidReschedule = true; -} - -void handleIOInSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("in %%dx, %%al" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 2: - asm("in %%dx, %%ax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 4: - asm("in %%dx, %%eax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - } -} - -void handleIOOutSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("out %0, %1" - : - : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 2: - asm("out %0, %1" - : - : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 4: - asm("out %0, %1" - : - : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - } -} - -extern void loadProgram(char *name, Syscall *respondingTo); - -void handleLoadFromInitrdSyscall(Syscall *call) { - Service *service = call->service; - char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - loadProgram(programName, (void *)call); - call->avoidReschedule = true; -} - -void handleGetServiceSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -void handleGetProviderSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *providerService = listGet(services, call->parameters[0]); - foreach (providerService->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -extern ListElement *interruptSubscriptions[255]; - -void handleSubscribeInterruptSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = "INTERRUPT"; - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - listAdd(&interruptSubscriptions[call->parameters[0]], provider); -} - -void handleCreateEventSyscall(Syscall *call) { - Event *event = malloc(sizeof(Provider)); - Service *service = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - event->subscriptions = NULL; - event->name = name; - call->returnValue = listCount(service->events); - listAdd(&service->events, event); -} - -void handleGetEventSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *service = listGet(services, call->parameters[0]); - foreach (service->events, Event *, event, { - if (stringEquals(event->name, name)) { - call->returnValue = i; - break; - } - i++; - }) - ; - unmapPage(name); -} - -void handleFireEventSyscall(Syscall *call) { - Service *service = call->service; - Event *event = listGet(service->events, call->parameters[0]); - foreach (event->subscriptions, Provider *, provider, - { scheduleProvider(provider, 0, 0, 0); }) - ; -} - -void handleSubscribeEventSyscall(Syscall *call) { - Service *eventService = listGet(services, call->parameters[0]); - Event *event = listGet(eventService->events, call->parameters[1]); - Provider *provider = malloc(sizeof(Provider)); - provider->name = "event subscription"; - provider->service = call->service; - provider->address = PTR(call->parameters[2]); - listAdd(&event->subscriptions, provider); -} - -void handleGetServiceIdSyscall(Syscall *call) { - uint32_t i = 0; - foreach (services, Service *, service, { - if (service == call->service) { - call->returnValue = i; - } - i++; - }) - ; -} +extern uintptr_t handleLoadFromInitrdSyscall; +extern uintptr_t handleIOInSyscall, handleIOOutSyscall; +extern uintptr_t handleGetServiceIdSyscall, handleGetProviderSyscall, + handleGetServiceSyscall, handleInstallSyscall, handleRequestSyscall; +extern uintptr_t handleCreateEventSyscall, handleGetEventSyscall, + handleFireEventSyscall, handleSubscribeEventSyscall; +extern uintptr_t handleSubscribeInterruptSyscall; void (*syscallHandlers[])(Syscall *) = { 0, - (void *)handleInstallSyscall, - (void *)handleRequestSyscall, - (void *)handleIOInSyscall, - (void *)handleIOOutSyscall, - (void *)handleLoadFromInitrdSyscall, - (void *)handleGetServiceSyscall, - (void *)handleGetProviderSyscall, - (void *)handleSubscribeInterruptSyscall, - (void *)handleCreateEventSyscall, - (void *)handleGetEventSyscall, - (void *)handleFireEventSyscall, - (void *)handleSubscribeEventSyscall, - (void *)handleGetServiceIdSyscall, + (void *)&handleInstallSyscall, + (void *)&handleRequestSyscall, + (void *)&handleIOInSyscall, + (void *)&handleIOOutSyscall, + (void *)&handleLoadFromInitrdSyscall, + (void *)&handleGetServiceSyscall, + (void *)&handleGetProviderSyscall, + (void *)&handleSubscribeInterruptSyscall, + (void *)&handleCreateEventSyscall, + (void *)&handleGetEventSyscall, + (void *)&handleFireEventSyscall, + (void *)&handleSubscribeEventSyscall, + (void *)&handleGetServiceIdSyscall, }; + +void processSyscall(Syscall *call) { + if (call->resume) { + resume(call); + free(call); + return; + } + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); + } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + } +} diff --git a/src/kernel/util/IOSyscalls.c b/src/kernel/util/IOSyscalls.c new file mode 100644 index 0000000..80e404b --- /dev/null +++ b/src/kernel/util/IOSyscalls.c @@ -0,0 +1,41 @@ +#include + +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { + case 1: + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + case 2: + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + case 4: + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + } +} + +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { + case 1: + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + case 2: + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + case 4: + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + } +} diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 5447f13..75bd5fa 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -24,6 +24,8 @@ ListElement *subscriptions; } Event; +extern ListElement *services; + extern Service *loadElf(void *fileData, char *serviceName); extern void resume(Syscall *syscall); diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index ff27850..46ac97c 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -17,6 +17,6 @@ } Syscall; extern void setupSyscalls(); -extern void (*syscallHandlers[])(Syscall *); +extern void processSyscall(Syscall *call); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index a60440e..a5e3154 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -33,5 +33,6 @@ extern void listAdd(ListElement **list, void *data); extern void *listPopFirst(ListElement **list); extern uint32_t listCount(ListElement *list); +extern void *listGet(ListElement *list, uint32_t position); #endif diff --git a/src/kernel/interrupts/interrupts.c b/src/kernel/interrupts/interrupts.c index 368b43f..7b94c99 100644 --- a/src/kernel/interrupts/interrupts.c +++ b/src/kernel/interrupts/interrupts.c @@ -9,7 +9,6 @@ idtEntries[i].offsetHigh = U32(&idtHandler##i) >> 16; extern void *idt; - extern GDTEntry newGDT; extern TSS tss; extern Syscall *currentSyscall; @@ -87,3 +86,13 @@ outb(0x21, 0xFF); outb(0xA1, 0xFF); } + +void handleSubscribeInterruptSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = "INTERRUPT"; + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + listAdd(&interruptSubscriptions[call->parameters[0]], provider); +} diff --git a/src/kernel/main.c b/src/kernel/main.c index 52a29f6..b5f5085 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -7,7 +7,6 @@ #include extern ListElement *callsToProcess; -extern void (*syscallHandlers[])(Syscall *); void *initrd; uint32_t initrdSize; @@ -45,18 +44,6 @@ asm("sti;hlt"); continue; } - if (call->resume) { - resume(call); - free(call); - continue; - } - void (*handler)(Syscall *) = syscallHandlers[call->function]; - if (handler) { - handler(call); - } - call->resume = true; - if (!call->avoidReschedule) { - listAdd(&callsToProcess, call); - } + processSyscall(call); } } diff --git a/src/kernel/multiboot/initrdSyscall.c b/src/kernel/multiboot/initrdSyscall.c new file mode 100644 index 0000000..3d48de5 --- /dev/null +++ b/src/kernel/multiboot/initrdSyscall.c @@ -0,0 +1,12 @@ +#include +#include + +extern void loadProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(Syscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + loadProgram(programName, (void *)call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/eventSyscalls.c b/src/kernel/service/eventSyscalls.c new file mode 100644 index 0000000..0f39c00 --- /dev/null +++ b/src/kernel/service/eventSyscalls.c @@ -0,0 +1,48 @@ +#include +#include + +void handleCreateEventSyscall(Syscall *call) { + Event *event = malloc(sizeof(Provider)); + Service *service = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + event->subscriptions = NULL; + event->name = name; + call->returnValue = listCount(service->events); + listAdd(&service->events, event); +} + +void handleGetEventSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *service = listGet(services, call->parameters[0]); + foreach (service->events, Event *, event, { + if (stringEquals(event->name, name)) { + call->returnValue = i; + break; + } + i++; + }) + ; + unmapPage(name); +} + +void handleFireEventSyscall(Syscall *call) { + Service *service = call->service; + Event *event = listGet(service->events, call->parameters[0]); + foreach (event->subscriptions, Provider *, provider, + { scheduleProvider(provider, 0, 0, 0); }) + ; +} + +void handleSubscribeEventSyscall(Syscall *call) { + Service *eventService = listGet(services, call->parameters[0]); + Event *event = listGet(eventService->events, call->parameters[1]); + Provider *provider = malloc(sizeof(Provider)); + provider->name = "event subscription"; + provider->service = call->service; + provider->address = PTR(call->parameters[2]); + listAdd(&event->subscriptions, provider); +} diff --git a/src/kernel/service/service.c b/src/kernel/service/service.c new file mode 100644 index 0000000..7ac6bd6 --- /dev/null +++ b/src/kernel/service/service.c @@ -0,0 +1,109 @@ +#include "elf.h" +#include "service.h" +#include +#include +#include + +extern void *functionsStart; +extern void *functionsEnd; +extern void(runFunction)(); + +ListElement *services, *callsToProcess; +Syscall *currentSyscall; +extern Service *hlib; + +void resume(Syscall *syscall) { + if (U32(syscall) < 0x1000) { + asm("hlt" ::"a"(syscall)); + } + currentSyscall = syscall; + runFunction(); +} + +Service *loadElf(void *elfStart, char *serviceName) { + // use this function ONLY to load the initrd/loader program(maybe also the + // ELF loader service)! + ElfHeader *header = elfStart; + ProgramHeader *programHeader = + elfStart + header->programHeaderTablePosition; + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; + void *current = &functionsStart; + if (hlib) { + service->pagingInfo.pageDirectory[0x3FC].pageTableID = + hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; + service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; + service->pagingInfo.pageDirectory[0x3FC].present = 1; + service->pagingInfo.pageDirectory[0x3FC].writable = 1; + } + for (uint32_t i = 0; i < 3; i++) { + // todo: make this unwritable! + sharePage(&(service->pagingInfo), current, current); + current += 0x1000; + } + for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { + if (hlib && programHeader->virtualAddress >= 0xF0000000) { + goto end; + } + for (uint32_t page = 0; page < programHeader->segmentMemorySize; + page += 0x1000) { + void *data = malloc(0x1000); + memset(data, 0, 0x1000); + memcpy(elfStart + programHeader->dataOffset, data, + MIN(0x1000, programHeader->segmentFileSize - page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); + } + end: + programHeader = (void *)programHeader + header->programHeaderEntrySize; + } + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(&services, service); + listAdd(&service->providers, main); + return service; +} + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Provider *findProvider(Service *service, char *name) { + foreach (service->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + return provider; + } + }) + ; + return NULL; +} + +void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, + Syscall *respondingTo) { + sharePage(&provider->service->pagingInfo, data, data); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = 0; + runCall->esp = malloc(0x1000); + runCall->respondingTo = respondingTo; + runCall->cr3 = + getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); + runCall->service = provider->service; + runCall->resume = true; + sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFF0; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 0x4) = &runEnd; + *(void **)(runCall->esp + 0x8) = data; + *(uint32_t *)(runCall->esp + 0xC) = dataLength; + listAdd(&callsToProcess, runCall); +} diff --git a/src/kernel/service/serviceSyscalls.c b/src/kernel/service/serviceSyscalls.c new file mode 100644 index 0000000..f92325a --- /dev/null +++ b/src/kernel/service/serviceSyscalls.c @@ -0,0 +1,68 @@ +#include +#include + +void handleGetServiceIdSyscall(Syscall *call) { + uint32_t i = 0; + foreach (services, Service *, service, { + if (service == call->service) { + call->returnValue = i; + } + i++; + }) + ; +} + +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + provider->name = providerName; + provider->address = PTR(call->parameters[1]); + provider->service = call->service; + call->returnValue = listCount(service->providers); + // todo make listAdd return the new index + listAdd(&service->providers, provider); +} + +void handleRequestSyscall(Syscall *call) { + Service *service = call->service; + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); + void *data = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); + scheduleProvider(provider, data, call->parameters[3], call); + call->avoidReschedule = true; +} diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c deleted file mode 100644 index 7ac6bd6..0000000 --- a/src/kernel/service/services.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "elf.h" -#include "service.h" -#include -#include -#include - -extern void *functionsStart; -extern void *functionsEnd; -extern void(runFunction)(); - -ListElement *services, *callsToProcess; -Syscall *currentSyscall; -extern Service *hlib; - -void resume(Syscall *syscall) { - if (U32(syscall) < 0x1000) { - asm("hlt" ::"a"(syscall)); - } - currentSyscall = syscall; - runFunction(); -} - -Service *loadElf(void *elfStart, char *serviceName) { - // use this function ONLY to load the initrd/loader program(maybe also the - // ELF loader service)! - ElfHeader *header = elfStart; - ProgramHeader *programHeader = - elfStart + header->programHeaderTablePosition; - Service *service = malloc(sizeof(Service)); - memset(service, 0, sizeof(Service)); - service->pagingInfo.pageDirectory = malloc(0x1000); - service->name = serviceName; - void *current = &functionsStart; - if (hlib) { - service->pagingInfo.pageDirectory[0x3FC].pageTableID = - hlib->pagingInfo.pageDirectory[0x3FC].pageTableID; - service->pagingInfo.pageDirectory[0x3FC].belongsToUserProcess = 1; - service->pagingInfo.pageDirectory[0x3FC].present = 1; - service->pagingInfo.pageDirectory[0x3FC].writable = 1; - } - for (uint32_t i = 0; i < 3; i++) { - // todo: make this unwritable! - sharePage(&(service->pagingInfo), current, current); - current += 0x1000; - } - for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { - if (hlib && programHeader->virtualAddress >= 0xF0000000) { - goto end; - } - for (uint32_t page = 0; page < programHeader->segmentMemorySize; - page += 0x1000) { - void *data = malloc(0x1000); - memset(data, 0, 0x1000); - memcpy(elfStart + programHeader->dataOffset, data, - MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(&service->pagingInfo, data, - PTR(programHeader->virtualAddress + page)); - } - end: - programHeader = (void *)programHeader + header->programHeaderEntrySize; - } - Provider *main = malloc(sizeof(Provider)); - main->name = "main"; - main->service = service; - main->address = PTR(header->entryPosition); - listAdd(&services, service); - listAdd(&service->providers, main); - return service; -} - -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} - -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void scheduleProvider(Provider *provider, void *data, uint32_t dataLength, - Syscall *respondingTo) { - sharePage(&provider->service->pagingInfo, data, data); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->function = 0; - runCall->esp = malloc(0x1000); - runCall->respondingTo = respondingTo; - runCall->cr3 = - getPhysicalAddressKernel(provider->service->pagingInfo.pageDirectory); - runCall->service = provider->service; - runCall->resume = true; - sharePage(&provider->service->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFF0; - *(void **)runCall->esp = provider->address; - *(void **)(runCall->esp + 0x4) = &runEnd; - *(void **)(runCall->esp + 0x8) = data; - *(uint32_t *)(runCall->esp + 0xC) = dataLength; - listAdd(&callsToProcess, runCall); -} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 6427a98..168c54b 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -17,8 +17,6 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -uint32_t n = 0; - void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, uint32_t parameter1, uint32_t parameter2, uint32_t parameter3) { @@ -51,202 +49,43 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - call->returnValue = listCount(service->providers); - // todo make listAdd return the new index - listAdd(&service->providers, provider); -} - -void *listGet(ListElement *list, uint32_t position) { - for (uint32_t i = 0; i < position; i++) { - list = list->next; - } - return list->data; -} - -extern ListElement *services; - -void handleRequestSyscall(Syscall *call) { - Service *service = call->service; - Service *providerService = listGet(services, call->parameters[0]); - Provider *provider = - listGet(providerService->providers, call->parameters[1]); - void *data = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[2]))); - scheduleProvider(provider, data, call->parameters[3], call); - call->avoidReschedule = true; -} - -void handleIOInSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("in %%dx, %%al" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 2: - asm("in %%dx, %%ax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - case 4: - asm("in %%dx, %%eax" - : "=a"(call->returnValue) - : "d"(call->parameters[1])); - break; - } -} - -void handleIOOutSyscall(Syscall *call) { - switch (call->parameters[0]) { - case 1: - asm("out %0, %1" - : - : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 2: - asm("out %0, %1" - : - : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - case 4: - asm("out %0, %1" - : - : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); - break; - } -} - -extern void loadProgram(char *name, Syscall *respondingTo); - -void handleLoadFromInitrdSyscall(Syscall *call) { - Service *service = call->service; - char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - loadProgram(programName, (void *)call); - call->avoidReschedule = true; -} - -void handleGetServiceSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -void handleGetProviderSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *providerService = listGet(services, call->parameters[0]); - foreach (providerService->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - call->returnValue = i; - return; - } - i++; - }) - ; -} - -extern ListElement *interruptSubscriptions[255]; - -void handleSubscribeInterruptSyscall(Syscall *call) { - Provider *provider = malloc(sizeof(Provider)); - Service *service = call->service; - char *providerName = "INTERRUPT"; - provider->name = providerName; - provider->address = PTR(call->parameters[1]); - provider->service = call->service; - listAdd(&interruptSubscriptions[call->parameters[0]], provider); -} - -void handleCreateEventSyscall(Syscall *call) { - Event *event = malloc(sizeof(Provider)); - Service *service = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); - event->subscriptions = NULL; - event->name = name; - call->returnValue = listCount(service->events); - listAdd(&service->events, event); -} - -void handleGetEventSyscall(Syscall *call) { - uint32_t i = 0; - Service *callService = call->service; - char *name = kernelMapPhysical(getPhysicalAddress( - callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); - Service *service = listGet(services, call->parameters[0]); - foreach (service->events, Event *, event, { - if (stringEquals(event->name, name)) { - call->returnValue = i; - break; - } - i++; - }) - ; - unmapPage(name); -} - -void handleFireEventSyscall(Syscall *call) { - Service *service = call->service; - Event *event = listGet(service->events, call->parameters[0]); - foreach (event->subscriptions, Provider *, provider, - { scheduleProvider(provider, 0, 0, 0); }) - ; -} - -void handleSubscribeEventSyscall(Syscall *call) { - Service *eventService = listGet(services, call->parameters[0]); - Event *event = listGet(eventService->events, call->parameters[1]); - Provider *provider = malloc(sizeof(Provider)); - provider->name = "event subscription"; - provider->service = call->service; - provider->address = PTR(call->parameters[2]); - listAdd(&event->subscriptions, provider); -} - -void handleGetServiceIdSyscall(Syscall *call) { - uint32_t i = 0; - foreach (services, Service *, service, { - if (service == call->service) { - call->returnValue = i; - } - i++; - }) - ; -} +extern uintptr_t handleLoadFromInitrdSyscall; +extern uintptr_t handleIOInSyscall, handleIOOutSyscall; +extern uintptr_t handleGetServiceIdSyscall, handleGetProviderSyscall, + handleGetServiceSyscall, handleInstallSyscall, handleRequestSyscall; +extern uintptr_t handleCreateEventSyscall, handleGetEventSyscall, + handleFireEventSyscall, handleSubscribeEventSyscall; +extern uintptr_t handleSubscribeInterruptSyscall; void (*syscallHandlers[])(Syscall *) = { 0, - (void *)handleInstallSyscall, - (void *)handleRequestSyscall, - (void *)handleIOInSyscall, - (void *)handleIOOutSyscall, - (void *)handleLoadFromInitrdSyscall, - (void *)handleGetServiceSyscall, - (void *)handleGetProviderSyscall, - (void *)handleSubscribeInterruptSyscall, - (void *)handleCreateEventSyscall, - (void *)handleGetEventSyscall, - (void *)handleFireEventSyscall, - (void *)handleSubscribeEventSyscall, - (void *)handleGetServiceIdSyscall, + (void *)&handleInstallSyscall, + (void *)&handleRequestSyscall, + (void *)&handleIOInSyscall, + (void *)&handleIOOutSyscall, + (void *)&handleLoadFromInitrdSyscall, + (void *)&handleGetServiceSyscall, + (void *)&handleGetProviderSyscall, + (void *)&handleSubscribeInterruptSyscall, + (void *)&handleCreateEventSyscall, + (void *)&handleGetEventSyscall, + (void *)&handleFireEventSyscall, + (void *)&handleSubscribeEventSyscall, + (void *)&handleGetServiceIdSyscall, }; + +void processSyscall(Syscall *call) { + if (call->resume) { + resume(call); + free(call); + return; + } + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); + } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + } +} diff --git a/src/kernel/util/IOSyscalls.c b/src/kernel/util/IOSyscalls.c new file mode 100644 index 0000000..80e404b --- /dev/null +++ b/src/kernel/util/IOSyscalls.c @@ -0,0 +1,41 @@ +#include + +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { + case 1: + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + case 2: + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + case 4: + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); + break; + } +} + +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { + case 1: + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + case 2: + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + case 4: + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); + break; + } +} diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index e13ba57..f427c1d 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -33,3 +33,10 @@ ; return i; } + +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +}