diff --git a/.gitignore b/.gitignore index cb25845..8807fd8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ kernel/obj/ *.o *.a tags +init/init diff --git a/Makefile b/Makefile index df74f7d..b98ab5b 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,14 @@ ifeq ($(MITTOS64),) $(error Build environment is not activated. Please source activate) endif -.PHONY: all clean kernel libc +.PHONY: all clean kernel libc init SHELL := bash CC=$(TARGET)-gcc FLAGS_TO_PASS:= \ CC=$(CC) -all: kernel libc +all: kernel libc init # A trick to only build phony target if necessary kernel: @@ -26,6 +26,12 @@ ifeq ($(shell make -sqC libc || echo 1), 1) $(MAKE) -C libc install $(FLAGS_TO_PASS) 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: ctags -R kernel @@ -34,5 +40,6 @@ clean: $(MAKE) -C kernel clean rm -f mittos64.iso $(MAKE) -C libc clean + $(MAKE) -C init clean rm -f qemu-error.log rm -f serial.log diff --git a/init/Makefile b/init/Makefile new file mode 100644 index 0000000..f9e5c58 --- /dev/null +++ b/init/Makefile @@ -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 diff --git a/init/init.c b/init/init.c new file mode 100644 index 0000000..59c9519 --- /dev/null +++ b/init/init.c @@ -0,0 +1,8 @@ +int main(int argc, char **argv) +{ + (void) argc; + (void) argv; + int i=0; + for(;;)i++; + return 0; +} diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index dcd3765..d3e3ea4 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -7,15 +7,8 @@ #include #include #include - -void thread_function() -{ - int i = 0; - while(1) - { - i++; - } -} +#include +#include 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"); diff --git a/kernel/boot/multiboot.c b/kernel/boot/multiboot.c index 3d67200..d641986 100644 --- a/kernel/boot/multiboot.c +++ b/kernel/boot/multiboot.c @@ -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; diff --git a/kernel/include/elf.h b/kernel/include/elf.h new file mode 100644 index 0000000..3cf05a1 --- /dev/null +++ b/kernel/include/elf.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include +#include + +void *load_elf(process_t *p, void *data); +thread_t *exec_elf(process_t *p, void *image); diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h index c311bf4..ceb6df1 100644 --- a/kernel/include/multiboot.h +++ b/kernel/include/multiboot.h @@ -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; diff --git a/kernel/proc/elf.c b/kernel/proc/elf.c new file mode 100644 index 0000000..0012da9 --- /dev/null +++ b/kernel/proc/elf.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/kernel/proc/exec_elf.c b/kernel/proc/exec_elf.c new file mode 100644 index 0000000..af6653d --- /dev/null +++ b/kernel/proc/exec_elf.c @@ -0,0 +1,14 @@ +#include +#include +#include + +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; +} diff --git a/util/grub.cfg b/util/grub.cfg index 39678ab..fdaab3c 100644 --- a/util/grub.cfg +++ b/util/grub.cfg @@ -1,9 +1,10 @@ set timeout=1 -set default=0 +set default=1 menuentry "mittos64" { multiboot2 /boot/kernel } menuentry "mittos64 MultiBoot1" { multiboot /boot/kernel + module /boot/init }