Newer
Older
honey-os / src / kernel / main.c
#include <memory.h>
#include <multiboot.h>
#include <service.h>
#include <stdint.h>
#include <syscall.h>
#include <syscalls.h>
#include <util.h>

// todo: use data structures more suited to the job
ListElement *services, *callsToProcess;

Service *findService(char *name) {
    foreach (services, Service *, service, {
        if (stringEquals(service->name, name)) {
            return service;
        }
    })
        ;
    return NULL;
}

Service *findServiceByCR3(uint32_t cr3) {
    foreach (services, Service *, service, {
        if (service->pagingInfo.pageDirectory == PTR(cr3)) {
            return service;
        }
    })
        ;
    return NULL;
}

Provider *findProvider(Service *service, char *name) {
    foreach (service->providers, Provider *, provider, {
        if (stringEquals(provider->name, name)) {
            return provider;
        }
    })
        ;
    return NULL;
}

void runRequest(Provider *provider, void *parameter) {
    run(provider->service, provider->address);
}

void kernelMain(void *multibootInfo) {
    setupMemory();
    void *address = kernelMapMultiplePhysicalPages(multibootInfo, 4);
    uint32_t tarSize = 0;
    void *initrd = findInitrd(address, &tarSize);
    setupSyscalls();
    void *loaderProgram = findTarFile(initrd, tarSize, "initrd/loader");
    loadElf(loaderProgram, "loader", &services);
    Service *loader = findService("loader");
    Provider *provider = findProvider(loader, "main");
    runRequest(provider, NULL);
    while (1) {
        Syscall *call = listPopFirst(&callsToProcess);
        if (!call) {
            asm("hlt");
            continue;
        }
        Service *service = findServiceByCR3(call->cr3);
        if (call->resume) {
            resume(call);
            continue;
        }
        switch (call->id) {
        case SYS_REGISTER_FUNCTION:;
            Provider *provider = malloc(sizeof(Provider));
            RegisterServiceProviderSyscall *registerCall = (void *)call;
            provider->name = registerCall->name;
            provider->address = registerCall->handler;
            provider->service = service;
            listAdd(&service->providers, provider);
        }
        call->resume = true;
        listAdd(&callsToProcess, call);
    }
}