CeDOS - Commit b8987bf4

Changed the behaviour of exec function to fit posix conventions, which also avoids having to copy data between different page directories
Celina Sophie Kalus
Fri, 24 Mar 2023 21:04:52 +0100
8 files changed, 77 insertions(+), 84 deletions(-)
M include/cedos/elf.hinclude/cedos/elf.h

@@ -7,6 +7,6 @@

/*! * Executes an elf file from memory */ -PROCESS_ID elf_exec(VIRT_ADDR elf_pointer, uint32_t size, char *name, char *args); +PROCESS_ID elf_exec(const char *fname, char *args); #endif
M include/cedos/fat.hinclude/cedos/fat.h

@@ -8,5 +8,6 @@ void *FAT_read_sector_offset(uint32_t lba, uint32_t *offset);

void *FAT_read_cluster(uint16_t cluster, void *buffer); uint16_t FAT_next_cluster(uint16_t cluster); int FAT_root_dir_next(int index, char *fname_buffer, uint16_t *first_cluster, uint32_t *file_size); +uint32_t FAT_read_file(const char *fname, void *buffer); #endif
M include/cedos/sched/process.hinclude/cedos/sched/process.h

@@ -61,6 +61,9 @@

//! Name of the process. const char *name; + //! Path to the ELF executable of this process + const char *exe; + //! String of arguments for the process char *args;
M include/cedos/sched/sched.hinclude/cedos/sched/sched.h

@@ -30,19 +30,9 @@ uint32_t eflags;

}__attribute__((packed)) SCHED_FRAME; /*! - * Creates a new process and returns its process ID. - */ -PROCESS_ID sched_create(const char *name, char *args); - -/*! - * Copies a piece of memory into the memory space of some process. - */ -int sched_copyto(PROCESS_ID pid, VIRT_ADDR src, uint32_t length, VIRT_ADDR dest); - -/*! - * Executes the (already created) task with the given process ID. + * Spawns a new process, loads it from the given ELF file, and returns its process ID. */ -int sched_exec(PROCESS_ID pid, PROCESS_MAIN *entry); +PROCESS_ID sched_spawn(const char *name, char *args); /*! * Return the ID of the current process.
M src/kernel/elf.csrc/kernel/elf.c

@@ -2,6 +2,9 @@ #include <stdint.h>

#include "cedos/elf.h" #include "cedos/core.h" +#include "cedos/fat.h" +#include "cedos/sched/process.h" + #include "assert.h" typedef struct {

@@ -115,28 +118,30 @@ printk("\n");

} } -PROCESS_ID elf_exec(VIRT_ADDR elf_pointer, uint32_t size, char *name, char *args) { - printk("Creating process %s...", name); - PROCESS_ID pid = sched_create(name, args); - printk("done, PID: %i.\n", pid); +PROCESS_ID elf_exec(const char *fname, char *args) { + printk("Loading ELF executable \"%s\".\n", fname); + VIRT_ADDR elf_addr = (VIRT_ADDR*)(0xA0000000); + // TODO: needs to change when we have other file systems + int size = FAT_read_file(fname, elf_addr); + assert(size != 0); - ELF_HEADER *header = (ELF_HEADER*)elf_pointer; + ELF_HEADER *header = (ELF_HEADER*)(elf_addr); // magic number correct - assert(((uint32_t*)(elf_pointer))[0] == 0x464C457F); + assert(((uint32_t*)(elf_addr))[0] == 0x464C457F); // header size correct assert(sizeof(ELF_HEADER) == 52); // get section table int sh_offset = header->secthead_offset; - SECT_HEADER *sect_headers = (SECT_HEADER*)(elf_pointer + sh_offset); + SECT_HEADER *sect_headers = (SECT_HEADER*)(elf_addr + sh_offset); int num_sections = header->sh_num; int section_size = header->sh_entry_size; SECT_HEADER sect_names_sh = sect_headers[header->sh_strndx]; - VIRT_ADDR sect_names_addr = elf_pointer + sect_names_sh.offset; + VIRT_ADDR sect_names_addr = elf_addr + sect_names_sh.offset; assert(sizeof(SECT_HEADER) == section_size);

@@ -147,16 +152,16 @@ SECT_HEADER sh = sect_headers[i];

char *name = (char*)(sect_names_addr + sh.name); if ((sh.flags & SHF_ALLOC) && (sh.flags & SHF_EXECINSTR)) { - VIRT_ADDR lma = elf_pointer + sh.offset; + VIRT_ADDR lma = elf_addr + sh.offset; VIRT_ADDR vma = sh.addr; uint32_t size = sh.size; printk("%p\n", sh.flags); printk("Copying code section %s to its destination ", name); printk("(LMA: %p, VMA: %p)\n", lma, vma); - sched_copyto(pid, lma, size, vma); + memcpy(vma, lma, size); } else if (sh.flags & SHF_ALLOC) { - VIRT_ADDR lma = elf_pointer + sh.offset; + VIRT_ADDR lma = elf_addr + sh.offset; VIRT_ADDR vma = sh.addr; printk("Allocating space for section %s ", name); printk("(LMA: %p, VMA: %p)\n", lma, vma);

@@ -170,11 +175,10 @@

printk("\n"); printk("Entry point: %p\n", header->entry); - printk("Starting process %i...", pid); - sched_exec(pid, header->entry); - - printk("done.\n"); + // enter the process + PROCESS_MAIN *entry = header->entry; + entry(args); return 0; }
M src/kernel/fat.csrc/kernel/fat.c

@@ -204,4 +204,33 @@ }

} return addr; +} + +uint32_t FAT_read_file(const char *fname, void *buffer) { + int i = 0; + + uint16_t first_cluster; + uint32_t file_size; + while (1) { + char buffer[832]; + + i = FAT_root_dir_next(i, buffer, &first_cluster, &file_size); + if (i <= 0) { return 0; } + + if (strcmp(buffer, fname) == 0) { break; } + } + + // copy all clusters + uint16_t cluster = first_cluster; + uint32_t size = 0; + + while (1) { + buffer = FAT_read_cluster(cluster, buffer); + cluster = FAT_next_cluster(cluster); + size += boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; + + if (cluster == 0xFFF || cluster == 0x000) { break; } + } + + return size; }
M src/kernel/main.csrc/kernel/main.c

@@ -172,13 +172,10 @@

// create test tasks printk("Creating tasks.\n"); - printk("Loading ELF executable.\n"); - VIRT_ADDR elf_addr = FAT_find_file("apps.o"); - assert(elf_addr != (void*)(0)); - printk("ELF address: %p\n", elf_addr); - elf_exec(elf_addr, 0x1000, "app1", "Hello World!"); - elf_exec(elf_addr, 0x1000, "app2", "Hello World!"); - elf_exec(elf_addr, 0x1000, "app3", "Hello World!"); + + sched_spawn("apps.o", "Hello World!"); + sched_spawn("apps.o", "Hello World!"); + sched_spawn("apps.o", "Hello World!"); printk("Starting scheduler.\n"); sched_start();
M src/kernel/sched/sched.csrc/kernel/sched/sched.c

@@ -11,6 +11,7 @@ #include "cedos/core.h"

#include "cedos/interrupts.h" #include "cedos/pit.h" #include "cedos/pic.h" +#include "cedos/elf.h" #include "assembly.h"

@@ -34,10 +35,16 @@

int sched_dispatcher(void); +void entry_idle(char *args) { + while (1) { + //printk("idle.\n"); + } +} + /*! - * Creates a new process and returns its process ID. + * Spawn a new process and returns its process ID. */ -PROCESS_ID sched_create(const char *name, char *args) { +PROCESS_ID sched_spawn(const char *name, char *args) { crit_enter(); PHYS_ADDR page_dir = create_empty_page_dir();

@@ -50,7 +57,6 @@ p->ebp = USER_STACK;

p->esp = USER_STACK - sizeof(SCHED_FRAME); p->eflags = PROCESS_STD_EFLAGS; p->entry = 0xDEADBEEF; - p->state = PSTATE_CREATED; // TODO: implement with malloc strcpy(p->name_buf, name);

@@ -61,40 +67,6 @@ p->args = &(p->args_buf);

PROCESS_ID pid = add_process(p, current_pid); - return pid; -} - - -/*! - * Copies a piece of memory into the memory space of some process. - */ -int sched_copyto(PROCESS_ID pid, VIRT_ADDR src, uint32_t length, VIRT_ADDR dest) { - crit_enter(); - - PROCESS* p = get_process(pid); - PHYS_ADDR page_dir = p->page_dir; - - copy_to_pdir(src, length, page_dir, dest); - - crit_exit(); - - return 0; -} - - -/*! - * Executes the (already created) task with the given process ID. - */ -int sched_exec(PROCESS_ID pid, PROCESS_MAIN *entry) { - crit_enter(); - - PROCESS* p = get_process(pid); - - if (p->state != PSTATE_CREATED) { - kpanic("Process executed multiple times after creation!"); - return -1; - } - // setup stack static SCHED_FRAME frame; frame.eax = frame.ebx = frame.ecx = frame.edx = 0;

@@ -102,9 +74,14 @@ frame.esi = frame.edi = 0;

frame.ebp = p->ebp; frame.esp = p->esp; frame.eflags = p->eflags; - frame.eip = sched_dispatcher; frame.cs = 0x8; + if (name == NULL) { + frame.eip = entry_idle; + } else { + frame.eip = sched_dispatcher; + } + // load stack copy_to_pdir(&frame, sizeof(frame), p->page_dir, p->esp);

@@ -114,7 +91,6 @@

/* TODO: check if code exists at entry point */ // start the process - p->entry = entry; p->state = PSTATE_READY; crit_exit();

@@ -175,12 +151,6 @@

pic1_eoi(); } -void entry_idle(char *args) { - while (1) { - //printk("idle.\n"); - } -} - extern void* sched_interrupt; int sched_init(void) {

@@ -190,8 +160,7 @@

current_pid = 0; // create idle process - PROCESS_ID idle = sched_create("idle", NULL); - sched_exec(idle, entry_idle); + PROCESS_ID idle = sched_spawn(NULL, NULL); return 1; }

@@ -260,10 +229,10 @@ int sched_dispatcher(void) {

//printk("Dispatching process %i...\n", current_pid); PROCESS* this = get_process(current_pid); - PROCESS_MAIN* entry = this->entry; + // enter the actual program - entry(this->args); + elf_exec(this->name, this->args); //printk("Process %i terminated.\n", current_pid);