AcessNative - Bugfixing
[tpg/acess2.git] / AcessNative / ld-acess_src / syscalls.c
index ec4af01..ff29997 100644 (file)
@@ -8,17 +8,17 @@
 #include <stdarg.h>
 #include <string.h>
 #include "request.h"
+#include "../syscalls.h"
 
 // === Types ===
 
 // === 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;
@@ -30,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 ++;
        
@@ -42,99 +41,95 @@ 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);
+               printf("val32 = 0x%x\n", val32);
+               
+               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);
+               printf("val64 = 0x%llx\n", val64);
+               
+               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 )
+               str = va_arg(*Args, char*);
+               printf("str = %p '%s'\n", str, str);
+               
+               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*);
+               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;
-               }
+               printf("len = %i, str = %p\n", len, str);
                
-               // Output ?
-               if( (direction & 1) && InDest )
+               // Save the pointer for later
+               if( PtrDest )   *PtrDest = str;
+               
+               // Create parameter block
+               Dest->Type = ARG_TYPE_DATA;
+               Dest->Length = len;
+               Dest->Flags = 0;
+               if( direction & 2 )
+                       Dest->Flags |= ARG_FLAG_RETURN;
+               
+               // 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;
 }
@@ -152,122 +147,165 @@ const char *ReadEntry(tOutValue **OutDest, tInValue **InDest,
  * ?d:  Bi-directional buffer (Preceded by valid size), buffer contents
  *      are returned
  */
-int _Syscall(const char *ArgTypes, ...)
+uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...)
 {
        va_list args;
-        int    outCount = 0;
-        int    inCount = 0;
+        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;
+       paramCount = 0;
+       dataLength = 0;
        while(*str)
        {
-                int    dir;
+               tRequestValue   tmpVal;
                
-               str = ReadEntry(NULL, NULL, &dir, str, args);
-               if( !str )      break;
-               
-               // Out!
-               if( dir & 1 )   outCount ++;
+               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;
                
-               // and.. In!
-               if( dir & 2 )   inCount ++;
+               if( tmpVal.Flags & ARG_FLAG_RETURN ) {
+                       retLength += tmpVal.Length;
+                       retCount ++;
+               }
        }
        va_end(args);
        
-       // Allocate buffers
-       output = malloc( outCount*sizeof(tOutValue*) );
-       input = malloc( inCount*sizeof(tInValue*) );
+       dataLength += sizeof(tRequestHeader) + paramCount*sizeof(tRequestValue);
+       retLength += sizeof(tRequestHeader) + retCount*sizeof(tRequestValue);
        
-       // - re-zero so they can be used as indicies
-       outCount = 0;
-       inCount = 0;
+       // Allocate buffers
+       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
+       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(req, dataLength) < 0 ) {
+               fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
+               exit(127);
+       }
        
+       // 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);
        
-       // Clean up
-       while(outCount--)       free(output[outCount]);
-       free(output);
-       while(inCount--)        free(input[inCount]);
-       free(input);
+       free( req );
        
        return 0;
 }
 
 // --- VFS Calls
 int open(const char *Path, int Flags) {
-       return _Syscall(">s >i", Path, Flags);
+       return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
 }
 
 void close(int FD) {
-       _Syscall(">i", FD);
+       _Syscall(SYS_CLOSE, ">i", FD);
 }
 
 size_t read(int FD, size_t Bytes, void *Dest) {
-       return _Syscall(">i >i <d", FD, Bytes, Bytes, Dest);
+       return _Syscall(SYS_READ, "<i >i >i <d", FD, Bytes, Bytes, Dest);
 }
 
 size_t write(int FD, size_t Bytes, void *Src) {
-       return _Syscall(">i >i >d", FD, Bytes, Bytes, Src);
+       return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
 }
 
 int seek(int FD, int64_t Ofs, int Dir) {
-       return _Syscall(">i >I >i", FD, Ofs, Dir);
+       return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
 }
 
 uint64_t tell(int FD) {
-       uint64_t        ret;
-       _Syscall("<I >i", &ret, FD);
-       return ret;
+       return _Syscall(SYS_TELL, ">i", FD);
 }
 
 int ioctl(int fd, int id, void *data) {
        // NOTE: 1024 byte size is a hack
-       return _Syscall(">i >i ?d", fd, id, 1024, data);
+       return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, 1024, data);
 }
 int finfo(int fd, t_sysFInfo *info, int maxacls) {
-       return _Syscall(">i <d >i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls);
+       return _Syscall(SYS_FINFO, ">i <d >i",
+               fd,
+               sizeof(t_sysFInfo)+maxacls*sizeof(t_sysACL), info,
+               maxacls);
 }
 
 int readdir(int fd, char *dest) {
-       return _Syscall(">i <s", fd, dest);
+       return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
 }
 
 int _SysOpenChild(int fd, char *name, int flags) {
-       return _Syscall(">i >s >i", fd, name, flags);
+       return _Syscall(SYS_OPENCHILD, ">i >s >i", fd, name, flags);
 }
 
 int _SysGetACL(int fd, t_sysACL *dest) {
-       return _Syscall(">i <d", fd, sizeof(t_sysACL), dest);
+       return _Syscall(SYS_GETACL, "<i >i <d", fd, sizeof(t_sysACL), dest);
 }
 
 int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) {
-       return _Syscall(">s >s >s >s", Device, Directory, Type, Options);
+       return _Syscall(SYS_MOUNT, ">s >s >s >s", Device, Directory, Type, Options);
 }
 
 

UCC git Repository :: git.ucc.asn.au