\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
all: $(BIN)\r
\r
clean:\r
- $(RM) $(BIN) $(OBJ)\r
+ $(RM) $(BIN) $(OBJ) $(DEPFILES)\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
+\r
+-include $(DEPFILES)\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)
tRequestHeader errorHeader;
int retSize = 0;
int sentSize;
+ int cur_client_id = 0;
#if USE_TCP
#else
while( Client->CurrentRequest == NULL )
SDL_CondWait(Client->WaitFlag, Client->Mutex);
- printf("Worker for %i, Job: %p\n", Client->ClientID, Client->CurrentRequest);
+ if(Client->ClientID != cur_client_id) {
+ Threads_SetThread( Client->ClientID );
+ cur_client_id = Client->ClientID;
+ }
+
+ 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)
);
tRequestHeader *req = (void*)data;
struct sockaddr_in addr;
uint clientSize = sizeof(addr);
- int length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
+ int length;
tClient *client;
+ length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
+
if( length == -1 ) {
perror("SyscallServer - recv");
break;
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)
clean:
- $(RM) $(BIN) $(OBJ)
+ $(RM) $(BIN) $(OBJ) $(DEPFILES)
$(BIN): link.ld.$(PLATFORM) $(OBJ)
# $(LD) -g -o $@ $(OBJ) -T link.ld.$(PLATFORM)
$(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 $(DEPFILES)
#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;
}
}
- // TODO: Search list of loaded binaries
+ // Search list of loaded binaries
for(bin = gLoadedBinaries; bin; bin = bin->Next)
{
if( !bin->Ready ) continue;
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
continue;\r
if( phtab[i].VAddr < base )\r
base = phtab[i].VAddr;\r
- if( phtab[i].VAddr > max )\r
- max = phtab[i].VAddr;\r
+ if( phtab[i].VAddr + phtab[i].MemSize > max )\r
+ max = phtab[i].VAddr + phtab[i].MemSize;\r
}\r
\r
LOG("base = %08x, max = %08x\n", base, max);\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
\r
hdr->entrypoint += iBaseDiff;\r
\r
+ hdr->misc.SymTable = 0;\r
+ hdr->misc.HashTable = 0;\r
+ \r
// === Get Symbol table and String Table ===\r
for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
{\r
break;\r
}\r
}\r
+ \r
+ LOG("hdr->misc.SymTable = %x, hdr->misc.HashTable = %x",\r
+ hdr->misc.SymTable, hdr->misc.HashTable);\r
\r
\r
// Alter Symbols to true base\r
pBuckets = PTR(hdr->misc.HashTable);\r
symtab = PTR(hdr->misc.SymTable);\r
\r
+// LOG("Base = %p : pBuckets = %p, symtab = %p\n", Base, pBuckets, symtab);\r
+ \r
+ if(!pBuckets || !symtab)\r
+ return 0;\r
+ \r
nbuckets = pBuckets[0];\r
iSymCount = pBuckets[1];\r
pBuckets = &pBuckets[2];\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;
}
/*
*/
+#define DEBUG 0
+
+
+#if DEBUG
+# define DEBUG_S printf
+#else
+# define DEBUG_S(...)
+# define DONT_INCLUDE_SYSCALL_NAMES
+#endif
+
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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);
+ DEBUG_S("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);
+ DEBUG_S(" 0x%08x", *(uint32_t*)data);
data += sizeof(uint32_t);
break;
case ARG_TYPE_INT64:
- printf("INT64 %llx", *(uint64_t*)data);
+ DEBUG_S(" 0x%016llx", *(uint64_t*)data);
data += sizeof(uint64_t);
break;
case ARG_TYPE_STRING:
- printf("STRING '%s'", (char*)data);
+ DEBUG_S(" '%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;
+ DEBUG_S(" %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");
}
+ DEBUG_S("\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)
exit(-1);
}
- printf("%i bytes read from socket\n", ret);
+ DEBUG_S("%i bytes read from socket\n", ret);
return ret;
}
#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;
+ DEBUG(": %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)", 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)", 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)", 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)", 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\")", 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)", 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)) {
+ printf("TODO: Set fault handler (asked to set to %p)\n", Handler);
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()");
+
+ newID = _Syscall(SYS_FORK, "<d", sizeof(int), &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 <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);
+}
+
+// --- 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,
CPPFLAGS += -I./include -I./arch/$(ARCHDIR)/include -D_MODULE_NAME_=\"Kernel\"
CPPFLAGS += -DARCH=$(ARCH) -DARCHDIR=$(ARCHDIR) -DKERNEL_VERSION=$(KERNEL_VERSION) -DBUILD_NUM=$(BUILD_NUM)
-CFLAGS += -Wall -Werror -fno-stack-protector -fno-builtin -Wstrict-prototypes -g
-CFLAGS += -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wuninitialized
-ASFLAGS += -D ARCH=\"$(ARCH)\" -D ARCHDIR=\"$(ARCHDIR)\"
+CFLAGS += -Wall -Werror -fno-stack-protector -fno-builtin -Wstrict-prototypes -g
+CFLAGS += -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wuninitialized
LDFLAGS += -T arch/$(ARCHDIR)/link.ld -g
ifeq ($(DEBUG_BUILD),yes)
CFLAGS += -g
endif
+ifeq ($(AS_SUFFIX),)
+ AS_SUFFIX = s
+endif
+
OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
OBJ += heap.o drvutil.o logging.o debug.o lib.o adt.o time.o
OBJ += messages.o modules.o syscalls.o system.o threads.o
OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS)))
-OBJ += drv/kb.o drv/vterm.o drv/proc.o drv/fifo.o drv/iocache.o drv/dma.o drv/pci.o drv/vga.o
+OBJ += drv/vterm.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o drv/vga.o
+#OBJ += drv/kb.o drv/dma.o
OBJ += binary.o bin/elf.o bin/pe.o
-OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o vfs/memfile.o vfs/nodecache.o vfs/handle.o vfs/select.o
+OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o
+OBJ += vfs/memfile.o vfs/nodecache.o vfs/handle.o vfs/select.o
OBJ += vfs/fs/root.o vfs/fs/devfs.o
OBJ += $(addprefix drv/, $(addsuffix .o,$(DRIVERS)))
OBJ := $(addsuffix .$(ARCH), $(OBJ))
DEPFILES := $(DEPFILES:%.o.$(ARCH)=%.d.$(ARCH))
SRCFILES = $(OBJ:%.o.$(ARCH)=%.c)
-SRCFILES := $(SRCFILES:%.ao.$(ARCH)=%.asm)
+SRCFILES := $(SRCFILES:%.ao.$(ARCH)=%.$(AS_SUFFIX))
.PHONY: all clean install apidoc
@$(RM) $(BIN) ../Acess2.$(ARCH).gz $(BIN).dsm ../Map.$(ARCH).txt LineCounts.$(ARCH).txt $(OBJ) $(DEPFILES)
install: $(BIN)
- gzip -c $(BIN) > ../Acess2.$(ARCH).gz
+ cp $(BIN) $(BIN)_
+ $(STRIP) $(BIN)_
+ gzip -c $(BIN)_ > ../Acess2.$(ARCH).gz
+ $(RM) $(BIN)_
$(xCP) ../Acess2.$(ARCH).gz $(DISTROOT)
apidoc:
@wc -l $(SRCFILES) include/*.h > LineCounts.$(ARCH).txt
@echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum.$(ARCH)
$(POSTBUILD)
- @$(STRIP) $(BIN)
+# $(STRIP) $(BIN)
-%.ao.$(ARCH): %.asm Makefile
+%.ao.$(ARCH): %.$(AS_SUFFIX) Makefile
@echo --- AS -o $@
@$(AS) $(ASFLAGS) $< -o $@
# endif
%.xo.$(ARCH):
- @make -C $* all
+ @BUILDTYPE=static make -C $* all
include/syscalls.h include/syscalls.inc.asm: syscalls.lst Makefile GenSyscalls.pl
perl GenSyscalls.pl
-BUILD_NUM = 237
+BUILD_NUM = 238
--- /dev/null
+#
+# Acess2 Kernel
+# arm7 Architecture Makefile
+# arch/arm7/Makefile
+
+CPPFLAGS =
+CFLAGS =
+ASFLAGS =
+
+ifeq ($(ARCH),integrator-cp)
+ MMU_PRESENT=1
+else
+ MMU_PRESENT=1
+endif
+
+
+
+#ASFLAGS += -D USE_MP=$(USE_MP) -D USE_PAE=$(USE_PAE)
+CPPFLAGS += -DMMU_PRESENT=$(MMU_PRESENT)
+
+A_OBJ = start.ao main.o
--- /dev/null
+/*
+ * Acess2
+ * ARM7 Architecture Header
+ */
+#ifndef _ARCH_H_
+#define _ARCH_H_
+
+// === CONSTANTS ===
+#define INVLPTR ((void*)-1)
+#define BITS 32
+
+// === TYPES ===
+typedef unsigned int Uint;
+typedef unsigned char Uint8;
+typedef unsigned short Uint16;
+typedef unsigned long Uint32;
+typedef unsigned long long Uint64;
+typedef signed int Sint;
+typedef signed char Sint8;
+typedef signed short Sint16;
+typedef signed long Sint32;
+typedef signed long long Sint64;
+
+typedef int size_t;
+typedef char BOOL;
+
+typedef Uint32 tVAddr;
+typedef Uint32 tPAddr;
+
+#include <lock.h>
+
+// --- Debug
+extern void Debug_PutCharDebug(char Ch);
+extern void Debug_PutStringDebug(const char *String);
+
+
+#endif
--- /dev/null
+/*
+ * Acess2
+ * ARM7 Architecture
+ *
+ * lock.h - Hardware level spinlocks
+ */
+#ifndef _LOCK_H_
+#define _LOCK_H_
+
+// === CODE ===
+struct sShortSpinlock {
+ int Lock;
+};
+
+// --- Spinlocks ---
+static inline int IS_LOCKED(struct sShortSpinlock *Lock)
+{
+ return !!Lock->Lock;
+}
+
+static inline int CPU_HAS_LOCK(struct sShortSpinlock *Lock)
+{
+ // TODO: Handle multiple CPUs
+ return !!Lock->Lock;
+}
+
+static inline int SHORTLOCK(struct sShortSpinlock *Lock)
+{
+ // Shamelessly copied from linux (/arch/arm/include/asm/spinlock.h) until I can fix stuff
+ Uint tmp;
+ __asm__ __volatile__ (
+ "1: ldrex %0, [%1]\n"
+ " teq %0, #0\n"
+ " strexeq %0, %2, [%1]\n" // Magic? TODO: Look up
+ " teqeq %0, #0\n"
+ " bne 1b"
+ : "=&r" (tmp) // Temp
+ : "r" (&Lock->Lock), "r" (1)
+ : "cc" // Condition codes clobbered
+ );
+ return 1;
+}
+
+static inline void SHORTREL(struct sShortSpinlock *Lock)
+{
+ Lock->Lock = 0;
+}
+
+#endif
+
--- /dev/null
+/*
+ * Acess2
+ * ARM7 Virtual Memory Manager Header
+ */
+#ifndef _MM_VIRT_H_
+#define _MM_VIRT_H_
+
+#define KERNEL_BASE 0x80000000 // 2GiB
+
+// Page Blocks are 12-bits wide (12 address bits used)
+// Hence, the table is 16KiB large (and must be so aligned)
+// and each block addresses 1MiB of data
+
+#define MM_KHEAP_BASE 0x80800000 // 8MiB of kernel code
+#define MM_KHEAP_MAX 0xC0000000 // 1GiB of kernel heap
+
+#define MM_FRACTAL 0xFFE00000 // 2nd last block
+
+#endif
--- /dev/null
+/*
+ * Acess2
+ * ARM7 Architecture
+ *
+ * proc.h - Arch-Dependent Process Management
+ */
+#ifndef _PROC_H_
+#define _PROC_H_
+
+#define MAX_CPUS 4
+
+// === STRUCTURES ===
+typedef struct {
+ Uint32 IP, LR, SP;
+ Uint32 UserIP, UserSP;
+} tTaskState;
+
+typedef struct {
+ Uint32 Base;
+} tMemoryState;
+
+typedef struct {
+ union {
+ Uint32 Num;
+ Uint32 Error;
+ };
+ union {
+ Uint32 Arg1;
+ Uint32 Return;
+ };
+ union {
+ Uint32 Arg2;
+ Uint32 RetHi;
+ };
+ Uint32 Arg3;
+ Uint32 Arg4;
+ Uint32 Arg5;
+ Uint32 Arg6; // R6
+ Uint32 Unused[13-6];
+ Uint32 StackPointer; // R13
+ Uint32 _lr;
+ Uint32 _ip;
+} tSyscallRegs;
+
+// === MACROS ===
+#define HALT() __asm__ __volatile__ ("nop")
+
+// === PROTOTYPES ===
+extern void Proc_Start(void);
+extern tTID Proc_Clone(Uint *Errno, int Flags);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 ARM7 Port
+ *
+ * lib.c - Library Functions
+ */
+#include <acess.h>
+
+// === CODE ===
--- /dev/null
+/*
+ * Acess2
+ *
+ * ARM7 Entrypoint
+ * arch/arm7/main.c
+ */
+
+// === IMPORTS ===
+extern void Interrupts_Setup(void);
+extern void MM_SetupPhys(void);
+
+// === PROTOTYPES ===
+ int kmain(void);
+
+// === CODE ===
+int kmain(void)
+{
+ Interrupts_Setup();
+
+ MM_SetupPhys();
+
+ //TODO:
+ for(;;);
+}
--- /dev/null
+interrupt_vector_table:
+ b . @ Reset
+ b .
+ b . @ SWI instruction
+ b .
+ b .
+ b .
+ b .
+ b .
+
+.comm stack, 0x10000 @ ; 64KiB Stack
+
+.globl _start
+_start:
+ ldr sp, =stack+0x10000 @ Set up stack
+ bl main
+1: b 1b @ Infinite loop
+
# i386 Architecture Makefile
# arch/i386/Makefile
-# Assuming build machine is 32-bit ELF
-#CC = gcc
-#AS = nasm
-#LD = ld
-#OBJDUMP = objdump
+AS_SUFFIX = asm
CPPFLAGS =
CFLAGS =
USE_PAE=1
endif
+#ASFLAGS += -D ARCH=\"$(ARCH)\" -D ARCHDIR=\"$(ARCHDIR)\"
ASFLAGS += -D USE_MP=$(USE_MP) -D USE_PAE=$(USE_PAE)
CPPFLAGS += -DUSE_MP=$(USE_MP) -DUSE_PAE=$(USE_PAE)
[extern SchedulerBase]
; AP's Timer Interrupt
Isr0xEE:
- push 0
+ push 0 ; Line up with interrupt number
xchg bx, bx ; MAGIC BREAK
jmp SchedulerBase
; Spurious Interrupt
[extern SchedulerBase]
[extern SetAPICTimerCount]
Isr240:
- push 0
+ push 0 ; Line up with Argument in errors
+ push 0 ; CPU Number
;xchg bx, bx ; MAGIC BREAK
Isr240.jmp:
%if USE_MP
call SyscallHandler
add esp, 4
+ ; Pass changes to TF on to the user
+ ; EFLAGS is stored at ESP[4+8+2+2]
+ ; 4 Segment Registers
+ ; 8 GPRs
+ ; 2 Error Code / Interrupt ID
+ ; 2 CS/EIP
+ pushf
+ pop eax
+ and eax, 0x100 ; 0x100 = Trace Flag
+ and WORD [esp+(4+8+2+2)*4], ~0x100 ; Clear
+ or DWORD [esp+(4+8+2+2)*4], eax ; Set for user
+
pop gs
pop fs
pop es
; ------------
[extern IRQ_Handler]
[global IRQCommon]
+[global IRQCommon_handled]
+IRQCommon_handled equ IRQCommon.handled
IRQCommon:
pusha
push ds
push esp
call IRQ_Handler
+.handled:
add esp, 4
pop gs
__asm__ __volatile__ ("cli");
+ // Debug exception (used for single-stepping)
+ if(Regs->int_num == 1)
+ {
+ static Uint32 lastEIP = 0;
+ tThread *thread = Proc_GetCurThread();
+ if( Regs->eip == lastEIP )
+ return;
+ Log("%p(%i %s) IP=%08x", thread, thread->TID, thread->ThreadName, Regs->eip);
+ lastEIP = Regs->eip;
+ return ;
+ }
+
// Page Fault
if(Regs->int_num == 14)
{
typedef struct {
Uint EIP, ESP, EBP;
+ Uint32 UserCS, UserEIP;
} tTaskState;
// === FUNCTIONS ===
+extern void Debug_PutCharDebug(char ch);
+extern void Debug_PutStringDebug(const char *String);
+
extern int IS_LOCKED(struct sShortSpinlock *Lock);
extern int CPU_HAS_LOCK(struct sShortSpinlock *Lock);
extern void SHORTLOCK(struct sShortSpinlock *Lock);
#ifndef _PROC_H
#define _PROC_H
-#include <threads.h>
+#include <threads_int.h>
// === TYPES ==
typedef struct sTSS {
* lib.c
*/
#include <acess.h>
-#include <threads.h>
+#include <threads_int.h>
#define TRACE_LOCKS 0
+#define DEBUG_TO_E9 1
+#define DEBUG_TO_SERIAL 1
+#define SERIAL_PORT 0x3F8
+#define GDB_SERIAL_PORT 0x2F8
+
+// === IMPRORTS ===
#if TRACE_LOCKS
extern struct sShortSpinlock glDebug_Lock;
#endif
-
-// === IMPRORTS ===
extern int GetCPUNum(void);
// === PROTOTYPES ==
Uint64 __udivdi3(Uint64 Num, Uint64 Den);
Uint64 __umoddi3(Uint64 Num, Uint64 Den);
+// === GLOBALS ===
+ int gbDebug_SerialSetup = 0;
+ int gbGDB_SerialSetup = 0;
+
// === CODE ===
/**
* \brief Determine if a short spinlock is locked
#endif
}
+// === DEBUG IO ===
+#if USE_GDB_STUB
+int putDebugChar(char ch)
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1)
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(GDB_SERIAL_PORT, ch);
+ return 0;
+}
+int getDebugChar(void)
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ;
+ return inb(GDB_SERIAL_PORT);
+}
+#endif /* USE_GDB_STUB */
+
+void Debug_PutCharDebug(char ch)
+{
+ #if DEBUG_TO_E9
+ __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
+ #endif
+
+ #if DEBUG_TO_SERIAL
+ if(!gbDebug_SerialSetup) {
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(SERIAL_PORT, ch);
+ #endif
+}
+
+void Debug_PutStringDebug(const char *String)
+{
+ while(*String)
+ Debug_PutCharDebug(*String++);
+}
+
// === IO Commands ===
void outb(Uint16 Port, Uint8 Data)
{
push fs
push gs
+ pushf
+ and BYTE [esp+1], 0xFE ; Clear Trap Flag
+ popf
+
mov eax, dr0
push eax ; Debug Register 0, Current Thread
pop ds
popa
- add esp, 4 ; CPU ID
+ add esp, 4*2 ; CPU ID + Dummy error code
; No Error code / int num
iret
; In child, so now set up stack frame
mov ebx, [esp+4] ; Child Function
mov edx, [esp+8] ; Argument
- ; Child
+ ; Child Function
push edx ; Argument
call ebx ; Function
+ ; Kill thread once done
push eax ; Exit Code
push 0 ; Kill this thread
call Threads_Exit ; Kill Thread
.justKillIt:
xor eax, eax
xor ebx, ebx
- dec ebx
+ dec ebx ; EBX = -1
int 0xAC
[global GetCPUNum]
mov eax, dr1
ret
+[extern GetEIP]
+[global GetEIP_Sched]
+[global GetEIP_Sched_ret]
+GetEIP_Sched_ret equ GetEIP_Sched.ret
+GetEIP_Sched:
+ call GetEIP
+GetEIP_Sched.ret:
+ ret
+
; Usermode code exported by the kernel
[section .usertext]
; Export a place for the user to jump to to call a syscall
#endif
// === FLAGS ===
-#define DEBUG_TRACE_SWITCH 0
+#define DEBUG_TRACE_SWITCH 1
#define DEBUG_DISABLE_DOUBLEFAULT 1
// === CONSTANTS ===
extern void APWait(void); // 16-bit AP pause code
extern void APStartup(void); // 16-bit AP startup code
extern Uint GetEIP(void); // start.asm
+extern Uint GetEIP_Sched(void); // proc.asm
extern int GetCPUNum(void); // start.asm
extern Uint32 gaInitPageDir[1024]; // start.asm
extern char Kernel_Stack_Top[];
extern void Proc_ReturnToUser(tVAddr Handler, Uint Argument, tVAddr KernelStack);
extern void scheduler_return; // Return address in SchedulerBase
extern void IRQCommon; // Common IRQ handler code
+extern void IRQCommon_handled; // IRQCommon call return location
+extern void GetEIP_Sched_ret; // GetEIP call return location
// === PROTOTYPES ===
void ArchThreads_Init(void);
#else
giNumCPUs = 1;
gTSSs = &gTSS0;
- MM_FinishVirtualInit();
#endif
#if !DEBUG_DISABLE_DOUBLEFAULT
newThread->SavedState.EBP = ebp;
eip = GetEIP();
if(eip == SWITCH_MAGIC) {
- __asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) );
+ //__asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) );
#if USE_MP
// ACK the interrupt
if( GetCPUNum() )
new->SavedState.EBP = ebp;
eip = GetEIP();
if(eip == SWITCH_MAGIC) {
- __asm__ __volatile__ ("mov %0, %%db0" : : "r"(new));
+ //__asm__ __volatile__ ("mov %0, %%db0" : : "r"(new));
#if USE_MP
// ACK the interrupt
if(GetCPUNum())
void Proc_DumpThreadCPUState(tThread *Thread)
{
- Uint32 *stack = (void *)Thread->SavedState.EBP; // EBP = ESP after call and PUSH
-
if( Thread->CurCPU > -1 )
{
- Log(" Currently running");
+ int maxBacktraceDistance = 6;
+ tRegs *regs = NULL;
+ Uint32 *stack;
+
+ if( Thread->CurCPU != GetCPUNum() ) {
+ Log(" Currently running");
+ return ;
+ }
+
+ // Backtrace to find the IRQ entrypoint
+ // - This will usually only be called by an IRQ, so this should
+ // work
+ __asm__ __volatile__ ("mov %%ebp, %0" : "=r" (stack));
+ while( maxBacktraceDistance -- )
+ {
+ // [ebp] = oldEbp
+ // [ebp+4] = retaddr
+
+ if( stack[1] == (tVAddr)&IRQCommon_handled ) {
+ regs = (void*)stack[2];
+ break;
+ }
+
+ stack = (void*)stack[0];
+ }
+
+ if( !regs ) {
+ Log(" Unable to find IRQ Entry");
+ return ;
+ }
+
+ Log(" at %04x:%08x", regs->cs, regs->eip);
return ;
}
if( diffFromClone > 0 && diffFromClone < 512 ) // When I last checked, GetEIP was at .+0x183
{
- // Just spawned full thread
Log(" Creating full thread");
return ;
}
if( diffFromSpawn > 0 && diffFromSpawn < 512 ) // When I last checked, GetEIP was at .+0x99
{
- // Just spawned worker thread
Log(" Creating worker thread");
return ;
}
if( diffFromScheduler > 0 && diffFromScheduler < 256 ) // When I last checked, GetEIP was at .+0x60
#else
- if( stack[1] == (Uint32)&IRQCommon + 25 )
+ Uint32 data[3];
+ MM_ReadFromAddrSpace(Thread->MemState.CR3, Thread->SavedState.EBP, data, 12);
+ if( data[1] == (Uint32)&IRQCommon + 25 )
{
- tRegs *regs = (void *) stack[2];
+ tRegs *regs = (void *) data[2];
Log(" oldebp = 0x%08x, ret = 0x%08x, regs = 0x%x",
- stack[0], stack[1], stack[2]
+ data[0], data[1], data[2]
);
// [EBP] = old EBP
// [EBP+0x04] = Return Addr
#endif
{
// Scheduled out
- tRegs *regs = (void *) &stack[4];
- Log(" oldebp = 0x%08x, ret = 0x%08x, cpu = %i, thread = 0x%x",
- stack[0], stack[1], stack[2], stack[3]);
- // [EBP] = old EBP
- // [EBP+0x04] = Return Addr
- // [EBP+0x08] = Arg 1 (CPU Number)
- // [EBP+0x0C] = Arg 2 (Thread)
- // [EBP+0x10] = GS (start of tRegs)
- Log(" At %02x:%08x", regs->cs, regs->eip);
+ Log(" At %04x:%08x", Thread->SavedState.UserCS, Thread->SavedState.UserEIP);
return ;
}
- Log(" Just created");
+ Log(" Just created (unknow %p)", Thread->SavedState.EIP);
}
/**
thread = gCurrentThread;
#endif
+ // NOTE:
+ // 2011-04-05
+ // Bug may be caused by DR0 not being maintained somewhere, hence
+ // login is getting loaded with the idle state.
if( thread )
{
+ tRegs *regs;
// Reduce remaining quantum and continue timeslice if non-zero
if( thread->Remaining-- )
return;
thread->SavedState.ESP = esp;
thread->SavedState.EBP = ebp;
thread->SavedState.EIP = eip;
+
+ // TODO: Make this more stable somehow
+ regs = (tRegs*)(ebp+(2+2)*4); // EBP,Ret + CPU,CurThread
+ thread->SavedState.UserCS = regs->cs;
+ thread->SavedState.UserEIP = regs->eip;
+
+ if(thread->bInstrTrace) {
+ regs->eflags |= 0x100; // Set TF
+ Log("%p De-scheduled", thread);
+ }
+ else
+ regs->eflags &= ~0x100; // Clear TF
}
// Get next thread to run
thread = Threads_GetNextToRun(CPU, thread);
+
+ #if DEBUG_TRACE_SWITCH
+ if(thread) {
+ Log("Switching to task %i, CR3 = 0x%x, EIP = %p",
+ thread->TID,
+ thread->MemState.CR3,
+ thread->SavedState.EIP
+ );
+ }
+ #endif
+
// No avaliable tasks, just go into low power mode (idle thread)
if(thread == NULL) {
#if USE_MP
gCurrentThread = thread;
#endif
- #if DEBUG_TRACE_SWITCH
- Log("Switching to task %i, CR3 = 0x%x, EIP = %p",
- thread->TID,
- thread->MemState.CR3,
- thread->SavedState.EIP
- );
- #endif
-
#if USE_MP // MP Debug
// Log("CPU = %i, Thread %p", CPU, thread);
#endif
}
#endif
+ if( thread->bInstrTrace ) {
+ Log("%p Scheduled", thread);
+ }
+
#if USE_PAE
# error "Todo: Implement PAE Address space switching"
#else
+ // Set thread pointer
+ __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(thread) );
// Switch threads
__asm__ __volatile__ (
"mov %4, %%cr3\n\t" // Set address space
"mov %1, %%esp\n\t" // Restore ESP
"mov %2, %%ebp\n\t" // and EBP
+ "or %5, 72(%%ebp)\n\t" // or trace flag to eflags (2+2+4+8+2)*4
"jmp *%3" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler)
"a"(SWITCH_MAGIC), "b"(thread->SavedState.ESP),
"d"(thread->SavedState.EBP), "c"(thread->SavedState.EIP),
- "r"(thread->MemState.CR3)
+ "r"(thread->MemState.CR3),
+ "r"(thread->bInstrTrace&&thread->SavedState.EIP==(Uint)&GetEIP_Sched_ret?0x100:0)
);
#endif
for(;;); // Shouldn't reach here
jmp .hlt
;
-; Multiprocessing AP Startup Code (Must be within 0x10FFF0)
+; Multiprocessing AP Startup Code (Must be within 0 - 0x10FFF0)
;
%if USE_MP
[extern gGDT]
[global APStartup]
APStartup:
;xchg bx, bx ; MAGIC BREAK!
+ ; Load initial GDT
mov ax, 0xFFFF
mov ds, ax
lgdt [DWORD ds:lGDTPtr-KERNEL_BASE-0xFFFF0]
+ ; Enable PMode in CR0
mov eax, cr0
or al, 1
mov cr0, eax
+ ; Jump into PMode
jmp 08h:DWORD .ProtectedMode-KERNEL_BASE
[bits 32]
.ProtectedMode:
[section .initpd]
[global gaInitPageDir]
[global gaInitPageTable]
-align 0x1000
+align 4096
gaInitPageDir:
dd gaInitPageTable-KERNEL_BASE+3 ; 0x000 - Low kernel
times 0x300-0x000-1 dd 0
times 0x3F0-0x300-1 dd 0
dd gaInitPageDir-KERNEL_BASE+3 ; 0xFC0 - Fractal
times 0x400-0x3F0-1 dd 0
-align 0x1000
+align 4096
gaInitPageTable:
%assign i 0
%rep 1024
%assign i i+1
%endrep
[global Kernel_Stack_Top]
-ALIGN 0x1000
+ALIGN 4096
times 1024 dd 0
Kernel_Stack_Top:
gInitAPStacks:
MAX_CPUS := 4
+AS_SUFFIX = asm
+
CPPFLAGS := -DMAX_CPUS=$(MAX_CPUS) -D USE_MP=0
CFLAGS := $(KERNEL_CFLAGS) -mno-sse -mno-mmx
ASFLAGS := -f elf64 -D MAX_CPUS=$(MAX_CPUS) -D USE_MP=0
extern void SHORTLOCK(struct sShortSpinlock *Lock);
extern void SHORTREL(struct sShortSpinlock *Lock);
+extern void Debug_PutCharDebug(char ch);
+extern void Debug_PutStringDebug(const char *Str);
+
#endif
#include <acess.h>
#include <arch.h>
+#define DEBUG_TO_E9 1
+#define DEBUG_TO_SERIAL 1
+#define SERIAL_PORT 0x3F8
+#define GDB_SERIAL_PORT 0x2F8
+
+
// === IMPORTS ===
extern int GetCPUNum(void);
extern void *Proc_GetCurThread(void);
+// === GLOBALS ===
+ int gbDebug_SerialSetup = 0;
+ int gbGDB_SerialSetup = 0;
+
+// === PROTOTYPEs ===
+ int putDebugChar(char ch);
+
// === CODE ===
/**
* \brief Determine if a short spinlock is locked
#endif
}
+// === DEBUG IO ===
+#if USE_GDB_STUB
+int putDebugChar(char ch)
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1)
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(GDB_SERIAL_PORT, ch);
+ return 0;
+}
+int getDebugChar(void)
+{
+ if(!gbGDB_SerialSetup) {
+ outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ;
+ return inb(GDB_SERIAL_PORT);
+}
+#endif
+
+void Debug_PutCharDebug(char ch)
+{
+ #if DEBUG_TO_E9
+ __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
+ #endif
+
+ #if DEBUG_TO_SERIAL
+ if(!gbDebug_SerialSetup) {
+ outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
+ outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
+ outb(SERIAL_PORT + 1, 0x00); // (hi byte)
+ outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
+ outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ gbDebug_SerialSetup = 1;
+ }
+ while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
+ outb(SERIAL_PORT, ch);
+ #endif
+}
+
+void Debug_PutStringDebug(const char *String)
+{
+ while(*String)
+ Debug_PutCharDebug(*String++);
+}
+
+// === PORT IO ===
void outb(Uint16 Port, Uint8 Data)
{
__asm__ __volatile__ ("outb %%al, %%dx"::"d"(Port),"a"(Data));
// === GLOBALS ===
tMutex glPhysicalPages;
-Uint64 *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB Per Word
+Uint64 *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB per Word
Uint64 *gaMainBitmap = (void*)MM_PAGE_BITMAP; // 1 bit = 1 Page, 256 KiB per Word
Uint64 *gaMultiBitmap = (void*)MM_PAGE_DBLBMP; // Each bit means that the page is being used multiple times
Uint32 *gaiPageReferences = (void*)MM_PAGE_COUNTS; // Reference Counts
#include <acess.h>
#include <proc.h>
#include <threads.h>
+#include <threads_int.h>
#include <desctab.h>
#include <mm_virt.h>
#include <errno.h>
void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP);
int Proc_Demote(Uint *Err, int Dest, tRegs *Regs);
void Proc_CallFaultHandler(tThread *Thread);
+void Proc_DumpThreadCPUState(tThread *Thread);
void Proc_Scheduler(int CPU);
// === GLOBALS ===
for(;;);
}
+void Proc_DumpThreadCPUState(tThread *Thread)
+{
+}
+
/**
* \fn void Proc_Scheduler(int CPU)
* \brief Swap current thread and clears dead threads
#include <acess.h>
#include <stdarg.h>
-#define DEBUG_TO_E9 1
-#define DEBUG_TO_SERIAL 1
-#define SERIAL_PORT 0x3F8
-#define GDB_SERIAL_PORT 0x2F8
#define DEBUG_MAX_LINE_LEN 256
#define LOCK_DEBUG_OUTPUT 1
extern void KernelPanic_PutChar(char Ch);
// === PROTOTYPES ===
- int putDebugChar(char ch);
- int getDebugChar(void);
static void Debug_Putchar(char ch);
static void Debug_Puts(int DbgOnly, const char *Str);
void Debug_DbgOnlyFmt(const char *format, va_list args);
// === GLOBALS ===
int gDebug_Level = 0;
int giDebug_KTerm = -1;
- int gbDebug_SerialSetup = 0;
- int gbGDB_SerialSetup = 0;
int gbDebug_IsKPanic = 0;
volatile int gbInPutChar = 0;
#if LOCK_DEBUG_OUTPUT
#endif
// === CODE ===
-int putDebugChar(char ch)
-{
- if(!gbGDB_SerialSetup) {
- outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
- outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
- outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
- outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte)
- outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1)
- outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
- outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
- gbDebug_SerialSetup = 1;
- }
- while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 );
- outb(GDB_SERIAL_PORT, ch);
- return 0;
-}
-int getDebugChar(void)
-{
- if(!gbGDB_SerialSetup) {
- outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts
- outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
- outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
- outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte)
- outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
- outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
- outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
- gbDebug_SerialSetup = 1;
- }
- while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ;
- return inb(GDB_SERIAL_PORT);
-}
-
-static void Debug_PutCharDebug(char ch)
-{
- #if DEBUG_TO_E9
- __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) );
- #endif
-
- #if DEBUG_TO_SERIAL
- if(!gbDebug_SerialSetup) {
- outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts
- outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
- outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud
- outb(SERIAL_PORT + 1, 0x00); // (hi byte)
- outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
- outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it
- outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
- gbDebug_SerialSetup = 1;
- }
- while( (inb(SERIAL_PORT + 5) & 0x20) == 0 );
- outb(SERIAL_PORT, ch);
- #endif
-}
-
static void Debug_Putchar(char ch)
{
Debug_PutCharDebug(ch);
static void Debug_Puts(int UseKTerm, const char *Str)
{
int len = 0;
- while( *Str )
- {
- Debug_PutCharDebug( *Str );
-
- if( gbDebug_IsKPanic )
- KernelPanic_PutChar(*Str);
- len ++;
- Str ++;
- }
- Str -= len;
+ Debug_PutStringDebug(Str);
+
+ if( gbDebug_IsKPanic )
+ {
+ for( len = 0; Str[len]; len ++ )
+ KernelPanic_PutChar( Str[len] );
+ }
+ else
+ for( len = 0; Str[len]; len ++ );
+ // Output to the kernel terminal
if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
{
if(gbInPutChar) return ;
}
/**
* \fn void Debug(const char *Msg, ...)
- * \brief Print only to the debug channel
+ * \brief Print only to the debug channel (not KTerm)
*/
void Debug(const char *Fmt, ...)
{
Threads_Dump();
- __asm__ __volatile__ ("xchg %bx, %bx");
- __asm__ __volatile__ ("cli;\n\thlt");
- for(;;) __asm__ __volatile__ ("hlt");
+// __asm__ __volatile__ ("xchg %bx, %bx");
+// __asm__ __volatile__ ("cli;\n\thlt");
+// for(;;) __asm__ __volatile__ ("hlt");
+ for(;;) ;
}
void Debug_SetKTerminal(const char *File)
+++ /dev/null
-/*\r
- * AcessOS 1.0\r
- * DMA Driver\r
- */\r
-#include <acess.h>\r
-#include <modules.h>\r
-\r
-#define DMA_SIZE (0x2400)\r
-#define DMA_ADDRESS(c) ((c)*DMA_SIZE+0x500) //Save Space for IDT and BDA\r
-\r
-#define LOWB(x) ((x)&0xFF)\r
-#define HIB(x) (((x)>>8)&0xFF)\r
-#define HIW(x) (((x)>>16)&0xFFFF)\r
-\r
-// === TYPES ===\r
-typedef struct\r
-{\r
- int mode;\r
- char *address;\r
-} t_dmaChannel;\r
-\r
-// === PROTOTYPES ===\r
- int DMA_Install(char **Arguments);\r
-void DMA_SetChannel(int Channel, int length, int read);\r
- int DMA_ReadData(int channel, int count, void *buffer);\r
- int DMA_WriteData(int channel, int count, const void *buffer);\r
-\r
-// === CONSTANTS ===\r
-const Uint8 cMASKPORT [8] = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };\r
-const Uint8 cMODEPORT [8] = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };\r
-const Uint8 cCLEARPORT[8] = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };\r
-const Uint8 cPAGEPORT [8] = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };\r
-const Uint8 cADDRPORT [8] = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };\r
-const Uint8 cCOUNTPORT[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };\r
-\r
-// === GLOBALS ===\r
-MODULE_DEFINE(0, 0x0100, ISADMA, DMA_Install, NULL, NULL);\r
-char *dma_addresses[8];\r
-t_dmaChannel dma_channels[8];\r
-\r
-// === CODE ===\r
-/**\r
- * \brief Initialise DMA channels\r
- * \param Arguments Arguments passed at boot time\r
- */\r
-int DMA_Install(char **Arguments)\r
-{\r
- Uint i;\r
- for(i=8;i--;)\r
- {\r
- outb( cMASKPORT[i], 0x04 | (i & 0x3) ); // mask channel\r
- outb( cCLEARPORT[i], 0x00 );\r
- outb( cMODEPORT[i], 0x48 | (i & 0x3) ); //Read Flag\r
- outb( 0xd8, 0xff); //Reset Flip-Flop\r
- outb( cADDRPORT[i], LOWB(DMA_ADDRESS(i)) ); // send address\r
- outb( cADDRPORT[i], HIB(DMA_ADDRESS(i)) ); // send address\r
- outb( 0xd8, 0xff); //Reset Flip-Flop\r
- outb( cCOUNTPORT[i], LOWB(DMA_SIZE) ); // send size\r
- outb( cCOUNTPORT[i], HIB(DMA_SIZE) ); // send size\r
- outb( cPAGEPORT[i], LOWB(HIW(DMA_ADDRESS(i))) ); // send page\r
- outb( cMASKPORT[i], i & 0x3 ); // unmask channel\r
- \r
- dma_channels[i].mode = 0;\r
- dma_addresses[i] = (char*)DMA_ADDRESS(i);\r
- dma_addresses[i] += KERNEL_BASE;\r
- }\r
- return MODULE_ERR_OK;\r
-}\r
-\r
-/**\r
- * \fn void DMA_SetChannel(int Channel, int length, int read)\r
- * \brief Set DMA Channel Length and RW\r
- */\r
-void DMA_SetChannel(int Channel, int length, int read)\r
-{\r
- Uint chan = Channel & 7;\r
- read = !!read;\r
- if(length > DMA_SIZE) length = DMA_SIZE;\r
- length --; //Adjust for DMA\r
- //__asm__ __volatile__ ("cli");\r
- outb( cMASKPORT[chan], 0x04 | (chan & 0x3) ); // mask channel\r
- outb( cCLEARPORT[chan], 0x00 );\r
- outb( cMODEPORT[chan], (0x44 + (!read)*4) | (chan & 0x3) );\r
- outb( cADDRPORT[chan], LOWB(DMA_ADDRESS(chan)) ); // send address\r
- outb( cADDRPORT[chan], HIB(DMA_ADDRESS(chan)) ); // send address\r
- outb( cPAGEPORT[chan], HIW(DMA_ADDRESS(chan)) ); // send page\r
- outb( cCOUNTPORT[chan], LOWB(length) ); // send size\r
- outb( cCOUNTPORT[chan], HIB(length) ); // send size\r
- outb( cMASKPORT[chan], chan & 0x3 ); // unmask channel\r
- dma_addresses[chan] = (char*)DMA_ADDRESS(chan);\r
- dma_addresses[chan] += KERNEL_BASE;\r
- //__asm__ __volatile__ ("sti");\r
-}\r
-\r
-/**\r
- * \fn void DMA_ReadData(int channel, int count, void *buffer)\r
- * \brief Read data from a DMA buffer\r
- */\r
-int DMA_ReadData(int channel, int count, void *buffer)\r
-{\r
- if(channel < 0 || channel > 7)\r
- return -1;\r
- if(count < 0 || count > DMA_SIZE)\r
- return -2;\r
- //LogF("memcpy(*0x%x, dma_channels[channel].address, count)\n", buffer\r
- memcpy(buffer, dma_addresses[channel], count);\r
- return 0;\r
-}\r
-\r
-/**\r
- * \fn void DMA_WriteData(int channel, int count, void *buffer)\r
- * \brief Write data to a DMA buffer\r
- */\r
-int DMA_WriteData(int channel, int count, const void *buffer)\r
-{\r
- if(channel < 0 || channel > 7)\r
- return -1;\r
- if(count < 0 || count > DMA_SIZE)\r
- return -2;\r
- \r
- memcpy(dma_addresses[channel], buffer, count);\r
- \r
- return 0;\r
-}\r
+++ /dev/null
-/*
- * Acess2
- * PS2 Keyboard Driver
- */
-#include <acess.h>
-#include <modules.h>
-#include <fs_devfs.h>
-#include <tpl_drv_common.h>
-#include <tpl_drv_keyboard.h>
-#include "kb_kbdus.h"
-
-// === CONSTANTS ===
-#define KB_BUFFER_SIZE 1024
-#define USE_KERNEL_MAGIC 1
-
-// === IMPORTS ===
-void Threads_Dump(void);
-void Heap_Stats(void);
-
-// === PROTOTYPES ===
- int KB_Install(char **Arguments);
-void KB_IRQHandler(int IRQNum);
-void KB_AddBuffer(char ch);
-Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
-void KB_UpdateLEDs(void);
- int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
-
-// === GLOBALS ===
-MODULE_DEFINE(0, 0x0100, PS2Keyboard, KB_Install, NULL, NULL);
-tDevFS_Driver gKB_DevInfo = {
- NULL, "PS2Keyboard",
- {
- .NumACLs = 0,
- .Size = 0,
- //.Read = KB_Read,
- .IOCtl = KB_IOCtl
- }
-};
-tKeybardCallback gKB_Callback = NULL;
-Uint32 **gpKB_Map = gpKBDUS;
-Uint8 gbaKB_States[3][256];
- int gbKB_ShiftState = 0;
- int gbKB_CapsState = 0;
- int gbKB_KeyUp = 0;
- int giKB_KeyLayer = 0;
-#if USE_KERNEL_MAGIC
- int gbKB_MagicState = 0;
- int giKB_MagicAddress = 0;
- int giKB_MagicAddressPos = 0;
-#endif
-//Uint64 giKB_ReadBase = 0;
-//Uint32 gaKB_Buffer[KB_BUFFER_SIZE]; //!< Keyboard Ring Buffer
-//volatile int giKB_InsertPoint = 0; //!< Writing location marker
-//volatile int giKB_ReadPoint = 0; //!< Reading location marker
-//volatile int giKB_InUse = 0; //!< Lock marker
-
-// === CODE ===
-/**
- * \brief Install the keyboard driver
- */
-int KB_Install(char **Arguments)
-{
- Uint8 temp;
-
- // Attempt to get around a strange bug in Bochs/Qemu by toggling
- // the controller on and off
- temp = inb(0x61);
- outb(0x61, temp | 0x80);
- outb(0x61, temp & 0x7F);
- inb(0x60); // Clear keyboard buffer
-
- IRQ_AddHandler(1, KB_IRQHandler);
- DevFS_AddDevice( &gKB_DevInfo );
- //Log("KB_Install: Installed");
- return MODULE_ERR_OK;
-}
-
-/**
- * \brief Called on a keyboard IRQ
- * \param IRQNum IRQ number (unused)
- */
-void KB_IRQHandler(int IRQNum)
-{
- Uint8 scancode;
- Uint32 ch;
- // int keyNum;
-
- // Check port 0x64 to tell if this is from the aux port
- //if( inb(0x64) & 0x20 ) return;
-
- scancode = inb(0x60); // Read from the keyboard's data buffer
- //Log_Debug("Keyboard", "scancode = %02x", scancode);
-
- // Ignore ACKs
- if(scancode == 0xFA) {
- // Oh man! This is anarchic (I'm leaving it here to represent
- // the mess that Acess once was)
- //kb_lastChar = KB_ACK;
- return;
- }
-
- // Layer +1
- if(scancode == 0xE0) {
- giKB_KeyLayer = 1;
- return;
- }
- // Layer +2
- if(scancode == 0xE1) {
- giKB_KeyLayer = 2;
- return;
- }
-
- #if KB_ALT_SCANCODES
- if(scancode == 0xF0)
- {
- gbKB_KeyUp = 1;
- return;
- }
- #else
- if(scancode & 0x80)
- {
- scancode &= 0x7F;
- gbKB_KeyUp = 1;
- }
- #endif
-
- // Translate
- ch = gpKB_Map[giKB_KeyLayer][scancode];
- //keyNum = giKB_KeyLayer * 256 + scancode;
- // Check for unknown key
- if(!ch && !gbKB_KeyUp)
- Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
-
- // Key Up?
- if (gbKB_KeyUp)
- {
- gbKB_KeyUp = 0;
- gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
-
- #if USE_KERNEL_MAGIC
- if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
- if(ch == KEY_LALT) gbKB_MagicState &= ~2;
- #endif
-
- if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
- if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
-
- // Call callback
- if(ch != 0 && gKB_Callback)
- gKB_Callback( ch & 0x80000000 );
-
- // Reset Layer
- giKB_KeyLayer = 0;
- return;
- }
-
- // Set the bit relating to the key
- gbaKB_States[giKB_KeyLayer][scancode] = 1;
- // Set shift key bits
- if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
- if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
-
- // Check for Caps Lock
- if(ch == KEY_CAPSLOCK) {
- gbKB_CapsState = !gbKB_CapsState;
- KB_UpdateLEDs();
- }
-
- // Reset Layer
- giKB_KeyLayer = 0;
-
- // Ignore Non-Printable Characters
- if(ch == 0) return;
-
- // --- Check for Kernel Magic Combos
- #if USE_KERNEL_MAGIC
- if(ch == KEY_LCTRL) {
- gbKB_MagicState |= 1;
- //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
- }
- if(ch == KEY_LALT) {
- gbKB_MagicState |= 2;
- //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
- }
- if(gbKB_MagicState == 3)
- {
- switch(ch)
- {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9': case 'a': case 'b':
- case 'c': case 'd': case 'e': case 'f':
- {
- char str[2] = {ch,0};
- if(giKB_MagicAddressPos == BITS/4) break;
- giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
- giKB_MagicAddressPos ++;
- }
- break;
-
- // Thread List Dump
- case 'p': Threads_Dump(); return;
- // Heap Statistics
- case 'h': Heap_Stats(); return;
- // Dump Structure
- case 's': return;
- }
- }
- #endif
-
- // Is shift pressed
- // - Darn ugly hacks !!x means (bool)x
- if( !!gbKB_ShiftState ^ gbKB_CapsState)
- {
- switch(ch)
- {
- case 0: break;
- case '`': ch = '~'; break;
- case '1': ch = '!'; break;
- case '2': ch = '@'; break;
- case '3': ch = '#'; break;
- case '4': ch = '$'; break;
- case '5': ch = '%'; break;
- case '6': ch = '^'; break;
- case '7': ch = '&'; break;
- case '8': ch = '*'; break;
- case '9': ch = '('; break;
- case '0': ch = ')'; break;
- case '-': ch = '_'; break;
- case '=': ch = '+'; break;
- case '[': ch = '{'; break;
- case ']': ch = '}'; break;
- case '\\': ch = '|'; break;
- case ';': ch = ':'; break;
- case '\'': ch = '"'; break;
- case ',': ch = '<'; break;
- case '.': ch = '>'; break;
- case '/': ch = '?'; break;
- default:
- if('a' <= ch && ch <= 'z')
- ch -= 0x20;
- break;
- }
- }
-
- if(gKB_Callback && ch != 0) gKB_Callback(ch);
-}
-
-/**
- * \fn void KB_UpdateLEDs(void)
- * \brief Updates the status of the keyboard LEDs
- */
-void KB_UpdateLEDs(void)
-{
- Uint8 leds;
-
- leds = (gbKB_CapsState ? 4 : 0);
-
- while( inb(0x64) & 2 ); // Wait for bit 2 to unset
- outb(0x60, 0xED); // Send update command
-
- while( inb(0x64) & 2 ); // Wait for bit 2 to unset
- outb(0x60, leds);
-}
-
-/**
- * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
- * \brief Calls an IOCtl Command
- */
-int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
-{
- switch(Id)
- {
- case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
- case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
- case DRV_IOCTL_VERSION: return 0x100;
- case DRV_IOCTL_LOOKUP: return 0;
-
- // Sets the Keyboard Callback
- case KB_IOCTL_SETCALLBACK:
- // Sanity Check
- if((Uint)Data < KERNEL_BASE) return 0;
- // Can only be set once
- if(gKB_Callback != NULL) return 0;
- // Set Callback
- gKB_Callback = Data;
- return 1;
-
- default:
- return 0;
- }
-}
+++ /dev/null
-\r
-#ifndef _KBDUS_H\r
-#define _KBDUS_H\r
-\r
-// - BASE (NO PREFIX)\r
-Uint32 gpKBDUS1[256] = {\r
-/*00*/ 0, KEY_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t',\r
-/*10*/ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', KEY_LCTRL, 'a', 's',\r
-/*20*/ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', KEY_LSHIFT,'\\', 'z', 'x', 'c', 'v',\r
-/*30*/ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT, KEY_KPSTAR,\r
- KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,\r
-/*40*/ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KPHOME,\r
- KEY_KPUP, KEY_KPPGUP, KEY_KPMINUS, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT, KEY_KPPLUS, KEY_KPEND,\r
-/*50*/ KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL, 0, 0, 0, KEY_F11,\r
- KEY_F12, 0, 0, 0, 0, 0, 0, 0,\r
-/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
-};\r
-// - 0xE0 Prefixed\r
-Uint32 gpKBDUS2[256] = {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
-/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
-/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_KPENTER, KEY_RCTRL, 0, 0,\r
-/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*30*/ 0, 0, 0, 0, 0, KEY_KPSLASH, 0, 0, KEY_RALT, 0, 0, 0, 0, 0, 0, 0,\r
-/*40*/ 0, 0, 0, 0, 0, 0, 0, KEY_HOME,\r
- KEY_UP, KEY_PGUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END,\r
-/*50*/ KEY_DOWN, KEY_PGDOWN, KEY_INS, KEY_DEL, 0, 0, 0, 0,\r
- 0, 0, KEY_WIN, 0, 0, KEY_MENU, 0, 0,\r
-/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
-};\r
-// - 0xE1 Prefixed\r
-Uint32 gpKBDUS3[256] = {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
-/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
-/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PAUSE, 0, 0,\r
-/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
-};\r
-\r
-\r
-Uint32 *gpKBDUS[3] = { gpKBDUS1, gpKBDUS2, gpKBDUS3 };\r
-\r
-#endif\r
child->Node.ReadDir = SysFS_Comm_ReadDir;
child->Node.FindDir = SysFS_Comm_FindDir;
if( !prev ) {
- //if(ent)
+ if(ent)
ent->Node.ImplPtr = child;
- //else
- // gSysFS_DriverInfo.RootNode.ImplPtr = child;
+ else
+ gSysFS_DriverInfo.RootNode.ImplPtr = child;
// ^^^ Impossible (There is already /Version)
}
else
child = ent->Node.ImplPtr;
else
child = gSysFS_DriverInfo.RootNode.ImplPtr;
- for( child = ent->Node.ImplPtr; child; prev = child, child = child->Next )
+ for( ; child; child = child->Next )
{
if( strcmp( &Path[start], child->Name ) == 0 )
break;
parent = file->Parent;
// Remove from file list
- prev->ListNext = file->ListNext;
+ if(prev)
+ prev->ListNext = file->ListNext;
+ else
+ gSysFS_FileList = file->ListNext;
file->Node.Size = 0;
file->Node.ImplPtr = NULL;
#include <errno.h>
#include <semaphore.h>
-#define USE_CTRL_ALT 0
+#define USE_CTRL_ALT 1
// === CONSTANTS ===
#define VERSION ((0<<8)|(50))
int InputRead; //!< Input buffer read position
int InputWrite; //!< Input buffer write position
char InputBuffer[MAX_INPUT_CHARS8];
- tSemaphore InputSemaphore;
+// tSemaphore InputSemaphore;
tVT_Char *Text;
Uint32 *Buffer;
Log_Debug("VTerm", "Argument '%s'", arg);
if( strcmp(opt, "Video") == 0 ) {
- gsVT_OutputDevice = strdup(val);
+ if( !gsVT_OutputDevice && Modules_InitialiseBuiltin( val ) == 0 )
+ gsVT_OutputDevice = strdup(val);
}
else if( strcmp(opt, "Input") == 0 ) {
- gsVT_InputDevice = strdup(val);
+ if( !gsVT_InputDevice && Modules_InitialiseBuiltin( val ) == 0 )
+ gsVT_InputDevice = strdup(val);
}
else if( strcmp(opt, "Width") == 0 ) {
giVT_RealWidth = atoi( val );
}
}
- if(gsVT_OutputDevice) Modules_InitialiseBuiltin( gsVT_OutputDevice );
- if(gsVT_InputDevice) Modules_InitialiseBuiltin( gsVT_InputDevice );
-
// Apply Defaults
if(!gsVT_OutputDevice) gsVT_OutputDevice = strdup(DEFAULT_OUTPUT);
if(!gsVT_InputDevice) gsVT_InputDevice = strdup(DEFAULT_INPUT);
gVT_Terminals[i].Node.Read = VT_Read;
gVT_Terminals[i].Node.Write = VT_Write;
gVT_Terminals[i].Node.IOCtl = VT_Terminal_IOCtl;
- Semaphore_Init(&gVT_Terminals[i].InputSemaphore, 0, MAX_INPUT_CHARS8, "VTerm", gVT_Terminals[i].Name);
+// Semaphore_Init(&gVT_Terminals[i].InputSemaphore, 0, MAX_INPUT_CHARS8, "VTerm", gVT_Terminals[i].Name);
}
// Add to DevFS
{
if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue;
+ gVT_Terminals[i].TextWidth = giVT_RealWidth/giVT_CharWidth;
+ gVT_Terminals[i].TextHeight = giVT_RealHeight/giVT_CharHeight;
+
gVT_Terminals[i].Text = realloc(
gVT_Terminals[i].Text,
newBufSize*sizeof(tVT_Char)
int pos = 0;
int avail;
tVTerm *term = &gVT_Terminals[ Node->Inode ];
+ Uint32 *codepoint_buf = Buffer;
+ Uint32 *codepoint_in;
Mutex_Acquire( &term->ReadingLock );
if(avail > Length - pos)
avail = Length/4 - pos;
+ codepoint_in = (void*)term->InputBuffer;
+ codepoint_buf = Buffer;
while( avail -- )
{
- ((Uint32*)Buffer)[pos] = ((Uint32*)term->InputBuffer)[term->InputRead];
+ codepoint_buf[pos] = codepoint_in[term->InputRead];
pos ++;
term->InputRead ++;
term->InputRead %= MAX_INPUT_CHARS32;
#else
case KEY_LALT: gbVT_AltDown &= ~1; break;
case KEY_RALT: gbVT_AltDown &= ~2; break;
- case KEY_LCTRL: gbVT_CtrlDown &= ~1 break;
+ case KEY_LCTRL: gbVT_CtrlDown &= ~1; break;
case KEY_RCTRL: gbVT_CtrlDown &= ~2; break;
#endif
}
else
{
// Encode the raw UTF-32 Key
- ((Uint32*)term->InputBuffer)[ term->InputWrite ] = Codepoint;
+ Uint32 *raw_in = (void*)term->InputBuffer;
+ raw_in[ term->InputWrite ] = Codepoint;
term->InputWrite ++;
term->InputWrite %= MAX_INPUT_CHARS32;
if(term->InputRead == term->InputWrite) {
default:
Term->Text[ Term->WritePos ].Ch = Ch;
Term->Text[ Term->WritePos ].Colour = Term->CurColour;
+ // Update the line before wrapping
+ if( (Term->WritePos + 1) % Term->TextWidth == 0 )
+ VT_int_UpdateScreen( Term, 0 );
Term->WritePos ++;
break;
}
{
//Debug("Term->WritePos (%i) >= %i",
// Term->WritePos,
- // Term->ViewPos + Term->Width*Term->Height
+ // Term->ViewPos + Term->TextWidth*Term->TextHeight
// );
//Debug("Scrolling screen only");
//Debug("Term->ViewPos = %i", Term->ViewPos);
VT_int_ScrollFramebuffer( Term );
VT_int_UpdateScreen( Term, 0 );
+
+ //VT_int_UpdateScreen( Term, 1 ); // HACK!
}
//LEAVE('-');
break;
case VIDEO_2DOP_BLIT:
- if(rem < 16) return Length-rem;
+ if(rem < 12) return Length-rem;
if(!Handlers->Blit) {
Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
);
rem -= 16;
- stream = (void*)((tVAddr)stream + 16);
+ stream = (void*)((tVAddr)stream + 12);
break;
}
// Print the block info?
#if 1
- Log_Debug("Heap", "%p - 0x%x (%i) Owned by %s:%i",
- head, head->Size, head->ValidSize, head->File, head->Line);
+ Log_Debug("Heap", "%p (0x%x) - 0x%x (%i) Owned by %s:%i",
+ head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size, head->ValidSize, head->File, head->Line);
#endif
}
typedef Sint64 tTimestamp;
typedef Sint64 tTime;
typedef struct sShortSpinlock tShortSpinlock;
-typedef struct sMutex tMutex;
-
-struct sMutex {
- tShortSpinlock Protector; //!< Protector for the lock strucure
- const char *Name; //!< Human-readable name
- struct sThread *volatile Owner; //!< Owner of the lock (set upon getting the lock)
- struct sThread *Waiting; //!< Waiting threads
- struct sThread *LastWaiting; //!< Waiting threads
-};
// --- Helper Macros ---
/**
extern int strcmp(const char *__str1, const char *__str2);
extern int strncmp(const char *Str1, const char *Str2, size_t num);
extern int strucmp(const char *Str1, const char *Str2);
-//extern char *strdup(const char *Str);
-#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
+// strdup macro is defined in heap.h
extern char *_strdup(const char *File, int Line, const char *Str);
extern char **str_split(const char *__str, char __ch);
extern char *strchr(const char *__s, int __c);
extern int SpawnTask(tThreadFunction Function, void *Arg);
extern Uint *Threads_GetCfgPtr(int Id);
extern int Threads_SetName(const char *NewName);
-extern int Mutex_Acquire(tMutex *Mutex);
-extern void Mutex_Release(tMutex *Mutex);
-extern int Mutex_IsLocked(tMutex *Mutex);
/**
* \}
*/
#include <binary_ext.h>
#include <vfs_ext.h>
#include <adt.h>
+#include <mutex.h>
#endif
#define free(ptr) Heap_Deallocate((ptr))
#define IsHeap(ptr) Heap_IsHeapAddr((ptr))
+#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
+
#endif
--- /dev/null
+/*
+ * Acess2 Kernel
+ * mutex.h
+ * - Mutual Exclusion syncronisation primitive
+ */
+#ifndef _MUTEX_H
+#define _MUTEX_H
+
+#include <acess.h>
+
+typedef struct sMutex tMutex;
+
+struct sMutex
+{
+ tShortSpinlock Protector; //!< Protector for the lock strucure
+ const char *Name; //!< Human-readable name
+ struct sThread *volatile Owner; //!< Owner of the lock (set upon getting the lock)
+ struct sThread *Waiting; //!< Waiting threads
+ struct sThread *LastWaiting; //!< Waiting threads
+};
+
+/**
+ * \brief Acquire a heavy mutex
+ * \param Mutex Mutex to acquire
+ * \return zero on success, -1 if terminated
+ *
+ * This type of mutex checks if the mutex is avaliable, and acquires it
+ * if it is. Otherwise, the current thread is added to the mutex's wait
+ * queue and the thread suspends. When the holder of the mutex completes,
+ * the oldest thread (top thread) on the queue is given the lock and
+ * restarted.
+ */
+extern int Mutex_Acquire(tMutex *Mutex);
+
+/**
+ * \brief Release a held mutex
+ * \param Mutex Mutex to release
+ * \note Releasing a non-held mutex has no effect
+ */
+extern void Mutex_Release(tMutex *Mutex);
+
+/**
+ * \brief Is this mutex locked?
+ * \param Mutex Mutex pointer
+ */
+extern int Mutex_IsLocked(tMutex *Mutex);
+
+#endif
#include <signal.h>
#include <proc.h>
-/**
- * \brief IPC Message
- */
-typedef struct sMessage
-{
- struct sMessage *Next; //!< Next message in thread's inbox
- tTID Source; //!< Source thread ID
- Uint Length; //!< Length of message data in bytes
- Uint8 Data[]; //!< Message data
-} tMsg;
-
-/**
- * \brief Core threading structure
- *
- */
-typedef struct sThread
-{
- // --- threads.c's
- /**
- * \brief Next thread in current list
- * \note Required to be first for linked list hacks to work
- */
- struct sThread *Next;
- struct sThread *GlobalNext; //!< Next thread in global list
- struct sThread *GlobalPrev; //!< Previous thread in global list
- tShortSpinlock IsLocked; //!< Thread's spinlock
- volatile int Status; //!< Thread Status
- void *WaitPointer; //!< What (Mutex/Thread/other) is the thread waiting on
- int RetStatus; //!< Return Status
-
- Uint TID; //!< Thread ID
- Uint TGID; //!< Thread Group (Process)
- struct sThread *Parent; //!< Parent Thread
- Uint UID, GID; //!< User and Group
- char *ThreadName; //!< Name of thread
-
- // --- arch/proc.c's responsibility
- //! Kernel Stack Base
- tVAddr KernelStack;
-
- //! Memory Manager State
- tMemoryState MemState;
-
- //! State on task switch
- tTaskState SavedState;
-
- // --- threads.c's
- int CurFaultNum; //!< Current fault number, 0: none
- tVAddr FaultHandler; //!< Fault Handler
-
- tMsg * volatile Messages; //!< Message Queue
- tMsg *LastMessage; //!< Last Message (speeds up insertion)
-
- int Quantum, Remaining; //!< Quantum Size and remaining timesteps
- int Priority; //!< Priority - 0: Realtime, higher means less time
-
- Uint Config[NUM_CFG_ENTRIES]; //!< Per-process configuration
-
- volatile int CurCPU;
-} tThread;
-
-
-enum {
- THREAD_STAT_NULL, // Invalid process
- THREAD_STAT_ACTIVE, // Running and schedulable process
- THREAD_STAT_SLEEPING, // Message Sleep
- THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
- THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
- THREAD_STAT_WAITING, // ??? (Waiting for a thread)
- THREAD_STAT_PREINIT, // Being created
- THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
- THREAD_STAT_DEAD, // Awaiting burial (free)
- THREAD_STAT_BURIED // If it's still on the list here, something's wrong
-};
-static const char * const casTHREAD_STAT[] = {
- "THREAD_STAT_NULL",
- "THREAD_STAT_ACTIVE",
- "THREAD_STAT_SLEEPING",
- "THREAD_STAT_MUTEXSLEEP",
- "THREAD_STAT_SEMAPHORESLEEP",
- "THREAD_STAT_WAITING",
- "THREAD_STAT_PREINIT",
- "THREAD_STAT_ZOMBIE",
- "THREAD_STAT_DEAD",
- "THREAD_STAT_BURIED"
-};
-
enum eFaultNumbers
{
FAULT_MISC,
#define GETMSG_IGNORE ((void*)-1)
-// === GLOBALS ===
-extern BOOL gaThreads_NoTaskSwitch[MAX_CPUS];
-
// === FUNCTIONS ===
-extern tThread *Proc_GetCurThread(void);
-
-extern tThread *Threads_GetThread(Uint TID);
-extern void Threads_SetPriority(tThread *Thread, int Pri);
-extern int Threads_Wake(tThread *Thread);
-extern void Threads_Kill(tThread *Thread, int Status);
-extern void Threads_AddActive(tThread *Thread);
-extern tThread *Threads_RemActive(void);
-extern tThread *Threads_GetNextToRun(int CPU, tThread *Last);
-
extern void Threads_SetFaultHandler(Uint Handler);
extern int Threads_SetUID(Uint *Errno, tUID ID);
extern int Threads_SetGID(Uint *Errno, tUID ID);
extern int Threads_WaitTID(int TID, int *Status);
-extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
-extern tThread *Threads_CloneThreadZero(void);
-
extern int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data);
extern int Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer);
--- /dev/null
+/*
+ * Internal Threading header
+ * - Only for use by stuff that needs access to the thread type.
+ */
+#ifndef _THREADS_INT_H_
+#define _THREADS_INT_H_
+
+#include <threads.h>
+#include <proc.h>
+
+/**
+ * \brief IPC Message
+ */
+typedef struct sMessage
+{
+ struct sMessage *Next; //!< Next message in thread's inbox
+ tTID Source; //!< Source thread ID
+ Uint Length; //!< Length of message data in bytes
+ Uint8 Data[]; //!< Message data
+} tMsg;
+
+/**
+ * \brief Core threading structure
+ *
+ */
+typedef struct sThread
+{
+ // --- threads.c's
+ /**
+ * \brief Next thread in current list
+ * \note Required to be first for linked list hacks to work
+ */
+ struct sThread *Next;
+ struct sThread *GlobalNext; //!< Next thread in global list
+ struct sThread *GlobalPrev; //!< Previous thread in global list
+ tShortSpinlock IsLocked; //!< Thread's spinlock
+ volatile int Status; //!< Thread Status
+ void *WaitPointer; //!< What (Mutex/Thread/other) is the thread waiting on
+ int RetStatus; //!< Return Status
+
+ Uint TID; //!< Thread ID
+ Uint TGID; //!< Thread Group (Process)
+ struct sThread *Parent; //!< Parent Thread
+ Uint UID, GID; //!< User and Group
+ char *ThreadName; //!< Name of thread
+
+ // --- arch/proc.c's responsibility
+ //! Kernel Stack Base
+ tVAddr KernelStack;
+
+ //! Memory Manager State
+ tMemoryState MemState;
+
+ //! State on task switch
+ tTaskState SavedState;
+
+ // --- threads.c's
+ int CurFaultNum; //!< Current fault number, 0: none
+ tVAddr FaultHandler; //!< Fault Handler
+
+ tMsg * volatile Messages; //!< Message Queue
+ tMsg *LastMessage; //!< Last Message (speeds up insertion)
+
+ int Quantum, Remaining; //!< Quantum Size and remaining timesteps
+ int Priority; //!< Priority - 0: Realtime, higher means less time
+
+ Uint Config[NUM_CFG_ENTRIES]; //!< Per-process configuration
+
+ volatile int CurCPU;
+
+ int bInstrTrace;
+} tThread;
+
+
+enum {
+ THREAD_STAT_NULL, // Invalid process
+ THREAD_STAT_ACTIVE, // Running and schedulable process
+ THREAD_STAT_SLEEPING, // Message Sleep
+ THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
+ THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
+ THREAD_STAT_WAITING, // ??? (Waiting for a thread)
+ THREAD_STAT_PREINIT, // Being created
+ THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
+ THREAD_STAT_DEAD, // Awaiting burial (free)
+ THREAD_STAT_BURIED // If it's still on the list here, something's wrong
+};
+static const char * const casTHREAD_STAT[] = {
+ "THREAD_STAT_NULL",
+ "THREAD_STAT_ACTIVE",
+ "THREAD_STAT_SLEEPING",
+ "THREAD_STAT_MUTEXSLEEP",
+ "THREAD_STAT_SEMAPHORESLEEP",
+ "THREAD_STAT_WAITING",
+ "THREAD_STAT_PREINIT",
+ "THREAD_STAT_ZOMBIE",
+ "THREAD_STAT_DEAD",
+ "THREAD_STAT_BURIED"
+};
+
+// === GLOBALS ===
+extern BOOL gaThreads_NoTaskSwitch[MAX_CPUS];
+
+// === FUNCTIONS ===
+extern tThread *Proc_GetCurThread(void);
+
+extern tThread *Threads_GetThread(Uint TID);
+extern void Threads_SetPriority(tThread *Thread, int Pri);
+extern int Threads_Wake(tThread *Thread);
+extern void Threads_Kill(tThread *Thread, int Status);
+extern void Threads_AddActive(tThread *Thread);
+extern tThread *Threads_RemActive(void);
+extern tThread *Threads_GetNextToRun(int CPU, tThread *Last);
+
+extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
+extern tThread *Threads_CloneThreadZero(void);
+
+#endif
*/
#include <acess.h>
#include <threads.h>
+#include <threads_int.h>
#include <errno.h>
// === IMPORTS ===
extern int UDI_LoadDriver(void *Base);
#endif
extern void StartupPrint(const char *Str);
-extern void gKernelModules;
-extern void gKernelModulesEnd;
+extern tModule gKernelModules;
+extern tModule gKernelModulesEnd;
// === GLOBALS ===
int giNumBuiltinModules = 0;
*/
#include <acess.h>
#include <threads.h>
+#include <threads_int.h>
#include <errno.h>
#include <semaphore.h>
void Threads_AddActive(tThread *Thread);
tThread *Threads_RemActive(void);
#endif
+void Threads_ToggleTrace(int TID);
void Threads_Fault(int Num);
void Threads_SegFault(tVAddr Addr);
#if 0
#endif
void Threads_Dump(void);
void Threads_DumpActive(void);
-
#if 0
int Mutex_Acquire(tMutex *Mutex);
void Mutex_Release(tMutex *Mutex);
{
ArchThreads_Init();
+ Log_Debug("Threads", "Offsets of tThread");
+ Log_Debug("Threads", ".Priority = %i", offsetof(tThread, Priority));
+
// Create Initial Task
#if SCHEDULER_TYPE == SCHED_RR_PRI
gaActiveThreads[gThreadZero.Priority] = &gThreadZero;
if(Thread == NULL) Thread = Proc_GetCurThread();
// Bounds checking
// - If < 0, set to lowest priority
+ // - Minumum priority is actualy a high number, 0 is highest
if(Pri < 0) Pri = MIN_PRIORITY;
if(Pri > MIN_PRIORITY) Pri = MIN_PRIORITY;
#if SCHEDULER_TYPE == SCHED_LOTTERY
giFreeTickets -= caiTICKET_COUNTS[Thread->Priority] - caiTICKET_COUNTS[Pri];
# if DEBUG_TRACE_TICKETS
- Log("Threads_SetTickets: new giFreeTickets = %i", giFreeTickets);
+ Log("Threads_SetTickets: new giFreeTickets = %i [-%i+%i]",
+ giFreeTickets,
+ caiTICKET_COUNTS[Thread->Priority], caiTICKET_COUNTS[Pri]);
# endif
#endif
Thread->Priority = Pri;
else
Thread->Priority = Pri;
#endif
+
+ #if DEBUG_TRACE_STATE
+ Log("Threads_SetPriority: %p(%i %s) pri set %i",
+ Thread, Thread->TID, Thread->ThreadName,
+ Pri);
+ #endif
}
/**
// Allocate and duplicate
new = malloc(sizeof(tThread));
- if(new == NULL) {
- *Err = -ENOMEM;
- return NULL;
- }
+ if(new == NULL) { *Err = -ENOMEM; return NULL; }
memcpy(new, cur, sizeof(tThread));
new->CurCPU = -1;
// Get Thread ID
new->TID = giNextTID++;
new->Parent = cur;
+ new->bInstrTrace = 0;
// Clone Name
new->ThreadName = strdup(cur->ThreadName);
// Set State
new->Remaining = new->Quantum = cur->Quantum;
new->Priority = cur->Priority;
+ new->bInstrTrace = 0;
// Set Signal Handlers
new->CurFaultNum = 0;
return ret;
}
+void Threads_ToggleTrace(int TID)
+{
+ tThread *thread = Threads_GetThread(TID);
+ if(!thread) return ;
+ thread->bInstrTrace = !thread->bInstrTrace;
+}
+
/**
* \brief Adds a thread to the active queue
*/
Log(" ERROR State (%i) != THREAD_STAT_ACTIVE (%i)", thread->Status, THREAD_STAT_ACTIVE);
Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
Log(" KStack 0x%x", thread->KernelStack);
+ if( thread->bInstrTrace )
+ Log(" Tracing Enabled");
Proc_DumpThreadCPUState(thread);
}
}
Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
Log(" KStack 0x%x", thread->KernelStack);
+ if( thread->bInstrTrace )
+ Log(" Tracing Enabled");
+ Proc_DumpThreadCPUState(thread);
}
}
}
#if SCHEDULER_TYPE == SCHED_LOTTERY && DEBUG_TRACE_TICKETS
else
- LogF("Log: CPU%i released %p (%i %s)->Status = %i (Released)\n",
+ LogF("Log: CPU%i released %p (%i %s)->Status = %i (Released,not in pool)\n",
CPU, Last, Last->TID, Last->ThreadName, Last->Status);
#endif
Last->CurCPU = -1;
return thread;
}
-/**
- * \brief Acquire a heavy mutex
- * \param Mutex Mutex to acquire
- *
- * This type of mutex checks if the mutex is avaliable, and acquires it
- * if it is. Otherwise, the current thread is added to the mutex's wait
- * queue and the thread suspends. When the holder of the mutex completes,
- * the oldest thread (top thread) on the queue is given the lock and
- * restarted.
- */
+// Acquire mutex (see mutex.h for documentation)
int Mutex_Acquire(tMutex *Mutex)
{
tThread *us = Proc_GetCurThread();
Mutex->Waiting = us;
Mutex->LastWaiting = us;
}
+
+ #if DEBUG_TRACE_STATE
+ Log("%p (%i %s) waiting on mutex %p",
+ us, us->TID, us->ThreadName, Mutex);
+ #endif
+
#if 0
{
int i = 0;
return 0;
}
-/**
- * \brief Release a held mutex
- * \param Mutex Mutex to release
- * \note Releasing a non-held mutex has no effect
- */
+// Release a mutex
void Mutex_Release(tMutex *Mutex)
{
SHORTLOCK( &Mutex->Protector );
#endif
}
-/**
- * \brief Is this mutex locked?
- * \param Mutex Mutex pointer
- */
+// Check if a mutex is locked
int Mutex_IsLocked(tMutex *Mutex)
{
return Mutex->Owner != NULL;
Sem->LastWaiting = us;
}
+ #if DEBUG_TRACE_STATE
+ Log("%p (%i %s) waiting on semaphore %p %s:%s",
+ us, us->TID, us->ThreadName,
+ Sem, Sem->ModName, Sem->Name);
+ #endif
+
SHORTREL( &glThreadListLock );
SHORTREL( &Sem->Protector );
while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
given = Sem->MaxValue - Sem->Value;
Sem->Value -= given;
+
+ #if DEBUG_TRACE_STATE
+ Log("%p (%i %s) woken by wait on %p %s:%s",
+ toWake, toWake->TID, toWake->ThreadName,
+ Sem, Sem->ModName, Sem->Name);
+ #endif
+
// Save the number we gave to the thread's status
toWake->RetStatus = given;
Sem->LastSignaling = us;
}
+ #if DEBUG_TRACE_STATE
+ Log("%p (%i %s) signaling semaphore %p %s:%s",
+ us, us->TID, us->ThreadName,
+ Sem, Sem->ModName, Sem->Name);
+ #endif
+
SHORTREL( &glThreadListLock );
SHORTREL( &Sem->Protector );
while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
{
tThread *toWake = Sem->Waiting;
+ // Remove thread from list (double ended, so clear LastWaiting if needed)
Sem->Waiting = Sem->Waiting->Next;
- // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
if( Sem->Waiting == NULL )
Sem->LastWaiting = NULL;
- // Figure out how much to give
+ // Figure out how much to give to woken thread
+ // - Requested count is stored in ->RetStatus
if( toWake->RetStatus && Sem->Value > toWake->RetStatus )
given = toWake->RetStatus;
else
// Save the number we gave to the thread's status
toWake->RetStatus = given;
+ if(toWake->bInstrTrace)
+ Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem);
+ #if DEBUG_TRACE_STATE
+ Log("%p (%i %s) woken by signal on %p %s:%s",
+ toWake, toWake->TID, toWake->ThreadName,
+ Sem, Sem->ModName, Sem->Name);
+ #endif
+
// Wake the sleeper
SHORTLOCK( &glThreadListLock );
if( toWake->Status != THREAD_STAT_ACTIVE )
for( ; child && Pos--; child = child->Next ) ;
- if(Pos) return strdup(child->Name);
+ if(child) return strdup(child->Name);
return NULL;
}
strcpy(ret, cwd);
ret[cwdLen] = '/';
strcpy(&ret[cwdLen+1], Path);
- //Log("ret = '%s'\n", ret);
+ //Log("ret = '%s'", ret);
}
// Parse Path
// Get handle
h = VFS_GetHandle(FD);
if(h == NULL) {
- Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x\n", FD);
+ Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x", FD);
return;
}
if( !Timeout || *Timeout > 0 )
{
ret = Semaphore_Wait(&thread_info->SleepHandle, 1);
+ // TODO: Do something with ret
}
// Fill output (modify *Handles)
# Compile Only
$(ALL_DYNMODS): all-%:
- @echo === Dynamic Module: $* && BUILDTYPE=dynamic $(SUBMAKE) all -C Modules/$*
+ +@echo === Dynamic Module: $* && BUILDTYPE=dynamic $(SUBMAKE) all -C Modules/$*
$(ALL_MODULES): all-%:
- @echo === Module: $* && BUILDTYPE=static $(SUBMAKE) all -C Modules/$*
+ +@echo === Module: $* && BUILDTYPE=static $(SUBMAKE) all -C Modules/$*
all-Kernel:
- @echo === Kernel && $(SUBMAKE) all -C Kernel
+ +@echo === Kernel && $(SUBMAKE) all -C Kernel
$(ALL_USRLIBS): all-%:
- @echo === User Library: $* && $(SUBMAKE) all -C Usermode/Libraries/$*_src
+ +@echo === User Library: $* && $(SUBMAKE) all -C Usermode/Libraries/$*_src
$(ALL_USRAPPS): all-%:
- @echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src
+ +@echo === User Application: $* && $(SUBMAKE) all -C Usermode/Applications/$*_src
# Compile & Install
$(AI_DYNMODS): allinstall-%:
- @echo === Dynamic Module: $* && BUILDTYPE=dynamic $(SUBMAKE) all install -C Modules/$*
+ +@echo === Dynamic Module: $* && BUILDTYPE=dynamic $(SUBMAKE) all install -C Modules/$*
$(AI_MODULES): allinstall-%:
- @echo === Module: $* && BUILDTYPE=static $(SUBMAKE) all install -C Modules/$*
+ +@echo === Module: $* && BUILDTYPE=static $(SUBMAKE) all install -C Modules/$*
allinstall-Kernel:
- @echo === Kernel && $(SUBMAKE) all install -C Kernel
+ +@echo === Kernel && $(SUBMAKE) all install -C Kernel
$(AI_USRLIBS): allinstall-%:
- @echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src
+ +@echo === User Library: $* && $(SUBMAKE) all install -C Usermode/Libraries/$*_src
$(AI_USRAPPS): allinstall-%:
- @echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src
+ +@echo === User Application: $* && $(SUBMAKE) all install -C Usermode/Applications/$*_src
# Clean up compilation
$(CLEAN_DYNMODS): clean-%:
- @BUILDTYPE=dynamic $(SUBMAKE) clean -C Modules/$*
+ +@BUILDTYPE=dynamic $(SUBMAKE) clean -C Modules/$*
$(CLEAN_MODULES): clean-%:
- @BUILDTYPE=static $(SUBMAKE) clean -C Modules/$*
+ +@BUILDTYPE=static $(SUBMAKE) clean -C Modules/$*
clean-Kernel:
- @$(SUBMAKE) clean -C Kernel
+ +@$(SUBMAKE) clean -C Kernel
$(CLEAN_USRLIBS): clean-%:
- @$(SUBMAKE) clean -C Usermode/Libraries/$*_src
+ +@$(SUBMAKE) clean -C Usermode/Libraries/$*_src
$(CLEAN_USRAPPS): clean-%:
- @$(SUBMAKE) clean -C Usermode/Applications/$*_src
+ +@$(SUBMAKE) clean -C Usermode/Applications/$*_src
# Install
$(INSTALL_DYNMODS): install-%:
MODULES := Storage/ATA Storage/FDD
MODULES += Network/NE2000
MODULES += Display/VESA
-#MODULES += Display/BochsGA
+MODULES += Display/BochsGA
MODULES += Filesystems/Ext2
MODULES += Filesystems/FAT
MODULES += Filesystems/NTFS
MODULES += IPStack
DYNMODS := USB/Core
MODULES += Interfaces/UDI
+MODULES += Input/PS2KbMouse
+MODULES += x86/ISADMA
{\r
VT_Font_Render(\r
chars->Ch,\r
- dest + x*giVT_CharWidth, gpBGA_CurrentMode->width,\r
+ dest + x*giVT_CharWidth, 32, gpBGA_CurrentMode->width*4,\r
VT_Colour12to24(chars->BGCol),\r
VT_Colour12to24(chars->FGCol)\r
);\r
Uint32 s_blocks_count; //!< Blocks count\r
Uint32 s_r_blocks_count; //!< Reserved blocks count\r
Uint32 s_free_blocks_count; //!< Free blocks count\r
+ \r
Uint32 s_free_inodes_count; //!< Free inodes count\r
Uint32 s_first_data_block; //!< First Data Block\r
Uint32 s_log_block_size; //!< Block size\r
Sint32 s_log_frag_size; //!< Fragment size\r
+ \r
Uint32 s_blocks_per_group; //!< Number Blocks per group\r
Uint32 s_frags_per_group; //!< Number Fragments per group\r
Uint32 s_inodes_per_group; //!< Number Inodes per group\r
Uint32 s_mtime; //!< Mount time\r
+ \r
Uint32 s_wtime; //!< Write time\r
Uint16 s_mnt_count; //!< Mount count\r
Sint16 s_max_mnt_count; //!< Maximal mount count\r
Uint16 s_state; //!< File system state\r
Uint16 s_errors; //!< Behaviour when detecting errors\r
Uint16 s_pad; //!< Padding\r
+ \r
Uint32 s_lastcheck; //!< time of last check\r
Uint32 s_checkinterval; //!< max. time between checks\r
Uint32 s_creator_os; //!< Formatting OS\r
Uint32 s_rev_level; //!< Revision level\r
+ \r
Uint16 s_def_resuid; //!< Default uid for reserved blocks\r
Uint16 s_def_resgid; //!< Default gid for reserved blocks\r
Uint32 s_reserved[235]; //!< Padding to the end of the block\r
#include "ipstack.h"
#include "firewall.h"
+#define MAX_ADDRTYPE 9
+
// === IMPORTS ===
// === TYPES ===
+typedef struct sKeyValue tKeyValue;
typedef struct sFirewallMod tFirewallMod;
typedef struct sModuleRule tModuleRule;
typedef struct sRule tRule;
typedef struct sChain tChain;
+// === STRUCTURES ===
+struct sKeyValue
+{
+ const char *Key;
+ const char *Value;
+};
+
+struct sFirewallMod
+{
+ const char *Name;
+
+ int (*Match)(tModuleRule *Rule, int AddrType,
+ const void *Src, const void *Dest,
+ Uint8 Type, Uint32 Flags,
+ size_t Length, const void *Data);
+
+ tModuleRule *(*Create)(tKeyValue *Params);
+};
+
struct sModuleRule
{
tModuleRule *Next;
int PacketCount; // Number of packets seen
int ByteCount; // Number of bytes seen (IP Payload bytes)
- int bInvertSource;
- void *Source;
- int SourceMask;
+ int bInvertSource; // Boolean NOT flag on source
+ void *Source; // Source address bytes
+ int SourceMask; // Source address mask bits
- int bInvertDest;
- void *Dest;
- int DestMask;
+ int bInvertDest; // Boolean NOT flag on destination
+ void *Dest; // Destination address bytes
+ int DestMask; // Destination address mask bits
- tModuleRule *Modules;
+ tModuleRule *Modules; // Modules loaded for this rule
- char Action[]; // Target rule name
+ char Target[]; // Target rule name
};
struct sChain
);
// === GLOBALS ===
-tChain *gapFirewall_Chains[10];
+tChain *gapFirewall_Chains[MAX_ADDRTYPE+1];
tChain gFirewall_DROP = {.Name="DROP"};
tChain gFirewall_ACCEPT = {.Name="ACCEPT"};
tChain gFirewall_RETURN = {.Name="RETURN"};
// === CODE ===
+/**
+ * \brief Apply a rule to a packet
+ * \return -1 for no match, -2 for RETURN, eFirewallAction otherwise
+ */
int IPTables_DoRule(
tRule *Rule, int AddrType,
const void *Src, const void *Dest,
Uint8 Type, Uint32 Flags,
size_t Length, const void *Data)
{
- return 0;
+ int rv;
+ // Check if source doesn't match
+ if( !IPStack_CompareAddress(AddrType, Src, Rule->Source, Rule->SourceMask) == !Rule->bInvertSource )
+ return -1;
+ // Check if destination doesn't match
+ if( !IPStack_CompareAddress(AddrType, Dest, Rule->Dest, Rule->DestMask) == !Rule->bInvertDest )
+ return -1;
+
+ // TODO: Handle modules (UDP/TCP/etc)
+ tModuleRule *modrule;
+ for( modrule = Rule->Modules; modrule; modrule = modrule->Next )
+ {
+ if( !modrule->Mod->Match ) continue;
+ rv = modrule->Mod->Match(modrule, AddrType, Src, Dest, Type, Flags, Length, Data);
+ if(rv == -1) return -1; // no match
+ // TODO: If != 0 maybe, allowing it to ask for a drop?
+ }
+
+ // Update statistics
+ Rule->PacketCount ++;
+ Rule->ByteCount += Length;
+
+ return IPTables_TestChain(Rule->Target, AddrType, Src, Dest, Type, Flags, Length, Data);
}
/**
tChain *chain;
tRule *rule;
+ if( AddressType >= MAX_ADDRTYPE ) return -1; // Bad address type
+
+ // Catch builtin targets
+ if(strcmp(RuleName, "") == 0) return -1; // No action
+ if(strcmp(RuleName, "ACCEPT") == 0) return 0; // Accept packet
+ if(strcmp(RuleName, "DROP") == 0) return 1; // Drop packet
+ if(strcmp(RuleName, "RETURN") == 0) return -2; // Return from rule
+
+ // Find the rule
for( chain = gapFirewall_Chains[AddressType]; chain; chain = chain->Next )
{
if( strcmp(chain->Name, RuleName) == 0 )
rv = IPTables_DoRule(rule, AddressType, Src, Dest, Type, Flags, Length, Data);
if( rv == -1 )
continue ;
+ if( rv == -2 ) // -2 = Return from a chain/table, pretend no match
+ return -1;
return rv;
}
extern int IPStack_AddFile(tSocketFile *File);
extern int IPStack_GetAddressSize(int AddressType);
-extern int IPStack_CompareAddress(int AddressType, void *Address1, void *Address2, int CheckBits);
-extern const char *IPStack_PrintAddress(int AddressType, void *Address);
+extern int IPStack_CompareAddress(int AddressType, const void *Address1, const void *Address2, int CheckBits);
+extern const char *IPStack_PrintAddress(int AddressType, const void *Address);
extern tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address);
hdr->HopLimit --;
rt = IPStack_FindRoute(6, NULL, &hdr->Destination); // Get the route (gets the interface)
- //to = ARP_Resolve6(rt->Interface, hdr->Destination); // Resolve address
+ to = ICMP6_ResolveHWAddr(rt->Interface, hdr->Destination); // Resolve address
// Send packet
Log_Log("IPv6", "Forwarding packet");
// === PROTOTYPES ===
int IPStack_Install(char **Arguments);
- int IPStack_CompareAddress(int AddressType, void *Address1, void *Address2, int CheckBits);
+ int IPStack_CompareAddress(int AddressType, const void *Address1, const void *Address2, int CheckBits);
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, IPStack, IPStack_Install, NULL, NULL);
/**
* \brief Compare two IP Addresses masked by CheckBits
*/
-int IPStack_CompareAddress(int AddressType, void *Address1, void *Address2, int CheckBits)
+int IPStack_CompareAddress(int AddressType, const void *Address1, const void *Address2, int CheckBits)
{
int size = IPStack_GetAddressSize(AddressType);
Uint8 mask;
- Uint8 *addr1 = Address1, *addr2 = Address2;
+ const Uint8 *addr1 = Address1, *addr2 = Address2;
// Sanity check size
if( CheckBits < 0 ) CheckBits = 0;
if( CheckBits > size*8 ) CheckBits = size*8;
- if( CheckBits == 0 ) return 1; // /0 matches anythin0
+ if( CheckBits == 0 ) return 1; // /0 matches anything
// Check first bits/8 bytes
if( memcmp(Address1, Address2, CheckBits/8) != 0 ) return 0;
return 0;
}
-const char *IPStack_PrintAddress(int AddressType, void *Address)
+const char *IPStack_PrintAddress(int AddressType, const void *Address)
{
switch( AddressType )
{
case 4: {
static char ret[4*3+3+1];
- Uint8 *addr = Address;
+ const Uint8 *addr = Address;
sprintf(ret, "%i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
return ret;
}
- case 6: {
+ case 6: { // TODO: address compression
static char ret[8*4+7+1];
- Uint16 *addr = Address;
+ const Uint16 *addr = Address;
sprintf(ret, "%x:%x:%x:%x:%x:%x:%x:%x",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5], addr[6], addr[7]
#define TCP_RECIEVE_BUFFER_SIZE 0x4000
// === PROTOTYPES ===
-void TCP_Initialise();
+void TCP_Initialise(void);
void TCP_StartConnection(tTCPConnection *Conn);
void TCP_SendPacket(tTCPConnection *Conn, size_t Length, tTCPHeader *Data);
void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
*
* Registers the client and server files and the GetPacket callback
*/
-void TCP_Initialise()
+void TCP_Initialise(void)
{
IPStack_AddFile(&gTCP_ServerFile);
IPStack_AddFile(&gTCP_ClientFile);
--- /dev/null
+#
+#
+
+OBJ = main.o kb.o ps2mouse.o
+NAME = PS2KbMouse
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess2
+ * PS2 Keyboard Driver
+ */
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <tpl_drv_common.h>
+#include <tpl_drv_keyboard.h>
+#include "kb_kbdus.h"
+
+// === CONSTANTS ===
+#define KB_BUFFER_SIZE 1024
+#define USE_KERNEL_MAGIC 1
+
+// === IMPORTS ===
+extern void Threads_ToggleTrace(int TID);
+extern void Threads_Dump(void);
+extern void Heap_Stats(void);
+
+// === PROTOTYPES ===
+ int KB_Install(char **Arguments);
+void KB_IRQHandler(int IRQNum);
+void KB_AddBuffer(char ch);
+Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
+void KB_UpdateLEDs(void);
+ int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
+
+// === GLOBALS ===
+tDevFS_Driver gKB_DevInfo = {
+ NULL, "PS2Keyboard",
+ {
+ .NumACLs = 0,
+ .Size = 0,
+ //.Read = KB_Read,
+ .IOCtl = KB_IOCtl
+ }
+};
+tKeybardCallback gKB_Callback = NULL;
+Uint32 **gpKB_Map = gpKBDUS;
+Uint8 gbaKB_States[3][256];
+ int gbKB_ShiftState = 0;
+ int gbKB_CapsState = 0;
+ int gbKB_KeyUp = 0;
+ int giKB_KeyLayer = 0;
+#if USE_KERNEL_MAGIC
+ int gbKB_MagicState = 0;
+ int giKB_MagicAddress = 0;
+ int giKB_MagicAddressPos = 0;
+#endif
+
+// === CODE ===
+/**
+ * \brief Install the keyboard driver
+ */
+int KB_Install(char **Arguments)
+{
+ Uint8 temp;
+
+ // Attempt to get around a strange bug in Bochs/Qemu by toggling
+ // the controller on and off
+ temp = inb(0x61);
+ outb(0x61, temp | 0x80);
+ outb(0x61, temp & 0x7F);
+ inb(0x60); // Clear keyboard buffer
+
+ IRQ_AddHandler(1, KB_IRQHandler);
+ DevFS_AddDevice( &gKB_DevInfo );
+ //Log("KB_Install: Installed");
+ return MODULE_ERR_OK;
+}
+
+/**
+ * \brief Called on a keyboard IRQ
+ * \param IRQNum IRQ number (unused)
+ */
+void KB_IRQHandler(int IRQNum)
+{
+ Uint8 scancode;
+ Uint32 ch;
+ // int keyNum;
+
+ // Check port 0x64 to tell if this is from the aux port
+ //if( inb(0x64) & 0x20 ) return;
+
+ scancode = inb(0x60); // Read from the keyboard's data buffer
+ //Log_Debug("Keyboard", "scancode = %02x", scancode);
+
+ // Ignore ACKs
+ if(scancode == 0xFA) {
+ // Oh man! This is anarchic (I'm leaving it here to represent
+ // the mess that Acess once was)
+ //kb_lastChar = KB_ACK;
+ return;
+ }
+
+ // Layer +1
+ if(scancode == 0xE0) {
+ giKB_KeyLayer = 1;
+ return;
+ }
+ // Layer +2
+ if(scancode == 0xE1) {
+ giKB_KeyLayer = 2;
+ return;
+ }
+
+ #if KB_ALT_SCANCODES
+ if(scancode == 0xF0)
+ {
+ gbKB_KeyUp = 1;
+ return;
+ }
+ #else
+ if(scancode & 0x80)
+ {
+ scancode &= 0x7F;
+ gbKB_KeyUp = 1;
+ }
+ #endif
+
+ // Translate
+ ch = gpKB_Map[giKB_KeyLayer][scancode];
+ // Check for unknown key
+ if(!ch && !gbKB_KeyUp)
+ Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
+
+ // Key Up?
+ if (gbKB_KeyUp)
+ {
+ gbKB_KeyUp = 0;
+ gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
+
+ #if USE_KERNEL_MAGIC
+ if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
+ if(ch == KEY_LALT) gbKB_MagicState &= ~2;
+ #endif
+
+ if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
+ if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
+
+ // Call callback
+ if(ch != 0 && gKB_Callback)
+ gKB_Callback( ch & 0x80000000 );
+
+ // Reset Layer
+ giKB_KeyLayer = 0;
+ return;
+ }
+
+ // Set the bit relating to the key
+ gbaKB_States[giKB_KeyLayer][scancode] = 1;
+ // Set shift key bits
+ if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
+ if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
+
+ // Check for Caps Lock
+ if(ch == KEY_CAPSLOCK) {
+ gbKB_CapsState = !gbKB_CapsState;
+ KB_UpdateLEDs();
+ }
+
+ // Reset Layer
+ giKB_KeyLayer = 0;
+
+ // Ignore Non-Printable Characters
+ if(ch == 0) return;
+
+ // --- Check for Kernel Magic Combos
+ #if USE_KERNEL_MAGIC
+ if(ch == KEY_LCTRL) {
+ gbKB_MagicState |= 1;
+ //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
+ }
+ if(ch == KEY_LALT) {
+ gbKB_MagicState |= 2;
+ //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
+ }
+ if(gbKB_MagicState == 3)
+ {
+ switch(ch)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9': case 'a': case 'b':
+ case 'c': case 'd': case 'e': case 'f':
+ {
+ char str[4] = {'0', 'x', ch, 0};
+ if(giKB_MagicAddressPos == BITS/4) return;
+ giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
+ giKB_MagicAddressPos ++;
+ }
+ return;
+
+ // Instruction Tracing
+ case 't':
+ Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
+ Threads_ToggleTrace( giKB_MagicAddress );
+ giKB_MagicAddress = 0; giKB_MagicAddressPos = 0;
+ return;
+
+ // Thread List Dump
+ case 'p': Threads_Dump(); return;
+ // Heap Statistics
+ case 'h': Heap_Stats(); return;
+ // Dump Structure
+ case 's': return;
+ }
+ }
+ #endif
+
+ // Capitals required?
+ if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0))
+ {
+ // TODO: Move this to the keyboard map header
+ switch(ch)
+ {
+ case 0: break;
+ case '`': ch = '~'; break;
+ case '1': ch = '!'; break;
+ case '2': ch = '@'; break;
+ case '3': ch = '#'; break;
+ case '4': ch = '$'; break;
+ case '5': ch = '%'; break;
+ case '6': ch = '^'; break;
+ case '7': ch = '&'; break;
+ case '8': ch = '*'; break;
+ case '9': ch = '('; break;
+ case '0': ch = ')'; break;
+ case '-': ch = '_'; break;
+ case '=': ch = '+'; break;
+ case '[': ch = '{'; break;
+ case ']': ch = '}'; break;
+ case '\\': ch = '|'; break;
+ case ';': ch = ':'; break;
+ case '\'': ch = '"'; break;
+ case ',': ch = '<'; break;
+ case '.': ch = '>'; break;
+ case '/': ch = '?'; break;
+ default:
+ if('a' <= ch && ch <= 'z')
+ ch -= 0x20;
+ break;
+ }
+ }
+
+ if(gKB_Callback && ch != 0) gKB_Callback(ch);
+}
+
+/**
+ * \fn void KB_UpdateLEDs(void)
+ * \brief Updates the status of the keyboard LEDs
+ */
+void KB_UpdateLEDs(void)
+{
+ Uint8 leds;
+
+ leds = (gbKB_CapsState ? 4 : 0);
+
+ while( inb(0x64) & 2 ); // Wait for bit 2 to unset
+ outb(0x60, 0xED); // Send update command
+
+ while( inb(0x64) & 2 ); // Wait for bit 2 to unset
+ outb(0x60, leds);
+}
+
+/**
+ * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
+ * \brief Calls an IOCtl Command
+ */
+int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
+{
+ switch(Id)
+ {
+ case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
+ case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
+ case DRV_IOCTL_VERSION: return 0x100;
+ case DRV_IOCTL_LOOKUP: return 0;
+
+ // Sets the Keyboard Callback
+ case KB_IOCTL_SETCALLBACK:
+ // Sanity Check
+ if((Uint)Data < KERNEL_BASE) return 0;
+ // Can only be set once
+ if(gKB_Callback != NULL) return 0;
+ // Set Callback
+ gKB_Callback = Data;
+ return 1;
+
+ default:
+ return 0;
+ }
+}
--- /dev/null
+\r
+#ifndef _KBDUS_H\r
+#define _KBDUS_H\r
+\r
+// - BASE (NO PREFIX)\r
+Uint32 gpKBDUS1[256] = {\r
+/*00*/ 0, KEY_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t',\r
+/*10*/ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', KEY_LCTRL, 'a', 's',\r
+/*20*/ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', KEY_LSHIFT,'\\', 'z', 'x', 'c', 'v',\r
+/*30*/ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT, KEY_KPSTAR,\r
+ KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,\r
+/*40*/ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KPHOME,\r
+ KEY_KPUP, KEY_KPPGUP, KEY_KPMINUS, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT, KEY_KPPLUS, KEY_KPEND,\r
+/*50*/ KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL, 0, 0, 0, KEY_F11,\r
+ KEY_F12, 0, 0, 0, 0, 0, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+// - 0xE0 Prefixed\r
+Uint32 gpKBDUS2[256] = {\r
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
+/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
+/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_KPENTER, KEY_RCTRL, 0, 0,\r
+/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*30*/ 0, 0, 0, 0, 0, KEY_KPSLASH, 0, 0, KEY_RALT, 0, 0, 0, 0, 0, 0, 0,\r
+/*40*/ 0, 0, 0, 0, 0, 0, 0, KEY_HOME,\r
+ KEY_UP, KEY_PGUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END,\r
+/*50*/ KEY_DOWN, KEY_PGDOWN, KEY_INS, KEY_DEL, 0, 0, 0, 0,\r
+ 0, 0, KEY_WIN, 0, 0, KEY_MENU, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+// - 0xE1 Prefixed\r
+Uint32 gpKBDUS3[256] = {\r
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
+/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
+/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PAUSE, 0, 0,\r
+/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+\r
+Uint32 *gpKBDUS[3] = { gpKBDUS1, gpKBDUS2, gpKBDUS3 };\r
+\r
+#endif\r
--- /dev/null
+/*
+ * Acess2
+ *
+ * PS/2 Keboard / Mouse Driver
+ */
+#include <acess.h>
+#include <modules.h>
+
+// === IMPORTS ===
+extern int KB_Install(char **Arguments);
+extern int Mouse_Install(char **Arguments);
+
+// === PROTOTYPES ===
+ int PS2_Install(char **Arguments);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, 0x0100, Input_PS2KbMouse, PS2_Install, NULL, NULL);
+MODULE_DEFINE(0, 0x0100, PS2Keyboard, KB_Install, NULL, NULL);
+
+// === CODE ===
+int PS2_Install(char **Arguments)
+{
+// KB_Install(Arguments);
+// Mouse_Install(Arguments);
+ return MODULE_ERR_OK;
+}
--- /dev/null
+/*\r
+ * Acess2 Mouse Driver\r
+ */\r
+#define DEBUG 0\r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <tpl_drv_common.h>\r
+#include <tpl_drv_joystick.h>\r
+\r
+// == CONSTANTS ==\r
+#define PS2_IO_PORT 0x60\r
+#define MOUSE_BUFFER_SIZE (sizeof(t_mouse_fsdata))\r
+#define MOUSE_SENS_BASE 5\r
+\r
+// == PROTOTYPES ==\r
+// - Internal -\r
+ int PS2Mouse_Install(char **Arguments);\r
+void PS2Mouse_IRQ(int Num);\r
+static void mouseSendCommand(Uint8 cmd);\r
+static void enableMouse();\r
+// - Filesystem -\r
+static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
+\r
+typedef struct {\r
+ int x, y, buttons, unk;\r
+} t_mouse_fsdata;\r
+\r
+// == GLOBALS ==\r
+ int giMouse_Sensitivity = 1;\r
+t_mouse_fsdata gMouse_Data = {0, 0, 0, 0};\r
+ int giMouse_MaxX = 640, giMouse_MaxY = 480;\r
+ int giMouse_Cycle = 0; // IRQ Position\r
+Uint8 gaMouse_Bytes[4] = {0,0,0,0};\r
+tDevFS_Driver gMouse_DriverStruct = {\r
+ NULL, "ps2mouse",\r
+ {\r
+ .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
+ .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl\r
+ }\r
+};\r
+\r
+// == CODE ==\r
+int Mouse_Install(char **Arguments)\r
+{\r
+ // Initialise Mouse Controller\r
+ IRQ_AddHandler(12, PS2Mouse_IRQ); // Set IRQ\r
+ giMouse_Cycle = 0; // Set Current Cycle position\r
+ enableMouse(); // Enable the mouse\r
+ \r
+ DevFS_AddDevice(&gMouse_DriverStruct);\r
+ \r
+ return MODULE_ERR_OK;\r
+}\r
+\r
+/* Handle Mouse Interrupt\r
+ */\r
+void PS2Mouse_IRQ(int Num)\r
+{\r
+ Uint8 flags;\r
+ int dx, dy;\r
+ //int log2x, log2y;\r
+ \r
+ gaMouse_Bytes[giMouse_Cycle] = inb(0x60);\r
+ if(giMouse_Cycle == 0 && !(gaMouse_Bytes[giMouse_Cycle] & 0x8))\r
+ return;\r
+ giMouse_Cycle++;\r
+ if(giMouse_Cycle == 3)\r
+ giMouse_Cycle = 0;\r
+ else\r
+ return;\r
+ \r
+ if(giMouse_Cycle > 0)\r
+ return;\r
+ \r
+ // Read Flags\r
+ flags = gaMouse_Bytes[0];\r
+ if(flags & 0xC0) // X/Y Overflow\r
+ return;\r
+ \r
+ #if DEBUG\r
+ //LogF(" PS2Mouse_Irq: flags = 0x%x\n", flags);\r
+ #endif\r
+ \r
+ // Calculate dX and dY\r
+ dx = (int) ( gaMouse_Bytes[1] | (flags & 0x10 ? ~0x00FF : 0) );\r
+ dy = (int) ( gaMouse_Bytes[2] | (flags & 0x20 ? ~0x00FF : 0) );\r
+ dy = -dy; // Y is negated\r
+ LOG("RAW dx=%i, dy=%i\n", dx, dy);\r
+ dx = dx*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
+ dy = dy*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
+ \r
+ //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2x) : "a" ((Uint)gaMouse_Bytes[1]));\r
+ //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2y) : "a" ((Uint)gaMouse_Bytes[2]));\r
+ //LogF(" PS2Mouse_Irq: dx=%i, log2x = %i\n", dx, log2x);\r
+ //LogF(" PS2Mouse_Irq: dy=%i, log2y = %i\n", dy, log2y);\r
+ //dx *= log2x;\r
+ //dy *= log2y;\r
+ \r
+ // Set Buttons\r
+ gMouse_Data.buttons = flags & 0x7; //Buttons (3 only)\r
+ \r
+ // Update X and Y Positions\r
+ gMouse_Data.x += (int)dx;\r
+ gMouse_Data.y += (int)dy;\r
+ \r
+ // Constrain Positions\r
+ if(gMouse_Data.x < 0) gMouse_Data.x = 0;\r
+ if(gMouse_Data.y < 0) gMouse_Data.y = 0;\r
+ if(gMouse_Data.x >= giMouse_MaxX) gMouse_Data.x = giMouse_MaxX-1;\r
+ if(gMouse_Data.y >= giMouse_MaxY) gMouse_Data.y = giMouse_MaxY-1; \r
+}\r
+\r
+/* Read mouse state (coordinates)\r
+ */\r
+static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+ if(Length < MOUSE_BUFFER_SIZE)\r
+ return -1;\r
+\r
+ memcpy(Buffer, &gMouse_Data, MOUSE_BUFFER_SIZE);\r
+ \r
+ return MOUSE_BUFFER_SIZE;\r
+}\r
+\r
+static const char *csaIOCtls[] = {DRV_IOCTLNAMES, NULL};\r
+/* Handle messages to the device\r
+ */\r
+static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+ struct {\r
+ int Num;\r
+ int Value;\r
+ } *info = Data;\r
+ switch(ID)\r
+ {\r
+ BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
+ \r
+ case JOY_IOCTL_GETSETAXISLIMIT:\r
+ if(!info) return 0;\r
+ switch(info->Num)\r
+ {\r
+ case 0: // X\r
+ if(info->Value != -1)\r
+ giMouse_MaxX = info->Value;\r
+ return giMouse_MaxX;\r
+ case 1: // Y\r
+ if(info->Value != -1)\r
+ giMouse_MaxY = info->Value;\r
+ return giMouse_MaxY;\r
+ }\r
+ return 0;\r
+ \r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+//== Internal Functions ==\r
+static inline void mouseOut64(Uint8 data)\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear\r
+ outb(0x64, data); // Send Command\r
+}\r
+static inline void mouseOut60(Uint8 data)\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear\r
+ outb(0x60, data); // Send Command\r
+}\r
+static inline Uint8 mouseIn60()\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && (inb(0x64) & 1) == 0); // Wait for Flag to set\r
+ return inb(0x60);\r
+}\r
+static void mouseSendCommand(Uint8 cmd)\r
+{\r
+ mouseOut64(0xD4);\r
+ mouseOut60(cmd);\r
+}\r
+\r
+static void enableMouse()\r
+{\r
+ Uint8 status;\r
+ Log_Log("PS2 Mouse", "Enabling Mouse...");\r
+ \r
+ // Enable AUX PS/2\r
+ mouseOut64(0xA8);\r
+ \r
+ // Enable AUX PS/2 (Compaq Status Byte)\r
+ mouseOut64(0x20); // Send Command\r
+ status = mouseIn60(); // Get Status\r
+ status &= 0xDF; status |= 0x02; // Alter Flags (Set IRQ12 (2) and Clear Disable Mouse Clock (20))\r
+ mouseOut64(0x60); // Send Command\r
+ mouseOut60(status); // Set Status\r
+ \r
+ //mouseSendCommand(0xF6); // Set Default Settings\r
+ mouseSendCommand(0xF4); // Enable Packets\r
+}\r
{\r
int i=0, id=-1;\r
int ret;\r
- Uint16 base;\r
\r
ENTER("");\r
\r
// Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices\r
while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS )\r
{\r
+ // NOTE: Check "protocol" from PCI?\r
+ \r
gUHCI_Controllers[i].PciId = id;\r
// Assign a port range (BAR4, Reserve 32 ports)\r
- base = PCI_AssignPort( id, 4, 0x20 );\r
- gUHCI_Controllers[i].IOBase = base;\r
+ //base = PCI_AssignPort( id, 4, 0x20 );\r
+ gUHCI_Controllers[i].IOBase = PCI_GetBAR4(id);\r
+ gUHCI_Controllers[i].IRQNum = PCI_GetIRQ(id);\r
\r
- Log("[USB ] Controller PCI #%i: IO Base = 0x%x", id, base);\r
+ Log("[USB ] Controller PCI #%i: IO Base = 0x%x, IRQ %i",\r
+ id, gUHCI_Controllers[i].IOBase, gUHCI_Controllers[i].IRQNum);\r
\r
// Initialise Host\r
ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]);\r
{\r
ENTER("pHost", Host);\r
\r
+ outw( Host->IOBase + USBCMD, 4 ); // GRESET\r
+ // TODO: Wait for at least 10ms\r
+ outw( Host->IOBase + USBCMD, 0 ); // GRESET\r
+ \r
// Allocate Frame List\r
Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList); // 1 Page, 32-bit\r
if( !Host->FrameList ) {\r
- Warning("[UHCI ] Unable to allocate frame list, aborting");\r
+ Log_Warning("UHCI", "Unable to allocate frame list, aborting");\r
LEAVE('i', -1);\r
return -1;\r
}\r
*/
Uint16 IOBase;
+ /**
+ * \brief IRQ Number assigned to the device
+ */
+ int IRQNum;
+
/**
* \brief Frame list
*
--- /dev/null
+#
+#
+
+OBJ := dma.o
+NAME := ISADMA
+
+-include ../Makefile.tpl
--- /dev/null
+/*\r
+ * AcessOS 1.0\r
+ * DMA Driver\r
+ */\r
+#include <acess.h>\r
+#include <modules.h>\r
+\r
+#define DMA_SIZE (0x2400)\r
+#define DMA_ADDRESS(c) ((c)*DMA_SIZE+0x500) //Save Space for IDT and BDA\r
+\r
+#define LOWB(x) ((x)&0xFF)\r
+#define HIB(x) (((x)>>8)&0xFF)\r
+#define HIW(x) (((x)>>16)&0xFFFF)\r
+\r
+// === TYPES ===\r
+typedef struct\r
+{\r
+ int mode;\r
+ char *address;\r
+} t_dmaChannel;\r
+\r
+// === PROTOTYPES ===\r
+ int DMA_Install(char **Arguments);\r
+void DMA_SetChannel(int Channel, int length, int read);\r
+ int DMA_ReadData(int channel, int count, void *buffer);\r
+ int DMA_WriteData(int channel, int count, const void *buffer);\r
+\r
+// === CONSTANTS ===\r
+const Uint8 cMASKPORT [8] = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };\r
+const Uint8 cMODEPORT [8] = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };\r
+const Uint8 cCLEARPORT[8] = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };\r
+const Uint8 cPAGEPORT [8] = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };\r
+const Uint8 cADDRPORT [8] = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };\r
+const Uint8 cCOUNTPORT[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, 0x0100, x86_ISADMA, DMA_Install, NULL, NULL);\r
+char *dma_addresses[8];\r
+t_dmaChannel dma_channels[8];\r
+\r
+// === CODE ===\r
+/**\r
+ * \brief Initialise DMA channels\r
+ * \param Arguments Arguments passed at boot time\r
+ */\r
+int DMA_Install(char **Arguments)\r
+{\r
+ Uint i;\r
+ for(i=8;i--;)\r
+ {\r
+ outb( cMASKPORT[i], 0x04 | (i & 0x3) ); // mask channel\r
+ outb( cCLEARPORT[i], 0x00 );\r
+ outb( cMODEPORT[i], 0x48 | (i & 0x3) ); //Read Flag\r
+ outb( 0xd8, 0xff); //Reset Flip-Flop\r
+ outb( cADDRPORT[i], LOWB(DMA_ADDRESS(i)) ); // send address\r
+ outb( cADDRPORT[i], HIB(DMA_ADDRESS(i)) ); // send address\r
+ outb( 0xd8, 0xff); //Reset Flip-Flop\r
+ outb( cCOUNTPORT[i], LOWB(DMA_SIZE) ); // send size\r
+ outb( cCOUNTPORT[i], HIB(DMA_SIZE) ); // send size\r
+ outb( cPAGEPORT[i], LOWB(HIW(DMA_ADDRESS(i))) ); // send page\r
+ outb( cMASKPORT[i], i & 0x3 ); // unmask channel\r
+ \r
+ dma_channels[i].mode = 0;\r
+ dma_addresses[i] = (char*)DMA_ADDRESS(i);\r
+ dma_addresses[i] += KERNEL_BASE;\r
+ }\r
+ return MODULE_ERR_OK;\r
+}\r
+\r
+/**\r
+ * \fn void DMA_SetChannel(int Channel, int length, int read)\r
+ * \brief Set DMA Channel Length and RW\r
+ */\r
+void DMA_SetChannel(int Channel, int length, int read)\r
+{\r
+ Uint chan = Channel & 7;\r
+ read = !!read;\r
+ if(length > DMA_SIZE) length = DMA_SIZE;\r
+ length --; //Adjust for DMA\r
+ //__asm__ __volatile__ ("cli");\r
+ outb( cMASKPORT[chan], 0x04 | (chan & 0x3) ); // mask channel\r
+ outb( cCLEARPORT[chan], 0x00 );\r
+ outb( cMODEPORT[chan], (0x44 + (!read)*4) | (chan & 0x3) );\r
+ outb( cADDRPORT[chan], LOWB(DMA_ADDRESS(chan)) ); // send address\r
+ outb( cADDRPORT[chan], HIB(DMA_ADDRESS(chan)) ); // send address\r
+ outb( cPAGEPORT[chan], HIW(DMA_ADDRESS(chan)) ); // send page\r
+ outb( cCOUNTPORT[chan], LOWB(length) ); // send size\r
+ outb( cCOUNTPORT[chan], HIB(length) ); // send size\r
+ outb( cMASKPORT[chan], chan & 0x3 ); // unmask channel\r
+ dma_addresses[chan] = (char*)DMA_ADDRESS(chan);\r
+ dma_addresses[chan] += KERNEL_BASE;\r
+ //__asm__ __volatile__ ("sti");\r
+}\r
+\r
+/**\r
+ * \fn void DMA_ReadData(int channel, int count, void *buffer)\r
+ * \brief Read data from a DMA buffer\r
+ */\r
+int DMA_ReadData(int channel, int count, void *buffer)\r
+{\r
+ if(channel < 0 || channel > 7)\r
+ return -1;\r
+ if(count < 0 || count > DMA_SIZE)\r
+ return -2;\r
+ //LogF("memcpy(*0x%x, dma_channels[channel].address, count)\n", buffer\r
+ memcpy(buffer, dma_addresses[channel], count);\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn void DMA_WriteData(int channel, int count, void *buffer)\r
+ * \brief Write data to a DMA buffer\r
+ */\r
+int DMA_WriteData(int channel, int count, const void *buffer)\r
+{\r
+ if(channel < 0 || channel > 7)\r
+ return -1;\r
+ if(count < 0 || count > DMA_SIZE)\r
+ return -2;\r
+ \r
+ memcpy(dma_addresses[channel], buffer, count);\r
+ \r
+ return 0;\r
+}\r
--- /dev/null
+CATEGORY = x86
+
+-include ../../Makefile.tpl
int Menubar_HandleMessage(tAxWin_Message *Message);
// === GLOBALS ===
-tAxWin_Handle ghMenubarWindow;
+tAxWin_Element geConsole;
// === CODE ===
int main(int argc, char *argv[])
{
AxWin_Register("Terminal");
+ //geConsole = AxWin_CreateElement();
+
AxWin_MessageLoop();
return 0;
// Set root window to no-border
WM_SetFlags(NULL, 0);
- // -- Create Sidebar --
+ // -- Create Sidebar (Menu and Window List) --
gpInterface_Sidebar = WM_CreateElement(NULL, ELETYPE_TOOLBAR, ELEFLAG_VERTICAL, "Sidebar");
WM_SetSize( gpInterface_Sidebar, giInterface_Width );
// > System Menu Button
btn = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, "SystemMenu");
WM_SetSize(btn, giInterface_Width-4);
- // TODO: Once image loading is implemented, switch to a logo
- #if 1
- //text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE);
+ //text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE, "MenuLogo");
text = WM_CreateElement(btn, ELETYPE_IMAGE, 0, "MenuLogo");
//WM_SetText(text, "file:///LogoSmall.sif");
WM_SetText(text, csLogoSmall);
- #else
- text = WM_CreateElement(btn, ELETYPE_TEXT, 0, NULL);
- WM_SetText(text, "Acess");
- #endif
+
// > Plain <hr/> style spacer
ele = WM_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Top");
WM_SetSize(ele, 4);
- // > Application List
+
+ // > Application List (Window list on most OSs)
gpInterface_ProgramList = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL, "ProgramList");
+
// > Plain <hr/> style spacer
ele = WM_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, ELEFLAG_NOSTRETCH, "SideBar Spacer Bottom");
WM_SetSize(ele, 4);
+
// > Version/Time
text = WM_CreateElement(gpInterface_Sidebar, ELETYPE_TEXT, ELEFLAG_NOSTRETCH, "Version String");
WM_SetSize(text, 20);
/**
* \brief Element visibility
*
- * If set, the element is not drawn.
+ * If set, the element is not drawn (but still is used for size calculations)
*/
ELEFLAG_INVISIBLE = 0x002,
/**
- * \brief Position an element absulutely
+ * \brief Position an element absulutely (ignored in size calcs)
*/
ELEFLAG_ABSOLUTEPOS = 0x004,
/**
* \brief Element "orientation"
+ *
+ * Vertical means that the children of this element are stacked,
+ * otherwise they list horizontally
*/
ELEFLAG_VERTICAL = 0x010,// ELEFLAG_HORIZONTAL = 0x000,
/**
/**
* \brief With (length) size action
* If this flag is set, the element will only be as large as
- * is required
+ * is required along it's parent
*/
ELEFLAG_NOSTRETCH = 0x080,
ELEFLAG_ALIGN_CENTER= 0x100,
/**
* \brief Right/Bottom alignment
+ *
+ * If set, the element aligns to the end of avaliable space (instead
+ * of the beginning)
*/
- ELEFLAG_ALIGN_END = 0x200
+ ELEFLAG_ALIGN_END = 0x200
};
/**
{
ELETYPE_NONE,
- ELETYPE_BOX, //!< Content box
+ ELETYPE_BOX, //!< Content box (invisible in itself)
ELETYPE_TABBAR, //!< Tab Bar
ELETYPE_TOOLBAR, //!< Tool Bar
ELETYPE_BUTTON, //!< Push Button
+
ELETYPE_TEXT, //!< Text
ELETYPE_IMAGE, //!< Image
- ELETYPE_SPACER, //!< Visual Spacer
+ ELETYPE_SPACER, //!< Visual Spacer (horizontal / vertical rule)
MAX_ELETYPES = 0x100
};
--- /dev/null
+# Project: imageview
+
+-include ../Makefile.cfg
+
+LDFLAGS += -luri
+
+OBJ := main.o
+BIN := imageview
+
+-include ../Makefile.tpl
+
--- /dev/null
+/*
+ * Acess2 Image Viewer
+ * By John Hodge (thePowersGang)
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <acess/sys.h>
+#include <uri.h>
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[]);
+void *SIF_Load(tURIFile *FP, int *Width, int *Height, uint32_t Magic);
+
+// === CONSTANTS ===
+const struct {
+ const char *Name;
+ uint32_t Mask;
+ uint32_t Ident;
+ void *(*Load)(tURIFile *FP, int *Width, int *Height, uint32_t Magic);
+} caFileTypes[] = {
+ {"SIF", 0xFFFF, 0x51F0, SIF_Load}
+ };
+#define NUM_FILE_TYPES (sizeof(caFileTypes)/sizeof(caFileTypes[0]))
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+ char *imageURI;
+ tURI *uri;
+ tURIFile *fp;
+ uint32_t idDWord = 0;
+ int i;
+ uint32_t *buffer;
+ int w, h;
+ int termW, termH;
+ int tmp;
+
+ // --- Parse Arguments
+ if( argc < 2 ) {
+ fprintf(stderr, "Usage: %s <image>\n", argv[0]);
+ return 0;
+ }
+ imageURI = argv[1];
+
+ // --- Open File
+ uri = URI_Parse(imageURI);
+ printf("uri = {Proto:'%s',Host:'%s',Port:%i('%s'),Path:'%s'}\n",
+ uri->Proto, uri->Host, uri->PortNum, uri->PortStr, uri->Path);
+ fp = URI_Open(URI_MODE_READ, uri);
+ printf("fp = %p\n", fp);
+ if(!fp) {
+ fprintf(stderr, "ERROR: Unable to open '%s'\nFile unable to open\n", imageURI);
+ return -1;
+ }
+ free(uri);
+
+
+ // --- Determine file type
+ i = URI_Read(fp, 4, &idDWord);
+ printf("i = %i\n", i);
+ printf("idDWord = 0x%08lx\n", idDWord);
+ for( i = 0; i < NUM_FILE_TYPES; i++ )
+ {
+ if( (idDWord & caFileTypes[i].Mask) == caFileTypes[i].Ident )
+ break;
+ }
+ if( i == NUM_FILE_TYPES ) {
+ fprintf(stderr, "ERROR: Unable to open '%s'\nUnknown file type\n", imageURI);
+ return -2;
+ }
+
+ // --- Load
+ buffer = caFileTypes[i].Load(fp, &w, &h, idDWord);
+ if( !buffer ) {
+ fprintf(stderr, "ERROR: Unable to open '%s'\nParsing failed\n", imageURI);
+ return -3;
+ }
+
+ printf("w=%i,h=%i\n", w, h);
+
+ // --- Display
+ termW = ioctl(1, 5, NULL); termW *= 8; ioctl(1, 5, &termW);
+ termH = ioctl(1, 6, NULL); termH *= 16; ioctl(1, 6, &termH);
+ //printf("termW = %i, termH = %i\n", termW, termH);
+ tmp = 1; ioctl(1, 4, &tmp);
+
+ seek(1, 0, SEEK_SET);
+ for( i = 0; i < (h < termH ? h : termH); i++ )
+ {
+ write(1, (w < termW ? w : termW) * 4, buffer + i*w);
+ if(w < termW)
+ seek(1, (termW-w)*4, SEEK_CUR);
+ }
+
+ for( ;; );
+
+ return 0;
+}
+
+// === Simple Image Format Loader ===
+void *SIF_Load(tURIFile *FP, int *Width, int *Height, uint32_t Magic)
+{
+ uint16_t flags = Magic >> 16;
+ uint16_t w, h;
+ int comp = flags & 3;
+ int ofs, i;
+ uint32_t *ret;
+
+ // First 4 bytes were read by main()
+ URI_Read(FP, 2, &w);
+ URI_Read(FP, 2, &h);
+
+ ret = malloc(w * h * 4);
+
+ switch(comp)
+ {
+ // Uncompressed 32-bpp data
+ case 0:
+ URI_Read( FP, w * h * 4, ret );
+ *Width = w;
+ *Height = h;
+ return ret;
+
+ // 1.7.32 RLE
+ // (1 Flag, 7-bit size, 32-bit value)
+ case 1:
+ ofs = 0;
+ while( ofs < w*h )
+ {
+ uint8_t len;
+ uint32_t val;
+ URI_Read(FP, 1, &len);
+ if(len & 0x80) {
+ len &= 0x7F;
+ URI_Read(FP, len, ret+ofs);
+ ofs += len;
+ }
+ else {
+ URI_Read(FP, 4, &val);
+ while(len--) ret[ofs++] = val;
+ }
+ }
+ return ret;
+
+ case 3:
+ // Alpha
+ ofs = 0;
+ while( ofs < w*h )
+ {
+ uint8_t len, val;
+ URI_Read(FP, 1, &len);
+ if(len & 0x80) {
+ len &= 0x7F;
+ while(len--) {
+ URI_Read(FP, 1, &val);
+ ret[ofs++] = (uint32_t)val << 24;
+ }
+ }
+ else {
+ URI_Read(FP, 1, &val);
+ while(len--)
+ ret[ofs++] = (uint32_t)val << 24;
+ }
+ }
+ // Red, Green, Blue
+ for( i = 0; i < 4; i++ )
+ {
+ ofs = 0;
+ while( ofs < w*h )
+ {
+ uint8_t len, val;
+ URI_Read(FP, 1, &len);
+ if(len & 0x80) {
+ len &= 0x7F;
+ while(len--) {
+ URI_Read(FP, 1, &val);
+ ret[ofs++] |= (uint32_t)val << (24-i*8);
+ }
+ }
+ else {
+ URI_Read(FP, 1, &val);
+ while(len--)
+ ret[ofs++] |= (uint32_t)val << (24-i*8);
+ }
+ }
+ }
+ return ret;
+
+ default:
+ fprintf(stderr, "Warning: Unknown compression scheme %i for SIF\n", comp);
+ return NULL;
+ }
+
+}
*/\r
EXPORT int fgetc(FILE *fp)\r
{\r
- int ret = 0;\r
+ char ret = 0;\r
if(!fp) return -1;\r
if(read(fp->FD, 1, &ret) == -1) return -1;\r
return ret;\r
/*
+ * SpiderScript Library
+ *
+ * AST Execution
*/
#include <stdlib.h>
#include <stdio.h>
// Perform assignment operation
if( Node->Assign.Operation != NODETYPE_NOP )
{
- tSpiderValue *varVal = Variable_GetValue(Block, Node->Assign.Dest);
- tSpiderValue *value;
+ tSpiderValue *varVal, *value;
+
+ varVal = Variable_GetValue(Block, Node->Assign.Dest);
+ if(varVal == ERRPTR) return ERRPTR;
+ #if 0
+ #else
+ if(varVal && varVal->ReferenceCount == 2) {
+ Object_Dereference(varVal);
+// printf("pre: (%s) varVal->ReferenceCount = %i\n",
+// Node->Assign.Dest->Variable.Name,
+// varVal->ReferenceCount);
+ }
+ #endif
value = AST_ExecuteNode_BinOp(Block, Node, Node->Assign.Operation, varVal, ret);
if(value == ERRPTR) return ERRPTR;
+
if(ret) Object_Dereference(ret);
+ #if 0
if(varVal) Object_Dereference(varVal);
+ #else
+ if(varVal && varVal->ReferenceCount == 1) {
+ Object_Reference(varVal);
+// printf("post: varVal->ReferenceCount = %i\n", varVal->ReferenceCount);
+ break; // If varVal was non-null, it has been updated by _BinOp
+ }
+ #endif
+ // Else, it was NULL, so has to be assigned
ret = value;
}
{
// Integer Operations
case SS_DATATYPE_INTEGER:
+ if( Value->ReferenceCount == 1 )
+ Object_Reference(ret = Value);
+ else
+ ret = SpiderScript_CreateInteger(0);
switch(Operation)
{
- case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Integer ); break;
- case NODETYPE_BWNOT: ret = SpiderScript_CreateInteger( ~Value->Integer ); break;
+ case NODETYPE_NEGATE: ret->Integer = -Value->Integer; break;
+ case NODETYPE_BWNOT: ret->Integer = ~Value->Integer; break;
default:
AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation);
+ Object_Dereference(ret);
ret = ERRPTR;
break;
}
case NODETYPE_ADD: // Concatenate
ret = Object_StringConcat(Left, Right);
break;
+ // TODO: Support python style 'i = %i' % i ?
+ // Might do it via a function call
+// case NODETYPE_MODULUS:
+// break;
+
default:
AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,String unknown op %i", Operation);
ret = ERRPTR;
break;
// Integer Operations
case SS_DATATYPE_INTEGER:
+ if( Left->ReferenceCount == 1 )
+ Object_Reference(ret = Left);
+ else
+ ret = SpiderScript_CreateInteger(0);
switch(Operation)
{
- case NODETYPE_ADD: ret = SpiderScript_CreateInteger( Left->Integer + Right->Integer ); break;
- case NODETYPE_SUBTRACT: ret = SpiderScript_CreateInteger( Left->Integer - Right->Integer ); break;
- case NODETYPE_MULTIPLY: ret = SpiderScript_CreateInteger( Left->Integer * Right->Integer ); break;
- case NODETYPE_DIVIDE: ret = SpiderScript_CreateInteger( Left->Integer / Right->Integer ); break;
- case NODETYPE_MODULO: ret = SpiderScript_CreateInteger( Left->Integer % Right->Integer ); break;
- case NODETYPE_BWAND: ret = SpiderScript_CreateInteger( Left->Integer & Right->Integer ); break;
- case NODETYPE_BWOR: ret = SpiderScript_CreateInteger( Left->Integer | Right->Integer ); break;
- case NODETYPE_BWXOR: ret = SpiderScript_CreateInteger( Left->Integer ^ Right->Integer ); break;
- case NODETYPE_BITSHIFTLEFT: ret = SpiderScript_CreateInteger( Left->Integer << Right->Integer ); break;
- case NODETYPE_BITSHIFTRIGHT:ret = SpiderScript_CreateInteger( Left->Integer >> Right->Integer ); break;
+ case NODETYPE_ADD: ret->Integer = Left->Integer + Right->Integer; break;
+ case NODETYPE_SUBTRACT: ret->Integer = Left->Integer - Right->Integer; break;
+ case NODETYPE_MULTIPLY: ret->Integer = Left->Integer * Right->Integer; break;
+ case NODETYPE_DIVIDE: ret->Integer = Left->Integer / Right->Integer; break;
+ case NODETYPE_MODULO: ret->Integer = Left->Integer % Right->Integer; break;
+ case NODETYPE_BWAND: ret->Integer = Left->Integer & Right->Integer; break;
+ case NODETYPE_BWOR: ret->Integer = Left->Integer | Right->Integer; break;
+ case NODETYPE_BWXOR: ret->Integer = Left->Integer ^ Right->Integer; break;
+ case NODETYPE_BITSHIFTLEFT: ret->Integer = Left->Integer << Right->Integer; break;
+ case NODETYPE_BITSHIFTRIGHT:ret->Integer = Left->Integer >> Right->Integer; break;
case NODETYPE_BITROTATELEFT:
- ret = SpiderScript_CreateInteger( (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer)) );
+ ret->Integer = (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer));
break;
default:
AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i", Operation);
+ Object_Dereference(ret);
ret = ERRPTR;
break;
}
// Real Numbers
case SS_DATATYPE_REAL:
+ if( Left->ReferenceCount == 1 )
+ Object_Reference(ret = Left);
+ else
+ ret = SpiderScript_CreateReal(0);
switch(Operation)
{
- case NODETYPE_ADD: ret = SpiderScript_CreateReal( Left->Real + Right->Real ); break;
- case NODETYPE_SUBTRACT: ret = SpiderScript_CreateReal( Left->Real - Right->Real ); break;
- case NODETYPE_MULTIPLY: ret = SpiderScript_CreateReal( Left->Real * Right->Real ); break;
- case NODETYPE_DIVIDE: ret = SpiderScript_CreateReal( Left->Real / Right->Real ); break;
+ case NODETYPE_ADD: ret->Real = Left->Real + Right->Real; break;
+ case NODETYPE_SUBTRACT: ret->Real = Left->Real - Right->Real; break;
+ case NODETYPE_MULTIPLY: ret->Real = Left->Real * Right->Real; break;
+ case NODETYPE_DIVIDE: ret->Real = Left->Real / Right->Real; break;
default:
AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation);
+ Object_Dereference(ret);
ret = ERRPTR;
break;
}
#define _ACESS_SYS_H_
#include <stdint.h>
-#include <sys/types.h>
+#include "../sys/types.h"
// === CONSTANTS ===
#ifndef NULL
# define SEEK_CUR 0
# define SEEK_END -1
#endif
-#define CLONE_VM 0x10
#define GETMSG_IGNORE ((void*)-1)
#define FILEFLAG_DIRECTORY 0x10
#define FILEFLAG_SYMLINK 0x20
// === TYPES ===
-struct s_sysACL {
- union {
- struct {
- unsigned group: 1;
- unsigned id: 31;
- };
- uint32_t object;
- };
- union {
- struct {
- unsigned invert: 1;
- unsigned perms: 31;
- };
- uint32_t rawperms;
- };
-};
-struct s_sysFInfo {
- uint uid, gid;
- uint flags;
- uint64_t size;
- uint64_t atime;
- uint64_t mtime;
- uint64_t ctime;
- int numacls;
- struct s_sysACL acls[];
-};
-typedef struct s_sysFInfo t_sysFInfo;
-typedef struct s_sysACL t_sysACL;
// === VARIABLES ===
extern int _errno;
#ifndef _STDTYPES_H_
#define _STDTYPES_H_
-typedef unsigned int uint;
+//typedef unsigned int uint;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
#define FD_SETSIZE 128
+
+#define CLONE_VM 0x10
+
/**
* \brief fd_set for select()
*/
uint16_t flags[FD_SETSIZE/16];
} fd_set;
+struct s_sysACL {
+ union {
+ struct {
+ unsigned group: 1;
+ unsigned id: 31;
+ };
+ uint32_t object;
+ };
+ union {
+ struct {
+ unsigned invert: 1;
+ unsigned perms: 31;
+ };
+ uint32_t rawperms;
+ };
+};
+struct s_sysFInfo {
+ unsigned int uid, gid;
+ unsigned int flags;
+ uint64_t size;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t ctime;
+ int numacls;
+ struct s_sysACL acls[];
+};
+typedef struct s_sysFInfo t_sysFInfo;
+typedef struct s_sysACL t_sysACL;
+
static inline void FD_ZERO(fd_set *fdsetp) {int i=FD_SETSIZE/16;while(i--)fdsetp->flags[i]=0; }
static inline void FD_CLR(int fd, fd_set *fdsetp) { fdsetp->flags[fd/16]&=~(1<<(fd%16)); }
static inline void FD_SET(int fd, fd_set *fdsetp) { fdsetp->flags[fd/16]|=1<<(fd%16); }
typedef uint32_t tid_t;
typedef int64_t time_t;
+typedef unsigned int uint;
+
#endif