elf: start writing elf loader

This commit is contained in:
RaphProductions 2025-05-08 15:17:13 +02:00
parent 175805604e
commit a6f371b4ad
12 changed files with 4706 additions and 72 deletions

43
kernel/src/exec/elf.c Normal file
View file

@ -0,0 +1,43 @@
#include <exec/elf.h>
#include <stdint.h>
#include <sys/log.h>
void elf_load(char *data) {
Elf64_Ehdr *ehdr = (Elf64_Ehdr*)data;
if ( ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
|| ehdr->e_ident[EI_MAG2] != ELFMAG2
|| ehdr->e_ident[EI_MAG3] != ELFMAG3)
{
log("elf - loading failed: magic is incorrect\n");
return;
}
log("elf - e_ident[EI_DATA]: %d\n", ehdr->e_ident[EI_DATA]);
log("elf - e_ident[EI_CLASS]: %d\n", ehdr->e_ident[EI_CLASS]);
log("elf - e_ident[EI_OSABI]: %d\n", ehdr->e_ident[EI_OSABI]);
log("elf - e_machine: %d\n", ehdr->e_machine);
log("elf - e_entry: %p\n", ehdr->e_entry);
log("elf - e_type: %p\n", ehdr->e_type);
if ( ehdr->e_ident[EI_CLASS] != ELFCLASS64
|| ehdr->e_machine != EM_X86_64)
{
log("elf - loading failed: is the file built for amd64?\n");
return;
}
if (ehdr->e_type != ET_EXEC)
{
log("elf - loading failed: ELF type isn't ET_EXEC\n");
return;
}
Elf64_Phdr *phdr = (Elf64_Phdr*)data + ehdr->e_phoff;
for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
if (phdr[i].p_type != PT_LOAD)
continue;
log("elf - Loadable program header: vaddr: %p", phdr[i].p_vaddr);
}
}

118
kernel/src/exec/elf.h Normal file
View file

@ -0,0 +1,118 @@
#pragma once
#include <stdint.h>
// ELF magic.
#define EI_MAG0 0
#define ELFMAG0 0x7f
#define EI_MAG1 1
#define ELFMAG1 'E'
#define EI_MAG2 2
#define ELFMAG2 'L'
#define EI_MAG3 3
#define ELFMAG3 'F'
// ELF class
#define EI_CLASS 4
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
// Is processor-specific data little-endian or big-endian?
#define EI_DATA 5
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
// ELF version
#define EI_VERSION 6
#define EV_NONE 0
#define EV_CURRENT 1
// ELF ABI
#define EI_OSABI 7
#define ELFOSABI_NONE 0
#define ELFOSABI_SYSV 0
#define ELFOSABI_HPUX 1
#define ELFOSABI_NETBSD 2
#define ELFOSABI_LINUX 3
#define ELFOSABI_SOLARIS 6
#define ELFOSABI_IRIX 8
#define ELFOSABI_FREEBSD 9
#define ELFOSABI_TRU64 10
#define ELFOSABI_ARM 97
#define ELFOSABI_STANDALONE 255
// ABI version
#define EI_ABIVERSION 8
// Unused bytes.
#define EI_PAD 9
// Magic size.
#define EI_NIDENT 16
// e_type
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
// e_machine (we only included machines supported by Soaplin.)
#define EM_X86_64 62
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef uint16_t Elf64_Section;
typedef uint16_t Elf64_Versym;
typedef uint8_t Elf_Byte;
typedef uint16_t Elf64_Half;
typedef int32_t Elf64_Sword;
typedef uint32_t Elf64_Word;
typedef int64_t Elf64_Sxword;
typedef uint64_t Elf64_Xword;
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf64_Ehdr;
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PF_X (1 << 0)
#define PF_W (1 << 1)
#define PF_R (1 << 2)
typedef struct {
uint32_t p_type;
uint32_t p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
} Elf64_Phdr;
void elf_load(char *data);

View file

@ -1,66 +1 @@
#pragma once
#include <stdint.h>
struct vfs {
struct vfs *vfs_next; /* next vfs in list */
struct vfsops *vfs_op; /* operations on vfs */
struct vnode *vfs_vnodecovered; /* vnode we cover */
int vfs_flag; /* flags */
int vfs_bsize; /* native block size */
uint64_t vfs_data; /* private data */
};
struct vfsops {
int (*vfs_mount)();
int (*vfs_unmount)();
int (*vfs_root)();
int (*vfs_statfs)();
int (*vfs_sync)();
int (*vfs_fid)();
int (*vfs_vget)();
};
enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VBAD };
struct vnode {
uint16_t v_flag; /* vnode flags */
uint16_t v_count; /* reference count */
uint16_t v_shlockc; /* # of shared locks */
uint16_t v_exlockc; /* # of exclusive locks */
struct vfs *v_vfsmountedhere; /* covering vfs */
struct vnodeops *v_op; /* vnode operations */
union {
struct socket *v_Socket; /* unix ipc */
struct stdata *v_Stream; /* stream */
};
struct vfs *v_vfsp; /* vfs we are in */
enum vtype v_type; /* vnode type */
uint64_t v_data; /* private data */
};
struct vnodeops {
int (*vn_open)();
int (*vn_close)();
int (*vn_rdwr)();
int (*vn_ioctl)();
int (*vn_select)();
int (*vn_getattr)();
int (*vn_setattr)();
int (*vn_access)();
int (*vn_lookup)();
int (*vn_create)();
int (*vn_remove)();
int (*vn_link)();
int (*vn_rename)();
int (*vn_mkdir)();
int (*vn_rmdir)();
int (*vn_readdir)();
int (*vn_symlink)();
int (*vn_readlink)();
int (*vn_fsync)();
int (*vn_inactive)();
int (*vn_bmap)();
int (*vn_strategy)();
int (*vn_bread)();
int (*vn_brelse)();
};

View file

@ -1,3 +1,4 @@
#include "exec/elf.h"
#include "mm/pmm.h"
#include "mm/vmm.h"
#include "rt.h"
@ -35,6 +36,12 @@ static volatile struct limine_framebuffer_request framebuffer_request = {
.revision = 0
};
__attribute__((used, section(".limine_requests")))
static volatile struct limine_module_request module_request = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0
};
/*__attribute__((used, section(".limine_requests")))
static volatile struct limine_entry_point_request entrypoint_request = {
.id = LIMINE_ENTRY_POINT_REQUEST,
@ -112,18 +119,23 @@ void kmain(void) {
vmm_init();
pit_init(1000);
//sched_init();
sched_init();
//user_init();
uint8_t *mem = pmm_request_page();
mem[0] = 0xCD;
mem[1] = 0x80;
struct limine_file *f = module_request.response->modules[0];
log("kmain - %s\n", f->path);
elf_load((char*)f->address);
//uint8_t *mem = pmm_request_page();
//mem[0] = 0xCD;
//mem[1] = 0x80;
//mem[2] = 0xF4;
//mem[3] = 0xFE;
pagemap_t* pm = vmm_alloc_pm();
vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
//pagemap_t* pm = vmm_alloc_pm();
//vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
//sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
log("kernel - Soaplin initialized sucessfully.\n");

View file

@ -90,6 +90,8 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t* pm, uin
log("sched - Standby mode has been"
"disabled.\n");
}
log("sched - created process '%s' (pid: %d, rip: %p)\n", proc->name, proc->pid, proc->regs.rip);
return proc;
}