/*
*/
+#define DONT_INCLUDE_SYSCALL_NAMES 1
#include "../../Usermode/include/acess/sys.h"
#include "common.h"
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
+#include <stddef.h>
#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;
// 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 ) {
+ 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;
}
* ?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, "<i >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 <d", &ret, FD, Bytes, Bytes, Dest);
- return ret;
+int acess_reopen(int FD, const char *Path, int Flags) {
+ DEBUG("reopen(0x%x, \"%s\", 0x%x)", FD, Path, Flags);
+ return _Syscall(SYS_REOPEN, ">i >s >i", FD, Path, Flags);
}
-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;
+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 <d", FD, Bytes, Bytes, Dest);
}
-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;
+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 >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 >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 <d >i",
- &ret, fd,
+int acess_finfo(int fd, t_sysFInfo *info, int maxacls) {
+ return _Syscall(SYS_FINFO, ">i <d >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 <d", &ret, fd, 256, dest);
- return ret;
+int acess_readdir(int fd, char *dest) {
+ DEBUG("readdir(%i, %p)", fd, dest);
+ return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
+}
+
+int acess_select(int nfds, fd_set *read, fd_set *write, fd_set *error, time_t *timeout)
+{
+ DEBUG("select(%i, %p, %p, %p, %p)", nfds, read, write, error, timeout);
+ return _Syscall(SYS_SELECT, ">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 >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 <d", &ret, fd, sizeof(t_sysACL), dest);
- return ret;
+int acess__SysGetACL(int fd, 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) {
- int ret = 0;
- _Syscall(SYS_MOUNT, "<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, "<d", sizeof(int), &kernel_tid);
+ ret = fork();
+ if(ret < 0) return ret;
+
+ if(ret == 0)
+ {
+ giSyscall_ClientID = newID;
+ return 0;
+ }
+
+ // Return the acess TID instead
+ return kernel_tid;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Threads currently unsupported\n");
+ exit(-1);
+ }
+}
+
+int acess_execve(char *path, char **argv, char **envp)
+{
+ int i, argc;
+
+ DEBUG("acess_execve: (path='%s', argv=%p, envp=%p)", path, argv, envp);
+
+ // Get argument count
+ for( argc = 0; argv[argc]; argc ++ ) ;
+ DEBUG(" acess_execve: argc = %i", argc);
+
+ char *new_argv[5+argc+1];
+ char key[11];
+ sprintf(key, "%i", giSyscall_ClientID);
+ new_argv[0] = "ld-acess"; // TODO: Get path to ld-acess executable
+ new_argv[1] = "--key"; // Set socket/client ID for Request.c
+ new_argv[2] = key;
+ new_argv[3] = "--binary"; // Set the binary path (instead of using argv[0])
+ new_argv[4] = path;
+ for( i = 0; i < argc; i ++ ) new_argv[5+i] = argv[i];
+ new_argv[5+i] = NULL;
+
+ #if 1
+ argc += 5;
+ for( i = 0; i < argc; i ++ )
+ printf("\"%s\" ", new_argv[i]);
+ printf("\n");
+ #endif
+
+ // Call actual execve
+ return execve("./ld-acess", new_argv, envp);
+}
+
+void acess_sleep(void)
+{
+ _Syscall(SYS_SLEEP, "");
+}
+
+int acess_waittid(int TID, int *ExitStatus)
+{
+ return _Syscall(SYS_WAITTID, ">i <d", TID, sizeof(int), &ExitStatus);
+}
+
+int acess_setuid(int ID)
+{
+ return _Syscall(SYS_SETUID, ">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, "<d <d",
+ SourceTID ? sizeof(int) : 0, SourceTID,
+ Data ? 4096 : 0, Data
+ );
+}
+
+// --- Logging
+void acess__SysDebug(const char *Format, ...)
+{
+ va_list args;
+
+ va_start(args, Format);
+
+ printf("[_SysDebug %i]", giSyscall_ClientID);
+ vprintf(Format, args);
+ printf("\n");
+
+ va_end(args);
+}
+
+void acess__exit(int Status)
+{
+ DEBUG("_exit(%i)", Status);
+ _Syscall(SYS_EXIT, ">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),
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]);