diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index c3ff4e3..51dd4c4 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -26,23 +26,31 @@ } asm("jmp runEndSyscall"); } + Service *service = currentSyscall->service; void *dataPhysical = - getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); - Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = cr3; - data->service = currentService; - listAdd(&callsToProcess, data); + getPhysicalAddress(service->pagingInfo.pageDirectory, callData); + Syscall *call = malloc(sizeof(RequestSyscall)); + void *data = mapTemporary(dataPhysical); + memcpy(data, call, sizeof(RequestSyscall)); + call->cr3 = cr3; + call->service = currentSyscall->service; + call->writeBack = dataPhysical; + if (!call->respondingTo) { + call->respondingTo = currentSyscall->respondingTo; + } + if (!call->address) { + asm("hlt" ::"a"(call), "b"(dataPhysical)); + } + listAdd(&callsToProcess, call); asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; -void *syscallStubPointer = &syscallStubPtr; void setupSyscalls() { writeMsrRegister(0x174, PTR(0x08)); // code segment register - writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // hadler stack + writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // handler stack writeMsrRegister(0x176, syscallStubPtr); // the handler - return; } void handleInstallSyscall(RegisterServiceProviderSyscall *call) { @@ -54,12 +62,9 @@ provider->address = call->handler; provider->service = call->service; listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); } void handleRequestSyscall(RequestSyscall *call) { - call->resume = true; Service *service = call->service; char *serviceName = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, call->serviceName)); @@ -80,6 +85,7 @@ runCall->esp += 0xFFC; *(void **)runCall->esp = &runEnd; listAdd(&callsToProcess, runCall); + call->avoidReschedule = true; } void handleIOInSyscall(IOPortInSyscall *call) { @@ -94,8 +100,6 @@ asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); } void handleIOOutSyscall(IOPortOutSyscall *call) { @@ -110,8 +114,16 @@ asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); +} + +extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, call->programName)); + loadInitrdProgram(programName, (void *)call); + call->avoidReschedule = true; } void (*syscallHandlers[])(Syscall *) = { @@ -120,4 +132,5 @@ (void *)handleRequestSyscall, (void *)handleIOInSyscall, (void *)handleIOOutSyscall, + (void *)handleLoadFromInitrdSyscall, }; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index c3ff4e3..51dd4c4 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -26,23 +26,31 @@ } asm("jmp runEndSyscall"); } + Service *service = currentSyscall->service; void *dataPhysical = - getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); - Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = cr3; - data->service = currentService; - listAdd(&callsToProcess, data); + getPhysicalAddress(service->pagingInfo.pageDirectory, callData); + Syscall *call = malloc(sizeof(RequestSyscall)); + void *data = mapTemporary(dataPhysical); + memcpy(data, call, sizeof(RequestSyscall)); + call->cr3 = cr3; + call->service = currentSyscall->service; + call->writeBack = dataPhysical; + if (!call->respondingTo) { + call->respondingTo = currentSyscall->respondingTo; + } + if (!call->address) { + asm("hlt" ::"a"(call), "b"(dataPhysical)); + } + listAdd(&callsToProcess, call); asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; -void *syscallStubPointer = &syscallStubPtr; void setupSyscalls() { writeMsrRegister(0x174, PTR(0x08)); // code segment register - writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // hadler stack + writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // handler stack writeMsrRegister(0x176, syscallStubPtr); // the handler - return; } void handleInstallSyscall(RegisterServiceProviderSyscall *call) { @@ -54,12 +62,9 @@ provider->address = call->handler; provider->service = call->service; listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); } void handleRequestSyscall(RequestSyscall *call) { - call->resume = true; Service *service = call->service; char *serviceName = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, call->serviceName)); @@ -80,6 +85,7 @@ runCall->esp += 0xFFC; *(void **)runCall->esp = &runEnd; listAdd(&callsToProcess, runCall); + call->avoidReschedule = true; } void handleIOInSyscall(IOPortInSyscall *call) { @@ -94,8 +100,6 @@ asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); } void handleIOOutSyscall(IOPortOutSyscall *call) { @@ -110,8 +114,16 @@ asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); +} + +extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, call->programName)); + loadInitrdProgram(programName, (void *)call); + call->avoidReschedule = true; } void (*syscallHandlers[])(Syscall *) = { @@ -120,4 +132,5 @@ (void *)handleRequestSyscall, (void *)handleIOInSyscall, (void *)handleIOOutSyscall, + (void *)handleLoadFromInitrdSyscall, }; diff --git a/src/kernel/util/strings.c b/src/kernel/util/strings.c index 9ceb113..b023bcb 100644 --- a/src/kernel/util/strings.c +++ b/src/kernel/util/strings.c @@ -1,3 +1,4 @@ +#include #include bool stringEquals(char *string1, char *string2) { @@ -10,3 +11,29 @@ } return *string1 == *string2; } + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +char *combineStrings(char *string1, char *string2) { + char *result = malloc(strlen(string1) + strlen(string2) + 1); + char *write = result; + while (*string1) { + *write = *string1; + write++; + string1++; + } + while (*string2) { + *write = *string2; + write++; + string2++; + } + *write = 0; + return result; +} diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index c3ff4e3..51dd4c4 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -26,23 +26,31 @@ } asm("jmp runEndSyscall"); } + Service *service = currentSyscall->service; void *dataPhysical = - getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); - Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = cr3; - data->service = currentService; - listAdd(&callsToProcess, data); + getPhysicalAddress(service->pagingInfo.pageDirectory, callData); + Syscall *call = malloc(sizeof(RequestSyscall)); + void *data = mapTemporary(dataPhysical); + memcpy(data, call, sizeof(RequestSyscall)); + call->cr3 = cr3; + call->service = currentSyscall->service; + call->writeBack = dataPhysical; + if (!call->respondingTo) { + call->respondingTo = currentSyscall->respondingTo; + } + if (!call->address) { + asm("hlt" ::"a"(call), "b"(dataPhysical)); + } + listAdd(&callsToProcess, call); asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; -void *syscallStubPointer = &syscallStubPtr; void setupSyscalls() { writeMsrRegister(0x174, PTR(0x08)); // code segment register - writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // hadler stack + writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // handler stack writeMsrRegister(0x176, syscallStubPtr); // the handler - return; } void handleInstallSyscall(RegisterServiceProviderSyscall *call) { @@ -54,12 +62,9 @@ provider->address = call->handler; provider->service = call->service; listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); } void handleRequestSyscall(RequestSyscall *call) { - call->resume = true; Service *service = call->service; char *serviceName = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, call->serviceName)); @@ -80,6 +85,7 @@ runCall->esp += 0xFFC; *(void **)runCall->esp = &runEnd; listAdd(&callsToProcess, runCall); + call->avoidReschedule = true; } void handleIOInSyscall(IOPortInSyscall *call) { @@ -94,8 +100,6 @@ asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); } void handleIOOutSyscall(IOPortOutSyscall *call) { @@ -110,8 +114,16 @@ asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); +} + +extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, call->programName)); + loadInitrdProgram(programName, (void *)call); + call->avoidReschedule = true; } void (*syscallHandlers[])(Syscall *) = { @@ -120,4 +132,5 @@ (void *)handleRequestSyscall, (void *)handleIOInSyscall, (void *)handleIOOutSyscall, + (void *)handleLoadFromInitrdSyscall, }; diff --git a/src/kernel/util/strings.c b/src/kernel/util/strings.c index 9ceb113..b023bcb 100644 --- a/src/kernel/util/strings.c +++ b/src/kernel/util/strings.c @@ -1,3 +1,4 @@ +#include #include bool stringEquals(char *string1, char *string2) { @@ -10,3 +11,29 @@ } return *string1 == *string2; } + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +char *combineStrings(char *string1, char *string2) { + char *result = malloc(strlen(string1) + strlen(string2) + 1); + char *write = result; + while (*string1) { + *write = *string1; + write++; + string1++; + } + while (*string2) { + *write = *string2; + write++; + string2++; + } + *write = 0; + return result; +} diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index d55cf86..3a6f72e 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -3,6 +3,8 @@ void syscall(void *callData) { Syscall *call = callData; + call->respondingTo = 0; + call->resume = false; asm("mov %%ebp, %%eax" : "=a"(call->esp)); call->address = &&returnAddress; asm("sysenter\n" ::"a"(callData)); @@ -11,53 +13,14 @@ return; } -uint32_t ioIn(uint16_t port, uint8_t size) { - IOPortInSyscall call = { - .function = SYS_IO_IN, - .port = port, - .size = size, - }; - syscall(&call); - return call.result; -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - IOPortOutSyscall call = { - .function = SYS_IO_OUT, - .port = port, - .value = value, - .size = size, - }; - syscall(&call); -} - -void writeParallel(uint8_t data) { - uint8_t control; - - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } - ioOut(0x378, data, sizeof(uint8_t)); - - control = ioIn(0x37A, sizeof(uint8_t)); - ioOut(0x37A, control | 1, sizeof(uint8_t)); - ioOut(0x37A, control, sizeof(uint8_t)); - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } -} - -void testProvider(void *requestData) { - writeParallel('t'); - writeParallel('e'); - writeParallel('s'); - writeParallel('t'); -} - -void makeRequest(char *moduleName, char *functionName) { +void makeRequest(char *moduleName, char *functionName, void *data, + uint32_t size) { RequestSyscall call = { .function = SYS_REQUEST, .serviceName = moduleName, .providerName = functionName, - .data = 0, + .data = data, + .dataSize = size, }; syscall(&call); } @@ -71,10 +34,27 @@ syscall(&call); } -void test() { makeRequest("loader", "test"); } +void loadFromInitrd(char *name) { + LoadFromInitrdSyscall call = { + .function = SYS_LOAD_INITRD, + .programName = name, + }; + syscall(&call); +} + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void log(char *message) { makeRequest("log", "log", message, strlen(message)); } int32_t main() { - installServiceProvider("test", testProvider); - test(); + loadFromInitrd("log"); + log("hello world"); return 0; } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index c3ff4e3..51dd4c4 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -26,23 +26,31 @@ } asm("jmp runEndSyscall"); } + Service *service = currentSyscall->service; void *dataPhysical = - getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); - Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = cr3; - data->service = currentService; - listAdd(&callsToProcess, data); + getPhysicalAddress(service->pagingInfo.pageDirectory, callData); + Syscall *call = malloc(sizeof(RequestSyscall)); + void *data = mapTemporary(dataPhysical); + memcpy(data, call, sizeof(RequestSyscall)); + call->cr3 = cr3; + call->service = currentSyscall->service; + call->writeBack = dataPhysical; + if (!call->respondingTo) { + call->respondingTo = currentSyscall->respondingTo; + } + if (!call->address) { + asm("hlt" ::"a"(call), "b"(dataPhysical)); + } + listAdd(&callsToProcess, call); asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; -void *syscallStubPointer = &syscallStubPtr; void setupSyscalls() { writeMsrRegister(0x174, PTR(0x08)); // code segment register - writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // hadler stack + writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // handler stack writeMsrRegister(0x176, syscallStubPtr); // the handler - return; } void handleInstallSyscall(RegisterServiceProviderSyscall *call) { @@ -54,12 +62,9 @@ provider->address = call->handler; provider->service = call->service; listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); } void handleRequestSyscall(RequestSyscall *call) { - call->resume = true; Service *service = call->service; char *serviceName = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, call->serviceName)); @@ -80,6 +85,7 @@ runCall->esp += 0xFFC; *(void **)runCall->esp = &runEnd; listAdd(&callsToProcess, runCall); + call->avoidReschedule = true; } void handleIOInSyscall(IOPortInSyscall *call) { @@ -94,8 +100,6 @@ asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); } void handleIOOutSyscall(IOPortOutSyscall *call) { @@ -110,8 +114,16 @@ asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); +} + +extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, call->programName)); + loadInitrdProgram(programName, (void *)call); + call->avoidReschedule = true; } void (*syscallHandlers[])(Syscall *) = { @@ -120,4 +132,5 @@ (void *)handleRequestSyscall, (void *)handleIOInSyscall, (void *)handleIOOutSyscall, + (void *)handleLoadFromInitrdSyscall, }; diff --git a/src/kernel/util/strings.c b/src/kernel/util/strings.c index 9ceb113..b023bcb 100644 --- a/src/kernel/util/strings.c +++ b/src/kernel/util/strings.c @@ -1,3 +1,4 @@ +#include #include bool stringEquals(char *string1, char *string2) { @@ -10,3 +11,29 @@ } return *string1 == *string2; } + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +char *combineStrings(char *string1, char *string2) { + char *result = malloc(strlen(string1) + strlen(string2) + 1); + char *write = result; + while (*string1) { + *write = *string1; + write++; + string1++; + } + while (*string2) { + *write = *string2; + write++; + string2++; + } + *write = 0; + return result; +} diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index d55cf86..3a6f72e 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -3,6 +3,8 @@ void syscall(void *callData) { Syscall *call = callData; + call->respondingTo = 0; + call->resume = false; asm("mov %%ebp, %%eax" : "=a"(call->esp)); call->address = &&returnAddress; asm("sysenter\n" ::"a"(callData)); @@ -11,53 +13,14 @@ return; } -uint32_t ioIn(uint16_t port, uint8_t size) { - IOPortInSyscall call = { - .function = SYS_IO_IN, - .port = port, - .size = size, - }; - syscall(&call); - return call.result; -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - IOPortOutSyscall call = { - .function = SYS_IO_OUT, - .port = port, - .value = value, - .size = size, - }; - syscall(&call); -} - -void writeParallel(uint8_t data) { - uint8_t control; - - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } - ioOut(0x378, data, sizeof(uint8_t)); - - control = ioIn(0x37A, sizeof(uint8_t)); - ioOut(0x37A, control | 1, sizeof(uint8_t)); - ioOut(0x37A, control, sizeof(uint8_t)); - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } -} - -void testProvider(void *requestData) { - writeParallel('t'); - writeParallel('e'); - writeParallel('s'); - writeParallel('t'); -} - -void makeRequest(char *moduleName, char *functionName) { +void makeRequest(char *moduleName, char *functionName, void *data, + uint32_t size) { RequestSyscall call = { .function = SYS_REQUEST, .serviceName = moduleName, .providerName = functionName, - .data = 0, + .data = data, + .dataSize = size, }; syscall(&call); } @@ -71,10 +34,27 @@ syscall(&call); } -void test() { makeRequest("loader", "test"); } +void loadFromInitrd(char *name) { + LoadFromInitrdSyscall call = { + .function = SYS_LOAD_INITRD, + .programName = name, + }; + syscall(&call); +} + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void log(char *message) { makeRequest("log", "log", message, strlen(message)); } int32_t main() { - installServiceProvider("test", testProvider); - test(); + loadFromInitrd("log"); + log("hello world"); return 0; } diff --git a/src/userland/log/Makefile b/src/userland/log/Makefile new file mode 100644 index 0000000..f8624c6 --- /dev/null +++ b/src/userland/log/Makefile @@ -0,0 +1,29 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 -e main +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name *.c -or -name *.asm -or -name *.s) +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../../initrd/loader: $(OBJS) + @echo "linking user program log" + @$(LD) $(LD_FLAGS) -o ../../../initrd/log $(OBJS) + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/include/syscalls.h b/src/include/syscalls.h index cc19d50..e52e178 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -5,11 +5,12 @@ #include typedef enum { - SYS_RUN, - SYS_REGISTER_FUNCTION, - SYS_REQUEST, - SYS_IO_IN, - SYS_IO_OUT, + SYS_RUN = 0, + SYS_REGISTER_FUNCTION = 1, + SYS_REQUEST = 2, + SYS_IO_IN = 3, + SYS_IO_OUT = 4, + SYS_LOAD_INITRD = 5, } SyscallIds; typedef struct Syscall { @@ -20,6 +21,8 @@ struct Syscall *respondingTo; void *service; bool resume; + bool avoidReschedule; + struct Syscall *writeBack; } Syscall; typedef struct { @@ -32,6 +35,7 @@ Syscall; char *serviceName; char *providerName; + uint32_t dataSize; void *data; } RequestSyscall; @@ -51,4 +55,9 @@ uint32_t value; } IOPortOutSyscall; +typedef struct { + Syscall; + char *programName; +} LoadFromInitrdSyscall; + #endif diff --git a/src/kernel/include/util.h b/src/kernel/include/util.h index 21e87e4..959c87b 100644 --- a/src/kernel/include/util.h +++ b/src/kernel/include/util.h @@ -14,6 +14,9 @@ #define PAGE_COUNT(x) (((x - 1) / 4096) + 1) extern bool stringEquals(char *string1, char *string2); +extern char *combineStrings(char *string1, char *string2); +extern uint32_t strlen(char *string); + extern void memcpy(void *source, void *destination, uint32_t size); typedef struct ListElement { diff --git a/src/kernel/main.c b/src/kernel/main.c index b51bd98..49ac65c 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,28 +9,40 @@ extern ListElement *callsToProcess; extern void (*syscallHandlers[])(Syscall *); +void *initrd; +uint32_t initrdSize; + +Syscall *loadInitrdProgram(char *name, Syscall *respondingTo) { + char *fileName = combineStrings("initrd/", name); + void *elfData = findTarFile(initrd, initrdSize, fileName); + free(fileName); + loadElf(elfData, name); + + Service *service = findService(name); + Provider *provider = findProvider(service, "main"); + Syscall *runTask = malloc(sizeof(Syscall)); + runTask->function = SYS_RUN; + runTask->address = provider->address; + runTask->resume = true; + runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); + runTask->esp = malloc(0x1000); + runTask->respondingTo = respondingTo; + runTask->service = service; + memset(runTask->esp, 0, 0x1000); + runTask->esp += 0xFFC; + *(void **)runTask->esp = &runEnd; + sharePage(&service->pagingInfo, runTask->esp, runTask->esp); + listAdd(&callsToProcess, runTask); + if (!runTask->address) { + asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); + } + return runTask; +} + 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 *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); - listAdd(&callsToProcess, runLoader); + initrd = findInitrd(address, &initrdSize); + loadInitrdProgram("loader", NULL); } void kernelMain(void *multibootInfo) { @@ -53,5 +65,11 @@ if (handler) { handler(call); } + call->resume = true; + if (!call->avoidReschedule) { + listAdd(&callsToProcess, call); + void *temporary = mapTemporary(call->writeBack); + memcpy(call, temporary, sizeof(IOPortInSyscall)); + } } } diff --git a/src/kernel/memory/paging.c b/src/kernel/memory/paging.c index 3754e57..9e528bd 100644 --- a/src/kernel/memory/paging.c +++ b/src/kernel/memory/paging.c @@ -33,7 +33,7 @@ kernelDataPageTable[3].writable = 1; kernelDataPageTable[3].present = 1; invalidatePage(0xFF803); - return temporaryPage; + return temporaryPage + (U32(physical) & 0xFFF); } void *getPhysicalAddress(PageDirectoryEntry *pageDirectory, void *address) { @@ -133,7 +133,13 @@ } void *kernelMapPhysical(void *address) { - return kernelMapMultiplePhysicalPages(address, 1); + uint32_t physicalPageId = U32(address) >> 12; + reservePage(kernelPhysicalPages, physicalPageId); + uint32_t virtualPageId = findPage(kernelVirtualPages); + reservePage(kernelVirtualPages, virtualPageId); + mapPage(kernelVirtualPages, PTR(physicalPageId << 12), + PTR(virtualPageId << 12), false); + return PTR((virtualPageId << 12) + (U32(address) & 0xFFF)); } void mapPage(PagingInfo *info, void *physical, void *virtual, bool userPage) { diff --git a/src/kernel/memory/tar.c b/src/kernel/memory/tar.c index 5504974..75b03a4 100644 --- a/src/kernel/memory/tar.c +++ b/src/kernel/memory/tar.c @@ -14,16 +14,19 @@ return result; } -void *findTarFile(void *fileData, uint32_t fileSize, char *fileName) { +uint32_t i = 0; + +void *findTarFile(void *fileData, uint32_t tarFileSize, char *fileName) { void *currentPosition = fileData; - while (currentPosition <= fileData + fileSize) { + i++; + while (currentPosition <= fileData + tarFileSize) { TarFileHeader *header = currentPosition; uint32_t fileSize = readOctal(header->fileSize); - if (!stringEquals(header->fileName, fileName)) { - currentPosition += 512 * (SECTOR_COUNT(fileSize) + 1); - continue; + if (stringEquals(header->fileName, fileName)) { + return currentPosition + 512; } - return currentPosition + 512; + // fixme! + currentPosition += 512; } return NULL; } diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index c8267c6..f538328 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -4,9 +4,7 @@ global runEnd global runEndSyscall -extern serviceCR3 -extern serviceESP -extern mainFunction +extern currentSyscall temporaryESP: resb 4 @@ -14,10 +12,11 @@ push ebp mov eax, esp mov [temporaryESP], eax - mov ecx, [serviceESP] + mov ebx, [currentSyscall] + mov ecx, [ebx + 8] mov ebp, ecx - mov edx, [mainFunction] - mov eax, [serviceCR3] + mov edx, [ebx + 4] + mov eax, [ebx + 12] mov cr3, eax sysexit runEnd: diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index e6f9ac4..450b4b2 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -5,25 +5,17 @@ #include #include -extern void *kernelCodePageTable; - -void *serviceCR3 = 0; -void *serviceESP = 0; -void *mainFunction = NULL; - extern void *functionsStart; extern void(runFunction)(); -Service *currentService; ListElement *services, *callsToProcess; Syscall *currentSyscall; void resume(Syscall *syscall) { currentSyscall = syscall; - mainFunction = syscall->address; - serviceESP = syscall->esp; - currentService = syscall->service; - serviceCR3 = syscall->cr3; + if (!syscall->address) { + asm("hlt" ::"a"(syscall)); + } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index c3ff4e3..51dd4c4 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -26,23 +26,31 @@ } asm("jmp runEndSyscall"); } + Service *service = currentSyscall->service; void *dataPhysical = - getPhysicalAddress(currentService->pagingInfo.pageDirectory, callData); - Syscall *data = kernelMapPhysical(dataPhysical); - data->cr3 = cr3; - data->service = currentService; - listAdd(&callsToProcess, data); + getPhysicalAddress(service->pagingInfo.pageDirectory, callData); + Syscall *call = malloc(sizeof(RequestSyscall)); + void *data = mapTemporary(dataPhysical); + memcpy(data, call, sizeof(RequestSyscall)); + call->cr3 = cr3; + call->service = currentSyscall->service; + call->writeBack = dataPhysical; + if (!call->respondingTo) { + call->respondingTo = currentSyscall->respondingTo; + } + if (!call->address) { + asm("hlt" ::"a"(call), "b"(dataPhysical)); + } + listAdd(&callsToProcess, call); asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; -void *syscallStubPointer = &syscallStubPtr; void setupSyscalls() { writeMsrRegister(0x174, PTR(0x08)); // code segment register - writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // hadler stack + writeMsrRegister(0x175, malloc(0x1000) + 0x1000); // handler stack writeMsrRegister(0x176, syscallStubPtr); // the handler - return; } void handleInstallSyscall(RegisterServiceProviderSyscall *call) { @@ -54,12 +62,9 @@ provider->address = call->handler; provider->service = call->service; listAdd(&service->providers, provider); - call->resume = true; - listAdd(&callsToProcess, call); } void handleRequestSyscall(RequestSyscall *call) { - call->resume = true; Service *service = call->service; char *serviceName = kernelMapPhysical(getPhysicalAddress( service->pagingInfo.pageDirectory, call->serviceName)); @@ -80,6 +85,7 @@ runCall->esp += 0xFFC; *(void **)runCall->esp = &runEnd; listAdd(&callsToProcess, runCall); + call->avoidReschedule = true; } void handleIOInSyscall(IOPortInSyscall *call) { @@ -94,8 +100,6 @@ asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); } void handleIOOutSyscall(IOPortOutSyscall *call) { @@ -110,8 +114,16 @@ asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); break; } - call->resume = true; - listAdd(&callsToProcess, call); +} + +extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); + +void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { + Service *service = call->service; + char *programName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, call->programName)); + loadInitrdProgram(programName, (void *)call); + call->avoidReschedule = true; } void (*syscallHandlers[])(Syscall *) = { @@ -120,4 +132,5 @@ (void *)handleRequestSyscall, (void *)handleIOInSyscall, (void *)handleIOOutSyscall, + (void *)handleLoadFromInitrdSyscall, }; diff --git a/src/kernel/util/strings.c b/src/kernel/util/strings.c index 9ceb113..b023bcb 100644 --- a/src/kernel/util/strings.c +++ b/src/kernel/util/strings.c @@ -1,3 +1,4 @@ +#include #include bool stringEquals(char *string1, char *string2) { @@ -10,3 +11,29 @@ } return *string1 == *string2; } + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +char *combineStrings(char *string1, char *string2) { + char *result = malloc(strlen(string1) + strlen(string2) + 1); + char *write = result; + while (*string1) { + *write = *string1; + write++; + string1++; + } + while (*string2) { + *write = *string2; + write++; + string2++; + } + *write = 0; + return result; +} diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index d55cf86..3a6f72e 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -3,6 +3,8 @@ void syscall(void *callData) { Syscall *call = callData; + call->respondingTo = 0; + call->resume = false; asm("mov %%ebp, %%eax" : "=a"(call->esp)); call->address = &&returnAddress; asm("sysenter\n" ::"a"(callData)); @@ -11,53 +13,14 @@ return; } -uint32_t ioIn(uint16_t port, uint8_t size) { - IOPortInSyscall call = { - .function = SYS_IO_IN, - .port = port, - .size = size, - }; - syscall(&call); - return call.result; -} - -void ioOut(uint16_t port, uint32_t value, uint8_t size) { - IOPortOutSyscall call = { - .function = SYS_IO_OUT, - .port = port, - .value = value, - .size = size, - }; - syscall(&call); -} - -void writeParallel(uint8_t data) { - uint8_t control; - - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } - ioOut(0x378, data, sizeof(uint8_t)); - - control = ioIn(0x37A, sizeof(uint8_t)); - ioOut(0x37A, control | 1, sizeof(uint8_t)); - ioOut(0x37A, control, sizeof(uint8_t)); - while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { - } -} - -void testProvider(void *requestData) { - writeParallel('t'); - writeParallel('e'); - writeParallel('s'); - writeParallel('t'); -} - -void makeRequest(char *moduleName, char *functionName) { +void makeRequest(char *moduleName, char *functionName, void *data, + uint32_t size) { RequestSyscall call = { .function = SYS_REQUEST, .serviceName = moduleName, .providerName = functionName, - .data = 0, + .data = data, + .dataSize = size, }; syscall(&call); } @@ -71,10 +34,27 @@ syscall(&call); } -void test() { makeRequest("loader", "test"); } +void loadFromInitrd(char *name) { + LoadFromInitrdSyscall call = { + .function = SYS_LOAD_INITRD, + .programName = name, + }; + syscall(&call); +} + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; +} + +void log(char *message) { makeRequest("log", "log", message, strlen(message)); } int32_t main() { - installServiceProvider("test", testProvider); - test(); + loadFromInitrd("log"); + log("hello world"); return 0; } diff --git a/src/userland/log/Makefile b/src/userland/log/Makefile new file mode 100644 index 0000000..f8624c6 --- /dev/null +++ b/src/userland/log/Makefile @@ -0,0 +1,29 @@ +CC = i686-elf-gcc +CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I ../../include -I include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 +LD = i686-elf-ld +LD_FLAGS = -z max-page-size=0x1000 -e main +AS = nasm +ASFlAGS = -felf32 + +BUILD_FOLDER = build + +SOURCE_FILES := $(shell find . -name *.c -or -name *.asm -or -name *.s) +OBJS := $(SOURCE_FILES:%=$(BUILD_FOLDER)/%.o) + +../../../initrd/loader: $(OBJS) + @echo "linking user program log" + @$(LD) $(LD_FLAGS) -o ../../../initrd/log $(OBJS) + +$(BUILD_FOLDER)/%.asm.o: %.asm + @echo "asembling $<" + @mkdir -p $(dir $@) + @$(AS) $(ASFlAGS) $< -o $@ + +$(BUILD_FOLDER)/%.c.o: %.c + @echo "compiling $<" + @mkdir -p $(dir $@) + @$(CC) $(CCFLAGS) -r $< -o $@ + +clean: + @echo "clearing build folder" + @rm -r $(BUILD_FOLDER) diff --git a/src/userland/log/main.c b/src/userland/log/main.c new file mode 100644 index 0000000..46827ae --- /dev/null +++ b/src/userland/log/main.c @@ -0,0 +1,83 @@ +#include +#include + +void syscall(void *callData) { + Syscall *call = callData; + call->respondingTo = 0; + call->resume = false; + asm("mov %%ebp, %%eax" : "=a"(call->esp)); + call->address = &&returnAddress; + asm("sysenter\n" ::"a"(callData)); +returnAddress: + asm("nop"); + return; +} + +uint32_t ioIn(uint16_t port, uint8_t size) { + IOPortInSyscall call = { + .function = SYS_IO_IN, + .port = port, + .size = size, + }; + syscall(&call); + return call.result; +} + +void ioOut(uint16_t port, uint32_t value, uint8_t size) { + IOPortOutSyscall call = { + .function = SYS_IO_OUT, + .port = port, + .value = value, + .size = size, + }; + syscall(&call); +} + +void writeParallel(uint8_t data) { + uint8_t control; + while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { + } + ioOut(0x378, data, sizeof(uint8_t)); + + control = ioIn(0x37A, sizeof(uint8_t)); + ioOut(0x37A, control | 1, sizeof(uint8_t)); + ioOut(0x37A, control, sizeof(uint8_t)); + while (!(ioIn(0x379, sizeof(uint8_t)) & 0x80)) { + } +} + +void log(void *requestData) { + writeParallel('l'); + writeParallel('o'); + writeParallel('g'); +} + +void makeRequest(char *moduleName, char *functionName) { + RequestSyscall call = { + .function = SYS_REQUEST, + .serviceName = moduleName, + .providerName = functionName, + .data = 0, + }; + syscall(&call); +} + +void installServiceProvider(char *name, void(provider)(void *)) { + RegisterServiceProviderSyscall call = { + .function = SYS_REGISTER_FUNCTION, + .name = name, + .handler = provider, + }; + syscall(&call); +} + +int32_t main() { + installServiceProvider("log", log); + writeParallel('m'); + writeParallel('a'); + writeParallel('i'); + writeParallel('n'); + writeParallel('\r'); + writeParallel('\n'); + return 0; +}