[USER] Load and run ELF module in userspace
This commit is contained in:
@@ -7,15 +7,8 @@
|
||||
#include <cpu.h>
|
||||
#include <timer.h>
|
||||
#include <string.h>
|
||||
|
||||
void thread_function()
|
||||
{
|
||||
int i = 0;
|
||||
while(1)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#include <cpu.h>
|
||||
#include <elf.h>
|
||||
|
||||
int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
||||
{
|
||||
@@ -32,18 +25,11 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
||||
pit_init();
|
||||
|
||||
process_t *p1 = process_spawn(0);
|
||||
uint64_t addr = 0x200000;
|
||||
thread_t *th = new_thread((void *)addr, 1);
|
||||
|
||||
// Write thread code to address
|
||||
procmm_map(p1->mmap, addr, addr+PAGE_SIZE, 0);
|
||||
vmm_p4_memcpy(p1->mmap->P4, (void *)addr, 0, thread_function, PAGE_SIZE);
|
||||
procmm_setup(p1);
|
||||
thread_t *th = exec_elf(p1, mboot_data.init);
|
||||
scheduler_insert(th);
|
||||
|
||||
procmm_print_map(p1->mmap);
|
||||
|
||||
process_attach(p1, th);
|
||||
scheduler_insert(th);
|
||||
|
||||
asm("sti");
|
||||
debug_info("BOOT COMPLETE\n");
|
||||
|
||||
@@ -25,6 +25,16 @@ void parse_multiboot1()
|
||||
mboot_data.mmap_size = data->mmap_len/sizeof(mboot1_mmap_entry);
|
||||
mboot_data.mmap = P2V(data->mmap_addr);
|
||||
}
|
||||
if(data->flags & (1<<3))
|
||||
{
|
||||
if(data->mods_count)
|
||||
{
|
||||
mboot1_module_entry *mod = P2V(data->mods_addr);
|
||||
mboot_data.init = P2V(mod->mod_start);
|
||||
mboot_data.init_len = mod->mod_end - mod->mod_start;
|
||||
debug_ok("[MBOOT1] init executable: %x (%x bytes)\n", mboot_data.init, mboot_data.init_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *mboot_tags_type[] = {
|
||||
@@ -120,6 +130,8 @@ void multiboot_init(uint64_t magic, void *data)
|
||||
|
||||
int multiboot_page_used(uintptr_t addr)
|
||||
{
|
||||
if(overlapsz(addr, PAGE_SIZE, V2P(mboot_data.init), mboot_data.init_len))
|
||||
return 1;
|
||||
if(mboot_data.version == 1)
|
||||
{
|
||||
mboot1_info *data = mboot_data.data;
|
||||
|
||||
7
kernel/include/elf.h
Normal file
7
kernel/include/elf.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <process.h>
|
||||
#include <thread.h>
|
||||
|
||||
void *load_elf(process_t *p, void *data);
|
||||
thread_t *exec_elf(process_t *p, void *image);
|
||||
@@ -51,6 +51,12 @@ typedef struct {
|
||||
uint32_t len_hi;
|
||||
uint32_t type;
|
||||
} mboot1_mmap_entry;
|
||||
typedef struct {
|
||||
uint32_t mod_start;
|
||||
uint32_t mod_end;
|
||||
uint32_t str_ptr;
|
||||
uint32_t reserved;
|
||||
} mboot1_module_entry;
|
||||
|
||||
// MULTIBOOT 2
|
||||
|
||||
@@ -95,6 +101,8 @@ typedef struct {
|
||||
void *mmap;
|
||||
uint32_t mmap_size;
|
||||
void *rsdp;
|
||||
void *init;
|
||||
uint64_t init_len;
|
||||
};
|
||||
extern struct mboot_data_st mboot_data;
|
||||
|
||||
|
||||
75
kernel/proc/elf.c
Normal file
75
kernel/proc/elf.c
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <mem.h>
|
||||
#include <debug.h>
|
||||
#include <process.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t identity[16];
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
uint32_t version;
|
||||
uint64_t entry;
|
||||
uint64_t ph_offset;
|
||||
uint64_t sh_offset;
|
||||
uint32_t flags;
|
||||
uint16_t header_size;
|
||||
uint16_t ph_size;
|
||||
uint16_t ph_num;
|
||||
uint16_t sh_size;
|
||||
uint16_t sh_num;
|
||||
uint16_t strtab_index;
|
||||
}__attribute__((packed)) elf_header;
|
||||
|
||||
#define ELF_TYPE_EXECUTABLE 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
uint64_t offset;
|
||||
uint64_t virtual_address;
|
||||
uint64_t physical_address;
|
||||
uint64_t file_size;
|
||||
uint64_t mem_size;
|
||||
uint64_t align;
|
||||
}__attribute__((packed)) elf_phead;
|
||||
|
||||
#define ELF_PT_LOAD 1
|
||||
|
||||
void load_elf_segment(process_t *p, uint8_t *file, elf_phead *phead)
|
||||
{
|
||||
uint64_t memsize = phead->mem_size;
|
||||
uint64_t filesize = phead->file_size;
|
||||
uint64_t mempos = phead->virtual_address;
|
||||
uint64_t filepos = phead->offset;
|
||||
debug(" Load segment %x to %x-%x\n", filepos, mempos, mempos+memsize);
|
||||
|
||||
procmm_map(p->mmap, mempos, mempos+memsize, 0);
|
||||
vmm_p4_memcpy(p->mmap->P4, (void *)mempos, 0, &file[filepos], filesize);
|
||||
vmm_p4_memset(p->mmap->P4, incptr(mempos, filesize), 0, memsize - filesize);
|
||||
}
|
||||
|
||||
void *load_elf(process_t *p, void *data)
|
||||
{
|
||||
elf_header *elf = data;
|
||||
if(memcmp(elf->identity, "\x7f""ELF", 4))
|
||||
{
|
||||
debug_error("ELF - No elf magic at %x\n", elf->identity);
|
||||
return 0;
|
||||
}
|
||||
if(elf->type != ELF_TYPE_EXECUTABLE)
|
||||
return 0;
|
||||
|
||||
debug_info("ELF - Loading ELF executable\n");
|
||||
elf_phead *phead = incptr(data, elf->ph_offset);
|
||||
for(uint32_t i = 0; i < elf->ph_num; i++)
|
||||
{
|
||||
if(phead[i].type == ELF_PT_LOAD)
|
||||
{
|
||||
load_elf_segment(p, data, &phead[i]);
|
||||
}
|
||||
}
|
||||
return (void *)elf->entry;
|
||||
}
|
||||
14
kernel/proc/exec_elf.c
Normal file
14
kernel/proc/exec_elf.c
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <elf.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
thread_t *exec_elf(process_t *p, void *image)
|
||||
{
|
||||
void *entry = load_elf(p, image);
|
||||
debug("Address:%x\n", entry);
|
||||
procmm_setup(p);
|
||||
thread_t *th = new_thread((void *)entry, 1);
|
||||
process_attach(p, th);
|
||||
|
||||
return th;
|
||||
}
|
||||
Reference in New Issue
Block a user