📄 crt.c
字号:
/* Copyright (C) 2005 David Decotigny Copyright (C) 2003 Thomas Petazzoni This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//** * @file crt.c * * The C RunTime environment for the basic support of SOS C user * programs */#include <hwcore/swintr.h>#include <string.h>#include "crt.h"/** * Starter function ! */void _start() __attribute__((noreturn));void _start(){ /* This starter function expects a main() function somewhere */ extern int main(); /* Reset the bss section */ extern char _bbss, _ebss; memset(& _bbss, 0x0, (& _ebss) - (& _bbss)); _sos_exit(main());}/* * By convention, the USER SOS programs always pass 4 arguments to the * kernel syscall handler: in eax/../edx. For less arguments, the * unused registers are filled with 0s. For more arguments, the 4th * syscall parameter gives the address of the array containing the * remaining arguments. In any case, eax corresponds to the syscall * IDentifier. */inlineint _sos_syscall3(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3){ int ret; asm volatile("movl %1,%%eax \n" "movl %2,%%ebx \n" "movl %3,%%ecx \n" "movl %4,%%edx \n" "int %5\n" "movl %%eax, %0" :"=g"(ret) :"g"(id),"g"(arg1),"g"(arg2),"g"(arg3) ,"i"(SOS_SWINTR_SOS_SYSCALL) :"eax","ebx","ecx","edx"); return ret;}int _sos_syscall0(int id){ return _sos_syscall3(id, 0, 0, 0);}int _sos_syscall1(int id, unsigned int arg1){ return _sos_syscall3(id, arg1, 0, 0);}int _sos_syscall2(int id, unsigned int arg1, unsigned int arg2){ return _sos_syscall3(id, arg1, arg2, 0);}int _sos_syscall4(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4){ unsigned int args[] = { arg3, arg4 }; return _sos_syscall3(id, arg1, arg2, (unsigned)args);}int _sos_syscall5(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5){ unsigned int args[] = { arg3, arg4, arg5 }; return _sos_syscall3(id, arg1, arg2, (unsigned)args);}int _sos_syscall6(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5, unsigned int arg6){ unsigned int args[] = { arg3, arg4, arg5, arg6 }; return _sos_syscall3(id, arg1, arg2, (unsigned)args);}int _sos_syscall7(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5, unsigned int arg6, unsigned int arg7){ unsigned int args[] = { arg3, arg4, arg5, arg6, arg7 }; return _sos_syscall3(id, arg1, arg2, (unsigned)args);}int _sos_syscall8(int id, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5, unsigned int arg6, unsigned int arg7, unsigned int arg8){ unsigned int args[] = { arg3, arg4, arg5, arg6, arg7, arg8 }; return _sos_syscall3(id, arg1, arg2, (unsigned)args);}void _sos_exit(int status){ _sos_syscall1(SOS_SYSCALL_ID_EXIT, (unsigned)status); /* Never reached ! */ for ( ; ; ) ;}int _sos_bochs_write(const char * str, unsigned length){ return _sos_syscall2(SOS_SYSCALL_ID_BOCHS_WRITE, (unsigned)str, length);}int _sos_fork(){ return _sos_syscall0(SOS_SYSCALL_ID_FORK);}int _sos_exec(const char * prog){ return _sos_syscall2(SOS_SYSCALL_ID_EXEC, (unsigned int)prog, (unsigned int)strlen(prog));}int _sos_fakemmap(void ** ptr_hint_addr, size_t len, int prot, int flags, const char *resource_path, loff_t offset){ return _sos_syscall7(SOS_SYSCALL_ID_FAKEMMAP, (unsigned int)ptr_hint_addr, len, prot, flags, (unsigned int)resource_path, /* offs64_hi */(offset >> 32), /* offs64_lo */(offset & 0xffffffff));}int _sos_munmap(void * start, size_t length){ return _sos_syscall2(SOS_SYSCALL_ID_MUNMAP, (unsigned int)start, length);}int _sos_mprotect(const void *addr, size_t len, int prot){ return _sos_syscall3(SOS_SYSCALL_ID_MPROTECT, (unsigned int)addr, len, (unsigned int)prot);}int _sos_mresize(void * old_addr, size_t old_len, void * *new_addr, size_t new_len, unsigned long flags){ return _sos_syscall5(SOS_SYSCALL_ID_MRESIZE, (unsigned int)old_addr, old_len, (unsigned int)new_addr, new_len, flags);}/** * Helper function that represents the start routine of a new user * thread created from user space (syscall new_thread). It takes 2 * arguments that are passsed in the eax/ebx registers (@see * cpu_ustate_init() in hwcore/cpu_context.c): the start function of * the new thread (eax), the argument passed to it (ebx). */static void thread_routine(){ /* NOTE: variables as named registers is a gcc extension */ register unsigned long int reg_arg1 asm("%eax"); register unsigned long int reg_arg2 asm("%ebx"); sos_thread_func_t * func = (sos_thread_func_t*)reg_arg1; unsigned long int arg = reg_arg2; func(arg); _sos_exit(0);}int _sos_new_thread(sos_thread_func_t *func, void* arg, size_t stack_size){ return _sos_syscall4(SOS_SYSCALL_ID_NEW_THREAD, (unsigned)thread_routine, (unsigned)func, (unsigned)arg, stack_size);}int _sos_nanosleep(unsigned long int sec, unsigned long int nanosec){ return _sos_syscall2(SOS_SYSCALL_ID_NANOSLEEP, sec, nanosec);}void * _sos_brk(void * new_top_address){ return (void*)_sos_syscall1(SOS_SYSCALL_ID_BRK, (unsigned)new_top_address);}int _sos_mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const char *args){ if (!target || !filesystemtype) return -1; return _sos_syscall7(SOS_SYSCALL_ID_MOUNT, (unsigned int)source, source?strlen(source):0, (unsigned int)target, strlen(target), (unsigned int)filesystemtype, mountflags, (unsigned int)args);}int _sos_umount(const char *target){ if (!target) return -1; return _sos_syscall2(SOS_SYSCALL_ID_UMOUNT, (unsigned int)target, strlen(target));}void _sos_sync(void){ _sos_syscall0(SOS_SYSCALL_ID_SYNC);}int _sos_statvfs(const char *path, struct statvfs *buf){ if (! path) return -1; return _sos_syscall3(SOS_SYSCALL_ID_VFSTAT64, (unsigned)path, strlen(path), (unsigned)buf);}int _sos_open(const char * pathname, int flags, int mode){ if (! pathname) return -1; return _sos_syscall4(SOS_SYSCALL_ID_OPEN, (unsigned)pathname, strlen(pathname), flags, mode);}int _sos_close(int fd){ return _sos_syscall1(SOS_SYSCALL_ID_CLOSE, fd);}int _sos_read(int fd, char * buf, size_t * len){ return _sos_syscall3(SOS_SYSCALL_ID_READ, fd, (unsigned int) buf, (unsigned int) len);}int _sos_write(int fd, const char * buf, size_t * len){ return _sos_syscall3(SOS_SYSCALL_ID_WRITE, fd, (unsigned int) buf, (unsigned int) len);}int _sos_seek64(int fd, loff_t * offset, int whence){ return _sos_syscall3(SOS_SYSCALL_ID_SEEK64, fd, (unsigned int)offset, (unsigned int)whence);}int _sos_fmmap(void ** ptr_hint_addr, size_t len, int prot, int flags, int fd, loff_t offset){ return _sos_syscall7(SOS_SYSCALL_ID_FSMMAP, (unsigned int)ptr_hint_addr, len, prot, flags, (unsigned int)fd, /* offs64_hi */(offset >> 32), /* offs64_lo */(offset & 0xffffffff));}int _sos_ftruncate64(int fd, loff_t length){ return _sos_syscall2(SOS_SYSCALL_ID_FTRUNCATE64, fd, (unsigned int)length); }int _sos_fcntl(int fd, int cmd, int arg){ return _sos_syscall3(SOS_SYSCALL_ID_FCNTL, fd, (unsigned int)cmd, (unsigned int)arg);}int _sos_creat(const char *pathname, int mode){ if (! pathname) return -1; return _sos_syscall3(SOS_SYSCALL_ID_CREAT, (unsigned int)pathname, strlen(pathname), mode);}int _sos_link (const char *oldpath, const char *newpath){ if (!oldpath || !newpath) return -1; return _sos_syscall4(SOS_SYSCALL_ID_LINK, (unsigned int)oldpath, strlen(oldpath), (unsigned int)newpath, strlen(newpath));}int _sos_unlink(const char *pathname){ if (! pathname) return -1; return _sos_syscall2(SOS_SYSCALL_ID_UNLINK, (unsigned int)pathname, strlen(pathname));}int _sos_rename (const char *oldpath, const char *newpath){ if (!oldpath || !newpath) return -1; return _sos_syscall4(SOS_SYSCALL_ID_RENAME, (unsigned int)oldpath, strlen(oldpath), (unsigned int)newpath, strlen(newpath));}int _sos_symlink(const char *target, const char *path){ if (!path || !target) return -1; return _sos_syscall4(SOS_SYSCALL_ID_SYMLINK, (unsigned int)path, strlen(path), (unsigned int)target, strlen(target));}struct dirent; /* Forward declaration */int _sos_readdir(int fd, struct dirent * dirent){ return _sos_syscall2(SOS_SYSCALL_ID_READDIR, fd, (unsigned int)dirent);}int _sos_mkdir(const char *pathname, mode_t mode){ if (!pathname) return -1; return _sos_syscall3(SOS_SYSCALL_ID_MKDIR, (unsigned int)pathname, strlen(pathname), mode);}int _sos_rmdir(const char *pathname){ if (!pathname) return -1; return _sos_syscall2(SOS_SYSCALL_ID_RMDIR, (unsigned int)pathname, strlen(pathname));}int _sos_chmod(const char *pathname, mode_t mode){ if (!pathname) return -1; return _sos_syscall3(SOS_SYSCALL_ID_CHMOD, (unsigned int)pathname, strlen(pathname), mode);}int _sos_stat(const char *pathname, int nofollow, struct stat * st){ if (!pathname || !st) return -1; return _sos_syscall4(SOS_SYSCALL_ID_STAT64, (unsigned int)pathname, strlen(pathname), nofollow, (unsigned int)st);}int _sos_chroot(const char *dirname){ if (!dirname) return -1; return _sos_syscall2(SOS_SYSCALL_ID_CHROOT, (unsigned int)dirname, strlen(dirname));}int _sos_chdir(const char *dirname){ if (!dirname) return -1; return _sos_syscall2(SOS_SYSCALL_ID_CHDIR, (unsigned int)dirname, strlen(dirname));}int _sos_fchdir(int fd){ return _sos_syscall1(SOS_SYSCALL_ID_FCHDIR, (unsigned int)fd);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -