almost got the term emu working and shell
This commit is contained in:
65
kernel/elf.c
Normal file
65
kernel/elf.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "elf.h"
|
||||
#include "vfs.h"
|
||||
#include "memory/mm.h"
|
||||
|
||||
#include <lib/memory.h>
|
||||
|
||||
uint32_t load_elf_program(const char* prgm) {
|
||||
int fd = open(prgm, 0);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf_header_t* e_hdr = kalloc(sizeof(elf_header_t));
|
||||
memset((void*)e_hdr, 0, sizeof(elf_header_t));
|
||||
|
||||
uint32_t bytes_rd = read(fd, e_hdr, sizeof(elf_header_t));
|
||||
if (bytes_rd <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t ph_table_ptr = e_hdr->e_phoff;
|
||||
elf_program_header_t* ph = kalloc(sizeof(elf_program_header_t));
|
||||
uint32_t heap_start = 0;
|
||||
|
||||
for (uint32_t i = 0; i < e_hdr->e_phnum; i++) {
|
||||
fseek(fd, ph_table_ptr);
|
||||
memset((void*)ph, 0, sizeof(elf_program_header_t));
|
||||
read(fd, ph, sizeof(elf_program_header_t));
|
||||
|
||||
if (ph->p_type == PT_LOAD) {
|
||||
uint32_t vstart = ph->p_vaddr;
|
||||
uint32_t vend = vstart + ph->p_memsz;
|
||||
|
||||
if (vend > heap_start) {
|
||||
heap_start = vend;
|
||||
}
|
||||
|
||||
uint32_t page_start = vstart & ~(PAGE_SIZE - 1);
|
||||
uint32_t page_end = (vend + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
|
||||
for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(v, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
uint32_t data_ptr = ph->p_offset;
|
||||
fseek(fd, data_ptr);
|
||||
read(fd, (void*)vstart, ph->p_filesz);
|
||||
|
||||
// 0 out bss
|
||||
if (ph->p_memsz > ph->p_filesz) {
|
||||
size_t bss_size = ph->p_memsz - ph->p_filesz;
|
||||
memset((void*)(vstart + ph->p_filesz), 0, bss_size);
|
||||
}
|
||||
}
|
||||
|
||||
ph_table_ptr += sizeof(elf_program_header_t);
|
||||
}
|
||||
|
||||
uint32_t eip = e_hdr->e_entry;
|
||||
kfree(ph);
|
||||
kfree(e_hdr);
|
||||
|
||||
return eip;
|
||||
}
|
||||
@@ -34,4 +34,6 @@ typedef struct {
|
||||
uint32_t p_align;
|
||||
} __attribute__((packed)) elf_program_header_t;
|
||||
|
||||
uint32_t load_elf_program(const char* prgm);
|
||||
|
||||
#endif
|
||||
@@ -64,65 +64,14 @@ void load_root_program(const char* path) {
|
||||
load_pd(cr3);
|
||||
flush_tlb();
|
||||
|
||||
int fd = open(path, 0);
|
||||
if (fd == -1) {
|
||||
kprintf("failed to open program: %s\n", path);
|
||||
return;;
|
||||
}
|
||||
elf_header_t* e_hdr = kalloc(sizeof(elf_header_t));
|
||||
memset((void*)e_hdr, 0, sizeof(elf_header_t));
|
||||
|
||||
uint32_t bytes_rd = read(fd, e_hdr, sizeof(elf_header_t));
|
||||
if (bytes_rd <= 0) {
|
||||
kprintf("failed to read program data for %s\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t ph_table_ptr = e_hdr->e_phoff;
|
||||
elf_program_header_t* ph = kalloc(sizeof(elf_program_header_t));
|
||||
uint32_t heap_start = 0;
|
||||
|
||||
for (uint32_t i = 0; i < e_hdr->e_phnum; i++) {
|
||||
fseek(fd, ph_table_ptr);
|
||||
memset((void*)ph, 0, sizeof(elf_program_header_t));
|
||||
read(fd, ph, sizeof(elf_program_header_t));
|
||||
|
||||
if (ph->p_type == PT_LOAD) {
|
||||
uint32_t vstart = ph->p_vaddr;
|
||||
uint32_t vend = vstart + ph->p_memsz;
|
||||
|
||||
if (vend > heap_start) {
|
||||
heap_start = vend;
|
||||
}
|
||||
|
||||
uint32_t page_start = vstart & ~(PAGE_SIZE - 1);
|
||||
uint32_t page_end = (vend + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
|
||||
for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(v, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
uint32_t data_ptr = ph->p_offset;
|
||||
fseek(fd, data_ptr);
|
||||
read(fd, (void*)vstart, ph->p_filesz);
|
||||
|
||||
// 0 out bss
|
||||
if (ph->p_memsz > ph->p_filesz) {
|
||||
size_t bss_size = ph->p_memsz - ph->p_filesz;
|
||||
memset((void*)(vstart + ph->p_filesz), 0, bss_size);
|
||||
}
|
||||
}
|
||||
|
||||
ph_table_ptr += sizeof(elf_program_header_t);
|
||||
}
|
||||
uint32_t eip = load_elf_program(path);
|
||||
|
||||
uint32_t stack_sz = PAGE_SIZE * 16;
|
||||
uint32_t stack_top = 0xBFFF0000;
|
||||
uint32_t stack_bottom = stack_top - stack_sz;
|
||||
for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
uint32_t* u_esp = (uint32_t*)stack_top;
|
||||
@@ -131,7 +80,7 @@ void load_root_program(const char* path) {
|
||||
*(--u_esp) = 0; // argc = 0
|
||||
|
||||
process_t* process = kalloc(sizeof(process_t));
|
||||
init_task(process, e_hdr->e_entry, (uint32_t)cr3, 1, (uint32_t)u_esp);
|
||||
init_task(process, eip, (uint32_t)cr3, 1, (uint32_t)u_esp);
|
||||
add_task(process);
|
||||
|
||||
unlock_scheduler();
|
||||
@@ -164,8 +113,8 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
kprintf("basic initializations complete\n");
|
||||
|
||||
vfs_node_t* vfs_root = vfs_create_root();
|
||||
|
||||
vfs_node_t* initrd_root = load_initrd();
|
||||
|
||||
if (!initrd_root) {
|
||||
kprintf("failed to load initrd\n");
|
||||
}
|
||||
@@ -177,8 +126,8 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
init_scheduler();
|
||||
enable_interrupts();
|
||||
|
||||
kprintf("loading test program\n");
|
||||
load_root_program("/test.elf");
|
||||
kprintf("loading terminal program\n");
|
||||
load_root_program("/vga_text_term.elf");
|
||||
|
||||
kprintf("kernel going to sleep...\n");
|
||||
}
|
||||
|
||||
@@ -267,4 +267,8 @@ void* clone_current_pd() {
|
||||
unmap_page(TEMP_TASKPD_VADDR);
|
||||
|
||||
return (void*)task_pd_addr;
|
||||
}
|
||||
|
||||
void clear_current_pd() {
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ uint32_t total_free_memory();
|
||||
|
||||
void* create_new_pd();
|
||||
void* clone_current_pd();
|
||||
void clear_current_pd();
|
||||
|
||||
int is_cow(uint32_t vaddr);
|
||||
|
||||
|
||||
@@ -99,6 +99,10 @@ void init_task (
|
||||
process->flags = user ? PROCESS_FLAG_USER : PROCESS_FLAG_KERNEL;
|
||||
total_processes++;
|
||||
|
||||
if (process->kstack_top != 0) {
|
||||
kfree((void*)process->kstack_top);
|
||||
}
|
||||
|
||||
void* kstack_bottom = kalloc(PAGE_SIZE);
|
||||
uint32_t kstack_top = (uint32_t)kstack_bottom + PAGE_SIZE;
|
||||
process->kstack_top = kstack_top;
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <drivers/pty/pty.h>
|
||||
#include "lib/memory.h"
|
||||
#include "lib/ringbuf.h"
|
||||
|
||||
#include "memory/mm.h"
|
||||
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "vfs.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include <drivers/vga/vga.h>
|
||||
#include <drivers/pty/pty.h>
|
||||
|
||||
#include <lib/print.h>
|
||||
#include <lib/string.h>
|
||||
@@ -53,11 +56,13 @@ static int32_t sys_read(int fd, void* buf, size_t count) {
|
||||
}
|
||||
|
||||
static int32_t sys_open(const char* filename, int flags) {
|
||||
return -1;
|
||||
return open(filename, flags);
|
||||
}
|
||||
|
||||
static int32_t sys_close(int fd) {
|
||||
return -1;
|
||||
process_t* task = current_task();
|
||||
task->fd_table[fd] = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int32_t sys_brk(uint32_t new_break) {
|
||||
@@ -155,6 +160,42 @@ static int32_t sys_fork(registers_t* parent_regs) {
|
||||
return child->pid;
|
||||
}
|
||||
|
||||
static int32_t sys_exec(registers_t* regs, const char* prgm) {
|
||||
clear_current_pd();
|
||||
|
||||
uint32_t eip = load_elf_program(prgm);
|
||||
|
||||
uint32_t stack_sz = PAGE_SIZE * 16;
|
||||
uint32_t stack_top = 0xBFFF0000;
|
||||
uint32_t stack_bottom = stack_top - stack_sz;
|
||||
for (uint32_t vaddr = stack_bottom; vaddr < stack_top; vaddr += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(vaddr, (uint32_t)phys_frame, PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER);
|
||||
}
|
||||
|
||||
uint32_t* u_esp = (uint32_t*)stack_top;
|
||||
*(--u_esp) = 0; // envp = NULL
|
||||
*(--u_esp) = 0; // argv = NULL
|
||||
*(--u_esp) = 0; // argc = 0
|
||||
|
||||
regs->eax = 0;
|
||||
regs->ecx = 0;
|
||||
regs->edx = 0;
|
||||
regs->ebp = 0;
|
||||
regs->esi = 0;
|
||||
regs->edi = 0;
|
||||
regs->eip = eip;
|
||||
regs->useresp = (uint32_t)u_esp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t sys_dup2(int src, int dst) {
|
||||
process_t* task = current_task();
|
||||
task->fd_table[dst] = task->fd_table[src];
|
||||
return dst;
|
||||
}
|
||||
|
||||
void syscall(registers_t* regs) {
|
||||
int32_t ret;
|
||||
switch(regs->eax) {
|
||||
@@ -166,6 +207,8 @@ void syscall(registers_t* regs) {
|
||||
case 12: ret = sys_brk(regs->ebx); break;
|
||||
case 20: ret = sys_pty((int*)regs->ebx); break;
|
||||
case 21: ret = sys_fork(regs); break;
|
||||
case 22: ret = sys_exec(regs, (const char*)regs->ebx); break;
|
||||
case 23: ret = sys_dup2(regs->ebx, regs->ecx); break;
|
||||
default: ret = -1;
|
||||
}
|
||||
regs->eax = ret;
|
||||
|
||||
Reference in New Issue
Block a user