Adds ELF loader to init.cpp

This commit is contained in:
Felix Queißner 2016-05-07 19:55:59 +02:00
parent c7973406c3
commit 72c33b4b05
4 changed files with 109 additions and 15 deletions

View file

@ -6,7 +6,7 @@ LD=ld
IDT_DISPATCH = _ZN3IDT8dispatchEP8CpuState
FLAGS = -mno-sse -DIDT_DISPATCH=$(IDT_DISPATCH) -ffreestanding -m32 -Werror -Wall -iquote include -iquote lists -O3 -g
FLAGS = -mno-sse -DIDT_DISPATCH=$(IDT_DISPATCH) -ffreestanding -m32 -Werror -Wall -iquote include -iquote lists -I../stdlib/include -O3 -g
ASFLAGS = $(FLAGS)
CFLAGS = $(FLAGS)
CXXFLAGS = $(FLAGS) -std=c++14 -fno-rtti -fno-exceptions -fno-leading-underscore -fno-use-cxa-atexit -nostdlib -fno-builtin
@ -15,11 +15,12 @@ SRCS = $(shell find -regextype egrep -regex '.*/.*\.(cpp|S|c)')
OBJS = $(addsuffix .o, $(notdir $(basename $(SRCS))))
LIBGCC = $(shell gcc -m32 -print-libgcc-file-name)
LIBSTD = ../stdlib/libstd.a
all: kernel-base.ker
kernel-base.ker: $(OBJS)
$(LD) -melf_i386 -Tlinker.ld -o kernel-base.ker $(addprefix obj/, $^) $(LIBGCC)
$(LD) -melf_i386 -Tlinker.ld -o kernel-base.ker $(addprefix obj/, $^) $(LIBGCC) $(LIBSTD)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o obj/$@ $<
@ -54,7 +55,7 @@ run:
-no-reboot \
-no-shutdown \
-serial stdio \
-initrd ../program0/program0.bin
-initrd ../program0/program
insight:
objdump -d kernel-base.ker | c++filt | less

View file

@ -0,0 +1,36 @@
#pragma once
#include <inttypes.h>
namespace elf
{
static const uint32_t MAGIC = 0x464C457F;
struct Header {
uint32_t magic;
uint32_t version;
uint64_t reserved;
uint64_t version2;
uint32_t entry;
uint32_t ph_offset;
uint32_t sh_offset;
uint32_t flags;
uint16_t header_size;
uint16_t ph_entry_size;
uint16_t ph_entry_count;
uint16_t sh_entry_size;
uint16_t sh_entry_count;
uint16_t sh_str_table_index;
} __attribute__((packed));
struct ProgramHeader {
uint32_t type;
uint32_t offset;
uint32_t virt_addr;
uint32_t phys_addr;
uint32_t file_size;
uint32_t mem_size;
uint32_t flags;
uint32_t alignment;
} __attribute__((packed));
}

View file

@ -8,6 +8,8 @@
#include "compat.h"
#include "io.hpp"
#include "vmm.hpp"
#include "elf.hpp"
#include "bsod.hpp"
#include "driver/timer.hpp"
#include "driver/keyboard.hpp"
@ -16,6 +18,8 @@
#include <inttypes.h>
#include <new>
#include <string.h>
using namespace multiboot;
using namespace console_tools;
@ -31,26 +35,76 @@ driver::Scheduler scheduler;
VMMContext *kernelContext;
static const uint32_t entryPointAddress = 0x40000000;
void run_program0(Module const & module)
{
for(uint32_t ptr = 0; ptr < module.size(); ptr += 0x1000)
{
kernelContext->provide(
virtual_t(0x40000000 + ptr),
VMMFlags::Writable | VMMFlags::UserSpace);
using namespace elf;
const Header *header = module.start.data<elf::Header>();
ProgramHeader *ph;
int i;
if (header->magic != MAGIC) {
BSOD::die(Error::InvalidELFImage, "Keine gueltige ELF-Magic!\n");
return;
}
char * src = module.start.data<char>();
char * dst = (char*)0x40000000;
for(uint32_t ptr = 0; ptr < module.size(); ptr++)
{
dst[ptr] = src[ptr];
ph = (ProgramHeader*)(((char*) header) + header->ph_offset);
for (i = 0; i < header->ph_entry_count; i++, ph++) {
void* dest = (void*) ph->virt_addr;
void* src = ((char*) header) + ph->offset;
/* Nur Program Header vom Typ LOAD laden */
if (ph->type != 1) {
continue;
}
if(ph->virt_addr < entryPointAddress) {
BSOD::die(Error::InvalidELFImage, "A LOAD section tried to sneak into the kernel!");
}
for(uint32_t i = 0; i < ph->mem_size; i += 0x1000) {
kernelContext->provide(
virtual_t(ph->virt_addr + i),
VMMFlags::Writable | VMMFlags::UserSpace);
}
memset(dest, 0, ph->mem_size);
memcpy(dest, src, ph->file_size);
}
using EntryPoint = void (*)();
EntryPoint ep = (EntryPoint)0x40000000;
EntryPoint ep = (EntryPoint)entryPointAddress;
ep();
}
static void dump_elf(elf::Header *header)
{
using namespace elf;
ProgramHeader *ph;
int i;
/* Ist es ueberhaupt eine ELF-Datei? */
if (header->magic != MAGIC) {
BSOD::die(Error::InvalidELFImage, "Keine gueltige ELF-Magic!\n");
return;
}
ph = (ProgramHeader*)(((char*) header) + header->ph_offset);
for (i = 0; i < header->ph_entry_count; i++, ph++) {
void* dest = (void*) ph->virt_addr;
void* src = ((char*) header) + ph->offset;
Console::main
<< "Header: " << ph->type << ", "
<< "Source: " << src << ", "
<< "Dest: " << dest << ", "
<< "Memsize: " << ph->mem_size << ", "
<< "Filesize: " << ph->file_size
<< "\n";
}
}
extern "C" void init(Structure const & data)
{
Console::main
@ -154,6 +208,8 @@ extern "C" void init(Structure const & data)
if(data.modules.length > 0)
{
Console::main << "ELF Modukle:\n";
dump_elf(data.modules[0].start.data<elf::Header>());
run_program0(data.modules[0]);
}

View file

@ -2,4 +2,5 @@ ERROR(0, Success, Nothing went wrong. This should never encounter
ERROR(1, OutOfMemory, The system has run out of memory.)
ERROR(2, UnhandledException, An unhandled exception has occurred.)
ERROR(3, UnhandledInterrupt, An unhandled interrupt has occurred.)
ERROR(4, DriverAlreadyInstalled, A driver was already installed.)
ERROR(4, DriverAlreadyInstalled, A driver was already installed.)
ERROR(5, InvalidELFImage, The file beeing loaded is not a valid ELF file.)