diff --git a/Makefile b/Makefile index 5078804..ad49a62 100644 --- a/Makefile +++ b/Makefile @@ -69,8 +69,8 @@ debug-nox: image.bin -ex "break _start" \ -ex "continue" -fs.img: kernel.bin tools/mkfs user/false user/greet user/div0 - tools/mkfs $@ $< user/false user/greet user/div0 +fs.img: kernel.bin tools/mkfs user/false user/greet user/div0 user/shout + tools/mkfs $@ $< user/false user/greet user/div0 user/shout LDFLAGS=-m elf_i386 diff --git a/cpu/idt.c b/cpu/idt.c index 7adc01d..ff4d3d8 100644 --- a/cpu/idt.c +++ b/cpu/idt.c @@ -109,6 +109,21 @@ void trap(registers_t *r) { } } +static void* get_userspace_ptr(uint32_t ptr) { + if (ptr >= 0xffffffff - USER_BASE) { + return 0; + } + return (void*)(ptr + USER_BASE); +} + +static int handle_puts(const char* s) { + if (!s) { + return -1; + } + printk(s); + return 0; +} + static void handle_syscall(registers_t* r) { switch (r->eax) { case SYS_exit: @@ -122,6 +137,13 @@ static void handle_syscall(registers_t* r) { printk("Hello world!\n"); r->eax = 0; break; + case SYS_putc: + printk((const char[]){r->ebx, '\0'}); + r->eax = 0; + break; + case SYS_puts: + r->eax = handle_puts(get_userspace_ptr(r->ebx)); + break; default: printk("Unknown syscall\n"); r->eax = -1; diff --git a/syscall.h b/syscall.h index 4c9ba03..7973ecb 100644 --- a/syscall.h +++ b/syscall.h @@ -4,6 +4,8 @@ enum { T_SYSCALL = 0x84, SYS_exit = 0, SYS_greet = 1, + SYS_putc = 2, + SYS_puts = 3, }; int syscall(int call, int arg); diff --git a/user/shout.c b/user/shout.c new file mode 100644 index 0000000..4f77e42 --- /dev/null +++ b/user/shout.c @@ -0,0 +1,16 @@ +#include "../syscall.h" +#include + +void userspace_puts(const char* s) { + char c; + while ((c = *s++)) { + syscall(SYS_putc, c); + } +} + +int main() { + const char* spell = "cra cra trif traf not sgnieflet\n"; + userspace_puts(spell); + syscall(SYS_puts, (uint32_t)spell); + return 0; +}