elf: start writing elf loader
This commit is contained in:
parent
175805604e
commit
a6f371b4ad
12 changed files with 4706 additions and 72 deletions
|
@ -182,6 +182,7 @@ $(IMAGE_NAME).iso: limine/limine kernel
|
||||||
cp -v limine.conf iso_root/boot/limine/
|
cp -v limine.conf iso_root/boot/limine/
|
||||||
mkdir -p iso_root/EFI/BOOT
|
mkdir -p iso_root/EFI/BOOT
|
||||||
ifeq ($(ARCH),x86_64)
|
ifeq ($(ARCH),x86_64)
|
||||||
|
cp -v testing/sk-hello.elf iso_root/
|
||||||
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
cp -v limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin iso_root/boot/limine/
|
||||||
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT/
|
||||||
cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/
|
cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT/
|
||||||
|
|
43
kernel/src/exec/elf.c
Normal file
43
kernel/src/exec/elf.c
Normal 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
118
kernel/src/exec/elf.h
Normal 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);
|
|
@ -1,66 +1 @@
|
||||||
#pragma once
|
#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)();
|
|
||||||
};
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "exec/elf.h"
|
||||||
#include "mm/pmm.h"
|
#include "mm/pmm.h"
|
||||||
#include "mm/vmm.h"
|
#include "mm/vmm.h"
|
||||||
#include "rt.h"
|
#include "rt.h"
|
||||||
|
@ -35,6 +36,12 @@ static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
.revision = 0
|
.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")))
|
/*__attribute__((used, section(".limine_requests")))
|
||||||
static volatile struct limine_entry_point_request entrypoint_request = {
|
static volatile struct limine_entry_point_request entrypoint_request = {
|
||||||
.id = LIMINE_ENTRY_POINT_REQUEST,
|
.id = LIMINE_ENTRY_POINT_REQUEST,
|
||||||
|
@ -112,18 +119,23 @@ void kmain(void) {
|
||||||
vmm_init();
|
vmm_init();
|
||||||
|
|
||||||
pit_init(1000);
|
pit_init(1000);
|
||||||
//sched_init();
|
sched_init();
|
||||||
//user_init();
|
//user_init();
|
||||||
|
|
||||||
uint8_t *mem = pmm_request_page();
|
struct limine_file *f = module_request.response->modules[0];
|
||||||
mem[0] = 0xCD;
|
log("kmain - %s\n", f->path);
|
||||||
mem[1] = 0x80;
|
|
||||||
|
elf_load((char*)f->address);
|
||||||
|
|
||||||
|
//uint8_t *mem = pmm_request_page();
|
||||||
|
//mem[0] = 0xCD;
|
||||||
|
//mem[1] = 0x80;
|
||||||
//mem[2] = 0xF4;
|
//mem[2] = 0xF4;
|
||||||
|
|
||||||
//mem[3] = 0xFE;
|
//mem[3] = 0xFE;
|
||||||
pagemap_t* pm = vmm_alloc_pm();
|
//pagemap_t* pm = vmm_alloc_pm();
|
||||||
vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
|
//vmm_map(pm, 0x1000, (uint64_t)mem, VMM_PRESENT | VMM_USER);
|
||||||
sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
|
//sched_create("Init", 0x1000, pm, SCHED_USER_PROCESS);
|
||||||
|
|
||||||
|
|
||||||
log("kernel - Soaplin initialized sucessfully.\n");
|
log("kernel - Soaplin initialized sucessfully.\n");
|
||||||
|
|
|
@ -90,6 +90,8 @@ sched_process *sched_create(char *name, uint64_t entry_point, pagemap_t* pm, uin
|
||||||
log("sched - Standby mode has been"
|
log("sched - Standby mode has been"
|
||||||
"disabled.\n");
|
"disabled.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log("sched - created process '%s' (pid: %d, rip: %p)\n", proc->name, proc->pid, proc->regs.rip);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,4 @@ verbose: yes
|
||||||
protocol: limine
|
protocol: limine
|
||||||
|
|
||||||
path: boot():/boot/soaplin
|
path: boot():/boot/soaplin
|
||||||
|
module_path: boot():/sk-hello.elf
|
20
testing/link.ld
Normal file
20
testing/link.ld
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
SECTIONS {
|
||||||
|
. = 0x1000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
}
|
||||||
|
}
|
BIN
testing/sk-hello.elf
Executable file
BIN
testing/sk-hello.elf
Executable file
Binary file not shown.
8
testing/test.asm
Normal file
8
testing/test.asm
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
bits 64
|
||||||
|
section .text
|
||||||
|
global _start
|
||||||
|
|
||||||
|
_start:
|
||||||
|
int 0x80
|
||||||
|
lol:
|
||||||
|
jmp lol
|
BIN
testing/test.o
Normal file
BIN
testing/test.o
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue