CeDOS - Commit 47024669

Shell Interface working!
Celina Kalus
Sat, 25 Mar 2023 17:04:34 +0100
19 files changed, 115 insertions(+), 53 deletions(-)
M include/assembly.hinclude/assembly.h

@@ -122,8 +122,9 @@ __asm__ volatile ( "mov %1, %%eax;"

"mov %2, %%ebx;" "mov %3, %%ecx;" "mov %4, %%edx;" + "mov %0, %%esi;" "int $0x30;" - "mov %%eax, %0;" : "=m" (res) : "" (eax), "" (ebx), "" (ecx), "" (edx) : "eax", "ebx", "ecx", "edx"); + : "=m" (res) : "" (eax), "" (ebx), "" (ecx), "" (edx) : "eax", "ebx", "ecx", "edx"); return res; }
M include/cedos/sched/sched.hinclude/cedos/sched/sched.h

@@ -71,6 +71,12 @@ */

int sched_kill(PROCESS_ID pid); /*! + * Wait for a process to terminate. + * \param pid Process ID of the process to wait for. + */ +void sched_wait(PROCESS_ID pid); + +/*! * The scheduler. */ void sched_interrupt_c(SCHED_FRAME * volatile frame, uint32_t volatile ebp);
M src/apps/common/assembly.hsrc/apps/common/assembly.h

@@ -8,11 +8,11 @@ "mov %1, %%eax;" \

"mov %2, %%ebx;" \ "mov %3, %%ecx;" \ "mov %4, %%edx;" \ + "lea %0, %%esi;" \ "int $" #num ";" \ - "mov %%eax, %0;" \ : "=m" (res) \ : "" (arg1), "" (arg2), "" (arg3), "" (arg4) \ - : "eax", "ebx", "ecx", "edx" \ + : "eax", "ebx", "ecx", "edx", "esi", "memory" \ ) /*!
M src/apps/common/cedos.csrc/apps/common/cedos.c

@@ -9,31 +9,36 @@ return res;

}*/ int yield() { - int res = 0; + volatile uint32_t res = 0; interrupt(0x20, res, 0, 0, 0, 0); return res; } int get_pid() { - int res = 0; + volatile uint32_t res = 0; interrupt(0x30, res, 3, 0, 0, 0); return res; } int sc_file_read(int fd, char *buffer, uint32_t size) { - int res = 0; + volatile uint32_t res = 0; interrupt(0x30, res, 0, fd, buffer, size); return res; } int sc_file_write(int fd, char *buffer, uint32_t size) { - int res = 0; + volatile uint32_t res = 0; interrupt(0x30, res, 1, fd, buffer, size); return res; } int process_spawn(const char *fname, const char *args) { - int res = 0; + volatile uint32_t res = 0; interrupt(0x30, res, 4, fname, args, 0); return res; +} + +void process_wait(int pid) { + volatile uint32_t res = 0; + interrupt(0x30, res, 5, pid, 0, 0); }
M src/apps/common/cedos.hsrc/apps/common/cedos.h

@@ -9,6 +9,7 @@ int sysprint(const char *fmt, int arg1, int arg2);

int yield(); int get_pid(); int process_spawn(const char *fname, const char *args); +void process_wait(int pid); int sc_file_read(int fd, char *buffer, uint32_t size); int sc_file_write(int fd, char *buffer, uint32_t size);
M src/apps/common/start.csrc/apps/common/start.c

@@ -2,10 +2,8 @@ #include "assembly.h"

#include <stdint.h> -extern void main(void); +extern void main(char *args); int _start(char *args) { - main(); - - while(1); + main(args); }
A src/apps/echo.c

@@ -0,0 +1,8 @@

+#include "common/cedos.h" +#include "common/stdio.h" + +#include <stdint.h> + +void main(char *args) { + printf(args); +}
M src/apps/fibonacci.csrc/apps/fibonacci.c

@@ -3,7 +3,7 @@ #include "common/stdio.h"

#include <stdint.h> -void main(void) { +void main(char *args) { uint32_t a = 0, b = 1, i = 0; while (1) { uint32_t tmp = a + b;

@@ -13,6 +13,7 @@ printf("fib (%i) = %i\n", i, a);

i++; char c = 0; sc_file_read(0, &c, 1); - printf("[%c]\n", (int)(uint32_t)c);//yield(); + if (c == 0x1B) { break; } + //printf("[%c]\n", (int)(uint32_t)c);//yield(); } }
M src/apps/shell.csrc/apps/shell.c

@@ -6,20 +6,28 @@

void read_line(char *buffer) { int i = 0; char c; + buffer[0] = 0; while (1) { sc_file_read(1, &c, 1); if (c == '\n') { break; } + if (c == 0) { continue; } + if (c == 0x08 && i <= 0) { continue; } - buffer[i++] = c; - sc_file_write(0, &c, 1); + if (c == 0x08) { + buffer[--i] = 0; + sc_file_write(0, &c, 1); + } else { + buffer[i++] = c; + sc_file_write(0, &c, 1); + } } buffer[i] = 0; sc_file_write(0, &c, 1); } -void main(void) { +void main(char *args) { uint32_t a = 0, b = 1, i = 0; printf("\n"); printf("CeDOS shell\n");

@@ -29,5 +37,19 @@ printf("/> ");

char buffer[256]; read_line(buffer); + + //printf("Executing %s...\n", buffer); + + int pid = process_spawn(buffer, "Hello, world!\n"); + + //printf("Child process %i spawned, waiting for termination...\n", pid); + + if (pid == -1) { + printf("File not found: %s\n", buffer); + } else { + process_wait(pid); + } + + //printf("Child process %i terminated.\n", pid); } }
M src/kernel/core.csrc/kernel/core.c

@@ -160,6 +160,7 @@ crit_exit();

} void kpanic(const char* string) { + cli(); printk(string); core_con->write_c('\n'); // register dump / stack dump
M src/kernel/drivers/vga_console.csrc/kernel/drivers/vga_console.c

@@ -112,8 +112,13 @@ return 1;

} void vga_con_write_c(const char c) { - write_char(c); - set_cursor(line, column); + if (c == 0x08) { + vga_con_backspace(); + set_cursor(line, column); + } else { + write_char(c); + set_cursor(line, column); + } } void vga_con_write_n(const char *string, uint32_t num) {
M src/kernel/elf.csrc/kernel/elf.c

@@ -128,7 +128,9 @@ PROCESS_ID elf_exec(const char *fname, char *args) {

PRINT_DBG("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); + int fd = FAT_openat(0, fname, 0); + assert(fd != -1); + int size = FAT_read(fd, elf_addr, 0); assert(size != 0); ELF_HEADER *header = (ELF_HEADER*)(elf_addr);
M src/kernel/fat.csrc/kernel/fat.c

@@ -184,44 +184,28 @@ return low | high;

} } -void *FAT_find_file(const char *fname) { +int FAT_openat(int fd, const char *fname, int flags) { int i = 0; - void *addr = (void *)(0); + // TODO: take fd into consideration (open file in that subdirectory) + + uint16_t first_cluster; while (1) { char buffer[832]; - uint16_t first_cluster; uint32_t file_size; i = FAT_root_dir_next(i, buffer, &first_cluster, &file_size); - if (i <= 0) { break; } + if (i <= 0) { return -1; } if (strcmp(buffer, fname) == 0) { // file found - addr = FAT_read_sector_offset(data_lba + ((first_cluster - 2) * boot_sect->sect_per_cluster), NULL); - break; + return first_cluster; } } - - 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 FAT_read(int fd, void *buffer, int count) { + uint16_t cluster = fd; uint32_t size = 0; while (1) {
M src/kernel/file.csrc/kernel/file.c

@@ -4,15 +4,17 @@ #include "cedos/drivers/console.h"

#include "cedos/drivers/keyboard.h" int file_read(int fd, char *buffer, uint32_t size) { - for (int i = 0; i < size; i++) { + int i = 0; + while (i < size) { char table[] = { - 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\\', '´', 0x08, + '^', 0x1B, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\\', '´', 0x08, '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '#', 0, '<', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-'}; uint32_t scancode = std_kb->read(); char c = scancode >= 0 && scancode <= 60 ? table[scancode] : 0; - buffer[i] = c; + if (c == 0) { continue; } + buffer[i++] = c; } }
M src/kernel/main.csrc/kernel/main.c

@@ -177,7 +177,8 @@ // create test tasks

printk("Creating tasks.\n"); - sched_spawn("shell.o", "Hello World!"); + int pid = sched_spawn("shell.o", "Hello World!"); + assert(pid != -1); //sched_spawn("fibonacci.o", "Hello World!"); //sched_spawn("fibonacci.o", "Hello World!");
M src/kernel/sched/sched.csrc/kernel/sched/sched.c

@@ -14,6 +14,7 @@ #include "cedos/pic.h"

#include "cedos/elf.h" #include "assembly.h" +#include "assert.h" #define KERNEL_PRIVATE_STACK (void*)(0xC0600000) #define USER_STACK (void*)(0xC0000000)

@@ -52,6 +53,11 @@ * Spawn a new process and returns its process ID.

*/ PROCESS_ID sched_spawn(const char *name, char *args) { crit_enter(); + + if (name != NULL) { + int fd = FAT_openat(0, name, 0); + if (fd == -1) { return -1; } + } PHYS_ADDR page_dir = create_empty_page_dir();

@@ -101,6 +107,8 @@ // start the process

p->state = PSTATE_READY; crit_exit(); + + return pid; }

@@ -177,6 +185,7 @@ current_pid = 0;

// create idle process PROCESS_ID idle = sched_spawn(NULL, NULL); + assert(idle != -1); return 1; }

@@ -225,6 +234,19 @@ crit_exit();

return success; } +void sched_wait(PROCESS_ID pid) { + assert(pid != current_pid); + + if (pid < 0) { return; } + + while (1) { + PROCESS *p = get_process(pid); + if (p->state == PSTATE_TERMINATED) { break; } + + sched_yield(); + } +} + int sched_start(void) { current_pid = 0;

@@ -243,7 +265,7 @@ pic_mask_interrupt(0);

} int sched_dispatcher(void) { - //PRINT_DBG("Dispatching process %i...\n", current_pid); + PRINT_DBG("Dispatching process %i...\n", current_pid); PROCESS* this = get_process(current_pid);

@@ -251,10 +273,10 @@

// enter the actual program elf_exec(this->name, this->args); - //PRINT_DBG("Process %i terminated.\n", current_pid); + PRINT_DBG("Process %i terminated.\n", current_pid); sched_kill(current_pid); // just for absolute safety - while (1); + kpanic("Executing a terminated process!!\n"); }
M src/kernel/sched/sched_strats.csrc/kernel/sched/sched_strats.c

@@ -5,7 +5,7 @@

PROCESS_ID next_schedule(PROCESS_ID current) { PROCESS* process = get_process(current); - if (process != NULL && process->next != NULL) { + if (process != NULL && process->next != NULL && process->next->state != PSTATE_TERMINATED) { return process->next->id; } else { PROCESS *first = get_first_process();
M src/kernel/syscall.csrc/kernel/syscall.c

@@ -16,7 +16,8 @@ file_read,

file_write, sched_yield, get_current_process, - sched_spawn + sched_spawn, + sched_wait }; extern void syscall_interrupt(void);
M src/kernel/syscall.ssrc/kernel/syscall.s

@@ -13,6 +13,8 @@ mov (%ecx, %eax, 4), %eax

call *%eax + mov %eax, (%esi) + // restore stack add $12, %esp iret