/* 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 #include #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. */ inline int _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); }