quinn-os/syscalls.c
2022-07-14 20:47:50 +10:00

322 lines
8.3 KiB
C

#include "pvec.h"
#include "schedule.h"
#include "syscalls.h"
#include "interrupts.h"
#include "vfs.h"
#include "gui.h"
#include "rtc.h"
#include "execve.h"
#include "memory.h"
#include "ether.h"
#include "socket.h"
#include "pci.h"
extern struct task_t *current_task;
extern unsigned long timer_ticks;
int last_syscall = 0;
struct window_req_t {
int x;
int y;
char name[128];
int width;
int height;
unsigned int flags;
char *icon;
};
struct window_blit_req_t {
int wh;
int x;
int y;
int w;
int h;
char *bmp;
};
struct socket_rcv_t {
char *buffer;
int len;
unsigned int *addr;
};
struct socket_bind_p_t {
unsigned short dest;
unsigned short src;
};
struct proc_info_t {
int pid;
char name[32];
};
void sys_exit(struct regs *r) {
unsigned int *status;
unsigned int *wait_return;
current_task->timetorun = 0;
current_task->state = TASK_ZOMBIE;
current_task->exit_status = r->ebx;
current_task->zombie_ttl = 5;
if (current_task->parent_task != (void *)0) {
if (current_task->parent_task->state == TASK_WAITING) {
wait_return = (unsigned int *)(current_task->parent_task->esp + 44);
status = (unsigned int *)(current_task->parent_task->esp + 32);
*wait_return = current_task->pid;
*status = current_task->exit_status;
current_task->parent_task->state = TASK_RUNNING;
current_task->state = TASK_FINISHED;
}
}
schedule(r);
}
int sys_fork(struct regs *r) {
struct task_t *new_task = sched_new_task();
unsigned int *stack_setup = (unsigned int *)new_task->esp;
*--stack_setup = r->ss;
*--stack_setup = r->useresp;
*--stack_setup = r->eflags;
*--stack_setup = r->cs;
*--stack_setup = r->eip;
*--stack_setup = 0;
*--stack_setup = 0;
*--stack_setup = 0; // EAX
*--stack_setup = r->ecx; // ECX
*--stack_setup = r->edx; // EDX
*--stack_setup = r->ebx; // EBX
*--stack_setup = 0; // Just an offset, no value
*--stack_setup = r->ebp; // EBP
*--stack_setup = r->esi; // ESI
*--stack_setup = r->edi; // EDI
*--stack_setup = r->ds; // DS
*--stack_setup = r->es; // ES
*--stack_setup = r->fs; // FS
*--stack_setup = r->gs; // GS
new_task->esp = (unsigned int)stack_setup;
new_task->state = TASK_RUNNING;
return new_task->pid;
}
void syscall_isr(struct regs *r) {
last_syscall = r->eax;
switch (r->eax) {
case SYS_EXIT:
sys_exit(r);
break;
case SYS_FORK:
r->eax = sys_fork(r);
break;
case SYS_CLOSE:
vfs_close_file(r->ebx);
break;
case SYS_GETPID:
r->eax = current_task->pid;
break;
case SYS_READ:
r->eax = vfs_read_file((int)r->ebx, (char *)r->ecx, (int)r->edx);
break;
case SYS_OPEN:
r->eax = vfs_open_file((char *)r->ebx, (int)r->ecx, (int)r->edx);
break;
case SYS_WRITE:
r->eax = vfs_write_file((int)r->ebx, (char *)r->ecx, r->edx);
break;
case SYS_ISATTY:
if (current_task->filehandles[(int)r->ebx].device != (void *)0) {
r->eax = (current_task->filehandles[(int)r->ebx].device->device == 0 ? 1 : 0);
} else {
r->eax = 0;
}
break;
case SYS_SBRK:
r->eax = mem_usr_sbrk((int)r->ebx);
break;
case SYS_LSEEK:
r->eax = vfs_lseek((int)r->ebx, (unsigned long long)r->ecx, (int)r->edx);
break;
case SYS_EXECVE:
r->eax = execve(r, (char *)r->ebx, (char **)r->ecx, (char **)r->edx);
break;
case SYS_SELECTDEV:
r->eax = vfs_select_device((char *)r->ebx);
break;
case SYS_GETDENTS:
r->eax = vfs_getdents((int)r->ebx, (char *)r->ecx, (int)r->edx);
break;
case SYS_STAT:
r->eax = vfs_stat((char *)r->ebx, (struct stat *)r->ecx);
break;
case SYS_STATFS:
r->eax = vfs_statfs((char *)r->ebx, (struct statfs *)r->ecx);
break;
case SYS_FSTAT:
r->eax = vfs_fstat((int)r->ebx, (struct stat *)r->ecx);
break;
case SYS_UNLINK:
r->eax = vfs_unlink((char *)r->ebx);
break;
case SYS_WAIT:
wait(r);
break;
case SYS_GETTIME:
r->eax = rtc_get_time();
break;
case SYS_MKDIR:
r->eax = vfs_mkdir((char *)r->ebx);
break;
case SYS_CHDIR:
r->eax = vfs_change_directory((char *)r->ebx);
break;
case SYS_WINDOW_REQ: {
struct window_req_t *req = (struct window_req_t *)r->ebx;
r->eax = gui_add_window((void *)0, req->name, req->x, req->y, req->width, req->height, (unsigned char *)req->icon, req->flags, (void *)0);
} break;
case SYS_WINDOW_BLIT: {
struct window_blit_req_t *req = (struct window_blit_req_t *)r->ebx;
r->eax = gui_blit(req->wh, req->x, req->y, req->w, req->h, (unsigned char *)req->bmp);
} break;
case SYS_WINDOW_INPUT: {
struct window_update_req *req = (struct window_update_req *)r->ecx;
r->eax = gui_req_input((int)r->ebx, req);
} break;
case SYS_WINDOW_WALLPAPER: {
r->eax = gui_set_wallpaper((char *)r->ecx, (int)r->ebx);
} break;
case SYS_WINDOW_FONT: {
r->eax = gui_set_font((unsigned char *)r->ebx);
} break;
case SYS_WINDOW_COLOURSCHEME: {
r->eax = gui_set_colour((struct gui_colour_scheme_t *)r->ebx);
} break;
case SYS_WINDOW_DESTROY:
gui_destroy_window_syscall((int)r->ebx);
break;
case SYS_WINDOW_CAPTION:
r->eax = gui_change_window_caption((int)r->ebx, (char *)r->ecx);
break;
case SYS_YIELD:
yield(r);
break;
case SYS_SEM_NEW:
sched_sem_new((unsigned char)r->ebx);
break;
case SYS_SEM_FREE:
sched_sem_free((unsigned int)r->ebx);
break;
case SYS_SEM_SIG:
sched_sem_signal((unsigned int)r->ebx, (unsigned char)r->ecx);
break;
case SYS_SEM_WAIT:
sched_sem_wait(r, (unsigned int)r->ebx, (int)r->ecx);
break;
case SYS_ETHER_UP:
r->eax = ether_enable((int)r->ebx, (unsigned int)r->ecx, (unsigned int)r->edx);
break;
case SYS_ETHER_DFGW:
r->eax = ether_add_default_gw((int)r->ebx, (unsigned int)r->ecx);
break;
case SYS_SOCK_OPEN:
r->eax = (unsigned int)socket_open((unsigned char)r->ebx);
break;
case SYS_SOCK_CONNECT:
r->eax = socket_connect(r->ebx, (unsigned int)r->ecx, (unsigned short)r->edx);
break;
case SYS_SOCK_STATUS:
r->eax = socket_status(r->ebx);
break;
case SYS_SOCK_CLOSE:
socket_close(r->ebx);
break;
case SYS_SOCK_READ:
r->eax = socket_read(r->ebx, (char *)r->ecx, r->edx);
break;
case SYS_SOCK_WRITE:
r->eax = socket_write(r->ebx, (unsigned char *)r->ecx, r->edx);
break;
case SYS_SOCK_LISTEN:
r->eax = socket_listen(r->ebx, (unsigned int)r->ecx, (unsigned short)r->edx);
break;
case SYS_SOCK_ACCEPT:
r->eax = (unsigned int)socket_accept(r->ebx, (struct inet_addr *)r->ecx);
break;
case SYS_MEM_INFO:
r->eax = mem_get_info((struct mem_info *)r->ebx);
break;
case SYS_PIPE:
r->eax = vfs_pipe((int *)r->ebx);
break;
case SYS_DUP:
r->eax = vfs_dup((int)r->ebx);
break;
case SYS_DUP2:
r->eax = vfs_dup2((int)r->ebx, (int)r->ecx);
break;
case SYS_SOCK_BIND: {
struct socket_bind_p_t *sbind = (struct socket_bind_p_t *)r->edx;
r->eax = (unsigned int)socket_bind(r->ebx, (unsigned int)r->ecx, sbind->dest, sbind->src);
} break;
case SYS_SOCK_RECV_FROM: {
struct socket_rcv_t *srecv = (struct socket_rcv_t *)r->ecx;
r->eax = (unsigned int)socket_recv_from(r->ebx, srecv->buffer, srecv->len, srecv->addr);
} break;
case SYS_GET_TICKS:
r->eax = timer_ticks;
break;
case SYS_ETHER_GETMAC:
r->eax = ether_get_mac((int)r->ebx, (unsigned char *)r->ecx);
break;
case SYS_KILL_PID:
r->eax = sched_kill_pid((int)r->ebx);
break;
case SYS_LIST_PROC:
r->eax = sched_proc_info((unsigned char *)r->ebx, (int)r->ecx, (int)r->edx);
break;
case SYS_LINK:
r->eax = vfs_link((char *)r->ebx, (char *)r->ecx);
break;
case SYS_VFS_SYNC:
r->eax = 0;
vfs_sync_all();
break;
case SYS_HALT:
vfs_sync_all();
gui_display_halt();
while (1) {
__asm__ volatile("hlt");
}
case SYS_LIST_PCI:
r->eax = pci_dev_info((unsigned char *)r->ebx, (int)r->ecx, (int)r->edx);
break;
case SYS_GETCWD:
r->eax = vfs_getcwd((char *)r->ebx, (int)r->ecx);
break;
case SYS_SOCK_IOCTL:
r->eax = socket_ioctl(r->ebx, r->ecx);
break;
case SYS_SLEEP:
sleep(r);
break;
case SYS_SOCK_POLL:
r->eax = socket_poll(r->ebx, r->ecx, r->edx);
break;
case SYS_SOCK_INFO:
r->eax = socket_info(r->ebx, r->ecx, r->edx);
break;
}
}
void init_syscalls() { irq_install_handler(0x10, syscall_isr, 0); }