[USER] Load and run ELF module in userspace

This commit is contained in:
Thomas Lovén 2016-11-29 09:16:04 +01:00
parent aa50bbcd0f
commit 63b3c3f2c0
11 changed files with 163 additions and 21 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ kernel/obj/
*.o *.o
*.a *.a
tags tags
init/init

View File

@ -4,14 +4,14 @@ ifeq ($(MITTOS64),)
$(error Build environment is not activated. Please source activate) $(error Build environment is not activated. Please source activate)
endif endif
.PHONY: all clean kernel libc .PHONY: all clean kernel libc init
SHELL := bash SHELL := bash
CC=$(TARGET)-gcc CC=$(TARGET)-gcc
FLAGS_TO_PASS:= \ FLAGS_TO_PASS:= \
CC=$(CC) CC=$(CC)
all: kernel libc all: kernel libc init
# A trick to only build phony target if necessary # A trick to only build phony target if necessary
kernel: kernel:
@ -26,6 +26,12 @@ ifeq ($(shell make -sqC libc || echo 1), 1)
$(MAKE) -C libc install $(FLAGS_TO_PASS) $(MAKE) -C libc install $(FLAGS_TO_PASS)
endif endif
init:
ifeq ($(shell make -sqC init || echo 1), 1)
@(. util/helpers.sh; print_info "Building init")
$(MAKE) -C init install $(FLAGS_TO_PASS)
endif
tags: tags:
ctags -R kernel ctags -R kernel
@ -34,5 +40,6 @@ clean:
$(MAKE) -C kernel clean $(MAKE) -C kernel clean
rm -f mittos64.iso rm -f mittos64.iso
$(MAKE) -C libc clean $(MAKE) -C libc clean
$(MAKE) -C init clean
rm -f qemu-error.log rm -f qemu-error.log
rm -f serial.log rm -f serial.log

23
init/Makefile Normal file
View File

@ -0,0 +1,23 @@
ifeq ($(MITTOS64),)
$(error Build environment is not activated. Please source activate)
endif
installdir := $(SYSROOT)/boot
CFLAGS ?= -Wall -Wextra -ggdb -O0
all: init
$(installdir)/init: init
mkdir -p $(dir $@)
cp $< $@
install: $(installdir)/init
clean:
rm -rf init
.PHONY: all clean install

8
init/init.c Normal file
View File

@ -0,0 +1,8 @@
int main(int argc, char **argv)
{
(void) argc;
(void) argv;
int i=0;
for(;;)i++;
return 0;
}

View File

@ -7,15 +7,8 @@
#include <cpu.h> #include <cpu.h>
#include <timer.h> #include <timer.h>
#include <string.h> #include <string.h>
#include <cpu.h>
void thread_function() #include <elf.h>
{
int i = 0;
while(1)
{
i++;
}
}
int kmain(uint64_t multiboot_magic, void *multiboot_data) int kmain(uint64_t multiboot_magic, void *multiboot_data)
{ {
@ -32,18 +25,11 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
pit_init(); pit_init();
process_t *p1 = process_spawn(0); process_t *p1 = process_spawn(0);
uint64_t addr = 0x200000; thread_t *th = exec_elf(p1, mboot_data.init);
thread_t *th = new_thread((void *)addr, 1); scheduler_insert(th);
// 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);
procmm_print_map(p1->mmap); procmm_print_map(p1->mmap);
process_attach(p1, th);
scheduler_insert(th);
asm("sti"); asm("sti");
debug_info("BOOT COMPLETE\n"); debug_info("BOOT COMPLETE\n");

View File

@ -25,6 +25,16 @@ void parse_multiboot1()
mboot_data.mmap_size = data->mmap_len/sizeof(mboot1_mmap_entry); mboot_data.mmap_size = data->mmap_len/sizeof(mboot1_mmap_entry);
mboot_data.mmap = P2V(data->mmap_addr); 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[] = { char *mboot_tags_type[] = {
@ -120,6 +130,8 @@ void multiboot_init(uint64_t magic, void *data)
int multiboot_page_used(uintptr_t addr) 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) if(mboot_data.version == 1)
{ {
mboot1_info *data = mboot_data.data; mboot1_info *data = mboot_data.data;

7
kernel/include/elf.h Normal file
View 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);

View File

@ -51,6 +51,12 @@ typedef struct {
uint32_t len_hi; uint32_t len_hi;
uint32_t type; uint32_t type;
} mboot1_mmap_entry; } 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 // MULTIBOOT 2
@ -95,6 +101,8 @@ typedef struct {
void *mmap; void *mmap;
uint32_t mmap_size; uint32_t mmap_size;
void *rsdp; void *rsdp;
void *init;
uint64_t init_len;
}; };
extern struct mboot_data_st mboot_data; extern struct mboot_data_st mboot_data;

75
kernel/proc/elf.c Normal file
View 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
View 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;
}

View File

@ -1,9 +1,10 @@
set timeout=1 set timeout=1
set default=0 set default=1
menuentry "mittos64" { menuentry "mittos64" {
multiboot2 /boot/kernel multiboot2 /boot/kernel
} }
menuentry "mittos64 MultiBoot1" { menuentry "mittos64 MultiBoot1" {
multiboot /boot/kernel multiboot /boot/kernel
module /boot/init
} }