X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Fld-acess_src%2Fsyscalls.c;h=546095612b70875b86a9ff91eb6fc267ebbd7f43;hb=11686aa86bc0adae2555aa7796fe229770bb02f7;hp=9bdde9b27e7dfade28832df5ced2e5841652975e;hpb=02cbaac1233be9c5228973a787431fa5e0aa178e;p=tpg%2Facess2.git diff --git a/AcessNative/ld-acess_src/syscalls.c b/AcessNative/ld-acess_src/syscalls.c index 9bdde9b2..54609561 100644 --- a/AcessNative/ld-acess_src/syscalls.c +++ b/AcessNative/ld-acess_src/syscalls.c @@ -1,5 +1,6 @@ /* */ +#define DONT_INCLUDE_SYSCALL_NAMES 1 #include "../../Usermode/include/acess/sys.h" #include "common.h" #include @@ -7,19 +8,28 @@ #include #include #include +#include #include "request.h" #include "../syscalls.h" +#define DEBUG(str, x...) Debug(str, x) + +#define NATIVE_FILE_MASK 0x40000000 +#define MAX_FPS 16 + // === Types === // === IMPORTS === +extern int giSyscall_ClientID; // Needed for execve + +// === GLOBALS === +FILE *gaSyscall_LocalFPs[MAX_FPS]; // === 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 +41,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 +52,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 ) { + Warning("ReadEntry: Recieving an integer is not defined"); + 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 ) + str = va_arg(*Args, char*); + + 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; - } + // Save the pointer for later + if( PtrDest ) *PtrDest = str; - // Output ? - if( (direction & 1) && InDest ) + // 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; } @@ -153,165 +153,380 @@ 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; + + // DEBUG! +// printf("&tRequestHeader->Params = %i\n", offsetof(tRequestHeader, Params)); +// printf("&tRequestValue->Flags = %i\n", offsetof(tRequestValue, Flags)); +// printf("&tRequestValue->Length = %i\n", offsetof(tRequestValue, Length)); // 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, retLength) < 0 ) { 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 + retCount = 0; + for( i = 1; i < req->NParams; i ++ ) + { + #if 0 + int j; + printf("Return Data %i: (%i)", i, req->Params[i].Length); + for( j = 0; j < req->Params[i].Length; j ++ ) + printf(" %02x", ((uint8_t*)dataPtr)[j]); + printf("\n"); + #endif + memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length ); + dataPtr += req->Params[i].Length; + } + + free( req ); + free( retPtrs ); + + DEBUG(": %llx", retValue); + + return retValue; } // --- VFS Calls -int open(const char *Path, int Flags) { - int ret = 0; - _Syscall(SYS_OPEN, "s >i", &ret, Path, Flags); - return ret; +int acess_chdir(const char *Path) +{ + return _Syscall(SYS_CHDIR, ">s", Path); } -void close(int FD) { +int acess_open(const char *Path, int Flags) +{ + if( strncmp(Path, "$$$$", 4) == 0 ) + { + int ret; + for(ret = 0; ret < MAX_FPS && gaSyscall_LocalFPs[ret]; ret ++ ) ; + if(ret == MAX_FPS) return -1; + // TODO: Handle directories + gaSyscall_LocalFPs[ret] = fopen(&Path[4], "r+"); + if(!gaSyscall_LocalFPs[ret]) return -1; + return ret|NATIVE_FILE_MASK; + } + DEBUG("open(\"%s\", 0x%x)", Path, Flags); + return _Syscall(SYS_OPEN, ">s >i", Path, Flags); +} + +void acess_close(int FD) { + if(FD & NATIVE_FILE_MASK) { + fclose( gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)] ); + gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)] = NULL; + return ; + } + DEBUG("close(%i)", FD); _Syscall(SYS_CLOSE, ">i", FD); } -size_t read(int FD, size_t Bytes, void *Dest) { - int ret = 0; - _Syscall(SYS_READ, "i >i i >s >i", FD, Path, Flags); } -size_t write(int FD, size_t Bytes, void *Src) { - int ret = 0; - _Syscall(SYS_WRITE, "i >i >d", &ret, FD, Bytes, Bytes, Src); - return ret; +size_t acess_read(int FD, size_t Bytes, void *Dest) { + if(FD & NATIVE_FILE_MASK) + return fread( Dest, Bytes, 1, gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)] ); + DEBUG("read(0x%x, 0x%x, *%p)", FD, Bytes, Dest); + return _Syscall(SYS_READ, ">i >i i >I >i", &ret, FD, Ofs, Dir); - return ret; +size_t acess_write(int FD, size_t Bytes, void *Src) { + if(FD & NATIVE_FILE_MASK) + return fwrite( Src, Bytes, 1, gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)] ); + DEBUG("write(0x%x, 0x%x, %p\"%.*s\")", FD, Bytes, Src, Bytes, (char*)Src); + return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src); } -uint64_t tell(int FD) { - uint64_t ret; - _Syscall(SYS_TELL, "i", &ret, FD); - return ret; +int acess_seek(int FD, int64_t Ofs, int Dir) { + if(FD & NATIVE_FILE_MASK) { + switch(Dir) { + case ACESS_SEEK_SET: Dir = SEEK_SET; break; + default: + case ACESS_SEEK_CUR: Dir = SEEK_CUR; break; + case ACESS_SEEK_END: Dir = SEEK_END; break; + } + return fseek( gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)], Ofs, Dir ); + } + DEBUG("seek(0x%x, 0x%llx, %i)", FD, Ofs, Dir); + return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir); } -int ioctl(int fd, int id, void *data) { - int ret = 0; +uint64_t acess_tell(int FD) { + if(FD & NATIVE_FILE_MASK) + return ftell( gaSyscall_LocalFPs[FD & (NATIVE_FILE_MASK-1)] ); + return _Syscall(SYS_TELL, ">i", FD); +} + +int acess_ioctl(int fd, int id, void *data) { // NOTE: 1024 byte size is a hack - _Syscall(SYS_IOCTL, "i >i ?d", &ret, fd, id, 1024, data); - return ret; + DEBUG("ioctl(%i, %i, %p)", fd, id, data); + return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, 1024, data); } -int finfo(int fd, t_sysFInfo *info, int maxacls) { - int ret = 0; - _Syscall(SYS_FINFO, "i i", - &ret, fd, +int acess_finfo(int fd, t_sysFInfo *info, int maxacls) { + return _Syscall(SYS_FINFO, ">i i", + fd, sizeof(t_sysFInfo)+maxacls*sizeof(t_sysACL), info, maxacls); - return ret; } -int readdir(int fd, char *dest) { - int ret = 0; - _Syscall(SYS_READDIR, "i i i ?d ?d ?d >d", nfds, + read ? (nfds+7)/8 : 0, read, + write ? (nfds+7)/8 : 0, write, + error ? (nfds+7)/8 : 0, error, + sizeof(*timeout), timeout + ); } -int _SysOpenChild(int fd, char *name, int flags) { - int ret = 0; - _Syscall(SYS_OPENCHILD, "i >s >i", &ret, fd, name, flags); - return ret; +int acess__SysOpenChild(int fd, char *name, int flags) { + return _Syscall(SYS_OPENCHILD, ">i >s >i", fd, name, flags); } -int _SysGetACL(int fd, t_sysACL *dest) { - int ret = 0; - _Syscall(SYS_GETACL, "i i s >s >s >s", &ret, Device, Directory, Type, Options); - return ret; +int acess__SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) { + return _Syscall(SYS_MOUNT, ">s >s >s >s", Device, Directory, Type, Options); } // --- Error Handler -int _SysSetFaultHandler(int (*Handler)(int)) { +int acess__SysSetFaultHandler(int (*Handler)(int)) { + printf("TODO: Set fault handler (asked to set to %p)\n", Handler); return 0; } +// --- Memory Management --- +uint64_t acess__SysAllocate(uint vaddr) +{ + if( AllocateMemory(vaddr, 0x1000) == -1 ) // Allocate a page + return 0; + + return vaddr; // Just ignore the need for paddrs :) +} + +// --- Process Management --- +int acess_clone(int flags, void *stack) +{ + extern int fork(void); + if(flags & CLONE_VM) { + int ret, newID, kernel_tid=0; + printf("fork()"); + + newID = _Syscall(SYS_FORK, "i i", ID); +} + +int acess_setgid(int ID) +{ + return _Syscall(SYS_SETGID, ">i", ID); +} + +int acess_SysSendMessage(int DestTID, int Length, void *Data) +{ + return _Syscall(SYS_SENDMSG, ">i >d", DestTID, Length, Data); +} + +int acess_SysGetMessage(int *SourceTID, void *Data) +{ + return _Syscall(SYS_GETMSG, "i", Status); + exit(Status); +} + // === Symbol List === -#define DEFSYM(name) {#name, name} +#define DEFSYM(name) {#name, acess_##name} const tSym caBuiltinSymbols[] = { - {"_exit", exit}, + DEFSYM(_exit), + DEFSYM(chdir), DEFSYM(open), DEFSYM(close), + DEFSYM(reopen), DEFSYM(read), DEFSYM(write), DEFSYM(seek), @@ -319,11 +534,25 @@ const tSym caBuiltinSymbols[] = { DEFSYM(ioctl), DEFSYM(finfo), DEFSYM(readdir), + DEFSYM(select), DEFSYM(_SysOpenChild), DEFSYM(_SysGetACL), DEFSYM(_SysMount), - {"_SysSetFaultHandler", _SysSetFaultHandler} + DEFSYM(clone), + DEFSYM(execve), + DEFSYM(sleep), + + DEFSYM(waittid), + DEFSYM(setuid), + DEFSYM(setgid), + + DEFSYM(SysSendMessage), + DEFSYM(SysGetMessage), + + DEFSYM(_SysAllocate), + DEFSYM(_SysDebug), + DEFSYM(_SysSetFaultHandler) }; const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]);