// MIT License, Copyright (c) 2020 Marvin Borner #include #include #include #include #include #include #include #include #include #include #include #include static void syscall_handler(struct regs *r) { enum sys num = r->eax; r->eax = 0; /* printf("[SYSCALL] %d from %s\n", num, proc_current()->name); */ switch (num) { case SYS_LOOP: { loop(); break; } case SYS_MALLOC: { r->eax = (u32)malloc(r->ebx); break; } case SYS_FREE: { free((void *)r->ebx); break; } case SYS_STAT: { r->eax = (u32)vfs_stat((char *)r->ebx, (struct stat *)r->ecx); break; } case SYS_READ: { if (vfs_ready((char *)r->ebx)) { r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); } else { if (vfs_wait((char *)r->ebx, (u32)vfs_read) < 0) r->eax = -1; else proc_yield(r); } break; } case SYS_WRITE: { r->eax = (u32)vfs_write((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); break; } case SYS_POLL: { s32 ret = vfs_poll((const char **)r->ebx); if (ret == PROC_MAX_WAIT_IDS + 1) proc_yield(r); else r->eax = ret; break; } case SYS_EXEC: { char *path = (char *)r->ebx; struct proc *proc = proc_make(); r->eax = (u32)bin_load(path, proc); u32 argc = 3; // TODO: Add argc evaluator char **argv = malloc(sizeof(*argv) * (argc + 1)); argv[0] = (char *)r->ecx; argv[1] = (char *)r->edx; argv[2] = (char *)r->esi; argv[3] = (char *)r->edi; argv[4] = NULL; ((u32 *)proc->regs.useresp)[0] = argc; ((u32 *)proc->regs.useresp)[1] = (u32)argv; if (r->eax) proc_exit(proc, (int)r->eax); proc_yield(r); break; } case SYS_EXIT: { proc_exit(proc_current(), (int)r->ebx); break; } case SYS_YIELD: { proc_yield(r); break; } case SYS_TIME: { r->eax = timer_get(); break; } case SYS_NET_OPEN: { r->eax = (int)net_open(r->ebx); break; } case SYS_NET_CLOSE: { struct socket *s = (void *)r->ebx; int status = net_close(s); if (!status) { proc_yield(r); return; } r->eax = net_close(s); break; } case SYS_NET_CONNECT: { struct socket *s = (void *)r->ebx; if (s->state == S_CONNECTED) r->eax = 1; else if (s->state == S_FAILED || s->state == S_CLOSED) r->eax = 0; else if (s->state == S_OPEN) r->eax = net_connect(s, r->ecx, r->edx); break; } case SYS_NET_SEND: { net_send((void *)r->ebx, (void *)r->ecx, r->edx); break; } case SYS_NET_RECEIVE: { r->eax = net_receive((void *)r->ebx, (void *)r->ecx, r->edx); break; } default: { print("Unknown syscall!\n"); break; } } } void syscall_init(void) { idt_set_gate(0x80, (u32)isr128, 0x08, 0x8E); isr_install_handler(0x80, syscall_handler); }