#include "utils.h"
#include "vmm.h"
+#include "errno.h"
+
#include "hal/cpu.h"
#include <stdint.h>
}
static int elf32_validate(const elf32_ehdr_t* eh, size_t file_len) {
- if (!eh) return -1;
- if (file_len < sizeof(*eh)) return -1;
+ if (!eh) return -EFAULT;
+ if (file_len < sizeof(*eh)) return -EINVAL;
if (eh->e_ident[0] != ELF_MAGIC0 ||
eh->e_ident[1] != ELF_MAGIC1 ||
eh->e_ident[2] != ELF_MAGIC2 ||
eh->e_ident[3] != ELF_MAGIC3) {
- return -1;
+ return -EINVAL;
}
- if (eh->e_ident[4] != ELFCLASS32) return -1;
- if (eh->e_ident[5] != ELFDATA2LSB) return -1;
+ if (eh->e_ident[4] != ELFCLASS32) return -EINVAL;
+ if (eh->e_ident[5] != ELFDATA2LSB) return -EINVAL;
- if (eh->e_type != ET_EXEC) return -1;
- if (eh->e_machine != EM_386) return -1;
+ if (eh->e_type != ET_EXEC) return -EINVAL;
+ if (eh->e_machine != EM_386) return -EINVAL;
- if (eh->e_phentsize != sizeof(elf32_phdr_t)) return -1;
- if (eh->e_phnum == 0) return -1;
+ if (eh->e_phentsize != sizeof(elf32_phdr_t)) return -EINVAL;
+ if (eh->e_phnum == 0) return -EINVAL;
uint32_t ph_end = eh->e_phoff + (uint32_t)eh->e_phnum * (uint32_t)sizeof(elf32_phdr_t);
- if (ph_end < eh->e_phoff) return -1;
- if (ph_end > file_len) return -1;
+ if (ph_end < eh->e_phoff) return -EINVAL;
+ if (ph_end > file_len) return -EINVAL;
- if (eh->e_entry == 0) return -1;
- if (eh->e_entry >= X86_KERNEL_VIRT_BASE) return -1;
+ if (eh->e_entry == 0) return -EINVAL;
+ if (eh->e_entry >= X86_KERNEL_VIRT_BASE) return -EINVAL;
return 0;
}
static int elf32_map_user_range(uintptr_t as, uintptr_t vaddr, size_t len, uint32_t flags) {
if (len == 0) return 0;
- if (vaddr == 0) return -1;
- if (vaddr >= X86_KERNEL_VIRT_BASE) return -1;
+ if (vaddr == 0) return -EINVAL;
+ if (vaddr >= X86_KERNEL_VIRT_BASE) return -EINVAL;
uintptr_t end = vaddr + len - 1;
- if (end < vaddr) return -1;
- if (end >= X86_KERNEL_VIRT_BASE) return -1;
+ if (end < vaddr) return -EINVAL;
+ if (end >= X86_KERNEL_VIRT_BASE) return -EINVAL;
uintptr_t start_page = vaddr & ~(uintptr_t)0xFFF;
uintptr_t end_page = end & ~(uintptr_t)0xFFF;
for (uintptr_t va = start_page;; va += 0x1000) {
void* phys = pmm_alloc_page_low_16mb();
- if (!phys) return -1;
+ if (!phys) return -ENOMEM;
vmm_as_map_page(as, (uint64_t)(uintptr_t)phys, (uint64_t)va, flags | VMM_FLAG_PRESENT | VMM_FLAG_USER);
}
int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uintptr_t* user_stack_top_out, uintptr_t* addr_space_out) {
- if (!filename || !entry_out || !user_stack_top_out || !addr_space_out) return -1;
- if (!fs_root) return -1;
+ if (!filename || !entry_out || !user_stack_top_out || !addr_space_out) return -EFAULT;
+ if (!fs_root) return -EINVAL;
uintptr_t new_as = vmm_as_create_kernel_clone();
- if (!new_as) return -1;
+ if (!new_as) return -ENOMEM;
uintptr_t old_as = hal_cpu_get_address_space();
vmm_as_activate(new_as);
uart_print("[ELF] file not found: ");
uart_print(filename);
uart_print("\n");
- return -1;
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -ENOENT;
}
uint32_t file_len = node->length;
- if (file_len < sizeof(elf32_ehdr_t)) return -1;
+ if (file_len < sizeof(elf32_ehdr_t)) {
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -EINVAL;
+ }
uint8_t* file = (uint8_t*)kmalloc(file_len);
- if (!file) return -1;
+ if (!file) {
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -ENOMEM;
+ }
uint32_t rd = vfs_read(node, 0, file_len, file);
if (rd != file_len) {
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return -EIO;
}
const elf32_ehdr_t* eh = (const elf32_ehdr_t*)file;
- if (elf32_validate(eh, file_len) < 0) {
+ int vrc = elf32_validate(eh, file_len);
+ if (vrc < 0) {
uart_print("[ELF] invalid ELF header\n");
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return vrc;
}
const elf32_phdr_t* ph = (const elf32_phdr_t*)(file + eh->e_phoff);
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return -EINVAL;
}
if (ph[i].p_vaddr >= X86_KERNEL_VIRT_BASE) {
uart_print("[ELF] PT_LOAD in kernel range rejected\n");
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return -EINVAL;
}
uint32_t seg_end = ph[i].p_vaddr + ph[i].p_memsz;
if (seg_end < ph[i].p_vaddr) {
kfree(file);
- return -1;
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -EINVAL;
}
if (seg_end >= X86_KERNEL_VIRT_BASE) {
kfree(file);
- return -1;
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -EINVAL;
}
if ((uint64_t)ph[i].p_offset + (uint64_t)ph[i].p_filesz > (uint64_t)file_len) {
uart_print("[ELF] segment outside file\n");
kfree(file);
- return -1;
+ vmm_as_activate(old_as);
+ vmm_as_destroy(new_as);
+ return -EINVAL;
}
const uint32_t map_flags = VMM_FLAG_RW;
- if (elf32_map_user_range(new_as, (uintptr_t)ph[i].p_vaddr, (size_t)ph[i].p_memsz, map_flags) < 0) {
+ int mrc = elf32_map_user_range(new_as, (uintptr_t)ph[i].p_vaddr, (size_t)ph[i].p_memsz, map_flags);
+ if (mrc < 0) {
uart_print("[ELF] OOM mapping user segment\n");
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return mrc;
}
if (ph[i].p_filesz) {
const uintptr_t user_stack_base = 0x00800000U;
const size_t user_stack_size = 0x1000;
- if (elf32_map_user_range(new_as, user_stack_base, user_stack_size, VMM_FLAG_RW) < 0) {
+ int src2 = elf32_map_user_range(new_as, user_stack_base, user_stack_size, VMM_FLAG_RW);
+ if (src2 < 0) {
uart_print("[ELF] OOM mapping user stack\n");
kfree(file);
vmm_as_activate(old_as);
vmm_as_destroy(new_as);
- return -1;
+ return src2;
}
*entry_out = (uintptr_t)eh->e_entry;