#include "exec.h"
#include "elf.h"
#include "pmm.h"
#include "mmu.h"
#include "task.h"
#include "string.h"


int load_elf(void* image, task_t* t) {
    Elf64_Ehdr* hdr = (Elf64_Ehdr*)image;
    if (hdr->e_ident[0] != 0x7F || hdr->e_ident[1] != 'E') return -1;

    for (int i = 0; i < hdr->e_phnum; i++) {
        Elf64_Phdr* ph = (Elf64_Phdr*)((char*)image + hdr->e_phoff + i * hdr->e_phentsize);
        if (ph->p_type != PT_LOAD) continue;

        uint64_t vaddr = ph->p_vaddr;
        uint64_t memsz = ph->p_memsz;
        uint64_t filesz = ph->p_filesz;
        uint64_t offset = ph->p_offset;

        for (uint64_t off = 0; off < memsz; off += 0x1000) {
            void* phys = pmm_alloc_page();
            if (!phys) return -1;

            map_page(t->pgdir, (void*)(vaddr + off), phys, MMU_FLAG_RW | MMU_FLAG_USER);

            uint64_t chunk_offset = off;
            uint64_t chunk_size = 0x1000;

            if (chunk_offset + chunk_size > filesz)
                chunk_size = (filesz > chunk_offset) ? (filesz - chunk_offset) : 0;

            if (chunk_size > 0)
                memcpy(phys, (char*)image + offset + chunk_offset, chunk_size);

            if (chunk_size < 0x1000)
                memset((char*)phys + chunk_size, 0, 0x1000 - chunk_size);
        }
    }

    t->entry = (void (*)(void))hdr->e_entry;
    return 0;
}

