#include <threads.h>
#include <events.h>
+#if 1
+# define MERR(f,v...) Log_Debug("Syscalls", "0x%x "f, callNum ,## v)
+#else
+# define MERR(v...) do{}while(0)
+#endif
+
#define CHECK_NUM_NULLOK(v,size) \
- if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NULLOK(v) \
- if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_ValidString((v))){MERR("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_NUM_NONULL(v,size) \
- if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NONULL(v) \
- if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_ValidString((v))){MERR("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
- CHECK_NUM_NONULL( tmp, sizeof(char**) ); \
- for(i=0;tmp[i];i++) { \
+ CHECK_NUM_NULLOK( tmp, sizeof(char**) ); \
+ for(i=0;tmp&&tmp[i];i++) { \
CHECK_STR_NONULL( tmp[i] ); \
CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \
}\
if(tmp[i]) break;\
} while(0)
+#if BITS==64
+#define ARG64(idx1,idx2) ***ARG64 not used on 64-bit***
+#else
+#define ARG64(idx1, idx2) (Regs->Arg##idx1|(((Uint64)Regs->Arg##idx2)<<32))
+#endif
+
// === IMPORTS ===
extern Uint Binary_Load(const char *file, Uint *entryPoint);
void SyscallHandler(tSyscallRegs *Regs);
int Syscall_ValidString(const char *Addr);
int Syscall_Valid(int Size, const void *Addr);
+ int Syscall_MM_SetFlags(void *Addr, Uint Flags, Uint Mask);
// === CODE ===
// TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel
// -- Put the current thread to sleep
case SYS_SLEEP: Threads_Sleep(); break;
+
+ case SYS_TIMEDSLEEP:
+ Time_Delay(Regs->Arg1);
+ break;
// -- Yield current timeslice
case SYS_YIELD: Threads_Yield(); break;
// -- Get the physical address of a page
case SYS_GETPHYS:
- ret = MM_GetPhysAddr(Regs->Arg1);
+ ret = MM_GetPhysAddr( (void*)Regs->Arg1 );
break;
// -- Map an address
- case SYS_MAP: MM_Map(Regs->Arg1, Regs->Arg2); break;
+ case SYS_MAP: MM_Map((void*)Regs->Arg1, Regs->Arg2); break;
// -- Allocate an address
- case SYS_ALLOCATE: ret = MM_Allocate(Regs->Arg1); break;
+ case SYS_ALLOCATE: ret = MM_Allocate((void*)Regs->Arg1); break;
// -- Unmap an address
- case SYS_UNMAP: MM_Deallocate(Regs->Arg1); break;
+ case SYS_UNMAP: MM_Deallocate((void*)Regs->Arg1); break;
+ // -- Change the protection on an address
+ case SYS_SETFLAGS:
+ ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ break;
+
// -- Get Thread/Process IDs
case SYS_GETTID: ret = Threads_GetTID(); break;
case SYS_GETPID: ret = Threads_GetPID(); break;
// -- Check for messages
case SYS_GETMSG:
CHECK_NUM_NULLOK( (Uint*)Regs->Arg1, sizeof(Uint) );
- // NOTE: Can't do range checking as we don't know the size
- // - Should be done by Proc_GetMessage
- if( Regs->Arg2 && Regs->Arg2 != -1 && !MM_IsUser(Regs->Arg2) ) {
- err = -EINVAL; ret = -1; break;
- }
+ if( Regs->Arg3 != -1 )
+ CHECK_NUM_NULLOK((void*)Regs->Arg3, Regs->Arg2);
// *Source, *Data
- ret = Proc_GetMessage((Uint*)Regs->Arg1, (void*)Regs->Arg2);
+ ret = Proc_GetMessage((Uint*)Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
break;
// -- Get the current timestamp
CHECK_STR_NONULL((const char*)Regs->Arg1);
CHECK_STR_ARRAY((const char**)Regs->Arg2);
CHECK_STR_ARRAY((const char**)Regs->Arg3);
- CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+ if( Regs->Arg4 > 0 )
+ CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
ret = Proc_SysSpawn(
(const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
Regs->Arg4, (int*)Regs->Arg5
// Path, *Entrypoint
ret = Binary_Load((char*)Regs->Arg1, (Uint*)Regs->Arg2);
break;
-
+
+ // -- Load a kernel module
+ case SYS_LOADMOD:
+ CHECK_STR_NONULL( (const char *)Regs->Arg1 );
+ if( Threads_GetUID() != 0 ) {
+ MERR("Not root");
+ ret = EACCES;
+ }
+ else {
+ LOG("Module_LoadFile(\"%s\", NULL)", (const char *)Regs->Arg1);
+ ret = Module_LoadFile( (const char *)Regs->Arg1, NULL );
+ }
+ break;
+
// ---
// Virtual Filesystem
// ---
LOG("VFS_Open(\"%s\", 0x%x)", (char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
ret = VFS_Open((char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
break;
+ case SYS_REOPEN:
+ CHECK_STR_NONULL( (char*)Regs->Arg2 );
+ LOG("VFS_Reopen(%i, \"%s\", 0x%x)", Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER);
+ ret = VFS_Reopen(Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER);
+ break;
case SYS_CLOSE:
LOG("VFS_Close(%i)", Regs->Arg1);
VFS_Close( Regs->Arg1 );
break;
+ case SYS_COPYFD:
+ LOG("VFS_DuplicateFD(%i,%i)", Regs->Arg1, Regs->Arg2);
+ ret = VFS_DuplicateFD(Regs->Arg1, Regs->Arg2);
+ break;
+
+ case SYS_FDCTL:
+ LOG("VFS_SetFDFlags(%i,0%o,0%o)", Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ ret = VFS_SetFDFlags(Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ break;
+
case SYS_SEEK:
#if BITS == 64
ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 );
#else
- ret = VFS_Seek( Regs->Arg1, Regs->Arg2|(((Uint64)Regs->Arg3)<<32), Regs->Arg4 );
+ ret = VFS_Seek( Regs->Arg1, ARG64(2, 3), Regs->Arg4 );
#endif
break;
CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
ret = VFS_Write( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 );
break;
+ case SYS_WRITEAT:
+ #if BITS == 64
+ CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg3 );
+ ret = VFS_WriteAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 );
+ #else
+ CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg4 );
+ Debug("VFS_WriteAt(%i, %lli, %i, %p)",
+ Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5);
+ ret = VFS_WriteAt( Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5 );
+ #endif
+ break;
case SYS_READ:
CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
ret = VFS_Read( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 );
break;
+ case SYS_READAT:
+ CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg2 );
+ #if BITS == 64
+ ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 );
+ #else
+ ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, ARG64(3, 4), (void*)Regs->Arg5 );
+ #endif
+ break;
+
+ case SYS_TRUNCATE:
+ ret = VFS_Truncate(
+ Regs->Arg1,
+ #if BITS == 32
+ ARG64(2,3)
+ #else
+ Regs->Arg2
+ #endif
+ );
+ break;
case SYS_FINFO:
CHECK_NUM_NONULL( (void*)Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
case SYS_IOCTL:
// All sanity checking should be done by the driver
if( Regs->Arg3 && !MM_IsUser(Regs->Arg3) ) {
+ MERR("IOCtl Invalid arg %p", Regs->Arg3);
err = -EINVAL; ret = -1; break;
}
ret = VFS_IOCtl( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
ret = -1;
break;
}
- // Sanity check the paths
- if(!Syscall_ValidString((char*)Regs->Arg1)
- || !Syscall_ValidString((char*)Regs->Arg2)
- || !Syscall_ValidString((char*)Regs->Arg3)
- || !Syscall_ValidString((char*)Regs->Arg4) ) {
- err = -EINVAL;
- ret = -1;
- break;
+
+ if( !Regs->Arg1 )
+ {
+ if( !Syscall_ValidString((char*)Regs->Arg2) ) {
+ err = -EINVAL;
+ ret = -1;
+ break;
+ }
+
+ ret = VFS_Unmount((char*)Regs->Arg2);
+ }
+ else
+ {
+ // Sanity check the paths
+ CHECK_STR_NONULL((char*)Regs->Arg1);
+ CHECK_STR_NONULL((char*)Regs->Arg2);
+ CHECK_STR_NULLOK((char*)Regs->Arg3);
+ CHECK_STR_NONULL((char*)Regs->Arg4);
+ ret = VFS_Mount(
+ (char*)Regs->Arg1, // Device
+ (char*)Regs->Arg2, // Mount point
+ (char*)Regs->Arg3, // Filesystem
+ (char*)Regs->Arg4 // Options
+ );
}
- ret = VFS_Mount(
- (char*)Regs->Arg1, // Device
- (char*)Regs->Arg2, // Mount point
- (char*)Regs->Arg3, // Filesystem
- (char*)Regs->Arg4 // Options
- );
break;
// Wait on a set of handles
0 // User handles
);
break;
+
+ case SYS_MMAP:
+ ret = (tVAddr)VFS_MMap(
+ (void*)Regs->Arg1, Regs->Arg2,
+ Regs->Arg3&0xFFFF, Regs->Arg3>>16,
+ Regs->Arg4,
+ #if BITS == 32
+ ARG64(5,6)
+ #else
+ Regs->Arg5
+ #endif
+ );
+ break;
+ case SYS_MUNMAP:
+ ret = VFS_MUnmap( (void*)Regs->Arg1, Regs->Arg2 );
+ break;
+
+ // Create a directory
+ case SYS_MKDIR:
+ CHECK_STR_NONULL( (char*)Regs->Arg1 );
+ ret = VFS_MkDir( (char*)Regs->Arg1 );
+ break;
+
+ case SYS_UNLINK:
+ Log_Error("Syscalls", "TODO: Impliment SYS_UNLINK");
+ break;
+ case SYS_MARSHALFD:
+ ret = VFS_MarshalHandle(Regs->Arg1);
+ break;
+ case SYS_UNMARSHALFD:
+ #if BITS == 64
+ ret = VFS_UnmarshalHandle( Regs->Arg1 );
+ #else
+ ret = VFS_UnmarshalHandle( ARG64(1,2) );
+ #endif
+ break;
+
// -- Debug
//#if DEBUG_BUILD
case SYS_DEBUG:
Regs->Arg2, Regs->Arg3, Regs->Arg4, Regs->Arg5, Regs->Arg6);
LogF("\r\n");
break;
+ case SYS_DEBUGHEX:
+ CHECK_STR_NONULL( (char*)Regs->Arg1 );
+ CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 );
+ Debug_HexDump( (const char*)Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 );
+ break;
//#endif
// -- Default (Return Error)
*/
int Syscall_Valid(int Size, const void *Addr)
{
- if(!MM_IsUser( (tVAddr)Addr )) return 0;
+ if(!MM_IsUser( (tVAddr)Addr )) {
+ Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr);
+ return 0;
+ }
return CheckMem( Addr, Size );
}
+
+int Syscall_MM_SetFlags(void *Addr, Uint Flags, Uint Mask)
+{
+ tPAddr paddr = MM_GetPhysAddr(Addr);
+ Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+ Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+
+ //Log_Debug("Syscalls", "SYS_SETFLAGS: %p %x %x", Addr, Flags, Mask);
+
+ // Enable write?
+ if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) {
+ void *node;
+ // HACK - Assume that RO mmap'd files are immutable
+ if( MM_GetPageNode(paddr, &node) == 0 && node ) {
+ Flags |= MM_PFLAG_COW;
+ Mask |= MM_PFLAG_COW;
+ }
+ }
+ MM_SetFlags(Addr, Flags, Mask);
+ return 0;
+}