diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index 3df25fa..b5576a4 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -1,6 +1,10 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include + extern void setupSyscalls(); +extern void (*syscallHandlers[])(Syscall *); + #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index 3df25fa..b5576a4 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -1,6 +1,10 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include + extern void setupSyscalls(); +extern void (*syscallHandlers[])(Syscall *); + #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 844c779..76909ef 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -6,112 +6,53 @@ #include #include -// todo: use data structures more suited to the job -ListElement *services, *callsToProcess; +extern ListElement *callsToProcess; +extern void (*syscallHandlers[])(Syscall *); -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} +void loadAndScheduleLoader(void *multibootInfo) { + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + uint32_t tarSize = 0; + void *initrd = findInitrd(address, &tarSize); + void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram, "loader"); -Service *findServiceByCR3(uint32_t cr3) { - foreach (services, Service *, service, { - if (getPhysicalAddressKernel(service->pagingInfo.pageDirectory) == - PTR(cr3)) { - return service; - } - }) - ; - return NULL; -} + Service *loader = findService("loader"); + Provider *provider = findProvider(loader, "main"); + Syscall *runLoader = malloc(sizeof(Syscall)); + runLoader->function = SYS_RUN; + runLoader->address = provider->address; + runLoader->resume = true; + runLoader->cr3 = getPhysicalAddressKernel(loader->pagingInfo.pageDirectory); + runLoader->esp = malloc(0x1000); + runLoader->respondingTo = NULL; + runLoader->service = loader; + memset(runLoader->esp, 0, 0x1000); + runLoader->esp += 0xFFC; + *(void **)runLoader->esp = runEnd; + sharePage(&loader->pagingInfo, runLoader->esp, runLoader->esp); -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void runRequest(Provider *provider, void *parameter) { - run(provider->service, provider->address); -} - -void handleInstallSyscall(Syscall *call, Service *service) { - Provider *provider = malloc(sizeof(Provider)); - RegisterServiceProviderSyscall *registerCall = (void *)call; - char *providerName = kernelMapPhysical( - getPhysicalAddress(registerCall->pageDirectory, registerCall->name)); - provider->name = providerName; - provider->address = registerCall->handler; - provider->service = service; - listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); -} - -extern void *runEnd; - -void handleRequestSyscall(Syscall *call, Service *service) { - RequestSyscall *request = (void *)call; - char *serviceName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->service)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->request)); - Provider *callProvider = findProvider(providerService, providerName); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->id = 0; - runCall->resume = true; - runCall->respondingTo = call; - runCall->pageDirectory = providerService->pagingInfo.pageDirectory; - runCall->cr3 = U32(getPhysicalAddressKernel(runCall->pageDirectory)); - runCall->returnEsp = malloc(0x1000); - runCall->returnAddress = callProvider->address; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->returnEsp, - runCall->returnEsp); - runCall->returnEsp += 0xFFC; - *(void **)runCall->returnEsp = runEnd; - listAdd(&callsToProcess, runCall); + listAdd(&callsToProcess, runLoader); } void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); - uint32_t tarSize = 0; - void *initrd = findInitrd(address, &tarSize); + // loading the loader also reserves the needed space for the + // multiboot-loaded stuff + loadAndScheduleLoader(multibootInfo); setupSyscalls(); - void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram, "loader", &services); - Service *loader = findService("loader"); - Provider *provider = findProvider(loader, "main"); - runRequest(provider, NULL); while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { asm("hlt"); continue; } - Service *service = findServiceByCR3(call->cr3); if (call->resume) { resume(call); continue; } - switch (call->id) { - case SYS_REGISTER_FUNCTION: - handleInstallSyscall(call, service); - break; - case SYS_REQUEST: - handleRequestSyscall(call, service); - break; + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); } } } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index 3df25fa..b5576a4 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -1,6 +1,10 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include + extern void setupSyscalls(); +extern void (*syscallHandlers[])(Syscall *); + #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 844c779..76909ef 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -6,112 +6,53 @@ #include #include -// todo: use data structures more suited to the job -ListElement *services, *callsToProcess; +extern ListElement *callsToProcess; +extern void (*syscallHandlers[])(Syscall *); -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} +void loadAndScheduleLoader(void *multibootInfo) { + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + uint32_t tarSize = 0; + void *initrd = findInitrd(address, &tarSize); + void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram, "loader"); -Service *findServiceByCR3(uint32_t cr3) { - foreach (services, Service *, service, { - if (getPhysicalAddressKernel(service->pagingInfo.pageDirectory) == - PTR(cr3)) { - return service; - } - }) - ; - return NULL; -} + Service *loader = findService("loader"); + Provider *provider = findProvider(loader, "main"); + Syscall *runLoader = malloc(sizeof(Syscall)); + runLoader->function = SYS_RUN; + runLoader->address = provider->address; + runLoader->resume = true; + runLoader->cr3 = getPhysicalAddressKernel(loader->pagingInfo.pageDirectory); + runLoader->esp = malloc(0x1000); + runLoader->respondingTo = NULL; + runLoader->service = loader; + memset(runLoader->esp, 0, 0x1000); + runLoader->esp += 0xFFC; + *(void **)runLoader->esp = runEnd; + sharePage(&loader->pagingInfo, runLoader->esp, runLoader->esp); -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void runRequest(Provider *provider, void *parameter) { - run(provider->service, provider->address); -} - -void handleInstallSyscall(Syscall *call, Service *service) { - Provider *provider = malloc(sizeof(Provider)); - RegisterServiceProviderSyscall *registerCall = (void *)call; - char *providerName = kernelMapPhysical( - getPhysicalAddress(registerCall->pageDirectory, registerCall->name)); - provider->name = providerName; - provider->address = registerCall->handler; - provider->service = service; - listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); -} - -extern void *runEnd; - -void handleRequestSyscall(Syscall *call, Service *service) { - RequestSyscall *request = (void *)call; - char *serviceName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->service)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->request)); - Provider *callProvider = findProvider(providerService, providerName); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->id = 0; - runCall->resume = true; - runCall->respondingTo = call; - runCall->pageDirectory = providerService->pagingInfo.pageDirectory; - runCall->cr3 = U32(getPhysicalAddressKernel(runCall->pageDirectory)); - runCall->returnEsp = malloc(0x1000); - runCall->returnAddress = callProvider->address; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->returnEsp, - runCall->returnEsp); - runCall->returnEsp += 0xFFC; - *(void **)runCall->returnEsp = runEnd; - listAdd(&callsToProcess, runCall); + listAdd(&callsToProcess, runLoader); } void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); - uint32_t tarSize = 0; - void *initrd = findInitrd(address, &tarSize); + // loading the loader also reserves the needed space for the + // multiboot-loaded stuff + loadAndScheduleLoader(multibootInfo); setupSyscalls(); - void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram, "loader", &services); - Service *loader = findService("loader"); - Provider *provider = findProvider(loader, "main"); - runRequest(provider, NULL); while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { asm("hlt"); continue; } - Service *service = findServiceByCR3(call->cr3); if (call->resume) { resume(call); continue; } - switch (call->id) { - case SYS_REGISTER_FUNCTION: - handleInstallSyscall(call, service); - break; - case SYS_REQUEST: - handleRequestSyscall(call, service); - break; + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); } } } diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index de8745f..8e3ede8 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,27 +13,26 @@ extern void *functionsStart; extern void(runFunction)(); -extern void(runEnd)(); +Service *currentService; + +ListElement *services, *callsToProcess; void run(Service *service, void *main) { - serviceESP = malloc(0x1000); - memset(serviceESP, 0, 0x1000); - serviceESP += 0xFFC; - *(void **)serviceESP = runEnd; - sharePage(&service->pagingInfo, serviceESP, serviceESP); serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; + currentService = service; runFunction(); } void resume(Syscall *syscall) { - mainFunction = syscall->returnAddress; - serviceESP = syscall->returnEsp; - serviceCR3 = PTR(syscall->cr3); + mainFunction = syscall->address; + serviceESP = syscall->esp; + currentService = syscall->service; + serviceCR3 = syscall->cr3; runFunction(); } -void loadElf(void *elfStart, char *serviceName, ListElement **services) { +void loadElf(void *elfStart, char *serviceName) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; @@ -63,6 +62,26 @@ main->name = "main"; main->service = service; main->address = PTR(header->entryPosition); - listAdd(services, service); + listAdd(&services, service); listAdd(&service->providers, main); } + +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; +} diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index 3df25fa..b5576a4 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -1,6 +1,10 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include + extern void setupSyscalls(); +extern void (*syscallHandlers[])(Syscall *); + #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 844c779..76909ef 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -6,112 +6,53 @@ #include #include -// todo: use data structures more suited to the job -ListElement *services, *callsToProcess; +extern ListElement *callsToProcess; +extern void (*syscallHandlers[])(Syscall *); -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} +void loadAndScheduleLoader(void *multibootInfo) { + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + uint32_t tarSize = 0; + void *initrd = findInitrd(address, &tarSize); + void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram, "loader"); -Service *findServiceByCR3(uint32_t cr3) { - foreach (services, Service *, service, { - if (getPhysicalAddressKernel(service->pagingInfo.pageDirectory) == - PTR(cr3)) { - return service; - } - }) - ; - return NULL; -} + Service *loader = findService("loader"); + Provider *provider = findProvider(loader, "main"); + Syscall *runLoader = malloc(sizeof(Syscall)); + runLoader->function = SYS_RUN; + runLoader->address = provider->address; + runLoader->resume = true; + runLoader->cr3 = getPhysicalAddressKernel(loader->pagingInfo.pageDirectory); + runLoader->esp = malloc(0x1000); + runLoader->respondingTo = NULL; + runLoader->service = loader; + memset(runLoader->esp, 0, 0x1000); + runLoader->esp += 0xFFC; + *(void **)runLoader->esp = runEnd; + sharePage(&loader->pagingInfo, runLoader->esp, runLoader->esp); -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void runRequest(Provider *provider, void *parameter) { - run(provider->service, provider->address); -} - -void handleInstallSyscall(Syscall *call, Service *service) { - Provider *provider = malloc(sizeof(Provider)); - RegisterServiceProviderSyscall *registerCall = (void *)call; - char *providerName = kernelMapPhysical( - getPhysicalAddress(registerCall->pageDirectory, registerCall->name)); - provider->name = providerName; - provider->address = registerCall->handler; - provider->service = service; - listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); -} - -extern void *runEnd; - -void handleRequestSyscall(Syscall *call, Service *service) { - RequestSyscall *request = (void *)call; - char *serviceName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->service)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->request)); - Provider *callProvider = findProvider(providerService, providerName); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->id = 0; - runCall->resume = true; - runCall->respondingTo = call; - runCall->pageDirectory = providerService->pagingInfo.pageDirectory; - runCall->cr3 = U32(getPhysicalAddressKernel(runCall->pageDirectory)); - runCall->returnEsp = malloc(0x1000); - runCall->returnAddress = callProvider->address; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->returnEsp, - runCall->returnEsp); - runCall->returnEsp += 0xFFC; - *(void **)runCall->returnEsp = runEnd; - listAdd(&callsToProcess, runCall); + listAdd(&callsToProcess, runLoader); } void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); - uint32_t tarSize = 0; - void *initrd = findInitrd(address, &tarSize); + // loading the loader also reserves the needed space for the + // multiboot-loaded stuff + loadAndScheduleLoader(multibootInfo); setupSyscalls(); - void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram, "loader", &services); - Service *loader = findService("loader"); - Provider *provider = findProvider(loader, "main"); - runRequest(provider, NULL); while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { asm("hlt"); continue; } - Service *service = findServiceByCR3(call->cr3); if (call->resume) { resume(call); continue; } - switch (call->id) { - case SYS_REGISTER_FUNCTION: - handleInstallSyscall(call, service); - break; - case SYS_REQUEST: - handleRequestSyscall(call, service); - break; + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); } } } diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index de8745f..8e3ede8 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,27 +13,26 @@ extern void *functionsStart; extern void(runFunction)(); -extern void(runEnd)(); +Service *currentService; + +ListElement *services, *callsToProcess; void run(Service *service, void *main) { - serviceESP = malloc(0x1000); - memset(serviceESP, 0, 0x1000); - serviceESP += 0xFFC; - *(void **)serviceESP = runEnd; - sharePage(&service->pagingInfo, serviceESP, serviceESP); serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; + currentService = service; runFunction(); } void resume(Syscall *syscall) { - mainFunction = syscall->returnAddress; - serviceESP = syscall->returnEsp; - serviceCR3 = PTR(syscall->cr3); + mainFunction = syscall->address; + serviceESP = syscall->esp; + currentService = syscall->service; + serviceCR3 = syscall->cr3; runFunction(); } -void loadElf(void *elfStart, char *serviceName, ListElement **services) { +void loadElf(void *elfStart, char *serviceName) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; @@ -63,6 +62,26 @@ main->name = "main"; main->service = service; main->address = PTR(header->entryPosition); - listAdd(services, service); + listAdd(&services, service); listAdd(&service->providers, main); } + +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; +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 3a1bf1e..db68c2d 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,15 +21,17 @@ if (!callData) { asm("jmp runEndSyscall"); } - callData->pageDirectory = kernelMapPhysical(cr3); - void *dataPhysical = getPhysicalAddress(callData->pageDirectory, callData); + void *dataPhysical = + getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = U32(cr3); + data->cr3 = cr3; + data->service = currentService; listAdd(&callsToProcess, data); asm("jmp runEndSyscall"); } extern void(syscallStub)(); + void *syscallStubPtr = syscallStub; void *syscallStubPointer = &syscallStubPtr; @@ -38,3 +41,44 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler return; } + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, registerCall->name)); + provider->name = providerName; + provider->address = registerCall->handler; + provider->service = call->service; + listAdd(&service->providers, provider); + call->resume = true; + listAdd(&callsToProcess, call); +} + +void handleRequestSyscall(Syscall *call) { + RequestSyscall *request = (void *)call; + Service *service = call->service; + char *serviceName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, request->serviceName)); + Service *providerService = findService(serviceName); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, request->providerName)); + Provider *callProvider = findProvider(providerService, providerName); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->address = callProvider->address; + runCall->esp = malloc(0x1000); + runCall->respondingTo = call; + runCall->cr3 = + getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); + runCall->service = providerService; + runCall->resume = true; + sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFFC; + *(void **)runCall->esp = runEnd; + listAdd(&callsToProcess, runCall); +} + +void (*syscallHandlers[])(Syscall *) = {0, handleInstallSyscall, + handleRequestSyscall}; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 5e5c46b..a3c11ad 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,17 +5,18 @@ #include typedef enum { - SYS_REGISTER_FUNCTION = 1, - SYS_REQUEST = 2, + SYS_RUN, + SYS_REGISTER_FUNCTION, + SYS_REQUEST, } SyscallIds; -typedef struct { - uint32_t id; - void *returnAddress; - void *returnEsp; - uint32_t cr3; - void *respondingTo; - void *pageDirectory; +typedef struct Syscall { + uint32_t function; + void *address; + void *esp; + void *cr3; + struct Syscall *respondingTo; + void *service; bool resume; } Syscall; @@ -27,8 +28,8 @@ typedef struct { Syscall; - char *service; - char *request; + char *serviceName; + char *providerName; void *data; } RequestSyscall; diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index 32931df..1f2a82b 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -18,8 +18,14 @@ Service *service; } Provider; -extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void loadElf(void *fileData, char *serviceName); extern void run(Service *service, void *address); extern void resume(Syscall *syscall); +extern void *runEnd; + +extern Service *findService(char *); +extern Provider *findProvider(Service *, char *); +extern Service *currentService; + #endif diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h index 3df25fa..b5576a4 100644 --- a/src/kernel/include/syscall.h +++ b/src/kernel/include/syscall.h @@ -1,6 +1,10 @@ #ifndef SYSCALL_H #define SYSCALL_H +#include + extern void setupSyscalls(); +extern void (*syscallHandlers[])(Syscall *); + #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 844c779..76909ef 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -6,112 +6,53 @@ #include #include -// todo: use data structures more suited to the job -ListElement *services, *callsToProcess; +extern ListElement *callsToProcess; +extern void (*syscallHandlers[])(Syscall *); -Service *findService(char *name) { - foreach (services, Service *, service, { - if (stringEquals(service->name, name)) { - return service; - } - }) - ; - return NULL; -} +void loadAndScheduleLoader(void *multibootInfo) { + void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); + uint32_t tarSize = 0; + void *initrd = findInitrd(address, &tarSize); + void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); + loadElf(loaderProgram, "loader"); -Service *findServiceByCR3(uint32_t cr3) { - foreach (services, Service *, service, { - if (getPhysicalAddressKernel(service->pagingInfo.pageDirectory) == - PTR(cr3)) { - return service; - } - }) - ; - return NULL; -} + Service *loader = findService("loader"); + Provider *provider = findProvider(loader, "main"); + Syscall *runLoader = malloc(sizeof(Syscall)); + runLoader->function = SYS_RUN; + runLoader->address = provider->address; + runLoader->resume = true; + runLoader->cr3 = getPhysicalAddressKernel(loader->pagingInfo.pageDirectory); + runLoader->esp = malloc(0x1000); + runLoader->respondingTo = NULL; + runLoader->service = loader; + memset(runLoader->esp, 0, 0x1000); + runLoader->esp += 0xFFC; + *(void **)runLoader->esp = runEnd; + sharePage(&loader->pagingInfo, runLoader->esp, runLoader->esp); -Provider *findProvider(Service *service, char *name) { - foreach (service->providers, Provider *, provider, { - if (stringEquals(provider->name, name)) { - return provider; - } - }) - ; - return NULL; -} - -void runRequest(Provider *provider, void *parameter) { - run(provider->service, provider->address); -} - -void handleInstallSyscall(Syscall *call, Service *service) { - Provider *provider = malloc(sizeof(Provider)); - RegisterServiceProviderSyscall *registerCall = (void *)call; - char *providerName = kernelMapPhysical( - getPhysicalAddress(registerCall->pageDirectory, registerCall->name)); - provider->name = providerName; - provider->address = registerCall->handler; - provider->service = service; - listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); -} - -extern void *runEnd; - -void handleRequestSyscall(Syscall *call, Service *service) { - RequestSyscall *request = (void *)call; - char *serviceName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->service)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical( - getPhysicalAddress(request->pageDirectory, request->request)); - Provider *callProvider = findProvider(providerService, providerName); - Syscall *runCall = malloc(sizeof(Syscall)); - runCall->id = 0; - runCall->resume = true; - runCall->respondingTo = call; - runCall->pageDirectory = providerService->pagingInfo.pageDirectory; - runCall->cr3 = U32(getPhysicalAddressKernel(runCall->pageDirectory)); - runCall->returnEsp = malloc(0x1000); - runCall->returnAddress = callProvider->address; - runCall->resume = true; - sharePage(&providerService->pagingInfo, runCall->returnEsp, - runCall->returnEsp); - runCall->returnEsp += 0xFFC; - *(void **)runCall->returnEsp = runEnd; - listAdd(&callsToProcess, runCall); + listAdd(&callsToProcess, runLoader); } void kernelMain(void *multibootInfo) { setupMemory(); - void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4); - uint32_t tarSize = 0; - void *initrd = findInitrd(address, &tarSize); + // loading the loader also reserves the needed space for the + // multiboot-loaded stuff + loadAndScheduleLoader(multibootInfo); setupSyscalls(); - void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram, "loader", &services); - Service *loader = findService("loader"); - Provider *provider = findProvider(loader, "main"); - runRequest(provider, NULL); while (1) { Syscall *call = listPopFirst(&callsToProcess); if (!call) { asm("hlt"); continue; } - Service *service = findServiceByCR3(call->cr3); if (call->resume) { resume(call); continue; } - switch (call->id) { - case SYS_REGISTER_FUNCTION: - handleInstallSyscall(call, service); - break; - case SYS_REQUEST: - handleRequestSyscall(call, service); - break; + void (*handler)(Syscall *) = syscallHandlers[call->function]; + if (handler) { + handler(call); } } } diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index de8745f..8e3ede8 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,27 +13,26 @@ extern void *functionsStart; extern void(runFunction)(); -extern void(runEnd)(); +Service *currentService; + +ListElement *services, *callsToProcess; void run(Service *service, void *main) { - serviceESP = malloc(0x1000); - memset(serviceESP, 0, 0x1000); - serviceESP += 0xFFC; - *(void **)serviceESP = runEnd; - sharePage(&service->pagingInfo, serviceESP, serviceESP); serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; + currentService = service; runFunction(); } void resume(Syscall *syscall) { - mainFunction = syscall->returnAddress; - serviceESP = syscall->returnEsp; - serviceCR3 = PTR(syscall->cr3); + mainFunction = syscall->address; + serviceESP = syscall->esp; + currentService = syscall->service; + serviceCR3 = syscall->cr3; runFunction(); } -void loadElf(void *elfStart, char *serviceName, ListElement **services) { +void loadElf(void *elfStart, char *serviceName) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; @@ -63,6 +62,26 @@ main->name = "main"; main->service = service; main->address = PTR(header->entryPosition); - listAdd(services, service); + listAdd(&services, service); listAdd(&service->providers, main); } + +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; +} diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 3a1bf1e..db68c2d 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -20,15 +21,17 @@ if (!callData) { asm("jmp runEndSyscall"); } - callData->pageDirectory = kernelMapPhysical(cr3); - void *dataPhysical = getPhysicalAddress(callData->pageDirectory, callData); + void *dataPhysical = + getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = U32(cr3); + data->cr3 = cr3; + data->service = currentService; listAdd(&callsToProcess, data); asm("jmp runEndSyscall"); } extern void(syscallStub)(); + void *syscallStubPtr = syscallStub; void *syscallStubPointer = &syscallStubPtr; @@ -38,3 +41,44 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler return; } + +void handleInstallSyscall(Syscall *call) { + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + Service *service = call->service; + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, registerCall->name)); + provider->name = providerName; + provider->address = registerCall->handler; + provider->service = call->service; + listAdd(&service->providers, provider); + call->resume = true; + listAdd(&callsToProcess, call); +} + +void handleRequestSyscall(Syscall *call) { + RequestSyscall *request = (void *)call; + Service *service = call->service; + char *serviceName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, request->serviceName)); + Service *providerService = findService(serviceName); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, request->providerName)); + Provider *callProvider = findProvider(providerService, providerName); + Syscall *runCall = malloc(sizeof(Syscall)); + runCall->function = SYS_RUN; + runCall->address = callProvider->address; + runCall->esp = malloc(0x1000); + runCall->respondingTo = call; + runCall->cr3 = + getPhysicalAddressKernel(providerService->pagingInfo.pageDirectory); + runCall->service = providerService; + runCall->resume = true; + sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); + runCall->esp += 0xFFC; + *(void **)runCall->esp = runEnd; + listAdd(&callsToProcess, runCall); +} + +void (*syscallHandlers[])(Syscall *) = {0, handleInstallSyscall, + handleRequestSyscall}; diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index 957fb57..620bb05 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -35,25 +35,21 @@ ; } -void bufferFunction() {} - void syscall(void *callData) { Syscall *call = callData; - asm("mov %%ebp, %%eax" : "=a"(call->returnEsp)); - call->returnAddress = &&returnAddress; - asm(".intel_syntax noprefix\n" - "sysenter\n" - ".att_syntax" ::"a"(callData)); + asm("mov %%ebp, %%eax" : "=a"(call->esp)); + call->address = &&returnAddress; + asm("sysenter\n" ::"a"(callData)); returnAddress: - bufferFunction(); + asm("nop"); return; } void makeRequest(char *moduleName, char *functionName) { RequestSyscall call = { - .id = SYS_REQUEST, - .service = moduleName, - .request = functionName, + .function = SYS_REQUEST, + .serviceName = moduleName, + .providerName = functionName, .data = 0, }; syscall(&call); @@ -61,7 +57,7 @@ void installServiceProvider(char *name, void(provider)(void *)) { RegisterServiceProviderSyscall call = { - .id = SYS_REGISTER_FUNCTION, + .function = SYS_REGISTER_FUNCTION, .name = name, .handler = provider, }; @@ -71,10 +67,7 @@ void test() { makeRequest("loader", "test"); } int32_t main() { - // writeParallel('I'); // install installServiceProvider("test", testProvider); - // writeParallel('C'); // call test(); - // writeParallel('E'); // end return 0; }