Fri, 24 Mar 2023 21:04:52 +0100
8 files changed,
77 insertions(+),
84 deletions(-)
M
include/cedos/elf.h
→
include/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.h
→
include/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.h
→
include/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.h
→
include/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.c
→
src/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.c
→
src/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.c
→
src/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.c
→
src/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);