sos-code-article7/userland/crt.c

184 lines
3.9 KiB
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.
*/
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);
}