\r
KERNEL_SRC = ../../Kernel/\r
\r
-KERNEL_OBJ := logging.o adt.o lib.o drvutil.o\r
-KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o vfs/nodecache.o vfs/mount.o vfs/memfile.o\r
+KERNEL_OBJ := logging.o adt.o lib.o drvutil.o debug.o\r
+KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o\r
+KERNEL_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o vfs/select.o\r
KERNEL_OBJ += vfs/fs/root.o vfs/fs/devfs.o\r
KERNEL_OBJ += drv/vterm.o drv/fifo.o drv/proc.o\r
\r
OBJ += $(addprefix $(KERNEL_SRC),$(KERNEL_OBJ))\r
\r
OBJ := $(addsuffix .$(PLATFORM),$(OBJ))\r
+DEPFILES = $(filter %.o.$(PLATFORM),$(OBJ))\r
+DEPFILES := $(DEPFILES:%.o.$(PLATFORM)=%.d.$(PLATFORM))\r
\r
CPPFLAGS += -I include/ -I $(KERNEL_SRC)include/\r
CFLAGS += -Wall -g\r
$(RM) $(BIN) $(OBJ)\r
\r
$(BIN): $(OBJ)\r
- $(CC) $(LDFLAGS) -o $@ $(OBJ)\r
+ @echo [LINK] -o $@\r
+ @$(CC) $(LDFLAGS) -o $@ $(OBJ)\r
\r
%.o.$(PLATFORM): %.c\r
- $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)\r
+ @echo [CC] -o $@\r
+ @$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)\r
+ @$(CC) -M $(CPPFLAGS) -MT $@ -o $*.d.$(PLATFORM) $<\r
#include <stdarg.h>
#include <sys/time.h>
+#if 0
void LogF(const char *Fmt, ...)
{
va_list args;
void Debug_SetKTerminal(const char *Path)
{
- // Ignored, kernel debug goes to stdout
+ // Ignored, kernel debug goes to stdout instead of a virtual terminal
+}
+#endif
+
+void KernelPanic_SetMode(void)
+{
+ // NOP - No need
+}
+void KernelPanic_PutChar(char ch)
+{
+ fprintf(stderr, "%c", ch);
+}
+void Debug_PutCharDebug(char ch)
+{
+ printf("%c", ch);
+}
+void Debug_PutStringDebug(const char *String)
+{
+ printf("%s", String);
}
void *Heap_Allocate(const char *File, int Line, int ByteCount)
return malloc(ByteCount);
}
+void *Heap_AllocateZero(const char *File, int Line, int ByteCount)
+{
+ return calloc(ByteCount, 1);
+}
+
+void *Heap_Reallocate(const char *File, int Line, void *Ptr, int Bytes)
+{
+ return realloc(Ptr, Bytes);
+}
+
+void Heap_Deallocate(void *Ptr)
+{
+ free(Ptr);
+}
+
tPAddr MM_GetPhysAddr(tVAddr VAddr)
{
return VAddr; // HACK!
typedef int BOOL;
-typedef uint32_t tTID;
-typedef uint32_t tPID;
-typedef uint32_t tUID;
-typedef uint32_t tGID;
+//typedef uint32_t tTID;
+//typedef uint32_t tPID;
+//typedef uint32_t tUID;
+//typedef uint32_t tGID;
struct sShortSpinlock
{
#define SHORTLOCK(...)
#define SHORTREL(...)
-#define NUM_CFG_ENTRIES 10
+//#define NUM_CFG_ENTRIES 10
#endif
// NOP (stdlib.h defines the heap functions)
// Heap_Allocate is used in _strdup
extern void *Heap_Allocate(const char *File, int Line, int ByteCount);
+extern void *Heap_AllocateZero(const char *File, int Line, size_t Bytes);
+extern void *Heap_Reallocate(const char *File, int Line, void *Ptr, size_t Bytes);
+extern void Heap_Deallocate(void *Ptr);
+extern int Heap_IsHeapAddr(void *Ptr);
+extern void Heap_Validate(void);
+
+#define malloc(size) Heap_Allocate(_MODULE_NAME_"/"__FILE__, __LINE__, (size))
+#define calloc(num,size) Heap_AllocateZero(_MODULE_NAME_"/"__FILE__, __LINE__, (num)*(size))
+#define realloc(ptr,size) Heap_Reallocate(_MODULE_NAME_"/"__FILE__, __LINE__, (ptr), (size))
+#define free(ptr) Heap_Deallocate((ptr))
+#define IsHeap(ptr) Heap_IsHeapAddr((ptr))
+
+#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
#endif
return MODULE_ERR_OK;
}
-static const char * const csaIOCTL_NAMES[] = {
+static const char * csaIOCTL_NAMES[] = {
DRV_IOCTLNAMES,
DRV_KEYBAORD_IOCTLNAMES,
NULL
extern int Video_Install(char **Arguments);
extern int NativeKeyboard_Install(char **Arguments);
extern int VT_Install(char **Arguments);
+extern int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options);
extern int SyscallServer(void);
+// === GLOBALS ===
+const char *gsAcessDir = "../Usermode/Output/i386";
+
// === CODE ===
int main(int argc, char *argv[])
{
// Parse command line settings
// Start UI subsystem
- UI_Initialise(640, 480);
+ UI_Initialise(800, 480);
// Initialise VFS
VFS_Init();
// - Start IO Drivers
Video_Install(NULL);
NativeKeyboard_Install(NULL);
+ NativeFS_Install(NULL);
// - Start VTerm
{
char *args[] = {
VT_Install(args);
}
+ VFS_Mount(gsAcessDir, "/Acess", "nativefs", "");
+
+ Debug_SetKTerminal("/Devices/VTerm/8");
+
// Start syscall server
// - Blocks
SyscallServer();
* nativefs.c\r
* - Host filesystem access\r
*/\r
-#include <acess.h>\r
-#include <vfs.h>\r
+#define DEBUG 1\r
+#include <acess.h> // Acess\r
+#include <vfs.h> // Acess\r
+#include <dirent.h> // Posix\r
+#include <sys/stat.h> // Posix\r
+#include <stdio.h> // Posix\r
+\r
+//NOTES:\r
+// tVFS_Node->ImplPtr is a pointer to the filesystem flags (tNativeFS)\r
+// tVFS_Node->Data is the path string (heap string)\r
+// tVFS_Node->ImplInt is the path length\r
+\r
+// === STRUCTURES ===\r
+typedef struct\r
+{\r
+ int InodeHandle;\r
+ int bReadOnly;\r
+} tNativeFS;\r
+\r
+// === PROTOTYPES ===\r
+ int NativeFS_Install(char **Arguments);\r
+tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments);\r
+void NativeFS_Unmount(tVFS_Node *Node);\r
+tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name);\r
+char *NativeFS_ReadDir(tVFS_Node *Node, int Position);\r
+Uint64 NativeFS_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
\r
// === GLOBALS ===\r
+tVFS_Driver gNativeFS_Driver = {\r
+ "nativefs", 0,\r
+ NativeFS_Mount, NativeFS_Unmount,\r
+ NULL,\r
+};\r
\r
// === CODE ===\r
-tVFS_Node *Native_Mount(const char *Device, const char **Arguments)\r
+int NativeFS_Install(char **Arguments)\r
+{\r
+ VFS_AddDriver(&gNativeFS_Driver);\r
+ return 0;\r
+}\r
+\r
+tVFS_Node *NativeFS_Mount(const char *Device, const char **Arguments)\r
+{\r
+ tVFS_Node *ret;\r
+ tNativeFS *info;\r
+ DIR *dp;\r
+ \r
+ dp = opendir(Device);\r
+ if(!dp) return NULL;\r
+ \r
+ // Check if directory exists\r
+ // Parse flags from arguments\r
+ info = malloc(sizeof(tNativeFS));\r
+ info->InodeHandle = Inode_GetHandle();\r
+ info->bReadOnly = 0;\r
+ // Create node\r
+ ret = malloc(sizeof(tVFS_Node));\r
+ memset(ret, 0, sizeof(tVFS_Node));\r
+ ret->Data = strdup(Device);\r
+ ret->ImplInt = strlen(ret->Data);\r
+ ret->ImplPtr = info;\r
+ ret->Inode = (Uint64)dp;\r
+ \r
+ ret->FindDir = NativeFS_FindDir;\r
+ ret->ReadDir = NativeFS_ReadDir;\r
+ \r
+ return ret;\r
+}\r
+\r
+void NativeFS_Unmount(tVFS_Node *Node)\r
{\r
+ tNativeFS *info = Node->ImplPtr;\r
+ Inode_ClearCache( info->InodeHandle );\r
+ closedir( (void *)Node->Inode );\r
+ free(Node->Data);\r
+ free(Node);\r
+ free(info);\r
+}\r
+\r
+void NativeFS_Close(tVFS_Node *Node)\r
+{\r
+ tNativeFS *info = Node->ImplPtr;\r
+ Inode_UncacheNode( info->InodeHandle, Node->Inode );\r
+}\r
+\r
+tVFS_Node *NativeFS_FindDir(tVFS_Node *Node, const char *Name)\r
+{\r
+ char *path = malloc(Node->ImplInt + 1 + strlen(Name) + 1);\r
+ tNativeFS *info = Node->ImplPtr;\r
+ tVFS_Node baseRet;\r
+ struct stat statbuf;\r
+\r
+ ENTER("pNode sName", Node, Name);\r
+ \r
+ // Create path\r
+ strcpy(path, Node->Data);\r
+ path[Node->ImplInt] = '/';\r
+ strcpy(path + Node->ImplInt + 1, Name);\r
+ \r
+ LOG("path = '%s'", path);\r
+ \r
+ // Check if file exists\r
+ if( stat(path, &statbuf) ) {\r
+ free(path);\r
+ LOG("Doesn't exist");\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ memset(&baseRet, 0, sizeof(tVFS_Node));\r
+ \r
+ // Check file type\r
+ if( S_ISDIR(statbuf.st_mode) )\r
+ {\r
+ LOG("Directory");\r
+ baseRet.Inode = (Uint64) opendir(path);\r
+ baseRet.FindDir = NativeFS_FindDir;\r
+ baseRet.ReadDir = NativeFS_ReadDir;\r
+ baseRet.Flags |= VFS_FFLAG_DIRECTORY;\r
+ }\r
+ else\r
+ {\r
+ LOG("File");\r
+ baseRet.Inode = (Uint64) fopen(path, "r+");\r
+ baseRet.Read = NativeFS_Read;\r
+ }\r
+ \r
+ // Create new node\r
+ baseRet.ImplPtr = info;\r
+ baseRet.ImplInt = strlen(path);\r
+ baseRet.Data = path;\r
+ \r
+ LEAVE('-');\r
+ return Inode_CacheNode(info->InodeHandle, &baseRet);\r
+}\r
+\r
+char *NativeFS_ReadDir(tVFS_Node *Node, int Position)\r
+{\r
+ // Keep track of the current directory position\r
return NULL;\r
}\r
+\r
+Uint64 NativeFS_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+ ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
+ if( fseek( (void *)Node->Inode, Offset, SEEK_SET ) != 0 )\r
+ {\r
+ LEAVE('i', 0);\r
+ return 0;\r
+ }\r
+ LEAVE('-');\r
+ return fread( Buffer, 1, Length, (void *)Node->Inode );\r
+}\r
# include <netinet/in.h>
#endif
#include "../syscalls.h"
+//#include <debug.h>
#define USE_TCP 0
#define MAX_CLIENTS 16
// === IMPORTS ===
extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
+extern int Threads_CreateRootProcess(void);
+// HACK: Should have these in a header
+extern void Log_Debug(const char *Subsys, const char *Message, ...);
+extern void Log_Notice(const char *Subsys, const char *Message, ...);
// === PROTOTYPES ===
tClient *Server_GetClient(int ClientID);
# define INVALID_SOCKET -1
int gSocket = INVALID_SOCKET;
#endif
- int giServer_NextClientID = 1;
tClient gaServer_Clients[MAX_CLIENTS];
// === CODE ===
tClient *ret = NULL;
int i;
+ // Allocate an ID if needed
+ if(ClientID == 0)
+ ClientID = Threads_CreateRootProcess();
+
for( i = 0; i < MAX_CLIENTS; i ++ )
{
if( gaServer_Clients[i].ClientID == ClientID ) {
- ret = &gaServer_Clients[i];
- break;
+ return &gaServer_Clients[i];
}
+ if(!ret && gaServer_Clients[i].ClientID == 0)
+ ret = &gaServer_Clients[i];
}
// Uh oh, no free slots
if( !ret )
return NULL;
- if( ClientID == 0 )
- {
- ret->ClientID = giServer_NextClientID ++;
- ret->CurrentRequest = NULL;
+ // Allocate a thread for the process
+ ret->ClientID = ClientID;
+ ret->CurrentRequest = NULL;
- if( !ret->WorkerThread ) {
- ret->WaitFlag = SDL_CreateCond();
- ret->Mutex = SDL_CreateMutex();
- SDL_mutexP( ret->Mutex );
- ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
- }
+ if( !ret->WorkerThread ) {
+ ret->WaitFlag = SDL_CreateCond();
+ ret->Mutex = SDL_CreateMutex();
+ SDL_mutexP( ret->Mutex );
+ ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
}
- return &gaServer_Clients[i];
+ return ret;
}
int Server_WorkerThread(void *ClientPtr)
while( Client->CurrentRequest == NULL )
SDL_CondWait(Client->WaitFlag, Client->Mutex);
- printf("Worker for %i, Job: %p\n", Client->ClientID, Client->CurrentRequest);
+ Log_Debug("AcessSrv", "Worker %i takes %p",
+ Client->ClientID, Client->CurrentRequest);
// Get the response
retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
if( !retHeader ) {
// Return an error to the client
- printf("Error returned by SyscallRecieve\n");
+ printf("ERROR: SyscallRecieve failed\n");
errorHeader.CallID = Client->CurrentRequest->CallID;
errorHeader.NParams = 0;
retHeader = &errorHeader;
// Mark the thread as ready for another job
Client->CurrentRequest = 0;
- printf("Sending %i to %x:%i\n",
+ Log_Debug("AcessSrv", "Sending %i to %x:%i (Client %i)",
retSize, ntohl(Client->ClientAddr.sin_addr.s_addr),
- ntohs(Client->ClientAddr.sin_port)
+ ntohs(Client->ClientAddr.sin_port),
+ Client->ClientID
);
// Return the data
listen(gSocket, 5);
#endif
- Log_Notice("Syscall", "Listening on 0.0.0.0:%i\n", SERVER_PORT);
+ Log_Notice("AcessSrv", "Listening on 0.0.0.0:%i", SERVER_PORT);
// Wait for something to do :)
for( ;; )
break ;
}
- printf("Client connection %x:%i",
+ Log("Client connection %x:%i\n",
ntohl(client.sin_addr), ntohs(client.sin_port)
);
continue;
}
- printf("client = %p, ClientID = %i\n", client, client->ClientID);
+ Log_Debug("AcessSrv", "Message from Client %i (%p)",
+ client->ClientID, client);
client->CurrentRequest = req;
SDL_CondSignal(client->WaitFlag);
* Syscall Distribution
*/
#include <acess.h>
+#include <threads.h>
#include "../syscalls.h"
+// === IMPORTS ===
+extern int Threads_Fork(void); // AcessNative only function
+
// === TYPES ===
-typedef int (*tSyscallHandler)(const char *Format, void *Args, int *Sizes);
+typedef int (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int *Sizes);
// === MACROS ===
-#define SYSCALL3(_name, _fmtstr, _t0, _t1, _t2, _call) int _name(const char*Fmt,void*Args,int*Sizes){\
+#define SYSCALL4(_name, _fmtstr, _t0, _t1, _t2, _t3, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
+ _t0 a0;_t1 a1;_t2 a2;_t3 a3;\
+ if(strcmp(Fmt,_fmtstr)!=0)return 0;\
+ a0 = *(_t0*)Args;Args+=sizeof(_t0);\
+ a1 = *(_t1*)Args;Args+=sizeof(_t1);\
+ a2 = *(_t2*)Args;Args+=sizeof(_t2);\
+ a3 = *(_t3*)Args;Args+=sizeof(_t3);\
+ _call\
+}
+
+#define SYSCALL3(_name, _fmtstr, _t0, _t1, _t2, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
_t0 a0;_t1 a1;_t2 a2;\
if(strcmp(Fmt,_fmtstr)!=0)return 0;\
a0 = *(_t0*)Args;Args+=sizeof(_t0);\
_call\
}
-#define SYSCALL2(_name, _fmtstr, _t0, _t1, _call) int _name(const char*Fmt,void*Args,int*Sizes){\
+#define SYSCALL2(_name, _fmtstr, _t0, _t1, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
_t0 a0;_t1 a1;\
if(strcmp(Fmt,_fmtstr)!=0)return 0;\
a0 = *(_t0*)Args;Args+=sizeof(_t0);\
_call;\
}
-#define SYSCALL1(_name, _fmtstr, _t0, _call) int _name(const char*Fmt, void*Args,int*Sizes){\
+#define SYSCALL1(_name, _fmtstr, _t0, _call) int _name(Uint*Errno,const char*Fmt, void*Args,int*Sizes){\
_t0 a0;\
if(strcmp(Fmt,_fmtstr)!=0)return 0;\
a0 = *(_t0*)Args;Args+=sizeof(_t0);\
_call;\
}
+#define SYSCALL0(_name, _call) int _name(Uint*Errno,const char*Fmt, void*Args,int*Sizes){\
+ if(strcmp(Fmt,"")!=0)return 0;\
+ _call;\
+}
+
// === CODE ===
-int Syscall_Null(const char *Format, void *Args, int *Sizes)
+int Syscall_Null(Uint*Errno, const char *Format, void *Args, int *Sizes)
{
return 0;
}
+SYSCALL1(Syscall_Exit, "i", int,
+ Threads_Exit(0, a0);
+ return 0;
+);
+
SYSCALL2(Syscall_Open, "si", const char *, int,
return VFS_Open(a0, a1|VFS_OPENFLAG_USER);
);
return 0;
);
SYSCALL3(Syscall_Read, "iid", int, int, void *,
- if( Sizes[2] <= a1 )
+ if( Sizes[2] < a1 )
return -1;
return VFS_Read(a0, a1, a2);
);
SYSCALL3(Syscall_Write, "iid", int, int, const void *,
- if( Sizes[2] <= a1 )
+ if( Sizes[2] < a1 )
return -1;
return VFS_Write(a0, a1, a2);
);
return -1;
return VFS_FInfo(a0, a1, a2);
);
+SYSCALL2(Syscall_ReadDir, "id", int, char *,
+ if(Sizes[1] < 255)
+ return -1;
+ return VFS_ReadDir(a0, a1);
+);
+SYSCALL3(Syscall_OpenChild, "isi", int, const char *, int,
+ return VFS_OpenChild(NULL, a0, a1, a2|VFS_OPENFLAG_USER);
+);
+SYSCALL2(Syscall_GetACL, "id", int, void *,
+ if(Sizes[1] < sizeof(tVFS_ACL))
+ return -1;
+ return VFS_GetACL(a0, (void*)a1);
+);
+SYSCALL4(Syscall_Mount, "ssss", const char *, const char *, const char *, const char *,
+ return VFS_Mount(a0, a1, a2, a3);
+);
+SYSCALL0(Syscall_Sleep,
+ Threads_Sleep();
+ return 0;
+);
+SYSCALL2(Syscall_WaitTID, "id", int, int *,
+ if(Sizes[1] < sizeof(int))
+ return -1;
+ return Threads_WaitTID(a0, a1);
+);
+SYSCALL1(Syscall_SetUID, "i", int,
+ if(Sizes[0] < sizeof(int)) {
+ *Errno = -EINVAL; // TODO: Better message
+ return -1;
+ }
+ return Threads_SetUID(Errno, a0);
+);
+SYSCALL1(Syscall_SetGID, "i", int,
+ if(Sizes[0] < sizeof(int)) {
+ *Errno = -EINVAL; // TODO: Better message
+ return -1;
+ }
+ return Threads_SetGID(Errno, a0);
+);
+SYSCALL0(Syscall_Fork,
+ return Threads_Fork();
+);
const tSyscallHandler caSyscalls[] = {
Syscall_Null,
+ Syscall_Exit,
Syscall_Open,
Syscall_Close,
Syscall_Read,
Syscall_Seek,
Syscall_Tell,
Syscall_IOCtl,
- Syscall_FInfo
+ Syscall_FInfo,
+ Syscall_ReadDir,
+ Syscall_OpenChild,
+ Syscall_GetACL,
+ Syscall_Mount,
+ NULL, // SYS_REOPEN
+
+ Syscall_WaitTID,
+ Syscall_SetUID,
+ Syscall_SetGID,
+
+ Syscall_Sleep,
+ Syscall_Fork
};
const int ciNumSyscalls = sizeof(caSyscalls)/sizeof(caSyscalls[0]);
/**
int retDataLen = sizeof(Uint64);
void *returnData[Request->NParams];
int argSizes[Request->NParams];
+ Uint ret_errno = 0;
// Sanity check
if( Request->CallID >= ciNumSyscalls ) {
return NULL;
}
+ if( !caSyscalls[Request->CallID] ) {
+ Log_Notice("Syscalls", "Unimplemented syscall %i", Request->CallID);
+ return NULL;
+ }
+
// Get size of argument list
for( i = 0; i < Request->NParams; i ++ )
{
}
formatString[i] = '\0';
- Log_Debug("Syscalls", "Request %i '%s'", Request->CallID, formatString);
+ LOG("Request %i(%s) '%s'", Request->CallID, casSYSCALL_NAMES[Request->CallID], formatString);
{
char argListData[argListLen];
case ARG_TYPE_VOID:
break;
case ARG_TYPE_INT32:
- Log_Debug("Syscalls", "Arg %i: 0x%x", i, *(Uint32*)inData);
+ LOG("Syscalls", "%i INT32: 0x%x", i, *(Uint32*)inData);
*(Uint32*)&argListData[argListLen] = *(Uint32*)inData;
argListLen += sizeof(Uint32);
inData += sizeof(Uint32);
break;
case ARG_TYPE_INT64:
- Log_Debug("Syscalls", "Arg %i: 0x%llx", i, *(Uint64*)inData);
+ LOG("Syscalls", "%i INT64: 0x%llx", i, *(Uint64*)inData);
*(Uint64*)&argListData[argListLen] = *(Uint64*)inData;
argListLen += sizeof(Uint64);
inData += sizeof(Uint64);
break;
case ARG_TYPE_STRING:
- Log_Debug("Syscalls", "Arg %i: '%s'", i, (char*)inData);
+ LOG("Syscalls", "%i STR: '%s'", i, (char*)inData);
*(char**)&argListData[argListLen] = (char*)inData;
argListLen += sizeof(void*);
inData += Request->Params[i].Length;
{
// Allocate and zero the buffer
returnData[i] = calloc(1, Request->Params[i].Length);
- Log_Debug("Syscalls", "Arg %i: %i %p", i,
+ LOG("Syscalls", "%i ZDAT: %i %p", i,
Request->Params[i].Length, returnData[i]);
*(void**)&argListData[argListLen] = returnData[i];
argListLen += sizeof(void*);
else
{
returnData[i] = (void*)inData;
- Log_Debug("Syscalls", "Arg %i: %i %p", i,
+ LOG("Syscalls", "%i DATA: %i %p", i,
Request->Params[i].Length, returnData[i]);
*(void**)&argListData[argListLen] = (void*)inData;
argListLen += sizeof(void*);
}
}
- retVal = caSyscalls[Request->CallID](formatString, argListData, argSizes);
+ retVal = caSyscalls[Request->CallID](&ret_errno, formatString, argListData, argSizes);
}
// Allocate the return
*(Uint64*)inData = retVal;
inData += sizeof(Uint64);
- Log_Debug("Syscalls", "Return 0x%llx", retVal);
+ LOG("Syscalls", "Return 0x%llx", retVal);
+ retValueCount = 1;
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;
+ ret->Params[retValueCount].Type = Request->Params[i].Type;
+ ret->Params[retValueCount].Flags = 0;
+ ret->Params[retValueCount].Length = Request->Params[i].Length;
+
+ LOG("Syscalls", "Ret %i: Type %i, Len %i",
+ i, Request->Params[i].Type, Request->Params[i].Length);
memcpy(inData, returnData[i], Request->Params[i].Length);
inData += Request->Params[i].Length;
if( Request->Params[i].Flags & ARG_FLAG_ZEROED )
free( returnData[i] ); // Free temp buffer from above
+ retValueCount ++;
}
*ReturnLength = sizeof(tRequestHeader)
* threads.c
* - Thread and process handling
*/
-#define _SIGNAL_H_
+#define _SIGNAL_H_ // Stop the acess signal.h being used
+#define _HEAP_H_ // Stop heap.h being imported (collides with stdlib heap)
+#define _VFS_EXT_H // Stop vfs_ext.h being imported (collides with fd_set)
#undef CLONE_VM // Such a hack
#include <arch.h>
+#undef NULL // Remove acess definition
+#include <acess.h>
+#include <mutex.h>
+#include <semaphore.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdint.h>
#include "/usr/include/signal.h"
+#include <SDL/SDL.h>
+
+// === IMPORTS ===
+void VFS_CloneHandleList(int PID);
// === STRUCTURES ===
#if 0
typedef struct sThread
{
+ struct sThread *GlobalNext;
struct sThread *Next;
int KernelTID;
char *ThreadName;
int State; // 0: Dead, 1: Active, 2: Paused, 3: Asleep
+ int ExitStatus;
#if 0
tState CurState;
#endif
+ // Threads waiting for this thread to exit.
+ // Quit logic:
+ // - Wait for `WaitingThreads` to be non-null (maybe?)
+ // - Wake first in the queue, wait for it to be removed
+ // - Repeat
+ // - Free thread and quit kernel thread
+ struct sThread *WaitingThreads;
+ struct sThread *WaitingThreadsEnd;
+
// Config?
Uint Config[NUM_CFG_ENTRIES];
} tThread;
+// === PROTOTYPES ===
+ int Threads_Wake(tThread *Thread);
+
// === GLOBALS ===
-tThread gThread_Zero = {
+tThread gThreadZero = {
State: 1,
ThreadName: "ThreadZero"
};
-tThread *gpThreads = &gThread_Zero;
-__thread tThread *gpCurrentThread = &gThread_Zero;
+tThread *gpThreads = &gThreadZero;
+__thread tThread *gpCurrentThread = &gThreadZero;
+ int giThreads_NextThreadID = 1;
// === CODE ===
+void Threads_Dump(void)
+{
+ tThread *thread;
+ for( thread = gpThreads; thread; thread = thread->GlobalNext )
+ {
+ Log_Log("Threads", "TID %i (%s), PID %i",
+ thread->TID, thread->ThreadName, thread->PID);
+ Log_Log("Threads", "User: %i, Group: %i",
+ thread->UID, thread->GID);
+ Log_Log("Threads", "Kernel Thread ID: %i",
+ thread->KernelTID);
+ }
+}
+
tThread *Threads_GetThread(int TID)
{
tThread *thread;
- for( thread = gpThreads; thread; thread = thread->Next )
+ for( thread = gpThreads; thread; thread = thread->GlobalNext )
{
if( thread->TID == TID )
return thread;
return NULL;
}
+/**
+ * \brief Clone a thread control block (with a different TID)
+ */
+tThread *Threads_CloneTCB(tThread *TemplateThread)
+{
+ tThread *ret = malloc(sizeof(tThread));
+
+ memcpy(ret, TemplateThread, sizeof(tThread));
+
+ ret->TID = giThreads_NextThreadID ++;
+
+ ret->ThreadName = strdup(TemplateThread->ThreadName);
+
+ ret->WaitingThreads = NULL;
+ ret->WaitingThreadsEnd = NULL;
+
+ // Add to the end of the queue
+ // TODO: Handle concurrency issues
+ ret->GlobalNext = gpThreads;
+ gpThreads = ret;
+
+ return ret;
+}
+
tUID Threads_GetUID() { return gpCurrentThread->UID; }
tGID Threads_GetGID() { return gpCurrentThread->GID; }
tTID Threads_GetTID() { return gpCurrentThread->TID; }
-tPID Threads_GetPID() {
- return SDL_ThreadID();
- //return gpCurrentThread->PID;
+tPID Threads_GetPID() { return gpCurrentThread->PID; }
+
+int Threads_SetUID(int *Errno, tUID NewUID)
+{
+ if(Threads_GetUID() != 0) {
+ if(Errno) *Errno = -EACCES;
+ return -1;
+ }
+
+ gpCurrentThread->UID = NewUID;
+ return 0;
+}
+
+int Threads_SetGID(int *Errno, tGID NewGID)
+{
+ if(Threads_GetUID() != 0) {
+ if(Errno) *Errno = -EACCES;
+ return -1;
+ }
+
+ gpCurrentThread->GID = NewGID;
+ return 0;
}
Uint *Threads_GetCfgPtr(int Index)
return &gpCurrentThread->Config[Index];
}
+int Threads_WaitTID(int TID, int *Status)
+{
+ // Any Child
+ if(TID == -1) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
+ return -1;
+ }
+
+ // Any peer/child thread
+ if(TID == 0) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=0) - Any Child/Sibling");
+ return -1;
+ }
+
+ // TGID = abs(TID)
+ if(TID < -1) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID<0) - TGID");
+ return -1;
+ }
+
+ // Specific Thread
+ if(TID > 0) {
+
+ tThread *thread = Threads_GetThread(TID);
+ tThread *us = gpCurrentThread;
+ if(!thread) return -1;
+
+ us->Next = NULL;
+ us->State = 3;
+ if(thread->WaitingThreadsEnd)
+ {
+ thread->WaitingThreadsEnd->Next = us;
+ thread->WaitingThreadsEnd = us;
+ }
+ else
+ {
+ thread->WaitingThreads = us;
+ thread->WaitingThreadsEnd = us;
+ }
+
+ while(thread->State != 0)
+ pause();
+
+ if(Status) *Status = thread->ExitStatus;
+ thread->WaitingThreads = thread->WaitingThreads->Next;
+ us->Next = NULL;
+
+ return TID;
+ }
+
+ return 0;
+}
+
void Threads_Sleep(void)
{
+ // TODO: Add to a sleeping queue
pause();
}
// yield();
}
+void Threads_Exit(int TID, int Status)
+{
+ tThread *toWake;
+
+// VFS_Handles_Cleanup();
+
+ #if 1
+ // Wait for the thread to be waited upon
+ while( gpCurrentThread->WaitingThreads == NULL )
+ SDL_Delay(10);
+ #endif
+
+ while( (toWake = gpCurrentThread->WaitingThreads) )
+ {
+ Threads_Wake(toWake);
+
+ while(gpCurrentThread->WaitingThreads == toWake)
+ SDL_Delay(10);
+ }
+}
+
+int Threads_Wake(tThread *Thread)
+{
+ kill( Thread->KernelTID, SIGUSR1 );
+ return 0;
+}
+
int Threads_WakeTID(tTID TID)
{
tThread *thread;
thread = Threads_GetThread(TID);
if( !thread ) return -1;
- kill( thread->KernelTID, SIGUSR1 );
- return 0;
+ return Threads_Wake(thread);
+}
+
+int Threads_CreateRootProcess(void)
+{
+ tThread *thread = Threads_CloneTCB(&gThreadZero);
+ thread->PID = thread->TID;
+
+ // Handle list is created on first open
+
+ return thread->PID;
+}
+
+int Threads_Fork(void)
+{
+ tThread *thread = Threads_CloneTCB(gpCurrentThread);
+ thread->PID = thread->TID;
+ // Duplicate the VFS handles (and nodes) from vfs_handle.c
+
+ VFS_CloneHandleList(thread->PID);
+
+ return thread->PID;
}
-void Mutex_Acquire(tMutex *Mutex)
+int Mutex_Acquire(tMutex *Mutex)
{
if(!Mutex->Protector.IsValid) {
pthread_mutex_init( &Mutex->Protector.Mutex, NULL );
Mutex->Protector.IsValid = 1;
}
pthread_mutex_lock( &Mutex->Protector.Mutex );
+ return 0;
}
void Mutex_Release(tMutex *Mutex)
pthread_mutex_unlock( &Mutex->Protector.Mutex );
}
+void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
+{
+ memset(Sem, 0, sizeof(tSemaphore));
+ // HACK: Use `Sem->Protector` as space for the semaphore pointer
+ *(void**)(&Sem->Protector) = SDL_CreateSemaphore(InitValue);
+}
+
+int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
+{
+ SDL_SemWait( *(void**)(&Sem->Protector) );
+ return 1;
+}
+
+int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
+{
+ int i;
+ for( i = 0; i < AmmountToAdd; i ++ )
+ SDL_SemPost( *(void**)(&Sem->Protector) );
+ return AmmountToAdd;
+}
+
#if 0
void Threads_Sleep()
{
// Start main thread
gInputThread = SDL_CreateThread(UI_MainThread, NULL);
+ while(gScreen == NULL)
+ SDL_Delay(10);
+
return 0;
}
SDL_Surface *tmp;
SDL_Rect dstRect;
+// printf("UI_BlitBitmap: Blit to (%i,%i) from %p (%ix%i 32bpp bitmap)\n",
+// DstX, DstY, Bitmap, SrcW, SrcH);
+
tmp = SDL_CreateRGBSurfaceFrom(Bitmap, SrcW, SrcH, 32, SrcW*4,
0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
SDL_SetAlpha(tmp, 0, SDL_ALPHA_OPAQUE);
dstRect.x = DstX; dstRect.y = DstY;
+ dstRect.w = -1; dstRect.h = -1;
SDL_BlitSurface(tmp, NULL, gScreen, &dstRect);
+ //SDL_BlitSurface(tmp, NULL, gScreen, NULL);
SDL_FreeSurface(tmp);
+// SDL_Flip(gScreen);
}
void UI_BlitFramebuffer(int DstX, int DstY, int SrcX, int SrcY, int W, int H)
dstRect.x = X; dstRect.y = Y;
dstRect.w = W; dstRect.h = H;
+// printf("UI_FillBitmap: gScreen = %p\n", gScreen);
SDL_FillRect(gScreen, &dstRect, Value);
}
void UI_Redraw(void)
{
- // No-Op, we're not using double buffering
+ // TODO: Keep track of changed rectangle
+ SDL_UpdateRect(gScreen, 0, 0, giUI_Width, giUI_Height);
}
* Acess2 VFS
* - AllocHandle, GetHandle
*/
-#define DEBUG 0
+#define DEBUG 1
#include <acess.h>
-#include "vfs.h"
-#include "vfs_int.h"
-#include "vfs_ext.h"
+#include <vfs.h>
+#include <vfs_int.h>
+#include <vfs_ext.h>
// === CONSTANTS ===
#define MAX_KERNEL_FILES 128
tVFS_Handle gaKernelHandles[MAX_KERNEL_FILES];
// === CODE ===
+tUserHandles *VFS_int_GetUserHandles(int PID, int bCreate)
+{
+ tUserHandles *ent, *prev = NULL;
+ for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
+ if( ent->PID == PID ) {
+ Log_Warning("VFS", "Process %i already has a handle list", PID);
+ return ent;
+ }
+ if( ent->PID > PID ) break;
+ }
+
+ if(!bCreate)
+ return NULL;
+
+ ent = calloc( 1, sizeof(tUserHandles) );
+ ent->PID = PID;
+ if( prev ) {
+ ent->Next = prev->Next;
+ prev->Next = ent;
+ }
+ else {
+ ent->Next = gpUserHandles;
+ gpUserHandles = ent;
+ }
+ Log_Notice("VFS", "Created handle list for process %i", PID);
+ return ent;
+}
+
+/**
+ * \brief Clone the handle list of the current process into another
+ */
+void VFS_CloneHandleList(int PID)
+{
+ tUserHandles *ent;
+ tUserHandles *cur;
+ int i;
+
+ cur = VFS_int_GetUserHandles(Threads_GetPID(), 0);
+ if(!cur) return ; // Don't need to do anything if the current list is empty
+
+ ent = VFS_int_GetUserHandles(PID, 1);
+
+ memcpy(ent->Handles, cur->Handles, CFGINT(CFG_VFS_MAXFILES)*sizeof(tVFS_Handle));
+
+ for( i = 0; i < CFGINT(CFG_VFS_MAXFILES); i ++ )
+ {
+ if(!cur->Handles[i].Node) continue;
+
+ if(ent->Handles[i].Node->Reference)
+ ent->Handles[i].Node->Reference(ent->Handles[i].Node);
+ }
+}
+
/**
* \fn tVFS_Handle *VFS_GetHandle(int FD)
* \brief Gets a pointer to the handle information structure
//Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
- if(FD < 0) return NULL;
+ if(FD < 0) {
+ LOG("FD (%i) < 0, RETURN NULL", FD);
+ return NULL;
+ }
if(FD & VFS_KERNEL_FLAG) {
FD &= (VFS_KERNEL_FLAG - 1);
- if(FD >= MAX_KERNEL_FILES) return NULL;
+ if(FD >= MAX_KERNEL_FILES) {
+ LOG("FD (%i) > MAX_KERNEL_FILES (%i), RETURN NULL", FD, MAX_KERNEL_FILES);
+ return NULL;
+ }
h = &gaKernelHandles[ FD ];
}
- else {
+ else
+ {
tUserHandles *ent;
- int pid = Server_GetClientID();
- for( ent = gpUserHandles; ent; ent = ent->Next ) {
- if( ent->PID == pid ) break;
- if( ent->PID > pid ) {
- Log_Error("VFS", "PID %i does not have a handle list", pid);
- return NULL;
- }
+ int pid = Threads_GetPID();
+
+ ent = VFS_int_GetUserHandles(pid, 0);
+ if(!ent) {
+ Log_Error("VFS", "Client %i does not have a handle list (>)", pid);
+ return NULL;
}
- if( !ent ) {
- Log_Error("VFS", "PID %i does not have a handle list", pid);
+
+ if(FD >= CFGINT(CFG_VFS_MAXFILES)) {
+ LOG("FD (%i) > Limit (%i), RETURN NULL", FD, CFGINT(CFG_VFS_MAXFILES));
return NULL;
}
- if(FD >= CFGINT(CFG_VFS_MAXFILES)) return NULL;
h = &ent->Handles[ FD ];
+ LOG("FD (%i) -> %p (Mode:0x%x,Node:%p)", FD, h, h->Mode, h->Node);
}
- if(h->Node == NULL) return NULL;
+ if(h->Node == NULL) {
+ LOG("FD (%i) Unused", FD);
+ return NULL;
+ }
//Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
return h;
}
// Check for a user open
if(bIsUser)
{
- tUserHandles *ent, *prev = NULL;
- int pid = Server_GetClientID();
- for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
- if( ent->PID == pid ) break;
- if( ent->PID > pid ) break;
- }
- if( !ent || ent->PID > pid ) {
- ent = calloc( 1, sizeof(tUserHandles) );
- ent->PID = pid;
- if( prev ) {
- ent->Next = prev->Next;
- prev->Next = ent;
- }
- else {
- ent->Next = gpUserHandles;
- gpUserHandles = ent;
- }
- }
+ tUserHandles *ent;
+ // Find the PID's handle list
+ ent = VFS_int_GetUserHandles(Threads_GetPID(), 1);
// Get a handle
for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
{
* Video Driver
*/
#define VERSION ((0<<8)|10)
+#define DEBUG 0
#include <acess.h>
#include <vfs.h>
#include <fs_devfs.h>
// Sanity Check
if( Offset > (Uint64)(heightInChars*widthInChars) ) {
+ Log_Notice("Video", "Offset (%i) > %i*%i (%i)", Offset,
+ heightInChars, widthInChars, heightInChars*widthInChars);
LEAVE('i', 0);
return 0;
}
Log_Notice("Video", "Clipping write size to %i characters", (int)Length);
}
+// Log_Debug("Video", "(%i,%i) %i chars", x, y, (int)Length);
+
// Print characters
for( i = 0; i < (int)Length; i++ )
{
- VT_Font_Render(
- chars->Ch,
- //dest + x*giVT_CharWidth, pitch,
- tmpBuf, giVT_CharWidth,
- VT_Colour12to24(chars->BGCol),
- VT_Colour12to24(chars->FGCol)
- );
- UI_BlitBitmap(
- x*giVT_CharWidth, y*giVT_CharHeight,
- giVT_CharWidth, giVT_CharHeight,
- tmpBuf
- );
+ if( chars->Ch )
+ {
+// Log_Debug("Video", "Render Char 0x%x in 0x%03x:%03x",
+// chars->Ch, chars->FGCol, chars->BGCol);
+ memset(tmpBuf, 0xFF, giVT_CharWidth*giVT_CharHeight*4);
+ VT_Font_Render(
+ chars->Ch,
+ tmpBuf, 32, giVT_CharWidth*4,
+ VT_Colour12to24(chars->BGCol),
+ VT_Colour12to24(chars->FGCol)
+ );
+ UI_BlitBitmap(
+ x*giVT_CharWidth, y*giVT_CharHeight,
+ giVT_CharWidth, giVT_CharHeight,
+ tmpBuf
+ );
+ }
+ else
+ {
+ UI_FillBitmap(
+ x*giVT_CharWidth, y*giVT_CharHeight,
+ giVT_CharWidth, giVT_CharHeight,
+ VT_Colour12to24(chars->BGCol)
+ );
+ }
chars ++;
x ++;
}
LOG("buffer = %p", Buffer);
- LOG("Updating Framebuffer (%p to %p)", destBuf, destBuf + (Uint)Length);
startX = Offset % giUI_Width;
startY = Offset / giUI_Width;
return Length;
}
-const char * const csaVIDEO_IOCTLS[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};
+const char * csaVIDEO_IOCTLS[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};
/**
* \brief Handle messages to the device
*/
CFLAGS += -Wall -Werror -g -m32
+DEPFILES = $(filter %.o.$(PLATFORM),$(OBJ))
+DEPFILES := $(DEPFILES:%.o.$(PLATFORM)=%.d.$(PLATFORM))
+
.PHONY: all clean
all: $(BIN)
$(CC) -g -o $@ $(OBJ) -m32 -Wl,-T,link.ld.$(PLATFORM)
%.o.$(PLATFORM): %.c
- $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)
+ @echo [CC] -o $@
+ @$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)
+ @$(CC) -M $(CPPFLAGS) -MT $@ -o $*.d.$(PLATFORM) $<
# Modify the default makefile to put the executable at 1MB instead
link.ld.lin:
- $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x0[08][0-9]*\b/0x00100000/g' > $@
+ @echo Making Linker Script ($@)
+ @$(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x0[08][0-9]*\b/0x00100000/g' > $@
#include <stdio.h>
#include <string.h>
-#define LIBRARY_PATH "../Usermode/Output/i386/Libs"
+#define LIBRARY_PATH "$$$$../Usermode/Output/i386/Libs"
// === TYPES ===
typedef struct sBinary {
} tBinary;
// === IMPORTS ===
-extern void *Elf_Load(FILE *FP);
+extern void *Elf_Load(int fd);
extern uintptr_t Elf_Relocate(void *Base);
extern int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);
extern int ciNumBuiltinSymbols;
{
char *envPath = getenv("ACESS_LIBRARY_PATH");
int nameLen = strlen(Name);
- FILE *fp;
+ int fd;
if( strcmp(Name, "libld-acess.so") == 0 ) {
return strdup("libld-acess.so");
strcat(tmp, "/");
strcat(tmp, Name);
- fp = fopen(tmp, "r");
- if(fp) {
- fclose(fp);
+ fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ if(fd != -1) {
+ acess_close(fd);
return strdup(tmp);
}
}
strcat(tmp, "/");
strcat(tmp, Name);
+ #if DEBUG
printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
+ #endif
- fp = fopen(tmp, "r");
- if(fp) {
- fclose(fp);
+ fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ if(fd != -1) {
+ acess_close(fd);
return strdup(tmp);
}
}
+ #if DEBUG
fprintf(stderr, "Unable to locate library '%s'\n", Name);
+ #endif
return NULL;
}
// Find File
path = Binary_LocateLibrary(Name);
+ #if DEBUG
printf("Binary_LoadLibrary: path = '%s'\n", path);
+ #endif
if( !path ) {
return NULL;
}
ret = Binary_Load(path, (uintptr_t*)&entry);
free(path);
+ #if DEBUG
printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry);
+ #endif
if( entry ) {
char *argv[] = {NULL};
+ #if DEBUG
printf("Calling '%s' entry point %p\n", Name, entry);
+ #endif
entry(0, argv, NULL);
}
void *Binary_Load(const char *Filename, uintptr_t *EntryPoint)
{
- FILE *fp;
- uint32_t dword;
+ int fd;
+ uint32_t dword = 0xFA17FA17;
void *ret;
uintptr_t entry = 0;
tBinFmt *fmt;
}
}
- fp = fopen(Filename, "r");
- if( !fp ) {
+ fd = acess_open(Filename, 2|1); // Execute and Read
+ if( fd == -1 ) {
// TODO: Handle libary directories
perror("Opening binary");
return NULL;
}
- fread(&dword, 1, 4, fp);
- fseek(fp, 0, SEEK_SET);
+ acess_read(fd, 4, &dword);
+ acess_seek(fd, 0, ACESS_SEEK_SET);
if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
fmt = &gElf_FormatDef;
}
else {
- fclose(fp);
+ fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
+ acess_close(fd);
return NULL;
}
- printf("fmt->Load(%p)...\n", fp);
- ret = fmt->Load(fp);
- printf("fmt->Load(%p): %p\n", fp, ret);
+ #if DEBUG
+ printf("fmt->Load(%i)...\n", fd);
+ #endif
+ ret = fmt->Load(fd);
+ acess_close(fd);
+ #if DEBUG
+ printf("fmt->Load(%p): %p\n", fd, ret);
+ #endif
if( !ret ) {
- fclose(fp);
return NULL;
}
Binary_AddToList(Filename, ret, fmt);
entry = fmt->Relocate(ret);
+ #if DEBUG
printf("fmt->Relocate(%p): %p\n", ret, (void*)entry);
+ #endif
if( !entry ) {
// TODO: Clean up
return NULL;
if( EntryPoint )
*EntryPoint = entry;
- fclose(fp);
-
Binary_SetReadyToUse(ret);
return ret;
extern void Warning(const char *Format, ...);
extern void Notice(const char *Format, ...);
+#define ACESS_SEEK_CUR 0
+#define ACESS_SEEK_SET 1
+#define ACESS_SEEK_END -1
+
+extern int acess_open(const char *Path, int Flags);
+extern void acess_close(int FD);
+extern size_t acess_read(int FD, size_t Bytes, void *Dest);
+extern int acess_seek(int FD, int64_t Offset, int Dir);
+
typedef struct {
char *Name;
void *Value;
typedef struct sBinFmt {
struct sBinFmt *Next;
char *Name;
- void *(*Load)(FILE *fp);
+ void *(*Load)(int fd);
uintptr_t (*Relocate)(void *base);
int (*GetSymbol)(void*,char*,uintptr_t*);
} tBinFmt;
#endif\r
\r
// === PROTOTYPES ===\r
-void *Elf_Load(FILE *FP);\r
+void *Elf_Load(int FD);\r
uintptr_t Elf_Relocate(void *Base);\r
int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);\r
int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *Base);\r
uint32_t Elf_Int_HashString(char *str);\r
\r
// === CODE ===\r
-void *Elf_Load(FILE *FP)\r
+void *Elf_Load(int FD)\r
{\r
Elf32_Ehdr hdr;\r
Elf32_Phdr *phtab;\r
uint32_t addr;\r
uint32_t baseDiff = 0;\r
\r
- ENTER("pFP", FP);\r
+ ENTER("iFD", FD);\r
\r
// Read ELF Header\r
- fread(&hdr, sizeof(hdr), 1, FP);\r
+ acess_read(FD, sizeof(hdr), &hdr);\r
\r
// Check the file type\r
if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') {\r
return NULL;\r
}\r
LOG("hdr.phoff = 0x%08x\n", hdr.phoff);\r
- fseek(FP, hdr.phoff, SEEK_SET);\r
- fread(phtab, sizeof(Elf32_Phdr), hdr.phentcount, FP);\r
+ acess_seek(FD, hdr.phoff, ACESS_SEEK_SET);\r
+ acess_read(FD, sizeof(Elf32_Phdr) * hdr.phentcount, phtab);\r
\r
// Count Pages\r
iPageCount = 0;\r
char *tmp;\r
//if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].FileSize);\r
- fseek(FP, phtab[i].Offset, SEEK_SET);\r
- fread(tmp, phtab[i].FileSize, 1, FP);\r
+ acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess_read(FD, phtab[i].FileSize, tmp);\r
//ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'\n", tmp);\r
free(tmp);\r
return NULL;\r
}\r
\r
- fseek(FP, phtab[i].Offset, SEEK_SET);\r
- fread( PTRMK(void, addr), phtab[i].FileSize, 1, FP );\r
+ acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess_read(FD, phtab[i].FileSize, PTRMK(void, addr) );\r
memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
}\r
\r
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
// === CODE ===
int main(int argc, char *argv[], char **envp)
int i;
int appArgc;
char **appArgv;
- char *appPath;
+ char *appPath = NULL;
int (*appMain)(int, char *[], char **);
void *base;
+ int syscall_handle = -1;
+
for( i = 1; i < argc; i ++ )
{
+ if(strcmp(argv[i], "--key") == 0) {
+ syscall_handle = atoi(argv[++i]);
+ continue ;
+ }
+
+ if(strcmp(argv[i], "--binary") == 0) {
+ appPath = argv[++i];
+ continue ;
+ }
+
+ if(strcmp(argv[i], "--open") == 0) {
+ if( acess_open(argv[++i], 6) == -1 ) { // Read/Write
+ fprintf(stderr, "Unable to open '%s'\n", argv[i]);
+ exit(1);
+ }
+ continue ;
+ }
+
if( argv[i][0] != '-' ) break;
}
return 1;
}
- appPath = argv[i];
+ if( !appPath )
+ appPath = argv[i];
appArgc = argc - i;
appArgv = &argv[i];
"push %2;\n\t"
"jmp *%3;\n\t"
: : "r" (envp), "r" (appArgv), "r" (appArgc), "r" (appMain) );
- //return appMain(appArgc, appArgv, envp);
return -1;
}
#endif
exit(0);
}
+ giSyscall_ClientID = gSocket; // A bit of a hack really :(
#endif
#if 0
return 0;
}
-int SendRequest(tRequestHeader *Request, int RequestSize)
+int SendRequest(tRequestHeader *Request, int RequestSize, int ResponseSize)
{
if( gSocket == INVALID_SOCKET )
{
{
int i;
char *data = (char*)&Request->Params[Request->NParams];
- printf("Request #%i\n", Request->CallID);
+ printf("Request #%i (%s) -", Request->CallID, casSYSCALL_NAMES[Request->CallID]);
for( i = 0; i < Request->NParams; i ++ )
{
- printf("%i: ", i);
switch(Request->Params[i].Type)
{
case ARG_TYPE_INT32:
- printf("INT32 %x", *(uint32_t*)data);
+ printf(" 0x%08x", *(uint32_t*)data);
data += sizeof(uint32_t);
break;
case ARG_TYPE_INT64:
- printf("INT64 %llx", *(uint64_t*)data);
+ printf(" 0x%016llx", *(uint64_t*)data);
data += sizeof(uint64_t);
break;
case ARG_TYPE_STRING:
- printf("STRING '%s'", (char*)data);
+ printf(" '%s'", (char*)data);
data += Request->Params[i].Length;
break;
case ARG_TYPE_DATA:
- printf("DATA %i %p", Request->Params[i].Length, (char*)data);
- data += Request->Params[i].Length;
+ printf(" %p:0x%x", (char*)data, Request->Params[i].Length);
+ if( !(Request->Params[i].Flags & ARG_FLAG_ZEROED) )
+ data += Request->Params[i].Length;
break;
}
- printf("\n");
}
+ printf("\n");
}
// Send it off
SendData(Request, RequestSize);
// Wait for a response (no timeout)
- return ReadData(Request, RequestSize, 0);
+ return ReadData(Request, ResponseSize, 0);
}
void SendData(void *Data, int Length)
#include "../syscalls.h"
-extern int SendRequest(tRequestHeader *Request, int RequestSize);
+extern int SendRequest(tRequestHeader *Request, int RequestSize, int ResponseSize);
#endif
/*
*/
+#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(x...) printf(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(tRequestValue *Dest, void *DataDest, void **PtrDest, const char *ArgTypes, va_list *Args)
}
val32 = va_arg(*Args, uint32_t);
- printf("val32 = 0x%x\n", val32);
Dest->Type = ARG_TYPE_INT32;
Dest->Length = sizeof(uint32_t);
}
val64 = va_arg(*Args, uint64_t);
- printf("val64 = 0x%llx\n", val64);
Dest->Type = ARG_TYPE_INT64;
Dest->Length = sizeof(uint64_t);
}
str = va_arg(*Args, char*);
- printf("str = %p '%s'\n", str, str);
Dest->Type = ARG_TYPE_STRING;
Dest->Length = strlen(str) + 1;
len = va_arg(*Args, int);
str = va_arg(*Args, char*);
- printf("len = %i, str = %p\n", len, str);
-
// Save the pointer for later
if( PtrDest ) *PtrDest = str;
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;
va_end(args);
// Send syscall request
- if( SendRequest(req, dataLength) < 0 ) {
+ if( SendRequest(req, dataLength, retLength) < 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 )
+ if( req->NParams >= 1 )
{
switch(req->Params[0].Type)
{
}
// Write changes to buffers
- va_start(args, ArgTypes);
+ retCount = 0;
for( i = 1; i < req->NParams; i ++ )
{
- memcpy( retPtrs[i-1], dataPtr, req->Params[i].Length );
+ #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;
}
- va_end(args);
free( req );
+ free( retPtrs );
- return 0;
+ printf("Return %llx\n", retValue);
+
+ return retValue;
}
// --- VFS Calls
-int open(const char *Path, int Flags) {
+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)\n", Path, Flags);
return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
}
-void close(int FD) {
+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)\n", FD);
_Syscall(SYS_CLOSE, ">i", FD);
}
-int reopen(int FD, const char *Path, int Flags) {
+int acess_reopen(int FD, const char *Path, int Flags) {
+ DEBUG("reopen(0x%x, \"%s\", 0x%x)\n", FD, Path, Flags);
return _Syscall(SYS_REOPEN, ">i >s >i", FD, Path, Flags);
}
-size_t read(int FD, size_t Bytes, void *Dest) {
- return _Syscall(SYS_READ, "<i >i >i <d", FD, Bytes, Bytes, Dest);
+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)\n", FD, Bytes, Dest);
+ return _Syscall(SYS_READ, ">i >i <d", FD, Bytes, Bytes, Dest);
}
-size_t write(int FD, size_t Bytes, void *Src) {
+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\"))\n", FD, Bytes, Src, Bytes, (char*)Src);
return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
}
-int seek(int FD, int64_t Ofs, int Dir) {
+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)\n", FD, Ofs, Dir);
return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
}
-uint64_t tell(int FD) {
+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 ioctl(int fd, int id, void *data) {
+int acess_ioctl(int fd, int id, void *data) {
// NOTE: 1024 byte size is a hack
return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, 1024, data);
}
-int finfo(int fd, t_sysFInfo *info, int maxacls) {
+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);
}
-int readdir(int fd, char *dest) {
+int acess_readdir(int fd, char *dest) {
return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
}
-int _SysOpenChild(int fd, char *name, int flags) {
+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 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 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)) {
return 0;
}
// --- Memory Management ---
-uint64_t _SysAllocate(uint vaddr)
+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()\n");
+
+ newID = _Syscall(SYS_FORK, "<i", &kernel_tid);
+ ret = fork();
+ if(ret < 0) return ret;
+
+ if(ret == 0)
+ {
+ giSyscall_ClientID = newID;
+ return 0;
+ }
+
+ // TODO: 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;
+
+ printf("acess_execve: (path='%s', argv=%p, envp=%p)\n", path, argv, envp);
+
+ // Get argument count
+ for( argc = 0; argv[argc]; argc ++ ) ;
+ printf(" acess_execve: argc = %i\n", 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 <i", TID, ExitStatus);
+}
+
+int acess_setuid(int ID)
+{
+ return _Syscall(SYS_SETUID, ">i", ID);
+}
+
+int acess_setgid(int ID)
+{
+ return _Syscall(SYS_SETGID, ">i", ID);
+}
+
+// --- Logging
+void acess__SysDebug(const char *Format, ...)
+{
+ va_list args;
+
+ va_start(args, Format);
+
+ printf("[_SysDebug] ");
+ vprintf(Format, args);
+ printf("\n");
+
+ va_end(args);
+}
+
+void acess__exit(int 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(open),
DEFSYM(close),
DEFSYM(_SysGetACL),
DEFSYM(_SysMount),
- DEFSYM(_SysAllocate),
+ DEFSYM(clone),
+ DEFSYM(execve),
+ DEFSYM(sleep),
+
+ DEFSYM(waittid),
+ DEFSYM(setuid),
+ DEFSYM(setgid),
- {"_SysSetFaultHandler", _SysSetFaultHandler}
+ DEFSYM(_SysAllocate),
+ DEFSYM(_SysDebug),
+ DEFSYM(_SysSetFaultHandler)
};
const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]);
typedef struct sRequestValue {
/// \see eArgumentTypes
uint16_t Type;
- uint8_t Flags;
+ uint16_t Flags;
uint16_t Length;
} tRequestValue;
enum eSyscalls {
SYS_NULL,
+
+ SYS_EXIT,
+
SYS_OPEN,
SYS_CLOSE,
SYS_READ,
SYS_GETACL,
SYS_MOUNT,
SYS_REOPEN,
+
+ SYS_WAITTID,
+ SYS_SETUID,
+ SYS_SETGID,
+
+ // IPC
+ SYS_SLEEP,
+ SYS_FORK,
+
N_SYSCALLS
};
+#ifndef DONT_INCLUDE_SYSCALL_NAMES
+static const char * casSYSCALL_NAMES[] = {
+ "SYS_NULL",
+
+ "SYS_EXIT",
+
+ "SYS_OPEN",
+ "SYS_CLOSE",
+ "SYS_READ",
+ "SYS_WRITE",
+ "SYS_SEEK",
+ "SYS_TELL",
+ "SYS_IOCTL",
+ "SYS_FINFO",
+ "SYS_READDIR",
+ "SYS_OPENCHILD",
+ "SYS_GETACL",
+ "SYS_MOUNT",
+ "SYS_REOPEN",
+
+ // IPC
+ "SYS_SLEEP"
+};
+#endif
+
enum eArgumentTypes {
ARG_TYPE_VOID,
ARG_TYPE_INT32,