KraKern

C++ Kernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/KraKern

commit f00b71e33070ddb2a19e56b7b7603e84e816a58e
parent 280c0ea5ec731bc9fddda9b6f758ea6fb40ba7ad
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Mon, 22 Feb 2016 19:08:53 +0100

Work(ELF): Not working yet.

Diffstat:
Mboot/x86/IDT.cpp | 2+-
Mclean.img | 0
Aincludes/core/ELF.hpp | 191+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mincludes/core/Kernel.hpp | 2++
Mincludes/core/Scheduler.hpp | 3+++
Akernel/ELF.cpp | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mkernel/Kernel.cpp | 5+++++
Mkernel/Makefile | 2+-
Mkernel/ProcessTable.cpp | 9++++++++-
Mkernel/Scheduler.cpp | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mqemu.sh | 2+-
11 files changed, 359 insertions(+), 6 deletions(-)

diff --git a/boot/x86/IDT.cpp b/boot/x86/IDT.cpp @@ -17,7 +17,7 @@ extern "C" { } void isr_schedule_int(void) { - __kern.sch.tick(); + //__kern.sch.tick(); __kern.io.obyte(0x20,0x20); __kern.io.obyte(0xA0,0x20); } diff --git a/clean.img b/clean.img Binary files differ. diff --git a/includes/core/ELF.hpp b/includes/core/ELF.hpp @@ -0,0 +1,191 @@ +#ifndef __ELF_CLASS__ +# define __ELF_CLASS__ + +# include <os.h> +struct process_st; + +class ELF { + public: + ELF(void); + + u32 load_elf(char *p, process_st *t); + int execv(char *file, int ac, char **av); + + private: + int _is_elf(char *p); + char *_name; + int _nbr_default; +}; + +# include <Process.hpp> + + +// ELF structures +/* + * ELF HEADER + */ +typedef struct { + unsigned char e_ident[16]; /* ELF identification */ + u16 e_type; /* 2 (exec file) */ + u16 e_machine; /* 3 (intel architecture) */ + u32 e_version; /* 1 */ + u32 e_entry; /* starting point */ + u32 e_phoff; /* program header table offset */ + u32 e_shoff; /* section header table offset */ + u32 e_flags; /* various flags */ + u16 e_ehsize; /* ELF header (this) size */ + + u16 e_phentsize; /* program header table entry size */ + u16 e_phnum; /* number of entries */ + + u16 e_shentsize; /* section header table entry size */ + u16 e_shnum; /* number of entries */ + + u16 e_shstrndx; /* index of the section name string table */ +} Elf32_Ehdr; + +/* + * ELF identification + */ +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +/* EI_MAG */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +/* EI_CLASS */ +#define ELFCLASSNONE 0 /* invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* EI_DATA */ +#define ELFDATANONE 0 /* invalide data encoding */ +#define ELFDATA2LSB 1 /* least significant byte first (0x01020304 is 0x04 0x03 0x02 0x01) */ +#define ELFDATA2MSB 2 /* most significant byte first (0x01020304 is 0x01 0x02 0x03 0x04) */ + +/* EI_VERSION */ +#define EV_CURRENT 1 +#define ELFVERSION EV_CURRENT + +/* + * PROGRAM HEADER + */ +typedef struct { + u32 p_type; /* type of segment */ + u32 p_offset; + u32 p_vaddr; + u32 p_paddr; + u32 p_filesz; + u32 p_memsz; + u32 p_flags; + u32 p_align; +} Elf32_Phdr; + +/* p_type */ +#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 PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* p_flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +enum eElfSectionTypes { + SHT_NULL, //0 + SHT_PROGBITS, //1 + SHT_SYMTAB, //2 + SHT_STRTAB, //3 + SHT_RELA, //4 + SHT_HASH, //5 + SHT_DYNAMIC, //6 + SHT_NOTE, //7 + SHT_NOBITS, //8 + SHT_REL, //9 + SHT_SHLIB, //A + SHT_DYNSYM, //B + SHT_LAST, //C + SHT_LOPROC = 0x70000000, + SHT_HIPROC = 0x7fffffff, + SHT_LOUSER = 0x80000000, + SHT_HIUSER = 0xffffffff +}; + +typedef struct { + u32 name; + u32 type; + u32 flags; + u32 address; + u32 offset; + u32 size; + u32 link; + u32 info; + u32 addralign; + u32 entsize; +} Elf32_Scdr; + +enum { + R_386_NONE=0, // none + R_386_32, // S+A + R_386_PC32, // S+A-P + R_386_GOT32, // G+A-P + R_386_PLT32, // L+A-P + R_386_COPY, // none + R_386_GLOB_DAT, // S + R_386_JMP_SLOT, // S + R_386_RELATIVE, // B+A + R_386_GOTOFF, // S+A-GOT + R_386_GOTPC, // GOT+A-P + R_386_LAST // none +}; + +typedef struct { + u16 d_tag; + u32 d_val; //Also d_ptr +} Elf32_dyn; + +enum { + DT_NULL, //!< Marks End of list + DT_NEEDED, //!< Offset in strtab to needed library + DT_PLTRELSZ, //!< Size in bytes of PLT + DT_PLTGOT, //!< Address of PLT/GOT + DT_HASH, //!< Address of symbol hash table + DT_STRTAB, //!< String Table address + DT_SYMTAB, //!< Symbol Table address + DT_RELA, //!< Relocation table address + DT_RELASZ, //!< Size of relocation table + DT_RELAENT, //!< Size of entry in relocation table + DT_STRSZ, //!< Size of string table + DT_SYMENT, //!< Size of symbol table entry + DT_INIT, //!< Address of initialisation function + DT_FINI, //!< Address of termination function + DT_SONAME, //!< String table offset of so name + DT_RPATH, //!< String table offset of library path + DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable + DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela) + DT_RELSZ, //!< Size of above table (bytes) + DT_RELENT, //!< Size of entry in above table + DT_PLTREL, //!< Relocation entry of PLT + DT_DEBUG, //!< Debugging Entry - Unknown contents + DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur + DT_JMPREL, //!< Address of PLT only relocation entries + DT_LOPROC = 0x70000000, //!< Low Definable + DT_HIPROC = 0x7FFFFFFF //!< High Definable +}; + +#endif diff --git a/includes/core/Kernel.hpp b/includes/core/Kernel.hpp @@ -10,6 +10,7 @@ # include <ProcessTable.hpp> # include <IDE.hpp> # include <Scheduler.hpp> +# include <ELF.hpp> class Modules; @@ -30,6 +31,7 @@ class Kernel { Modules *mods; IDE ide; Scheduler sch; + ELF elf; }; # include <Modules.hpp> diff --git a/includes/core/Scheduler.hpp b/includes/core/Scheduler.hpp @@ -2,6 +2,7 @@ # define __SCHEDULER__ # include <os.h> +# include <signals.h> struct process_st; @@ -12,6 +13,8 @@ class Scheduler { void tick(void); private: void _switch_to_task(process_st *current, int mode); + int _dequeue_signal(int mask); + int _handle_signal(int sig); }; # include <Process.hpp> diff --git a/kernel/ELF.cpp b/kernel/ELF.cpp @@ -0,0 +1,77 @@ +# include <ELF.hpp> + +ELF::ELF(void) { + this->_name = (char *)__kern.mem.kmalloc(strlen("_proc_") + 1); + strcpy(this->_name, "_proc_"); + this->_nbr_default = '0'; +} + +int ELF::_is_elf(char *file) { + Elf32_Ehdr *hdr; + + hdr = (Elf32_Ehdr *)file; + if (hdr->e_ident[0] == 0x7f && hdr->e_ident[1] == 'E' && hdr->e_ident[2] == 'L' && hdr->e_ident[3] == 'F') + return 1; + return 0; +} + +u32 ELF::load_elf(char *file, process_st *proc) { + u32 v_begin, v_end; + Elf32_Ehdr *hdr; + Elf32_Phdr *p_entry; + Elf32_Scdr *s_entry; + char *p; + int i; + + hdr = (Elf32_Ehdr *)file; + p_entry = (Elf32_Phdr *)(file + hdr->e_phoff); + s_entry = (Elf32_Scdr *)(file + hdr->e_shoff); + if (!this->_is_elf(file)) + __kern.io.panic("ELF: load_elf(): File not in ELF format !"); + for (int pe = 0; pe < hdr->e_phnum; pe++, p_entry++) { + if (p_entry->p_type == PT_LOAD) { + v_begin = p_entry->p_vaddr; + v_end = p_entry->p_vaddr + p_entry->p_memsz; + if (v_begin < USER_OFFSET || v_end > USER_STACK) + __kern.io.panic("ELF: load_elf(): Can't load executable"); + if (p_entry->p_flags == PF_X + PF_R) { + proc->b_exec = (char *)v_begin; + proc->e_exec = (char *)v_end; + } + if (p_entry->p_flags == PF_W + PF_R) { + proc->b_bss = (char *)v_begin; + proc->e_bss = (char *)v_end; + } + memcpy((char *)v_begin, (char *)(file + p_entry->p_offset), p_entry->p_filesz); + if (p_entry->p_memsz > p_entry->p_filesz) { + for (p = (char *)p_entry->p_vaddr, i = p_entry->p_filesz; i < (int)p_entry->p_memsz; i++) + p[i] = 0; + } + } + } + return hdr->e_entry; +} + +int ELF::execv(char *file, int ac, char **av) { + char *map_elf, *name; + File *fp = __kern.fs.path(file); + Process *proc; + + if (!fp) + return -1; + map_elf = (char *)__kern.mem.kmalloc(fp->get_size()); + fp->open(0); + fp->read(0, (u8 *)map_elf, fp->get_size()); + fp->close(); + if (ac <= 0) { + this->_name[strlen(this->_name) - 1] = this->_nbr_default; + this->_nbr_default++; + name = this->_name; + } else { + name = av[0]; + } + proc = new Process(name); + proc->create(map_elf, ac, av); + __kern.mem.kfree(map_elf); + return proc->get_pid(); +} diff --git a/kernel/Kernel.cpp b/kernel/Kernel.cpp @@ -14,6 +14,8 @@ void list_files(File *root, int depth) { for (tmp = root->get_child(); tmp; tmp = tmp->get_next()) { for (int i = 0; i < depth; __kern.io.puts(" "), i++); __kern.io.printk("%s\n", tmp->get_name()); + if (tmp->get_type() == TYPE_DIRECTORY) + tmp->scan(); if (tmp->get_child()) list_files(tmp, depth + 1); } @@ -41,10 +43,13 @@ void Kernel::init(multiboot_info *mbi) { this->pt = *(new ProcessTable()); this->pt.init(); this->sch = *(new Scheduler()); + this->elf = *(new ELF()); this->ready(); __kern.io.puts("\n"); asm("sti"); //list_files(this->fs.get_root(), 0); + char *p[] = {"Test", 0x0}; + this->elf.execv("./a.out", 0, p); while (1); } diff --git a/kernel/Makefile b/kernel/Makefile @@ -1 +1 @@ -OBJS += kernel/main.o kernel/Io.o kernel/Kernel.o kernel/Memory.o kernel/Process.o kernel/File.o kernel/FileSystem.o kernel/ProcessTable.o kernel/Modules.o kernel/IDE.o kernel/Scheduler.o +OBJS += kernel/main.o kernel/Io.o kernel/Kernel.o kernel/Memory.o kernel/Process.o kernel/File.o kernel/FileSystem.o kernel/ProcessTable.o kernel/Modules.o kernel/IDE.o kernel/Scheduler.o kernel/ELF.o diff --git a/kernel/ProcessTable.cpp b/kernel/ProcessTable.cpp @@ -43,7 +43,14 @@ int ProcessTable::create_proc(process_st *info, char *f, int ac, char **av) { previous = this->_current->get_p_info(); current = info; asm("mov %0, %%eax; mov %%eax, %%cr3"::"m"((info->pd)->base->p_addr)); - e_entry = 0; // ELF HERE + e_entry = (u32)__kern.elf.load_elf(f, info); + if (!e_entry) { + for (i = 0; i < ac; i++) + __kern.mem.kfree(av[i]); + __kern.mem.kfree(av); + current = previous; + asm("mov %0, %%eax ;mov %%eax, %%cr3"::"m" (current->regs.cr3)); + } stackp = USER_STACK - 16; if (ac) { uparam = (char **)__kern.mem.kmalloc(sizeof(char *) * ac); diff --git a/kernel/Scheduler.cpp b/kernel/Scheduler.cpp @@ -36,7 +36,6 @@ void Scheduler::tick(void) { current->regs.esp = stack_ptr[9] + 12; current->regs.ss = dtss.ss0; } - current->kstack.ss0 = dtss.ss0; current->kstack.esp0 = dtss.esp0; __kern.io.printk("Schedule %s\n", pcurrent->get_name()); @@ -53,8 +52,10 @@ void Scheduler::_switch_to_task(process_st *current, int mode) { u32 kesp, eflags; u16 kss, ss, cs; struct tss t = __kern.gdt.get_tss(); + int sig; - // signals + if ((sig = this->_dequeue_signal(current->signal))) + this->_handle_signal(sig); t.ss0 = current->kstack.ss0; t.esp0 = current->kstack.esp0; __kern.gdt.set_tss(t); @@ -94,3 +95,70 @@ void Scheduler::_switch_to_task(process_st *current, int mode) { [mode] "g"(mode) ); } + +int Scheduler::_dequeue_signal(int mask) { + int sig; + + if (mask) { + sig = 1; + while (!(mask & 1)) { + mask = mask >> 1; + sig++; + } + } else { + sig = 0; + } + return sig; +} + +int Scheduler::_handle_signal(int sig) { + Process *pcurrent = __kern.pt.get_current(); + process_st *current; + u32 *esp; + + if (!pcurrent) + return 0; + current = pcurrent->get_p_info(); + if (current->sigfn[sig] == (void *)SIG_IGN) { + clear_signal(&(current->signal), sig); + } else if (current->sigfn[sig] == (void *)SIG_DFL) { + switch (sig) { + case SIGHUP: case SIGINT: case SIGQUIT: + asm("mov %0, %%eax; mov %%eax, %%cr3"::"m"(current->regs.cr3)); + pcurrent->exit(); + break; + case SIGCHLD: break; + default: + clear_signal(&(current->signal), sig); + }; + } else { + esp = (u32 *)current->regs.esp - 20; + asm("mov %0, %%eax; mov %%eax, %%cr3"::"m"(current->regs.cr3)); + esp[19] = 0x0030CD00; + esp[18] = 0x00000EB8; + esp[17] = current->kstack.esp0; + esp[16] = current->regs.ss; + esp[15] = current->regs.esp; + esp[14] = current->regs.eflags; + esp[13] = current->regs.cs; + esp[12] = current->regs.eip; + esp[11] = current->regs.eax; + esp[10] = current->regs.ecx; + esp[9] = current->regs.edx; + esp[8] = current->regs.ebx; + esp[7] = current->regs.ebp; + esp[6] = current->regs.esi; + esp[5] = current->regs.edi; + esp[4] = current->regs.ds; + esp[3] = current->regs.es; + esp[2] = current->regs.fs; + esp[1] = current->regs.gs; + esp[0] = (u32)&esp[18]; + current->regs.esp = (u32)esp; + current->regs.eip = (u32)current->sigfn[sig]; + current->sigfn[sig] = (void*) SIG_DFL; + if (sig != SIGCHLD) + clear_signal(&(current->signal), sig); + } + return 0; +} diff --git a/qemu.sh b/qemu.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo kvm -m 1024 -s -hda ./kern.img -redir tcp:2323::23 -curses +sudo kvm -m 2048 -s -hda ./kern.img -redir tcp:2323::23 -curses