#include "lib/string/string.h" #include "lib/printf/printf.h" #include "fs/ext2.h" #include "kernel.h" #include "driver/vesa.h" #include "fifo.h" #include "fd.h" #include "fs/elf.h" #include "driver/terminal.h" #include "driver/screen.h" #include #include #include #include #include "syscalls.h" #include "scheduler.h" #include "log.h" #include "timer.h" #include "mount.h" #include "mem.h" #include "reent.h" #include "errno.h" void set_errno(int no) { struct _reent *impure_ptr=VMEM_USER_NEWLIB; impure_ptr->_errno=no; } static fd fds[MAX_FD]; static uint32_t next_fd=0; // fifos for backing up some file descrpitors static fifo fifos[MAX_FIFOS]; static uint32_t next_fifo=0; // screen / terminal term_out screen; terminal_tty tty1; char* syscall_get_name(uint32_t num) { switch(num) { case 60: return "SYSCALL_EXIT"; case 66: return "SYSCALL_CLOSE"; case 64: return "SYSCALL_EXECVE"; case 72: return "SYSCALL_FORK"; case 78: return "SYSCALL_GETPID"; case 68: return "SYSCALL_ISATTY"; case 82: return "SYSCALL_LINK"; case 69: return "SYSCALL_LSEEK"; case 65: return "SYSCALL_OPEN"; case 62: return "SYSCALL_READ"; case 70: return "SYSCALL_SBRK"; case 74: return "SYSCALL_STAT"; case 67: return "SYSCALL_FSTAT"; case 79: return "SYSCALL_LSTAT"; case 75: return "SYSCALL_TIMES"; case 76: return "SYSCALL_UNLINK"; case 77: return "SYSCALL_WAIT"; case 61: return "SYSCALL_WRITE"; case 71: return "SYSCALL_GETTIMEOFDAY"; case 63: return "SYSCALL_READDIR"; case 73: return "SYSCALL_KILL"; case 80: return "SYSCALL_POLL"; case 83: return "SYSCALL_CLONE"; } return "UNKNOWN SYSCALL NUM"; } int syscall_unhandled(int nr) { char msg[256]; tfp_sprintf(msg, "unhandled syscall : %d",nr); kpanic("%s",msg); } int syscall_gettimeofday(struct timeval *tv, struct timezone *tz) { if(tv!=NULL) { uint64_t t=timer_get_ms(); tv->tv_sec=t/1000+2*3600; // add gmt+2 tv->tv_usec=0;//t-tv->tv_sec*1000; } // tz struct is obsolote if(tz!=NULL) { tz->tz_minuteswest=0;// -21*60; // warsaw tz->tz_dsttime=DST_NONE; } return 0; } int syscall_lseek(int file,int ptr,int dir) { #ifndef SEEK_SET #define SEEK_SET 0 /* set file offset to offset */ #endif #ifndef SEEK_CUR #define SEEK_CUR 1 /* set file offset to current plus offset */ #endif #ifndef SEEK_END #define SEEK_END 2 /* set file offset to EOF plus offset */ #endif if(dir==SEEK_CUR) { uint32_t *dat=fds[file].data; dat[1]+=ptr; return dat[1]; } kpanic("not fully handled lseek! dir=%d",dir); return 0; } // TODO: /dev/console or /dev/tty1 - /dev/ttyN int syscall_write(int file, char *buf, int len) { for(int i=0;itty->set_buff=true; get_fool()->tty->set_echo=true; } if(v1==1) // gaming tty mode { get_fool()->tty->set_buff=false; get_fool()->tty->set_echo=false; } */ return 0; } int copy_args(char **in, char **out) { //klog("copy_args(0x%08x, 0x%08X)",in,out); int count=0; while(in[count]!=NULL) { // klog("args(0x%08x: %s)",in[count],out); count++; }; // klog("copy_args : count: %d",count); char **pos=out; pos+=sizeof(char **)*(count+1); int i=0; do{ int l=strlen(in[i]); char *var=pos; memcpy(var,in[i],l+1); pos+=sizeof(char *)*(l+1); out[i]=var; i++; }while(in[i]!=NULL); out[i]=NULL; return count; } /** does not return on success otherwise -1 and errrno set */ int syscall_execve(const char *name, char *const argv[], char *const env[], int pid) { fixme("not overwrite yourself?"); int arg_count=0; while(argv[arg_count]!=NULL)arg_count++; char **argv1=VMEM_USER_ENV; if(argv!=NULL)copy_args(argv,argv1); else argv1=NULL; char **env1=VMEM_USER_ENV+1024*2; if(env!=NULL)copy_args(env,env1); else env1=NULL; uint32_t alloc; uint32_t entry_global=load_elf(name,&alloc); if(!entry_global){ set_errno(ENOENT); return -1; } uint32_t *stack=VMEM_USER_STACK_TOP-4*32; *--stack=argv1; *--stack=arg_count; *--stack=env1; task_reset(pid,entry_global,stack,alloc); return 0; } // minihack int get_max_fd() { return next_fd-1; } // TODO: support other files too (not only fifo pipes) // TODO: allow opening existing files/named pipes int syscall_open(char *name, int flags, int mode) { if( next_fifo>=MAX_FIFOS || next_fd>=MAX_FD)kpanic("we ran out of fd's or fifo's"); bool create_fifo=true; if(name[0]!='~')create_fifo=false; if(create_fifo) { if(!strcmp(name,"~term")) { screen.put_char=console_put_char; screen.update_cursor=update_cursor; tty1=terminal_init(&screen,NULL); fifos[next_fifo].data=&tty1; fifos[next_fifo].put=terminal_put; fds[next_fd]=fd_from_fifo(&fifos[next_fifo]); } else if(!strcmp(name,"~xterm")) { screen.put_char=vesa_console_put_char; screen.update_cursor=vesa_update_cursor; tty1=terminal_init(&screen,NULL); fifos[next_fifo].data=&tty1; fifos[next_fifo].put=terminal_put; fds[next_fd]=fd_from_fifo(&fifos[next_fifo]); } else { fifos[next_fifo]=fifo_create_buffered(1); fds[next_fd]=fd_from_fifo(&fifos[next_fifo]); } next_fifo++; } else { fds[next_fd]=mount_file_open(name); if(*(uint32_t *)fds[next_fd].data==0)return -1; } next_fd++; return next_fd-1; } uint32_t syscall_fork(int pid) { return task_fork(pid); } uint32_t syscall_clone(int pid) { return task_clone(pid); } uint32_t syscall_wait(int pid) { return 0; } uint32_t syscall_exit(int pid) { fixme("free allll mem"); task_exit(pid); return 0; } //newcomers // int syscall_close(int file,int none1,int none2) { if(file<3)return 0; fd_close(&fds[file]); return 0; } // TODO: check if file is termminal! int syscall_isatty(int file,int none1,int none2) { return 1; } // TODO: per process basis! uint32_t syscall_sbrk(uint32_t incr, int none1, int none2, uint32_t pid) { uint32_t alloc=task_get_brk(pid); uint32_t oldalloc=alloc; alloc+=incr; task_set_brk(pid,alloc); fixme("fake syscall_sbrk(0x%08X) return %08X",incr,oldalloc); return oldalloc; } // stat, fstat, lstat int syscall_stat(const char *path, struct stat *st,int none) { st->st_mode = S_IFCHR; return 0; } /// there also is task_fork, task_wait, task_exit.. which is in scheduler.c //////////////////////////////////////// uint32_t syscall_generic_test(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) { switch(nr){ case SYSCALL_WAIT : return !task_runs(p1); case SYSCALL_READ : return fd_has(&fds[p1]); case SYSCALL_EXIT : return 1; } return 1; } uint32_t syscall_generic(uint32_t nr,uint32_t p1, uint32_t p2, uint32_t p3, uint32_t pid) { switch(nr){ case SYSCALL_EXIT : return syscall_exit(pid); case SYSCALL_CLOSE : return syscall_close(p1,p2,p3); case SYSCALL_EXECVE : return syscall_execve(p1,p2,p3,pid); case SYSCALL_FORK : return syscall_fork(pid); case SYSCALL_CLONE : return syscall_clone(pid); case SYSCALL_GETPID : // return syscall_getpid(p1,p2,p3); return -1; case SYSCALL_ISATTY : return syscall_isatty(p1,p2,p3); case SYSCALL_LINK : // return syscall_link(p1,p2,p3); return -1; case SYSCALL_LSEEK : return syscall_lseek(p1,p2,p3); case SYSCALL_OPEN : return syscall_open(p1,p2,p3); case SYSCALL_READ : return syscall_read(p1,p2,p3); case SYSCALL_SBRK : return syscall_sbrk(p1,p2,p3,pid); case SYSCALL_STAT : return syscall_stat(p1,p2,p3); case SYSCALL_FSTAT : return syscall_stat(p1,p2,p3); case SYSCALL_LSTAT : return syscall_stat(p1,p2,p3); case SYSCALL_TIMES : // return syscall_times(p1,p2,p3); return -1; case SYSCALL_UNLINK : // return syscall_unlink(p1,p2,p3); return -1; case SYSCALL_WAIT : return syscall_wait(pid); case SYSCALL_WRITE : return syscall_write(p1,p2,p3); case SYSCALL_GETTIMEOFDAY: return syscall_gettimeofday(p1,p2); case SYSCALL_READDIR : return syscall_readdir(p1,p2,p3); case SYSCALL_KILL : // return task_kill(p1,p2,p3); return -1; case SYSCALL_POLL : return syscall_poll(p1); } return -1; }