3 * - Acess kernel emulation on another OS using SDL and UDP
8 #include "../syscalls.h"
11 typedef int (*tSyscallHandler)(const char *Format, void *Args, int *Sizes);
14 #define SYSCALL3(_name, _fmtstr, _t0, _t1, _t2, _call) int _name(const char*Fmt,void*Args,int*Sizes){\
15 _t0 a0;_t1 a1;_t2 a2;\
16 if(strcmp(Fmt,_fmtstr)!=0)return 0;\
17 a0 = *(_t0*)Args;Args+=sizeof(_t0);\
18 a1 = *(_t1*)Args;Args+=sizeof(_t1);\
19 a2 = *(_t2*)Args;Args+=sizeof(_t2);\
23 #define SYSCALL2(_name, _fmtstr, _t0, _t1, _call) int _name(const char*Fmt,void*Args,int*Sizes){\
25 if(strcmp(Fmt,_fmtstr)!=0)return 0;\
26 a0 = *(_t0*)Args;Args+=sizeof(_t0);\
27 a1 = *(_t1*)Args;Args+=sizeof(_t1);\
31 #define SYSCALL1(_name, _fmtstr, _t0, _call) int _name(const char*Fmt, void*Args,int*Sizes){\
33 if(strcmp(Fmt,_fmtstr)!=0)return 0;\
34 a0 = *(_t0*)Args;Args+=sizeof(_t0);\
39 int Syscall_Null(const char *Format, void *Args, int *Sizes)
44 SYSCALL2(Syscall_Open, "si", const char *, int,
45 return VFS_Open(a0, a1|VFS_OPENFLAG_USER);
47 SYSCALL1(Syscall_Close, "i", int,
51 SYSCALL3(Syscall_Read, "iid", int, int, void *,
54 return VFS_Read(a0, a1, a2);
56 SYSCALL3(Syscall_Write, "iid", int, int, const void *,
59 return VFS_Write(a0, a1, a2);
61 SYSCALL3(Syscall_Seek, "iIi", int, int64_t, int,
62 return VFS_Seek(a0, a1, a2);
64 SYSCALL1(Syscall_Tell, "i", int,
67 SYSCALL3(Syscall_IOCtl, "iid", int, int, void *,
68 return VFS_IOCtl(a0, a1, a2);
70 SYSCALL3(Syscall_FInfo, "idi", int, void *, int,
71 if( Sizes[1] < sizeof(tFInfo)+a2*sizeof(tVFS_ACL))
73 return VFS_FInfo(a0, a1, a2);
77 const tSyscallHandler caSyscalls[] = {
88 const int ciNumSyscalls = sizeof(caSyscalls)/sizeof(caSyscalls[0]);
90 * \brief Recieve a syscall structure from the server code
92 tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
94 char formatString[Request->NParams+1];
95 char *inData = (char*)&Request->Params[Request->NParams];
99 int retValueCount = 1;
100 int retDataLen = sizeof(Uint64);
101 void *returnData[Request->NParams];
102 int argSizes[Request->NParams];
105 if( Request->CallID >= ciNumSyscalls ) {
106 Log_Notice("Syscalls", "Unknown syscall number %i", Request->CallID);
110 // Get size of argument list
111 for( i = 0; i < Request->NParams; i ++ )
113 argSizes[i] = Request->Params[i].Length;
114 switch(Request->Params[i].Type)
117 formatString[i] = '-';
120 formatString[i] = 'i';
121 argListLen += sizeof(Uint32);
124 formatString[i] = 'I';
125 argListLen += sizeof(Uint64);
128 formatString[i] = 'd';
129 argListLen += sizeof(void*);
131 case ARG_TYPE_STRING:
132 formatString[i] = 's';
133 argListLen += sizeof(char*);
136 return NULL; // ERROR!
139 formatString[i] = '\0';
141 Log_Debug("Syscalls", "Request %i '%s'", Request->CallID, formatString);
144 char argListData[argListLen];
146 // Build argument list
147 for( i = 0; i < Request->NParams; i ++ )
149 returnData[i] = NULL;
150 switch(Request->Params[i].Type)
155 Log_Debug("Syscalls", "Arg %i: 0x%x", i, *(Uint32*)inData);
156 *(Uint32*)&argListData[argListLen] = *(Uint32*)inData;
157 argListLen += sizeof(Uint32);
158 inData += sizeof(Uint32);
161 Log_Debug("Syscalls", "Arg %i: 0x%llx", i, *(Uint64*)inData);
162 *(Uint64*)&argListData[argListLen] = *(Uint64*)inData;
163 argListLen += sizeof(Uint64);
164 inData += sizeof(Uint64);
166 case ARG_TYPE_STRING:
167 Log_Debug("Syscalls", "Arg %i: '%s'", i, (char*)inData);
168 *(char**)&argListData[argListLen] = (char*)inData;
169 argListLen += sizeof(void*);
170 inData += Request->Params[i].Length;
173 // Data gets special handling, because only it can be returned to the user
174 // (ARG_TYPE_DATA is a pointer)
176 // Prepare the return values
177 if( Request->Params[i].Flags & ARG_FLAG_RETURN )
179 retDataLen += Request->Params[i].Length;
183 // Check for non-resident data
184 if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
186 // Allocate and zero the buffer
187 returnData[i] = calloc(1, Request->Params[i].Length);
188 Log_Debug("Syscalls", "Arg %i: %i %p", i,
189 Request->Params[i].Length, returnData[i]);
190 *(void**)&argListData[argListLen] = returnData[i];
191 argListLen += sizeof(void*);
195 returnData[i] = (void*)inData;
196 Log_Debug("Syscalls", "Arg %i: %i %p", i,
197 Request->Params[i].Length, returnData[i]);
198 *(void**)&argListData[argListLen] = (void*)inData;
199 argListLen += sizeof(void*);
200 inData += Request->Params[i].Length;
206 retVal = caSyscalls[Request->CallID](formatString, argListData, argSizes);
209 // Allocate the return
210 ret = malloc(sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue)
212 ret->ClientID = Request->ClientID;
213 ret->CallID = Request->CallID;
214 ret->NParams = retValueCount;
215 inData = (char*)&ret->Params[ ret->NParams ];
217 // Static Uint64 return value
218 ret->Params[0].Type = ARG_TYPE_INT64;
219 ret->Params[0].Flags = 0;
220 ret->Params[0].Length = sizeof(Uint64);
221 *(Uint64*)inData = retVal;
222 inData += sizeof(Uint64);
224 Log_Debug("Syscalls", "Return 0x%llx", retVal);
226 for( i = 0; i < Request->NParams; i ++ )
228 if( Request->Params[i].Type != ARG_TYPE_DATA ) continue;
229 if( !(Request->Params[i].Flags & ARG_FLAG_RETURN) ) continue;
231 ret->Params[1 + i].Type = Request->Params[i].Type;
232 ret->Params[1 + i].Flags = 0;
233 ret->Params[1 + i].Length = Request->Params[i].Length;
235 memcpy(inData, returnData[i], Request->Params[i].Length);
236 inData += Request->Params[i].Length;
238 if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
239 free( returnData[i] ); // Free temp buffer from above
242 *ReturnLength = sizeof(tRequestHeader)
243 + retValueCount * sizeof(tRequestValue)