#define FOOLOS_MODULE_NAME "syscalls" #include "lib/buffer/ringbuffer.h" #include "lib/logger/log.h" #include "lib/bool/bool.h" #include "fs/fs.h" #include "fs/ext2.h" #include "kernel/console.h" #include "kernel/config.h" #include #define EI_NIDENT 16 typedef uint32_t Elf32_Addr; typedef uint32_t Elf32_Off; typedef uint16_t Elf32_Section; typedef uint16_t Elf32_Versym; typedef unsigned char Elf_Byte; typedef uint16_t Elf32_Half; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef int64_t Elf32_Sxword; typedef uint64_t Elf32_Xword; typedef struct { unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr; typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize; } Elf32_Shdr; typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align; } Elf32_Phdr; static uint32_t alloc=0x900000; int syscall_unhandled(int nr) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"syscall: %d", nr); panic(FOOLOS_MODULE_NAME,"unhandled syscall"); } int syscall_lseek(int file,int ptr,int dir) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"lseek (file=%d, ptr=%d, dir=%d)", file,ptr,dir); #endif panic(FOOLOS_MODULE_NAME,"unhandled syscall"); return 0; } int syscall_write(int file, char *buf, int len) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"write(file=%d, buf=0x%08X, len=%d)", file,buf,len); #endif if(file!=1&&file!=2) panic(FOOLOS_MODULE_NAME,"unhandled syscall"); // ALL output to stdout for(int i=0;i0) { console_del_char(); buf--; l--; } } else{ *buf=c; buf++; l++; if(c!=0x04)console_put_char_red(c); if(c=='\n')return l; if(c==0x04) { l--; buf--; eof=true; return l; } } } } } } //TODO: replace with dirent! int syscall_readdir(const char *name,fs_dirent *dirs,int max) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"readdir(name=0x%08X, dirs=0x%08X, %d)", name,dirs,max); #endif return fs_readdir(name,dirs,max); } int syscall_execve(char *name, char **argv, char **env) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"execve (name=0x%08X(%s), argvs=0x%08X, env=0x%08X)", name,name,argv,env); #endif int inode_nr=ext2_filename_to_inode(EXT2_RAM_ADDRESS,name); if(inode_nr<1)return -1; char arg1[100]; char arg2[100]; char arg3[100]; char arg4[100]; char arg5[100]; char *argvcopy[]={arg1,arg2,arg3,arg4,arg5}; int argc=0; if(argv!=NULL) { while(argv[argc]!=NULL) { //log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"arg at 0x%08X: %s", argv[argc],argv[argc]); int i=-1; do{ i++; argvcopy[argc][i]=argv[argc][i]; }while(argv[argc][i]!=0); argc++; } } argvcopy[argc]=NULL; // char *env1="PS1=$ "; char *env2="PATH=/bin"; char *env3="PWD=/home/miguel"; char environstr[256]; char **oldenviron=env; char **environ=0xf00001; if(oldenviron==0) { environ[0]=env1; environ[1]=env2; environ[2]=env3; environ[3]=NULL; } else { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"environ: (0x%08X)",oldenviron); int i=0; int k=-1; while(oldenviron[i]!=NULL) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"copy env: %s (0x%08X)",oldenviron[i],oldenviron[i]); int start=k+1; int j=-1; do{ j++; k++; environstr[k]=oldenviron[i][j]; }while(oldenviron[i][j]!=0); environ[i]=&environstr[start]; i++; } environ[i]=NULL; } //TODO: load ELF binary and move this to own compilation unit //load binary ext2_check(EXT2_RAM_ADDRESS); ext2_inode_content(EXT2_RAM_ADDRESS,inode_nr,0x800000,0x100000); Elf32_Ehdr *elf; elf=0x800000; if(elf->e_ident[0]!=0x7f||elf->e_ident[1]!='E'||elf->e_ident[2]!='L'||elf->e_ident[3]!='F') panic(FOOLOS_MODULE_NAME,"ELF mismatch!?"); /* log(FOOLOS_MODULE_NAME, FOOLOS_LOG_INFO, "elf id: class=%d, data=%d, version=%d osabi=%d abiv=%d ", elf->e_ident[4],elf->e_ident[5],elf->e_ident[6], elf->e_ident[7],elf->e_ident[8]); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf type: 0x%04x",elf->e_type); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf machine: 0x%04x",elf->e_machine); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf version: %d",elf->e_version); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf entry: 0x%08X",elf->e_entry); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf ph-offset: 0x%08X",elf->e_phoff); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf sh-offset: 0x%08X",elf->e_shoff); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf flags: 0x%08X",elf->e_flags); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf eh-size (bytes): %d",elf->e_ehsize); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf ph-ent-size(bytes): %d",elf->e_phentsize); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf ph-num: %d",elf->e_phnum); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf sh-ent-size(byte): %d",elf->e_shentsize); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf sh-num: %d",elf->e_shnum); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"elf sh-strndx: %d",elf->e_shstrndx); */ // iterate over section headers for(int phidx=0;phidxe_phnum;phidx++) { Elf32_Phdr *phdr=0x800000+elf->e_phoff+phidx*elf->e_phentsize; if(phidx==0) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"text: 0x%08X-0x%08X",phdr->p_vaddr,phdr->p_vaddr+phdr->p_filesz); } if(phidx==1) { /* log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"-- PROGRAMM HEADER %d --",phidx+1); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"p-type: %d",phdr->p_type); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"p-offset: 0x%08X",phdr->p_offset); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"p-vaddr: 0x%08X",phdr->p_vaddr); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"p-filesz: 0x%08X",phdr->p_filesz); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"p-memsz: 0x%08X",phdr->p_memsz); */ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"data: 0x%08X-0x%08X",phdr->p_vaddr,phdr->p_vaddr+phdr->p_filesz); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"bss: 0x%08X-0x%08X",phdr->p_vaddr+phdr->p_filesz,phdr->p_vaddr+phdr->p_memsz); // let's copy the rw- data block uint32_t *data=0x800000+phdr->p_offset; for(uint32_t *addr=phdr->p_vaddr; addr<=phdr->p_vaddr+phdr->p_filesz; addr++) { *addr=*data; data++; } // let's zero init bss and set alloc (heap) just right after it! for(uint32_t *addr=phdr->p_vaddr+phdr->p_filesz; addr<=phdr->p_vaddr+phdr->p_memsz; addr++) { *addr=0; } alloc=phdr->p_vaddr+phdr->p_memsz; } } int i=0; do{ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"envvar %d : 0x%08X : %s" ,i,environ[i],environ[i]); i++; }while(environ[i]!=NULL); asm("mov $0xf00000,%esp"); // set stack pointer asm("push %0" :: "r" (argvcopy)); asm("push %0" :: "r" (argc)); asm("push %0" :: "r" (environ)); // push addr and return to it asm("push %0"::"r"(elf->e_entry)); asm("ret"); // this is never reached! } int syscall_open(char *name, int flags, int mode) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"open (name=0x%08X(\"%s\"), flags=%d, mode=%d)",name, name,flags,mode); #endif panic(FOOLOS_MODULE_NAME,"unhandled syscall"); } //newcomers // int syscall_close(int file,int none1,int none2) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"close (file=%d)", file); #endif if(file!=0&&file!=1&&file!=2) panic(FOOLOS_MODULE_NAME,"unhandled syscall"); return -1; } // TODO: check if file is termminal! int syscall_isatty(int file,int none1,int none2) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"isatty (file=%d)", file); #endif return 1; } uint32_t syscall_sbrk(int incr, int none1, int none2) { uint32_t oldalloc=alloc; alloc+=incr; #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"sbrk (incr=%d) = 0x%08X", incr,oldalloc); #endif return oldalloc; } int syscall_exit(int ret, char **env, int none2) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"exit (ret=%d) (env=0x%08X)", ret, env); #endif int i=0; while(env[i]!=NULL) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"envvar %s (0x%08X)\n" ,env[i],env[i]); i++; } asm("mov $0x05bff,%esp"); // set stack pointer static char *argv[]={"shell","--silent",NULL}; syscall_execve("/bin/foolshell",argv,env); // start shell } // stat, fstat, lstat int syscall_stat(const char *path, struct stat *st,int none) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"stat (path=0x%08X,stat=0x%08X)", path,st); #endif st->st_mode = S_IFCHR; return 0; } int syscall_fstat(int file, struct stat *st,int none) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"fstat (file=%d,stat=0x%08X)", file,st); #endif st->st_mode = S_IFCHR; return 0; } int syscall_lstat(const char *path, struct stat *st,int none) { #ifdef LOG_SYSCALLS log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"lstat (path=0x%08X,stat=0x%08X)", path,st); #endif st->st_mode = S_IFCHR; return 0; }