From d599a063b3b453b705925c58180c93e1f9cb3d79 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 23 Jan 2011 10:41:09 +0800 Subject: [PATCH] AcessNative - Reworked protocol to be simpler - Completed the interface code, not tested yet - Switched to a single list of parameters, with flags for returned values --- AcessNative/acesskernel_src/server.c | 247 ++++++++++++++++++++++++ AcessNative/acesskernel_src/syscalls.c | 76 +++++++- AcessNative/ld-acess_src/request.c | 91 +-------- AcessNative/ld-acess_src/request.h | 15 +- AcessNative/ld-acess_src/syscalls.c | 255 +++++++++++++------------ AcessNative/syscalls.h | 6 +- 6 files changed, 470 insertions(+), 220 deletions(-) create mode 100644 AcessNative/acesskernel_src/server.c diff --git a/AcessNative/acesskernel_src/server.c b/AcessNative/acesskernel_src/server.c new file mode 100644 index 00000000..7491d74a --- /dev/null +++ b/AcessNative/acesskernel_src/server.c @@ -0,0 +1,247 @@ +/* + * Acess2 Native Kernel + * - Acess kernel emulation on another OS using SDL and UDP + * + * Syscall Server + */ +#include +#include +#include +#include +#ifdef __WIN32__ +# include +# include +#else +# include +# include +# include +#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; +} diff --git a/AcessNative/acesskernel_src/syscalls.c b/AcessNative/acesskernel_src/syscalls.c index 7e8d1ecd..85a82325 100644 --- a/AcessNative/acesskernel_src/syscalls.c +++ b/AcessNative/acesskernel_src/syscalls.c @@ -42,7 +42,7 @@ int Syscall_Null(const char *Format, void *Args) 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 *); @@ -59,13 +59,18 @@ const int ciNumSyscalls = sizeof(caSyscalls)/sizeof(caSyscalls[0]); /** * \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; } @@ -90,6 +95,10 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request) formatString[i] = 'd'; argListLen += sizeof(void*); break; + case ARG_TYPE_STRING: + formatString[i] = 's'; + argListLen += sizeof(char*); + break; default: return NULL; // ERROR! } @@ -115,11 +124,36 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request) 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; } } @@ -127,5 +161,35 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request) 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; } diff --git a/AcessNative/ld-acess_src/request.c b/AcessNative/ld-acess_src/request.c index 1fff68e8..3bef3d3e 100644 --- a/AcessNative/ld-acess_src/request.c +++ b/AcessNative/ld-acess_src/request.c @@ -114,11 +114,14 @@ int _InitSyscalls() 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; } @@ -127,81 +130,21 @@ int _InitSyscalls() 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;iNParams != 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) diff --git a/AcessNative/ld-acess_src/request.h b/AcessNative/ld-acess_src/request.h index 8c89e6f6..b33a80f9 100644 --- a/AcessNative/ld-acess_src/request.h +++ b/AcessNative/ld-acess_src/request.h @@ -8,19 +8,8 @@ #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 diff --git a/AcessNative/ld-acess_src/syscalls.c b/AcessNative/ld-acess_src/syscalls.c index 9bdde9b2..50352f87 100644 --- a/AcessNative/ld-acess_src/syscalls.c +++ b/AcessNative/ld-acess_src/syscalls.c @@ -15,11 +15,10 @@ // === 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; @@ -31,11 +30,10 @@ const char *ReadEntry(tOutValue **OutDest, tInValue **InDest, // Get direction switch(*ArgTypes) { + default: // Defaults to output case '>': direction = 1; break; case '<': direction = 2; break; case '?': direction = 3; break; - default: - return NULL; } ArgTypes ++; @@ -43,99 +41,90 @@ const char *ReadEntry(tOutValue **OutDest, tInValue **InDest, 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; } @@ -153,82 +142,118 @@ const char *ReadEntry(tOutValue **OutDest, tInValue **InDest, * ?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, "s >i", &ret, Path, Flags); - return ret; + return _Syscall(SYS_OPEN, ">s >i", Path, Flags); } void close(int FD) { @@ -236,27 +261,19 @@ void close(int FD) { } size_t read(int FD, size_t Bytes, void *Dest) { - int ret = 0; - _Syscall(SYS_READ, "i >i i >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", &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", &ret, FD); - return ret; + return _Syscall(SYS_TELL, ">i", FD); } int ioctl(int fd, int id, void *data) { diff --git a/AcessNative/syscalls.h b/AcessNative/syscalls.h index 903cbfae..4a64474b 100644 --- a/AcessNative/syscalls.h +++ b/AcessNative/syscalls.h @@ -17,6 +17,7 @@ typedef struct sRequestValue { /// \see eArgumentTypes uint16_t Type; + uint8_t Flags; uint16_t Length; } tRequestValue; @@ -24,7 +25,6 @@ typedef struct sRequestHeader { uint16_t ClientID; uint16_t CallID; //!< \see eSyscalls uint16_t NParams; - uint16_t NReturn; tRequestValue Params[]; } tRequestHeader; @@ -53,5 +53,9 @@ enum eArgumentTypes { 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 -- 2.20.1