diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/features/load.c | 77 | ||||
-rw-r--r-- | kernel/inc/load.h | 100 |
2 files changed, 177 insertions, 0 deletions
diff --git a/kernel/features/load.c b/kernel/features/load.c index 65d76d4..7d0c3c0 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -49,3 +49,80 @@ s32 bin_load(const char *path, struct proc *proc) memory_switch_dir(prev); return 0; } + +s32 elf_load(const char *path, struct proc *proc) +{ + if (!path || !memory_valid(path) || !proc) + return -EFAULT; + + struct stat s = { 0 }; + memory_bypass_enable(); + s32 stat = vfs_stat(path, &s); + memory_bypass_disable(); + if (stat != 0) + return stat; + + strcpy(proc->name, path); + + struct elf_header header = { 0 }; + s32 read = vfs_read(path, &header, 0, sizeof(header)); + if (read < 0) + return read; + if (read != sizeof(header)) + return -ENOEXEC; + + // Valid? + u8 *magic = header.ident; + u8 valid_magic = magic[ELF_IDENT_MAG0] == ELF_MAG0 && magic[ELF_IDENT_MAG1] == ELF_MAG1 && + magic[ELF_IDENT_MAG2] == ELF_MAG2 && magic[ELF_IDENT_MAG3] == ELF_MAG3 && + magic[ELF_IDENT_CLASS] == ELF_IDENT_CLASS_32 && + magic[ELF_IDENT_DATA] == ELF_IDENT_DATA_LSB; + if (!valid_magic || (header.type != ELF_ETYPE_REL && header.type != ELF_ETYPE_EXEC) || + header.version != 1 || header.machine != ELF_MACHINE_386) + return -ENOEXEC; + + // I need to implement ext2 offset reading first + panic("TUDU, Marvin!\n"); + + for (u32 i = 0; i < header.phnum; i++) { + struct elf_program program = { 0 }; + if (vfs_read(path, &program, header.phoff + header.phentsize * i, + sizeof(program)) != sizeof(program)) + return -ENOEXEC; + + if (program.vaddr == 0) + continue; + + if (program.vaddr <= 0x100000) + return -ENOEXEC; + + struct page_dir *prev; + memory_backup_dir(&prev); + memory_switch_dir(proc->page_dir); + + struct memory_range range = memory_range_around(program.vaddr, program.memsz); + struct memory_range prange = physical_alloc(range.size); + virtual_map(proc->page_dir, prange, range.base, MEMORY_CLEAR | MEMORY_USER); + + if ((u32)vfs_read(proc->name, (void *)program.vaddr, program.offset, + program.filesz) != program.filesz) { + memory_switch_dir(prev); + return -ENOEXEC; + } + + memory_switch_dir(prev); + } + + struct page_dir *prev; + memory_backup_dir(&prev); + memory_switch_dir(proc->page_dir); + + u32 stack = (u32)memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_USER | MEMORY_CLEAR); + proc->regs.ebp = stack; + proc->regs.useresp = stack; + proc->regs.eip = header.entry; + proc->entry = header.entry; + + memory_switch_dir(prev); + return 0; +} diff --git a/kernel/inc/load.h b/kernel/inc/load.h index bd3b10d..28bdc54 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -6,6 +6,106 @@ #include <def.h> #include <proc.h> +/** + * ELF + */ + +#define ELF_MAG0 0x7F +#define ELF_MAG1 'E' +#define ELF_MAG2 'L' +#define ELF_MAG3 'F' + +#define ELF_IDENT_COUNT 16 +#define ELF_IDENT_MAG0 0 +#define ELF_IDENT_MAG1 1 +#define ELF_IDENT_MAG2 2 +#define ELF_IDENT_MAG3 3 + +#define ELF_IDENT_CLASS 4 +#define ELF_IDENT_CLASS_NONE 0 +#define ELF_IDENT_CLASS_32 1 +#define ELF_IDENT_CLASS_64 2 + +#define ELF_IDENT_DATA 5 +#define ELF_IDENT_DATA_NONE 0 +#define ELF_IDENT_DATA_LSB 1 +#define ELF_IDENT_DATA_MSB 2 + +#define ELF_IDENT_VERSION 6 +#define ELF_IDENT_OSABI 7 +#define ELF_IDENT_ABIVERSION 8 +#define ELF_IDENT_PAD 9 + +#define ELF_ETYPE_NONE 0 +#define ELF_ETYPE_REL 1 +#define ELF_ETYPE_EXEC 2 +#define ELF_ETYPE_DYN 3 +#define ELF_ETYPE_CORE 4 + +#define ELF_MACHINE_NONE 0 +#define ELF_MACHINE_SPARC 2 +#define ELF_MACHINE_386 3 +#define ELF_MACHINE_SPARC32PLUS 18 +#define ELF_MACHINE_SPARCV9 43 +#define ELF_MACHINE_AMD64 62 + +#define ELF_FLAG_SPARC_EXT_MASK 0xffff00 +#define ELF_FLAG_SPARC_32PLUS 0x000100 +#define ELF_FLAG_SPARC_SUN_US1 0x000200 +#define ELF_FLAG_SPARC_HAL_R1 0x000400 +#define ELF_FLAG_SPARC_SUN_US3 0x000800 +#define ELF_FLAG_SPARCV9_MM 0x3 +#define ELF_FLAG_SPARCV9_TSO 0x0 +#define ELF_FLAG_SPARCV9_PSO 0x1 +#define ELF_FLAG_SPARCV9_RMO 0x2 + +#define ELF_PROGRAM_X 0x1 +#define ELF_PROGRAM_W 0x2 +#define ELF_PROGRAM_R 0x4 + +#define ELF_SECTION_TYPE_NULL 0 +#define ELF_SECTION_TYPE_PROGBITS 1 +#define ELF_SECTION_TYPE_SYMTAB 2 +#define ELF_SECTION_TYPE_STRTAB 3 +#define ELF_SECTION_TYPE_RELA 4 +#define ELF_SECTION_TYPE_HASH 5 +#define ELF_SECTION_TYPE_DYNAMIC 6 +#define ELF_SECTION_TYPE_NOTE 7 +#define ELF_SECTION_TYPE_NOBITS 8 +#define ELF_SECTION_TYPE_REL 9 +#define ELF_SECTION_TYPE_SHLIB 10 +#define ELF_SECTION_TYPE_DYNSYM 11 +#define ELF_SECTION_TYPE_COUNT 12 + +struct PACKED elf_header { + u8 ident[ELF_IDENT_COUNT]; + u16 type; + u16 machine; + u32 version; + u32 entry; + u32 phoff; + u32 shoff; + u32 flags; + u16 ehsize; + u16 phentsize; + u16 phnum; + u16 shentsize; + u16 shnum; + u16 shstrndx; +}; + +struct elf_program { + u32 type; + u32 offset; + u32 vaddr; + u32 paddr; + u32 filesz; + u32 memsz; + u32 flags; + u32 align; +}; + s32 bin_load(const char *path, struct proc *proc); +s32 elf_load(const char *path, struct proc *proc); #endif |