diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h deleted file mode 100644 index e1955f4..0000000 --- a/src/kernel/service/service.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -#include - -typedef struct { - uint32_t registers[20]; -} Context; - -typedef struct { - PagingInfo pagingInfo; - uint32_t operationCount; - void **operationLocations; - char **operationNames; - // AllocationBlock allocationBlocks[12]; -} Service; - -typedef struct { - uint32_t operation; - void *parameters; -} Request; - -#endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h deleted file mode 100644 index e1955f4..0000000 --- a/src/kernel/service/service.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -#include - -typedef struct { - uint32_t registers[20]; -} Context; - -typedef struct { - PagingInfo pagingInfo; - uint32_t operationCount; - void **operationLocations; - char **operationNames; - // AllocationBlock allocationBlocks[12]; -} Service; - -typedef struct { - uint32_t operation; - void *parameters; -} Request; - -#endif diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index dc117b0..de8745f 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -2,46 +2,50 @@ #include "service.h" #include #include +#include #include -Service loaderService; -Service kernelService; -Context kernelContext; - extern void *kernelCodePageTable; -// these are temporary variables but I need the pointers in the asm parts -void *currentCr3 = 0; -void *currentEsp = 0; +void *serviceCR3 = 0; +void *serviceESP = 0; void *mainFunction = NULL; -void *returnStack = 0; extern void *functionsStart; extern void(runFunction)(); extern void(runEnd)(); void run(Service *service, void *main) { - currentEsp = malloc(0x1000); - memset(currentEsp, 0, 0x1000); - ((void **)currentEsp)[0x3FF] = runEnd; - sharePage(&service->pagingInfo, currentEsp, currentEsp); - currentCr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + serviceESP = malloc(0x1000); + memset(serviceESP, 0, 0x1000); + serviceESP += 0xFFC; + *(void **)serviceESP = runEnd; + sharePage(&service->pagingInfo, serviceESP, serviceESP); + serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; - asm("jmp runFunction"); + runFunction(); } -void loadElf(void *elfStart) { +void resume(Syscall *syscall) { + mainFunction = syscall->returnAddress; + serviceESP = syscall->returnEsp; + serviceCR3 = PTR(syscall->cr3); + runFunction(); +} + +void loadElf(void *elfStart, char *serviceName, ListElement **services) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; ProgramHeader *programHeader = elfStart + header->programHeaderTablePosition; - PagingInfo *paging = &loaderService.pagingInfo; - memset(paging, 0, sizeof(PagingInfo)); - paging->pageDirectory = malloc(0x1000); + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; // todo: make this unwritable! // todo: use functionsStart as the reference - sharePage(paging, PTR(0xFFC02000), + sharePage(&(service->pagingInfo), PTR(0xFFC02000), PTR(0xFFC02000)); // functionsStart, functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; @@ -50,9 +54,15 @@ memset(data, 0, 0x1000); memcpy(elfStart + programHeader->dataOffset, data, MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(paging, data, PTR(programHeader->virtualAddress + page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); } programHeader = (void *)programHeader + header->programHeaderEntrySize; } - run(&loaderService, PTR(header->entryPosition)); + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(services, service); + listAdd(&service->providers, main); } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h deleted file mode 100644 index e1955f4..0000000 --- a/src/kernel/service/service.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -#include - -typedef struct { - uint32_t registers[20]; -} Context; - -typedef struct { - PagingInfo pagingInfo; - uint32_t operationCount; - void **operationLocations; - char **operationNames; - // AllocationBlock allocationBlocks[12]; -} Service; - -typedef struct { - uint32_t operation; - void *parameters; -} Request; - -#endif diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index dc117b0..de8745f 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -2,46 +2,50 @@ #include "service.h" #include #include +#include #include -Service loaderService; -Service kernelService; -Context kernelContext; - extern void *kernelCodePageTable; -// these are temporary variables but I need the pointers in the asm parts -void *currentCr3 = 0; -void *currentEsp = 0; +void *serviceCR3 = 0; +void *serviceESP = 0; void *mainFunction = NULL; -void *returnStack = 0; extern void *functionsStart; extern void(runFunction)(); extern void(runEnd)(); void run(Service *service, void *main) { - currentEsp = malloc(0x1000); - memset(currentEsp, 0, 0x1000); - ((void **)currentEsp)[0x3FF] = runEnd; - sharePage(&service->pagingInfo, currentEsp, currentEsp); - currentCr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + serviceESP = malloc(0x1000); + memset(serviceESP, 0, 0x1000); + serviceESP += 0xFFC; + *(void **)serviceESP = runEnd; + sharePage(&service->pagingInfo, serviceESP, serviceESP); + serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; - asm("jmp runFunction"); + runFunction(); } -void loadElf(void *elfStart) { +void resume(Syscall *syscall) { + mainFunction = syscall->returnAddress; + serviceESP = syscall->returnEsp; + serviceCR3 = PTR(syscall->cr3); + runFunction(); +} + +void loadElf(void *elfStart, char *serviceName, ListElement **services) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; ProgramHeader *programHeader = elfStart + header->programHeaderTablePosition; - PagingInfo *paging = &loaderService.pagingInfo; - memset(paging, 0, sizeof(PagingInfo)); - paging->pageDirectory = malloc(0x1000); + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; // todo: make this unwritable! // todo: use functionsStart as the reference - sharePage(paging, PTR(0xFFC02000), + sharePage(&(service->pagingInfo), PTR(0xFFC02000), PTR(0xFFC02000)); // functionsStart, functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; @@ -50,9 +54,15 @@ memset(data, 0, 0x1000); memcpy(elfStart + programHeader->dataOffset, data, MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(paging, data, PTR(programHeader->virtualAddress + page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); } programHeader = (void *)programHeader + header->programHeaderEntrySize; } - run(&loaderService, PTR(header->entryPosition)); + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(services, service); + listAdd(&service->providers, main); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 2178ffb..93006dc 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -4,6 +4,9 @@ #include #include +extern void *runEndSyscall; +extern ListElement *callsToProcess; + void wrmsr(uint32_t msr, uint32_t low, uint32_t high) { asm("wrmsr" ::"a"(low), "d"(high), "c"(msr)); } @@ -13,16 +16,16 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void *handleSyscall(void *cr3, Syscall *callData) { +void handleSyscall(void *cr3, Syscall *callData) { + if (!callData) { + asm("jmp runEndSyscall"); + } void *pageDirectory = mapTemporary(cr3); void *dataPhysical = getPhysicalAddress(pageDirectory, callData); Syscall *data = kernelMapPhysical(dataPhysical); - switch (data->id) { - case SYS_REGISTER_FUNCTION: - - break; - } - return data; + data->cr3 = U32(cr3); + listAdd(&callsToProcess, data); + asm("jmp runEndSyscall"); } extern void(syscallStub)(); diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h deleted file mode 100644 index e1955f4..0000000 --- a/src/kernel/service/service.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -#include - -typedef struct { - uint32_t registers[20]; -} Context; - -typedef struct { - PagingInfo pagingInfo; - uint32_t operationCount; - void **operationLocations; - char **operationNames; - // AllocationBlock allocationBlocks[12]; -} Service; - -typedef struct { - uint32_t operation; - void *parameters; -} Request; - -#endif diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index dc117b0..de8745f 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -2,46 +2,50 @@ #include "service.h" #include #include +#include #include -Service loaderService; -Service kernelService; -Context kernelContext; - extern void *kernelCodePageTable; -// these are temporary variables but I need the pointers in the asm parts -void *currentCr3 = 0; -void *currentEsp = 0; +void *serviceCR3 = 0; +void *serviceESP = 0; void *mainFunction = NULL; -void *returnStack = 0; extern void *functionsStart; extern void(runFunction)(); extern void(runEnd)(); void run(Service *service, void *main) { - currentEsp = malloc(0x1000); - memset(currentEsp, 0, 0x1000); - ((void **)currentEsp)[0x3FF] = runEnd; - sharePage(&service->pagingInfo, currentEsp, currentEsp); - currentCr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + serviceESP = malloc(0x1000); + memset(serviceESP, 0, 0x1000); + serviceESP += 0xFFC; + *(void **)serviceESP = runEnd; + sharePage(&service->pagingInfo, serviceESP, serviceESP); + serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; - asm("jmp runFunction"); + runFunction(); } -void loadElf(void *elfStart) { +void resume(Syscall *syscall) { + mainFunction = syscall->returnAddress; + serviceESP = syscall->returnEsp; + serviceCR3 = PTR(syscall->cr3); + runFunction(); +} + +void loadElf(void *elfStart, char *serviceName, ListElement **services) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; ProgramHeader *programHeader = elfStart + header->programHeaderTablePosition; - PagingInfo *paging = &loaderService.pagingInfo; - memset(paging, 0, sizeof(PagingInfo)); - paging->pageDirectory = malloc(0x1000); + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; // todo: make this unwritable! // todo: use functionsStart as the reference - sharePage(paging, PTR(0xFFC02000), + sharePage(&(service->pagingInfo), PTR(0xFFC02000), PTR(0xFFC02000)); // functionsStart, functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; @@ -50,9 +54,15 @@ memset(data, 0, 0x1000); memcpy(elfStart + programHeader->dataOffset, data, MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(paging, data, PTR(programHeader->virtualAddress + page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); } programHeader = (void *)programHeader + header->programHeaderEntrySize; } - run(&loaderService, PTR(header->entryPosition)); + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(services, service); + listAdd(&service->providers, main); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 2178ffb..93006dc 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -4,6 +4,9 @@ #include #include +extern void *runEndSyscall; +extern ListElement *callsToProcess; + void wrmsr(uint32_t msr, uint32_t low, uint32_t high) { asm("wrmsr" ::"a"(low), "d"(high), "c"(msr)); } @@ -13,16 +16,16 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void *handleSyscall(void *cr3, Syscall *callData) { +void handleSyscall(void *cr3, Syscall *callData) { + if (!callData) { + asm("jmp runEndSyscall"); + } void *pageDirectory = mapTemporary(cr3); void *dataPhysical = getPhysicalAddress(pageDirectory, callData); Syscall *data = kernelMapPhysical(dataPhysical); - switch (data->id) { - case SYS_REGISTER_FUNCTION: - - break; - } - return data; + data->cr3 = U32(cr3); + listAdd(&callsToProcess, data); + asm("jmp runEndSyscall"); } extern void(syscallStub)(); diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c new file mode 100644 index 0000000..4fbc79e --- /dev/null +++ b/src/kernel/util/list.c @@ -0,0 +1,27 @@ +#include +#include + +void listAdd(ListElement **list, void *data) { + ListElement *element = *list; + if (!element) { + *list = malloc(sizeof(ListElement)); + element = *list; + } else { + while (element->next) { + element = element->next; + } + element->next = malloc(sizeof(ListElement)); + element = element->next; + } + element->next = NULL; + element->data = data; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + void *result = (*list)->data; + *list = (*list)->next; + return result; +} diff --git a/src/include/syscalls.h b/src/include/syscalls.h index 19d9c15..bfedf35 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -1,9 +1,10 @@ #ifndef SYSCALLS_H #define SYSCALLS_H +#include #include -enum { +typedef enum { SYS_REGISTER_FUNCTION, SYS_REQUEST, } SyscallIds; @@ -12,6 +13,8 @@ uint32_t id; void *returnAddress; void *returnEsp; + uint32_t cr3; + bool resume; } Syscall; typedef struct { diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 9f875fa..2ab0784 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -41,5 +41,6 @@ void *address); extern uint32_t findPage(PagingInfo *info); extern void *mapTemporary(void *address); +extern void *getMultiplePages(uint32_t size); #endif diff --git a/src/kernel/include/service.h b/src/kernel/include/service.h index b746d66..32931df 100644 --- a/src/kernel/include/service.h +++ b/src/kernel/include/service.h @@ -1,6 +1,25 @@ #ifndef SERVICE_H #define SERVICE_H -extern void loadElf(void *fileData); +#include +#include +#include + +typedef struct { + PagingInfo pagingInfo; + char *name; + ListElement *providers; +} Service; + +// the name is subject to change +typedef struct { + char *name; + void *address; + Service *service; +} Provider; + +extern void loadElf(void *fileData, char *serviceName, ListElement **services); +extern void run(Service *service, void *address); +extern void resume(Syscall *syscall); #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 748a044..21e87e4 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -16,4 +16,17 @@ extern bool stringEquals(char *string1, char *string2); extern void memcpy(void *source, void *destination, uint32_t size); +typedef struct ListElement { + struct ListElement *next; + void *data; +} ListElement; + +#define foreach(list, type, varname, ...) \ + for (ListElement *current = list; current; current = current->next) { \ + type varname = current->data; \ + __VA_ARGS__ \ + } + +extern void listAdd(ListElement **list, void *data); +extern void *listPopFirst(ListElement **list); #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index fd079cd..350adc8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,45 @@ #include #include #include +#include +#include + +// todo: use data structures more suited to the job +ListElement *services, *callsToProcess; + +Service *findService(char *name) { + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + return service; + } + }) + ; + return NULL; +} + +Service *findServiceByCR3(uint32_t cr3) { + foreach (services, Service *, service, { + if (service->pagingInfo.pageDirectory == PTR(cr3)) { + 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 runRequest(Provider *provider, void *parameter) { + run(provider->service, provider->address); +} void kernelMain(void *multibootInfo) { setupMemory(); @@ -11,8 +50,31 @@ void *initrd = findInitrd(address, &tarSize); setupSyscalls(); void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader"); - loadElf(loaderProgram); - asm("mov %%eax, %0" ::"r"(0xB105F00D)); - while (1) - ; + 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:; + Provider *provider = malloc(sizeof(Provider)); + RegisterServiceProviderSyscall *registerCall = (void *)call; + provider->name = registerCall->name; + provider->address = registerCall->handler; + provider->service = service; + listAdd(&service->providers, provider); + } + call->resume = true; + listAdd(&callsToProcess, call); + } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index b6b9b40..e715905 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -21,7 +21,7 @@ void *malloc(uint32_t size) { uint32_t sizeBit = LOG2(size) + 1; if (sizeBit > 10) { - return getPage(); + return getMultiplePages(((size - 1) >> 12) + 1); } AllocationBlock *block = allocationData[sizeBit], *last = 0; while (1) { diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index cc9c13d..3754e57 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -169,6 +169,18 @@ return PTR(virtual << 12); } +void *getMultiplePages(uint32_t count) { + uint32_t virtual = findMultiplePages(kernelVirtualPages, count); + for (uint32_t i = 0; i < count; i++) { + reservePage(kernelVirtualPages, virtual + i); + uint32_t physical = findPage(kernelPhysicalPages); + reservePage(kernelPhysicalPages, physical); + mapPage(kernelVirtualPages, PTR(physical << 12), + PTR((virtual + i) << 12), false); + } + return PTR(virtual << 12); +} + void sharePage(PagingInfo *destination, void *sourceAddress, void *destinationAddress) { PagingInfo *sourcePagingInfo = kernelVirtualPages; diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index 7ffdba1..c8267c6 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,27 +2,29 @@ global runFunction global runEnd +global runEndSyscall -extern currentCr3 -extern returnStack -extern currentEsp +extern serviceCR3 +extern serviceESP extern mainFunction +temporaryESP: resb 4 + runFunction: + push ebp mov eax, esp - mov [returnStack], eax - mov ecx, [currentEsp] - add ecx, 0xFFC + mov [temporaryESP], eax + mov ecx, [serviceESP] + mov ebp, ecx mov edx, [mainFunction] - mov eax, [currentCr3] + mov eax, [serviceCR3] mov cr3, eax sysexit runEnd: - ; todo: make a sysenter call to go back to ring 0, writing to cr3 is not possible in ring 3 - jmp $ - mov eax, 0x500000 - mov cr3, eax - mov eax, [returnStack] + mov eax, 0 + sysenter +runEndSyscall: + mov eax, [temporaryESP] mov esp, eax - jmp $ + pop ebp ret diff --git a/src/kernel/service/service.h b/src/kernel/service/service.h deleted file mode 100644 index e1955f4..0000000 --- a/src/kernel/service/service.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SERVICE_H -#define SERVICE_H - -#include - -typedef struct { - uint32_t registers[20]; -} Context; - -typedef struct { - PagingInfo pagingInfo; - uint32_t operationCount; - void **operationLocations; - char **operationNames; - // AllocationBlock allocationBlocks[12]; -} Service; - -typedef struct { - uint32_t operation; - void *parameters; -} Request; - -#endif diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index dc117b0..de8745f 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -2,46 +2,50 @@ #include "service.h" #include #include +#include #include -Service loaderService; -Service kernelService; -Context kernelContext; - extern void *kernelCodePageTable; -// these are temporary variables but I need the pointers in the asm parts -void *currentCr3 = 0; -void *currentEsp = 0; +void *serviceCR3 = 0; +void *serviceESP = 0; void *mainFunction = NULL; -void *returnStack = 0; extern void *functionsStart; extern void(runFunction)(); extern void(runEnd)(); void run(Service *service, void *main) { - currentEsp = malloc(0x1000); - memset(currentEsp, 0, 0x1000); - ((void **)currentEsp)[0x3FF] = runEnd; - sharePage(&service->pagingInfo, currentEsp, currentEsp); - currentCr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + serviceESP = malloc(0x1000); + memset(serviceESP, 0, 0x1000); + serviceESP += 0xFFC; + *(void **)serviceESP = runEnd; + sharePage(&service->pagingInfo, serviceESP, serviceESP); + serviceCR3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); mainFunction = main; - asm("jmp runFunction"); + runFunction(); } -void loadElf(void *elfStart) { +void resume(Syscall *syscall) { + mainFunction = syscall->returnAddress; + serviceESP = syscall->returnEsp; + serviceCR3 = PTR(syscall->cr3); + runFunction(); +} + +void loadElf(void *elfStart, char *serviceName, ListElement **services) { // use this function ONLY to load the initrd/loader program(maybe also the // ELF loader service)! ElfHeader *header = elfStart; ProgramHeader *programHeader = elfStart + header->programHeaderTablePosition; - PagingInfo *paging = &loaderService.pagingInfo; - memset(paging, 0, sizeof(PagingInfo)); - paging->pageDirectory = malloc(0x1000); + Service *service = malloc(sizeof(Service)); + memset(service, 0, sizeof(Service)); + service->pagingInfo.pageDirectory = malloc(0x1000); + service->name = serviceName; // todo: make this unwritable! // todo: use functionsStart as the reference - sharePage(paging, PTR(0xFFC02000), + sharePage(&(service->pagingInfo), PTR(0xFFC02000), PTR(0xFFC02000)); // functionsStart, functionsStart); for (uint32_t i = 0; i < header->programHeaderEntryCount; i++) { for (uint32_t page = 0; page < programHeader->segmentMemorySize; @@ -50,9 +54,15 @@ memset(data, 0, 0x1000); memcpy(elfStart + programHeader->dataOffset, data, MIN(0x1000, programHeader->segmentFileSize - page)); - sharePage(paging, data, PTR(programHeader->virtualAddress + page)); + sharePage(&service->pagingInfo, data, + PTR(programHeader->virtualAddress + page)); } programHeader = (void *)programHeader + header->programHeaderEntrySize; } - run(&loaderService, PTR(header->entryPosition)); + Provider *main = malloc(sizeof(Provider)); + main->name = "main"; + main->service = service; + main->address = PTR(header->entryPosition); + listAdd(services, service); + listAdd(&service->providers, main); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 2178ffb..93006dc 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -4,6 +4,9 @@ #include #include +extern void *runEndSyscall; +extern ListElement *callsToProcess; + void wrmsr(uint32_t msr, uint32_t low, uint32_t high) { asm("wrmsr" ::"a"(low), "d"(high), "c"(msr)); } @@ -13,16 +16,16 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void *handleSyscall(void *cr3, Syscall *callData) { +void handleSyscall(void *cr3, Syscall *callData) { + if (!callData) { + asm("jmp runEndSyscall"); + } void *pageDirectory = mapTemporary(cr3); void *dataPhysical = getPhysicalAddress(pageDirectory, callData); Syscall *data = kernelMapPhysical(dataPhysical); - switch (data->id) { - case SYS_REGISTER_FUNCTION: - - break; - } - return data; + data->cr3 = U32(cr3); + listAdd(&callsToProcess, data); + asm("jmp runEndSyscall"); } extern void(syscallStub)(); diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c new file mode 100644 index 0000000..4fbc79e --- /dev/null +++ b/src/kernel/util/list.c @@ -0,0 +1,27 @@ +#include +#include + +void listAdd(ListElement **list, void *data) { + ListElement *element = *list; + if (!element) { + *list = malloc(sizeof(ListElement)); + element = *list; + } else { + while (element->next) { + element = element->next; + } + element->next = malloc(sizeof(ListElement)); + element = element->next; + } + element->next = NULL; + element->data = data; +} + +void *listPopFirst(ListElement **list) { + if (!*list) { + return NULL; + } + void *result = (*list)->data; + *list = (*list)->next; + return result; +} diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index c443790..8d8fec5 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -32,23 +32,27 @@ writeParallel('t'); } +void bufferFunction() {} + void syscall(void *callData) { Syscall *call = callData; - asm("mov %%esp, %%eax" : "=a"(call->returnEsp)); + asm("mov %%ebp, %%eax" : "=a"(call->returnEsp)); call->returnAddress = &&returnAddress; asm(".intel_syntax noprefix\n" "sysenter\n" ".att_syntax" ::"a"(callData)); returnAddress: - call->id = 0; + bufferFunction(); return; } void makeRequest(char *moduleName, char *functionName) { - RequestSyscall call = {.id = SYS_REQUEST, - .service = moduleName, - .request = functionName, - .data = 0}; + RequestSyscall call = { + .id = SYS_REQUEST, + .service = moduleName, + .request = functionName, + .data = 0, + }; syscall(&call); }