--- /dev/null
+/*
+ * Acess2 Native Kernel
+ * - Acess kernel emulation on another OS using SDL and UDP
+ *
+ * Syscall Server
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <SDL/SDL.h>
+#ifdef __WIN32__
+# include <windows.h>
+# include <winsock.h>
+#else
+# include <unistd.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+#endif
+#include "../syscalls.h"
+
+#define USE_TCP 0
+#define MAX_CLIENTS 16
+
+// === TYPES ===
+typedef struct {
+ int ClientID;
+ SDL_Thread *WorkerThread;
+ #if USE_TCP
+ #else
+ tRequestHeader *CurrentRequest;
+ struct sockaddr_in ClientAddr;
+ SDL_cond *WaitFlag;
+ SDL_mutex *Mutex;
+ #endif
+} tClient;
+
+// === IMPORTS ===
+extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
+
+// === PROTOTYPES ===
+tClient *Server_GetClient(int ClientID);
+ int Server_WorkerThread(void *ClientPtr);
+ int SyscallServer(void);
+
+// === GLOBALS ===
+#ifdef __WIN32__
+WSADATA gWinsock;
+SOCKET gSocket = INVALID_SOCKET;
+#else
+# define INVALID_SOCKET -1
+ int gSocket = INVALID_SOCKET;
+#endif
+ int giServer_NextClientID = 1;
+tClient gaServer_Clients[MAX_CLIENTS];
+
+// === CODE ===
+tClient *Server_GetClient(int ClientID)
+{
+ tClient *ret = NULL;
+ int i;
+
+ for( i = 0; i < MAX_CLIENTS; i ++ )
+ {
+ if( gaServer_Clients[i].ClientID == ClientID ) {
+ ret = &gaServer_Clients[i];
+ break;
+ }
+ }
+
+ // Uh oh, no free slots
+ // TODO: Dynamic allocation
+ if( !ret )
+ return NULL;
+
+ if( ClientID == 0 )
+ {
+ ret->ClientID = giServer_NextClientID ++;
+ ret->CurrentRequest = NULL;
+
+ if( !ret->WorkerThread ) {
+ ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
+ ret->WaitFlag = SDL_CreateCond();
+ ret->Mutex = SDL_CreateMutex();
+ SDL_mutexP( ret->Mutex );
+ }
+ }
+
+ return &gaServer_Clients[i];
+}
+
+int Server_WorkerThread(void *ClientPtr)
+{
+ tClient *Client = ClientPtr;
+ tRequestHeader *retHeader;
+ int retSize = 0;
+ int sentSize;
+
+ #if USE_TCP
+ #else
+ for( ;; )
+ {
+ // Wait for something to do
+ while( !Client->CurrentRequest ) ;
+
+ // Get the response
+ retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
+
+ if( !retHeader ) {
+ // Return an error to the client
+ printf("Error returned by SyscallRecieve\n");
+ }
+
+ // Return the data
+ sentSize = sendto(gSocket, retHeader, retSize, 0,
+ (struct sockaddr*)&Client->ClientAddr, sizeof(Client->ClientAddr)
+ );
+ if( sentSize != retSize ) {
+ perror("Server_WorkerThread - send");
+ }
+
+ // Free allocated header
+ free( retHeader );
+
+ Client->CurrentRequest = 0;
+
+ // Wait for something else
+ SDL_CondWait(Client->WaitFlag, Client->Mutex);
+ }
+ #endif
+}
+
+int SyscallServer(void)
+{
+ struct sockaddr_in server;
+
+ #ifdef __WIN32__
+ /* Open windows connection */
+ if (WSAStartup(0x0101, &gWinsock) != 0)
+ {
+ fprintf(stderr, "Could not open Windows connection.\n");
+ exit(0);
+ }
+ #endif
+
+ #if USE_TCP
+ // Open TCP Connection
+ gSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ #else
+ // Open UDP Connection
+ gSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ #endif
+ if (gSocket == INVALID_SOCKET)
+ {
+ fprintf(stderr, "Could not create socket.\n");
+ #if __WIN32__
+ WSACleanup();
+ #endif
+ exit(0);
+ }
+
+ // Set server address
+ memset(&server, 0, sizeof(struct sockaddr_in));
+ server.sin_family = AF_INET;
+ server.sin_port = htons(SERVER_PORT);
+ server.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ // Bind
+ if( bind(gSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1 )
+ {
+ fprintf(stderr, "Cannot bind address to socket.\n");
+ perror("SyscallServer - bind");
+ #if __WIN32__
+ closesocket(gSocket);
+ WSACleanup();
+ #else
+ close(gSocket);
+ #endif
+ exit(0);
+ }
+
+ #if USE_TCP
+ listen(gSocket, 5);
+ #endif
+
+ Log_Notice("Syscall", "Listening on 0.0.0.0:%i\n", SERVER_PORT);
+
+ // Wait for something to do :)
+ for( ;; )
+ {
+ #if USE_TCP
+ struct sockaddr_in client;
+ uint clientSize = sizeof(client);
+ int clientSock = accept(gSocket, (struct sockaddr*)&client, &clientSize);
+ if( clientSock < 0 ) {
+ perror("SyscallServer - accept");
+ break ;
+ }
+
+ printf("Client connection %x:%i",
+ ntohl(client.sin_addr), ntohs(client.sin_port)
+ );
+
+ #else
+ char data[BUFSIZ];
+ tRequestHeader *req = (void*)data;
+ struct sockaddr_in addr;
+ uint clientSize = sizeof(addr);
+ int length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
+ tClient *client;
+
+ if( length == -1 ) {
+ perror("SyscallServer - recv");
+ break;
+ }
+
+ // Hand off to a worker thread
+ // - TODO: Actually have worker threads
+ printf("%i bytes from %x:%i\n", length,
+ ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
+
+ client = Server_GetClient(req->ClientID);
+ if( req->ClientID == 0 )
+ {
+ memcpy(&client->ClientAddr, &addr, sizeof(addr));
+ }
+ else if( memcmp(&client->ClientAddr, &addr, sizeof(addr)) != 0 )
+ {
+ printf("ClientID %i used by %x:%i\n",
+ client->ClientID, ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
+ printf(" actually owned by %x:%i\n",
+ ntohl(client->ClientAddr.sin_addr.s_addr), ntohs(client->ClientAddr.sin_port));
+ continue;
+ }
+
+ if( client->CurrentRequest ) {
+ printf("Worker thread for %x:%i is busy\n",
+ ntohl(client->ClientAddr.sin_addr.s_addr), ntohs(client->ClientAddr.sin_port));
+ continue;
+ }
+
+ client->CurrentRequest = req;
+ SDL_CondSignal(client->WaitFlag);
+ #endif
+ }
+
+ return -1;
+}
return 0;
}
-SYSCALL2(Syscall_Open, VFS_Open, "di", const char *, int);
+SYSCALL2(Syscall_Open, VFS_Open, "si", const char *, int);
SYSCALL1V(Syscall_Close, VFS_Close, "i", int);
SYSCALL3(Syscall_Read, VFS_Read, "iid", int, int, void *);
SYSCALL3(Syscall_Write, VFS_Write, "iid", int, int, const void *);
/**
* \brief Recieve a syscall structure from the server code
*/
-tRequestHeader *SyscallRecieve(tRequestHeader *Request)
+tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength)
{
char formatString[Request->NParams+1];
- char *inData = (char*)&Request->Params[Request->NParams+Request->NReturn];
+ char *inData = (char*)&Request->Params[Request->NParams];
int argListLen = 0;
int i, retVal;
+ tRequestHeader *ret;
+ int retValueCount = 1;
+ int retDataLen = sizeof(Uint64);
+ void *mallocdData[Request->NParams];
+ // Sanity check
if( Request->CallID > ciNumSyscalls ) {
return NULL;
}
formatString[i] = 'd';
argListLen += sizeof(void*);
break;
+ case ARG_TYPE_STRING:
+ formatString[i] = 's';
+ argListLen += sizeof(char*);
+ break;
default:
return NULL; // ERROR!
}
argListLen += sizeof(Uint64);
inData += sizeof(Uint64);
break;
- case ARG_TYPE_DATA:
case ARG_TYPE_STRING:
*(void**)&argListData[argListLen] = *(void**)inData;
argListLen += sizeof(void*);
- inData += sizeof(void*);
+ inData += Request->Params[i].Length;
+ break;
+
+ // Data gets special handling, because only it can be returned to the user
+ // (ARG_TYPE_DATA is a pointer)
+ case ARG_TYPE_DATA:
+ // Prepare the return values
+ if( Request->Params[i].Flags & ARG_FLAG_RETURN )
+ {
+ retDataLen += Request->Params[i].Length;
+ retValueCount ++;
+ }
+
+ // Check for non-resident data
+ if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
+ {
+ // Allocate and zero the buffer
+ mallocdData[i] = calloc(1, Request->Params[i].Length);
+ *(void**)&argListData[argListLen] = mallocdData[i];
+ argListLen += sizeof(void*);
+ }
+ else
+ {
+ *(void**)&argListData[argListLen] = (void*)inData;
+ argListLen += sizeof(void*);
+ inData += Request->Params[i].Length;
+ }
break;
}
}
retVal = caSyscalls[Request->CallID](formatString, argListData);
}
- return NULL;
+ // Allocate the return
+ ret = malloc(sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue)
+ + retDataLen);
+ ret->ClientID = Request->ClientID;
+ ret->CallID = Request->CallID;
+ ret->NParams = retValueCount;
+ inData = &ret->Params[ ret->NParams ];
+
+ // Static Uint64 return value
+ ret->Params[0].Type = ARG_TYPE_INT64;
+ ret->Params[0].Flags = 0;
+ ret->Params[0].Length = sizeof(Uint64);
+ *(Uint64*)inData = retVal;
+ inData += sizeof(Uint64);
+
+ for( i = 0; i < Request->NParams; i ++ )
+ {
+ if( Request->Params[i].Type != ARG_TYPE_DATA ) continue;
+ if( !(Request->Params[i].Flags & ARG_FLAG_RETURN) ) continue;
+
+ ret->Params[1 + i].Type = Request->Params[i].Type;
+ ret->Params[1 + i].Flags = 0;
+ ret->Params[1 + i].Length = Request->Params[i].Length;
+
+ memcpy(inData, mallocdData[i], Request->Params[i].Length);
+ inData += Request->Params[i].Length;
+
+ free( mallocdData[i] ); // Free temp buffer from above
+ }
+
+ return ret;
}
req.ClientID = 0;
req.CallID = 0;
req.NParams = 0;
- req.NReturn = 0;
SendData(&req, sizeof(req));
len = ReadData(&req, sizeof(req), 5);
+ if( len == 0 ) {
+ fprintf(stderr, "Unable to connect to server (localhost:%i)\n", SERVER_PORT);
+ exit(-1);
+ }
giSyscall_ClientID = req.ClientID;
}
return 0;
}
-int SendRequest(int RequestID, int NumOutput, tOutValue **Output, int NumInput, tInValue **Input)
+int SendRequest(tRequestHeader *Request, int RequestSize)
{
- tRequestHeader *request;
- tRequestValue *value;
- char *data;
- int requestLen;
- int i;
-
if( gSocket == INVALID_SOCKET )
{
_InitSyscalls();
}
- // See ../syscalls.h for details of request format
- requestLen = sizeof(tRequestHeader) + (NumOutput + NumInput) * sizeof(tRequestValue);
-
- // Get total param length
- for( i = 0; i < NumOutput; i ++ )
- requestLen += Output[i]->Length;
-
- // Allocate request
- request = malloc( requestLen );
- value = request->Params;
- data = (char*)&request->Params[ NumOutput + NumInput ];
-
// Set header
- request->ClientID = giSyscall_ClientID;
- request->CallID = RequestID; // Syscall
- request->NParams = NumOutput;
- request->NReturn = NumInput;
+ Request->ClientID = giSyscall_ClientID;
- // Set parameters
- for( i = 0; i < NumOutput; i ++ )
- {
- switch(Output[i]->Type)
- {
- case 'i': value->Type = ARG_TYPE_INT32; break;
- case 'I': value->Type = ARG_TYPE_INT64; break;
- case 'd': value->Type = ARG_TYPE_DATA; break;
- case 's': value->Type = ARG_TYPE_DATA; break;
- default:
- fprintf(stderr, __FILE__" SendRequest: Unknown output type '%c'\n",
- Output[i]->Type);
- return -1;
- }
- value->Length = Output[i]->Length;
-
- memcpy(data, Output[i]->Data, Output[i]->Length);
-
- value ++;
- data += Output[i]->Length;
- }
-
- // Set return values
- for( i = 0; i < NumInput; i ++ )
- {
- switch(Input[i]->Type)
- {
- case 'i': value->Type = ARG_TYPE_INT32; break;
- case 'I': value->Type = ARG_TYPE_INT64; break;
- case 'd': value->Type = ARG_TYPE_DATA; break;
- default:
- fprintf(stderr, " SendRequest: Unknown input type '%c'\n",
- Input[i]->Type);
- return -1;
- }
- value->Length = Input[i]->Length;
- value ++;
- }
#if 0
- printf("value = %p\n", value);
{
- for(i=0;i<requestLen;i++)
+ for(i=0;i<RequestSize;i++)
{
- printf("%02x ", ((uint8_t*)request)[i]);
+ printf("%02x ", ((uint8_t*)Request)[i]);
if( i % 16 == 15 ) printf("\n");
}
printf("\n");
#endif
// Send it off
- SendData(request, requestLen);
+ SendData(Request, RequestSize);
// Wait for a response (no timeout)
- requestLen = ReadData(request, requestLen, -1);
-
- // Parse response out
- if( request->NParams != NumInput ) {
- fprintf(stderr, "SendRequest: Unexpected number of values retured (%i, exp %i)\n",
- request->NParams, NumInput
- );
- free( request );
- return -1;
- }
-
- // Free memory
- free( request );
-
- return 0;
+ return ReadData(Request, RequestSize, -1);
}
void SendData(void *Data, int Length)
#ifndef _REQUEST_H_
#define _REQUEST_H_
-typedef struct {
- char Type;
- int Length;
- char Data[];
-} tOutValue;
+#include "../syscalls.h"
-typedef struct {
- char Type;
- int Length;
- void *Data;
-} tInValue;
-
-extern int SendRequest(int RequestID, int NumOutput, tOutValue **Output,
- int NumInput, tInValue **Input);
+extern int SendRequest(tRequestHeader *Request, int RequestSize);
#endif
// === IMPORTS ===
// === CODE ===
-const char *ReadEntry(tOutValue **OutDest, tInValue **InDest,
- int *Direction, const char *ArgTypes, va_list Args)
+const char *ReadEntry(tRequestValue *Dest, void *DataDest, void **PtrDest, const char *ArgTypes, va_list Args)
{
- uint64_t val64, *ptr64;
- uint32_t val32, *ptr32;
+ uint64_t val64;
+ uint32_t val32;
int direction = 0; // 0: Invalid, 1: Out, 2: In, 3: Out
char *str;
int len;
// Get direction
switch(*ArgTypes)
{
+ default: // Defaults to output
case '>': direction = 1; break;
case '<': direction = 2; break;
case '?': direction = 3; break;
- default:
- return NULL;
}
ArgTypes ++;
while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++;
if( *ArgTypes == '\0' ) return ArgTypes;
- // Internal helper macro
- #define MAKE_OUT(_dest,_typeChar,_typeName,_value) do{if((_dest)){\
- *(_dest) = (tOutValue*)malloc(sizeof(tOutValue)+sizeof(_typeName));\
- (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\
- *(_typeName*)((*(_dest))->Data) = (_value);\
- }}while(0)
- #define MAKE_IN(_dest,_typeChar,_typeName,_value) do{if((_dest)){\
- *(_dest) = (tInValue*)malloc(sizeof(tInValue));\
- (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\
- (*(_dest))->Data = (_value);\
- }}while(0)
-
// Get type
switch(*ArgTypes)
{
- case 'i': // 32-bit integer
- // Input?
- if( direction & 2 )
- {
- ptr32 = va_arg(Args, uint32_t*);
- MAKE_IN(InDest, 'i', uint32_t*, ptr32);
- if( direction & 1 )
- MAKE_OUT(OutDest, 'i', uint32_t, *ptr32);
- }
- else
- {
- val32 = va_arg(Args, uint32_t);
- MAKE_OUT(OutDest, 'i', uint32_t, val32);
+ // 32-bit integer
+ case 'i':
+
+ if( direction != 1 ) {
+ fprintf(stderr, "ReadEntry: Recieving an integer is not defined\n");
+ return NULL;
}
+
+ val32 = va_arg(Args, uint32_t);
+
+ Dest->Type = ARG_TYPE_INT32;
+ Dest->Length = sizeof(uint32_t);
+ Dest->Flags = 0;
+
+ if( DataDest )
+ *(uint32_t*)DataDest = val32;
break;
- case 'I': // 64-bit integer
- // Input?
- if( direction & 2 )
- {
- ptr64 = va_arg(Args, uint64_t*);
- MAKE_IN(InDest, 'I', uint64_t*, ptr64);
- if( direction & 1 )
- MAKE_OUT(OutDest, 'I', uint64_t, *ptr64);
- }
- else
- {
- val64 = va_arg(Args, uint64_t);
- MAKE_OUT(OutDest, 'I', uint64_t, val64);
+ // 64-bit integer
+ case 'I':
+
+ if( direction != 1 ) {
+ fprintf(stderr, "ReadEntry: Recieving an integer is not defined\n");
+ return NULL;
}
+
+ val64 = va_arg(Args, uint64_t);
+
+ Dest->Type = ARG_TYPE_INT64;
+ Dest->Length = sizeof(uint64_t);
+ Dest->Flags = 0;
+ if( DataDest )
+ *(uint64_t*)DataDest = val64;
break;
+ // String
case 's':
// Input string makes no sense!
- if( direction & 2 ) {
- fprintf(stderr, "ReadEntry: Incoming string is not defined\n");
+ if( direction != 1 ) {
+ fprintf(stderr, "ReadEntry: Recieving a string is not defined\n");
return NULL;
}
str = va_arg(Args, char*);
- if( OutDest )
+
+ Dest->Type = ARG_TYPE_STRING;
+ Dest->Length = strlen(str) + 1;
+ Dest->Flags = 0;
+
+ if( DataDest )
{
- int len = strlen(str) + 1;
- *OutDest = malloc( sizeof(tOutValue) + len );
- (*OutDest)->Type = 's';
- (*OutDest)->Length = len;
- memcpy((*OutDest)->Data, str, len);
+ memcpy(DataDest, str, Dest->Length);
}
break;
-
+ // Data (special handling)
case 'd':
len = va_arg(Args, int);
str = va_arg(Args, char*);
- // Input ?
- if( (direction & 2) && InDest )
- {
- *InDest = (tInValue*)malloc( sizeof(tInValue) );
- (*InDest)->Type = 'd';
- (*InDest)->Length = len;
- (*InDest)->Data = str;
- }
+ // Save the pointer for later
+ if( PtrDest ) *PtrDest = str;
+
+ // Create parameter block
+ Dest->Type = ARG_TYPE_INT64;
+ Dest->Length = sizeof(uint64_t);
+ Dest->Flags = 0;
+ if( direction & 2 )
+ Dest->Flags |= ARG_FLAG_RETURN;
- // Output ?
- if( (direction & 1) && InDest )
+ // Has data?
+ if( direction & 1 )
{
- *OutDest = (tOutValue*)malloc( sizeof(tOutValue) + len );
- (*OutDest)->Type = 'd';
- (*OutDest)->Length = len;
- memcpy((*OutDest)->Data, str, len);
+ if( DataDest )
+ memcpy(DataDest, str, len);
}
+ else
+ Dest->Flags |= ARG_FLAG_ZEROED;
break;
default:
return NULL;
}
ArgTypes ++;
- #undef MAKE_ASSIGN
-
- *Direction = direction;
return ArgTypes;
}
* ?d: Bi-directional buffer (Preceded by valid size), buffer contents
* are returned
*/
-void _Syscall(int SyscallID, const char *ArgTypes, ...)
+uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
{
va_list args;
- int outCount;
- int inCount;
+ int paramCount, dataLength;
+ int retCount = 1, retLength = sizeof(uint64_t);
+ void **retPtrs; // Pointers to return buffers
const char *str;
- tOutValue **output;
- tInValue **input;
+ tRequestHeader *req;
+ void *dataPtr;
+ uint64_t retValue;
+ int i;
// Get data size
va_start(args, ArgTypes);
str = ArgTypes;
- outCount = 0;
- inCount = 0;
+ paramCount = 0;
+ dataLength = 0;
while(*str)
{
- int dir;
+ tRequestValue tmpVal;
- str = ReadEntry(NULL, NULL, &dir, str, args);
+ str = ReadEntry(&tmpVal, NULL, NULL, str, args);
if( !str ) {
fprintf(stderr, "syscalls.c: ReadEntry failed (SyscallID = %i)\n", SyscallID);
exit(127);
}
+ paramCount ++;
+ if( !(tmpVal.Flags & ARG_FLAG_ZEROED) )
+ dataLength += tmpVal.Length;
- // Out!
- if( dir & 1 ) outCount ++;
-
- // and.. In!
- if( dir & 2 ) inCount ++;
+ if( tmpVal.Flags & ARG_FLAG_RETURN ) {
+ retLength += tmpVal.Length;
+ retCount ++;
+ }
}
va_end(args);
+ dataLength += sizeof(tRequestHeader) + paramCount*sizeof(tRequestValue);
+ retLength += sizeof(tRequestHeader) + retCount*sizeof(tRequestValue);
+
// Allocate buffers
- output = malloc( outCount*sizeof(tOutValue*) );
- input = malloc( inCount*sizeof(tInValue*) );
+ retPtrs = malloc( sizeof(void*) * (retCount+1) );
+ if( dataLength > retLength)
+ req = malloc( dataLength );
+ else
+ req = malloc( retLength );
+ req->ClientID = 0; //< Filled later
+ req->CallID = SyscallID;
+ req->NParams = paramCount;
+ dataPtr = &req->Params[paramCount];
// Fill `output` and `input`
va_start(args, ArgTypes);
str = ArgTypes;
// - re-zero so they can be used as indicies
- outCount = 0;
- inCount = 0;
+ paramCount = 0;
+ retCount = 0;
while(*str)
- {
- tOutValue *outParam;
- tInValue *inParam;
- int dir;
-
- str = ReadEntry(&outParam, &inParam, &dir, str, args);
+ {
+ str = ReadEntry(&req->Params[paramCount], dataPtr, &retPtrs[retCount], str, args);
if( !str ) break;
- if( dir & 1 )
- output[outCount++] = outParam;
- if( dir & 2 )
- input[inCount++] = inParam;
+ if( !(req->Params[paramCount].Flags & ARG_FLAG_ZEROED) )
+ dataPtr += req->Params[paramCount].Length;
+ if( req->Params[paramCount].Flags & ARG_FLAG_RETURN )
+ retCount ++;
+
+ paramCount ++;
}
va_end(args);
// Send syscall request
- if( SendRequest(SyscallID, outCount, output, inCount, input) ) {
+ if( SendRequest(req, dataLength) ) {
fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
exit(127);
}
- // Clean up
- while(outCount--) free(output[outCount]);
- free(output);
- while(inCount--) free(input[inCount]);
- free(input);
+ // Parse return value
+ dataPtr = &req->Params[req->NParams];
+ retValue = 0;
+ if( req->NParams > 1 )
+ {
+ switch(req->Params[0].Type)
+ {
+ case ARG_TYPE_INT64:
+ retValue = *(uint64_t*)dataPtr;
+ dataPtr += req->Params[0].Length;
+ break;
+ case ARG_TYPE_INT32:
+ retValue = *(uint32_t*)dataPtr;
+ dataPtr += req->Params[0].Length;
+ break;
+ }
+ }
+
+ // Write changes to buffers
+ va_start(args, ArgTypes);
+ for( i = 1; i < req->NParams; i ++ )
+ {
+ memcpy( retPtrs[i-1], dataPtr, req->Params[i].Length );
+ dataPtr += req->Params[i].Length;
+ }
+ va_end(args);
+
+ free( req );
+
+ return 0;
}
// --- VFS Calls
int open(const char *Path, int Flags) {
- int ret = 0;
- _Syscall(SYS_OPEN, "<i >s >i", &ret, Path, Flags);
- return ret;
+ return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
}
void close(int FD) {
}
size_t read(int FD, size_t Bytes, void *Dest) {
- int ret = 0;
- _Syscall(SYS_READ, "<i >i >i <d", &ret, FD, Bytes, Bytes, Dest);
- return ret;
+ return _Syscall(SYS_READ, "<i >i >i <d", FD, Bytes, Bytes, Dest);
}
size_t write(int FD, size_t Bytes, void *Src) {
- int ret = 0;
- _Syscall(SYS_WRITE, "<i >i >i >d", &ret, FD, Bytes, Bytes, Src);
- return ret;
+ return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
}
int seek(int FD, int64_t Ofs, int Dir) {
- int ret = 0;
- _Syscall(SYS_SEEK, "<i >i >I >i", &ret, FD, Ofs, Dir);
- return ret;
+ return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
}
uint64_t tell(int FD) {
- uint64_t ret;
- _Syscall(SYS_TELL, "<I >i", &ret, FD);
- return ret;
+ return _Syscall(SYS_TELL, ">i", FD);
}
int ioctl(int fd, int id, void *data) {
typedef struct sRequestValue {
/// \see eArgumentTypes
uint16_t Type;
+ uint8_t Flags;
uint16_t Length;
} tRequestValue;
uint16_t ClientID;
uint16_t CallID; //!< \see eSyscalls
uint16_t NParams;
- uint16_t NReturn;
tRequestValue Params[];
} tRequestHeader;
ARG_TYPE_STRING,
ARG_TYPE_DATA
};
+enum eArgumentFlags {
+ ARG_FLAG_RETURN = 0x40, // Pass back in the return message
+ ARG_FLAG_ZEROED = 0x80 // Not present in the message, just fill with zero
+};
#endif