-all:
- @$(MAKE) -C acesskernel_src
- @$(MAKE) -C ld-acess_src
+.PHONY: all clean
+
+all clean:
+ @$(MAKE) -C acesskernel_src $@
+ @$(MAKE) -C ld-acess_src $@
\r
KERNEL_SRC = ../../KernelLand/Kernel/\r
\r
-KERNEL_OBJ := logging.o adt.o lib.o drvutil.o debug.o messages.o\r
+KERNEL_OBJ := logging.o adt.o lib.o libc.o debug.o messages.o drvutil_disk.o drvutil_video.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
BUILDINFO_OBJ := obj-$(PLATFORM)/buildinfo.o\r
BUILDINFO_SRC := $(BUILDINFO_OBJ:%.o=%.c)\r
\r
-OBJ := helpers.o threads.o server.o syscalls.o time.o\r
+OBJ := helpers.o threads.o threads_glue.o server.o syscalls.o time.o\r
OBJ += video.o keyboard.o mouse.o nativefs.o vfs_handle.o ui_sdl.o\r
OBJ := $(addprefix obj-$(PLATFORM)/,$(OBJ))\r
N_OBJ := $(addprefix obj-$(PLATFORM)/,$(N_OBJ))\r
DEPFILES = $(filter %.o,$(OBJ) $(N_OBJ) $(K_OBJ))\r
DEPFILES := $(DEPFILES:%=%.dep)\r
\r
-CPPFLAGS += -I include/ -I $(KERNEL_SRC)include/\r
-CFLAGS += -Wall -g\r
+KCPPFLAGS = -I include/ -I $(KERNEL_SRC)include/\r
+CFLAGS += -Wall -g -std=gnu99\r
LDFLAGS += -lSDL -lSDLmain -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
\r
ifeq ($(PLATFORM),win)\r
BIN := ../AcessKernel.exe\r
+ LDFLAGS += -lws2_32 -lpthread\r
endif\r
ifeq ($(PLATFORM),lin)\r
BIN := ../AcessKernel\r
- CFLAGS +=\r
+ CFLAGS += \r
+ LDFLAGS += -lpthread\r
endif\r
\r
.PHONY: all clean\r
$(OBJ): obj-$(PLATFORM)/%.o: %.c\r
@mkdir -p $(dir $@)\r
@echo [CC] -o $@\r
- @$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)\r
+ @$(CC) -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
\r
$(K_OBJ): $(KERNEL_SRC)obj-native-$(PLATFORM)/%.o: $(KERNEL_SRC)%.c\r
@mkdir -p $(dir $@)\r
@echo [CC] -o $@\r
- @$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS)\r
+ $(CC) -ffreestanding -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
\r
\r
$(N_OBJ): obj-$(PLATFORM)/%.o: %.c\r
@mkdir -p $(dir $@)\r
@echo [CC] -o $@\r
- @$(CC) -c $< -o $@ $(CFLAGS)\r
+ @$(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS)\r
\r
$(BUILDINFO_SRC): $(filter-out $(BUILDINFO_OBJ), $(OBJ)) Makefile\r
@echo "" > $@\r
+ $(eval _GITHASH=$(shell (git log -n 1 | head -n 1 | awk '{print $$2}') || echo UNK))\r
+ $(eval _GITCHANGED=$(shell (git status --porcelain | grep -c '^ M ') || echo UNK))\r
@echo "const char gsKernelVersion[] = \"$(ACESS_VERSION)\";" >> $@\r
- @echo "const char gsGitHash[] = \""`git log -n 1 | head -n 1 | awk '{print $$2}'`"\";" >> $@\r
+ @echo "const char gsGitHash[] = \"$(_GITHASH)\";" >> $@\r
+ @echo "const char gsBuildInfo[] = \"Acess2 v$(KERNEL_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@\r
+ @echo " \"Build $(shell hostname --fqdn):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@\r
@echo "const int giBuildNumber = $(BUILD_NUM);" >> $@\r
$(BUILDINFO_OBJ): $(BUILDINFO_SRC)\r
@echo [CC] -o $@\r
free(Ptr);
}
+void Heap_Dump(void)
+{
+}
+
tPAddr MM_GetPhysAddr(tVAddr VAddr)
{
return VAddr; // HACK!
return tv.tv_sec * 1000 + tv.tv_usec/1000;
}
+void IPStack_SendDebugText(const char *str)
+{
+ // nop
+}
+
#include <stdint.h>
//#include <stdlib.h>
-#include <pthread.h>
#undef CLONE_VM
#define _MODULE_NAME_ "NativeKernel"
typedef int BOOL;
+#include <stddef.h>
+#undef NULL
+#undef offsetof
+
struct sShortSpinlock
{
- int IsValid;
- pthread_mutex_t Mutex;
+ void *Mutex;
};
#define SHORTLOCK(...)
#define SHORTREL(...)
+#define CPU_HAS_LOCK(...) 0
//#define NUM_CFG_ENTRIES 10
--- /dev/null
+
+#ifndef _ACESSNATIVE__MOUSE_INT_H_
+#define _ACESSNATIVE__MOUSE_INT_H_
+
+#include <api_drv_joystick.h>
+
+typedef struct sPointer tPointer;
+
+#define MAX_BUTTONS 5
+#define MAX_AXIES 2
+#define MAX_FILESIZE (sizeof(tJoystick_FileHeader) + MAX_AXIES*sizeof(tJoystick_Axis) + MAX_BUTTONS)
+
+/**
+ */
+struct sPointer
+{
+ tPointer *Next;
+
+ // Node
+ tVFS_Node Node;
+
+ // Data
+ Uint8 FileData[MAX_FILESIZE];
+ tJoystick_FileHeader *FileHeader;
+ tJoystick_Axis *Axies;
+ Uint8 *Buttons;
+
+ // Limits for axis positions
+ Uint16 AxisLimits[MAX_AXIES];
+};
+
+extern void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
+
+#endif
+
--- /dev/null
+/*
+ */
+#ifndef _ACESSNATIVE__THREADS_GLUE_H_
+#define _ACESSNATIVE__THREADS_GLUE_H_
+
+
+extern void Threads_Glue_Yield(void);
+extern void Threads_Glue_AcquireMutex(void **Lock);
+extern void Threads_Glue_ReleaseMutex(void **Lock);
+extern void Threads_Glue_SemInit(void **Ptr, int Val);
+extern int Threads_Glue_SemWait(void *Ptr, int Max);
+extern int Threads_Glue_SemSignal( void *Ptr, int AmmountToAdd );
+
+#endif
+
THREAD_STAT_DEAD, // Awaiting burial (free)
THREAD_STAT_BURIED // If it's still on the list here, something's wrong
};
-extern tThread *Threads_GetThread(Uint TID);
+extern struct sThread *Threads_GetThread(Uint TID);
#endif
#endif
#include <unistd.h>
#include <string.h>
+#include "../../KernelLand/Kernel/include/logdebug.h"
+
+#define VALGRIND_CLIENT 0
// === IMPORTS ===
extern int UI_Initialise(int Width, int Height);
extern int NativeFS_Install(char **Arguments);
extern void Debug_SetKTerminal(char *Path);
extern int VT_Install(char **Arguments);
+extern int Mouse_Install(char **Arguments);
extern int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options);
extern int VFS_MkDir(const char *Path);
extern int SyscallServer(void);
+extern int Server_Shutdown(void);
extern const char gsKernelVersion[];
extern const char gsGitHash[];
extern int giBuildNumber;
const char *gsAcessDir = "../Usermode/Output/x86_64";
// === CODE ===
+#ifndef __WIN32__
+#define P_NOWAIT 0
+int spawnv(int flags, const char *execuable, char * const argv[])
+{
+ int pid = fork();
+ if( pid != 0 ) return pid;
+
+ execv(execuable, argv);
+ perror("spawnv - execve");
+ for(;;);
+}
+#endif
+
int main(int argc, char *argv[])
{
char **rootapp = NULL;
UI_Initialise(800, 480);
// - Ignore SIGUSR1 (used to wake threads)
+ #ifdef SIGUSR1
signal(SIGUSR1, SIG_IGN);
+ #endif
// Initialise VFS
VFS_Init();
Log_Error("Init", "Unable to load NativeKeyboard");
}
NativeFS_Install(NULL);
+ Mouse_Install(NULL);
// - Start VTerm
{
char *args[] = {
if( rootapp )
{
int pid;
- char *args[7+rootapp_argc+1];
-
- args[0] = "ld-acess";
- args[1] = "--open"; args[2] = "/Devices/VTerm/0";
- args[3] = "--open"; args[4] = "/Devices/VTerm/0";
- args[5] = "--open"; args[6] = "/Devices/VTerm/0";
+ int argcount = 0;
+ const char *args[7+rootapp_argc+1+1];
+
+ #if VALGRIND_CLIENT
+ args[argcount++] = "valgrind";
+ #endif
+ args[argcount++] = "./ld-acess";
+ args[argcount++] = "--open"; args[argcount++] = "/Devices/VTerm/0";
+ args[argcount++] = "--open"; args[argcount++] = "/Devices/VTerm/0";
+ args[argcount++] = "--open"; args[argcount++] = "/Devices/VTerm/0";
for( i = 0; i < rootapp_argc; i ++ )
- args[7+i] = rootapp[i];
- args[7+rootapp_argc] = NULL;
-
- pid = fork();
+ args[argcount+i] = rootapp[i];
+ args[argcount+rootapp_argc] = NULL;
+ pid = spawnv(P_NOWAIT, "./ld-acess", args);
if(pid < 0) {
perror("Starting root application [fork(2)]");
return 1;
}
- if(pid == 0)
- {
- #ifdef __LINUX__
- prctl(PR_SET_PDEATHSIG, SIGHUP); // LINUX ONLY!
- #endif
- execv("./ld-acess", args);
- }
printf("Root application running as PID %i\n", pid);
}
void AcessNative_Exit(void)
{
// TODO: Close client applications too
+ Server_Shutdown();
exit(0);
}
+/*
+ * Acess2 Kernel - Mouse Mulitplexing Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Mouse mulitplexing
+ */
+#define DEBUG 0
+#define VERSION VER2(0,1)
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include "include/mouse_int.h"
+
+// === PROTOTYPES ===
+ int Mouse_Install(char **Arguments);
+ int Mouse_Cleanup(void);
+// - "User" side
+ int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name);
+ int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data);
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data);
+// - Device Side
+void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
+
+// === GLOBALS ===
+tVFS_NodeType gMouse_RootNodeType = {
+ .ReadDir = Mouse_Root_ReadDir,
+ .FindDir = Mouse_Root_FindDir
+};
+tVFS_NodeType gMouse_DevNodeType = {
+ .IOCtl = Mouse_Dev_IOCtl,
+ .Read = Mouse_Dev_Read
+};
+tDevFS_Driver gMouse_DevInfo = {
+ NULL, "Mouse",
+ { .Flags = VFS_FFLAG_DIRECTORY, .Type = &gMouse_RootNodeType, .Size = 1 }
+};
+tPointer gMouse_Pointer;
+
+// === CODE ===
+/**
+ * \brief Initialise the keyboard driver
+ */
+int Mouse_Install(char **Arguments)
+{
+ /// - Register with DevFS
+ DevFS_AddDevice( &gMouse_DevInfo );
+
+ gMouse_Pointer.Node.Type = &gMouse_DevNodeType;
+ gMouse_Pointer.Node.ImplPtr = &gMouse_Pointer;
+ gMouse_Pointer.FileHeader = (void*)gMouse_Pointer.FileData;
+ gMouse_Pointer.Axies = (void*)( gMouse_Pointer.FileHeader + 1 );
+ gMouse_Pointer.Buttons = (void*)( gMouse_Pointer.Axies + MAX_AXIES );
+ gMouse_Pointer.FileHeader->NAxies = MAX_AXIES;
+ gMouse_Pointer.FileHeader->NButtons = MAX_BUTTONS;
+
+ return 0;
+}
+
+/**
+ * \brief Pre-unload cleanup function
+ */
+int Mouse_Cleanup(void)
+{
+ return 0;
+}
+
+// --- VFS Interface ---
+int Mouse_Root_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
+{
+ if( Pos != 0 )
+ return -EINVAL;
+ strcpy(Dest, "system");
+ return 0;
+}
+
+tVFS_Node *Mouse_Root_FindDir(tVFS_Node *Node, const char *Name)
+{
+ if( strcmp(Name, "system") != 0 ) return NULL;
+ return &gMouse_Pointer.Node;
+}
+
+static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_JOY_IOCTLNAMES, NULL};
+/**
+ * \brief IOCtl handler for the mouse
+ */
+int Mouse_Dev_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+ tJoystick_NumValue *numval = Data;
+ tPointer *ptr = Node->ImplPtr;
+ switch(ID)
+ {
+ BASE_IOCTLS(DRV_TYPE_MOUSE, "Mouse", VERSION, csaIOCTL_NAMES);
+
+ case JOY_IOCTL_GETSETAXISLIMIT:
+ if( !numval || !CheckMem(numval, sizeof(*numval)) )
+ return -1;
+ LOG("GetSetAxisLimit %i = %i", numval->Num, numval->Value);
+ if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
+ return 0;
+ if(numval->Value != -1)
+ ptr->AxisLimits[numval->Num] = numval->Value;
+ return ptr->AxisLimits[numval->Num];
+
+ case JOY_IOCTL_GETSETAXISPOSITION:
+ if( !numval || !CheckMem(numval, sizeof(*numval)) )
+ return -1;
+ if(numval->Num < 0 || numval->Num >= ptr->FileHeader->NAxies)
+ return 0;
+ if(numval->Value != -1)
+ ptr->Axies[numval->Num].CursorPos = numval->Value;
+ return ptr->Axies[numval->Num].CursorPos;
+ }
+ return -1;
+}
+
+/**
+ * \brief Read from a device
+ */
+size_t Mouse_Dev_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Data)
+{
+ tPointer *ptr = Node->ImplPtr;
+ int n_buttons = ptr->FileHeader->NButtons;
+ int n_axies = ptr->FileHeader->NAxies;
+
+ ENTER("pNode iLength pData", Node, Length, Data);
+
+ // TODO: Locking (Acquire)
+
+ Length = MIN(
+ Length,
+ sizeof(tJoystick_FileHeader) + n_axies*sizeof(tJoystick_Axis) + n_buttons
+ );
+
+ // Mark as checked
+ VFS_MarkAvaliable( Node, 0 );
+
+ memcpy( Data, ptr->FileData, Length );
+
+ // TODO: Locking (Release)
+
+ LEAVE('i', Length);
+ return Length;
+}
+
+// --- Device Interface ---
+/*
+ * Handle a mouse event (movement or button press/release)
+ * - See Input/Mouse/include/mouse.h
+ */
+void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues)
+{
+ tPointer *ptr = &gMouse_Pointer;
+
+ ENTER("pHandle xButtonState pAxisDeltas", Handle, ButtonState, AxisDeltas);
+
+ // Update cursor position
+ for( int i = 0; i < 2; i ++ )
+ {
+ ptr->Axies[i].CursorPos = AxisValues[i];
+ ptr->Axies[i].CurValue = AxisDeltas ? AxisDeltas[i] : 0;
+ }
+ for( int i = 0; i < 5; i ++ )
+ ptr->Buttons[i] = ButtonState & (1 << i) ? 255 : 0;
+
+ VFS_MarkAvaliable( &ptr->Node, 1 );
+ LEAVE('-');
+}
+
#include <string.h>
#include <SDL/SDL.h>
#ifdef __WIN32__
+# define _WIN32_WINNT 0x0501
# include <windows.h>
-# include <winsock.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# define close(fd) closesocket(fd)
+typedef int socklen_t;
#else
# include <unistd.h>
# include <sys/socket.h>
# include <netinet/in.h>
+# include <netdb.h> // getaddrinfo
#endif
+#define DONT_INCLUDE_SYSCALL_NAMES
#include "../syscalls.h"
-//#include <debug.h>
+#include <logdebug.h> // acess but std
+#include <errno.h>
-#define USE_TCP 0
+#define USE_TCP 1
#define MAX_CLIENTS 16
// === TYPES ===
int ClientID;
SDL_Thread *WorkerThread;
#if USE_TCP
+ int Socket;
#else
tRequestHeader *CurrentRequest;
struct sockaddr_in ClientAddr;
extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
extern int Threads_CreateRootProcess(void);
extern void Threads_SetThread(int TID);
-// 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, ...);
+extern void *Threads_GetThread(int TID);
+extern void Threads_PostEvent(void *Thread, uint32_t Event);
// === PROTOTYPES ===
tClient *Server_GetClient(int ClientID);
// Allocate a thread for the process
ret->ClientID = ClientID;
+ #if USE_TCP
+ ret->Socket = 0;
+ #else
ret->CurrentRequest = NULL;
+ #endif
if( !ret->WorkerThread ) {
+ #if USE_TCP
+ #else
ret->WaitFlag = SDL_CreateCond();
ret->Mutex = SDL_CreateMutex();
SDL_mutexP( ret->Mutex );
+ #endif
+ Log_Debug("Server", "Creating worker for %p", ret);
ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
}
int Server_WorkerThread(void *ClientPtr)
{
tClient *Client = ClientPtr;
+
+ Log_Debug("Server", "Worker %p", ClientPtr);
+
+ #if USE_TCP
+ while( *((volatile typeof(Client->Socket)*)&Client->Socket) == 0 )
+ ;
+ Threads_SetThread( Client->ClientID );
+
+ while( Client->ClientID != -1 )
+ {
+ fd_set fds;
+ int nfd = Client->Socket+1;
+ FD_ZERO(&fds);
+ FD_SET(Client->Socket, &fds);
+
+ int rv = select(nfd, &fds, NULL, NULL, NULL); // TODO: Timeouts?
+ if(rv < 0) {
+ perror("select");
+ continue ;
+ }
+// Log_Debug("Server", "%p: rv=%i", Client, rv);
+
+ if( FD_ISSET(Client->Socket, &fds) )
+ {
+ const int ciMaxParamCount = 6;
+ char lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
+ tRequestHeader *hdr = (void*)lbuf;
+ size_t len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
+// Log_Debug("Server", "%i bytes of header", len);
+ if( len == 0 ) {
+ Log_Notice("Server", "Zero RX on %i (worker %p)", Client->Socket, Client);
+ break;
+ }
+ if( len == -1 ) {
+ perror("recv header");
+// Log_Warning("Server", "recv() error - %s", strerror(errno));
+ break;
+ }
+ if( len != sizeof(*hdr) ) {
+ // Oops?
+ Log_Warning("Server", "FD%i bad sized (%i != exp %i)",
+ Client->Socket, len, sizeof(*hdr));
+ continue ;
+ }
+
+ if( hdr->NParams > ciMaxParamCount ) {
+ // Oops.
+ Log_Warning("Server", "FD%i too many params (%i > max %i)",
+ Client->Socket, hdr->NParams, ciMaxParamCount);
+ break ;
+ }
+
+ if( hdr->NParams > 0 )
+ {
+ len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
+// Log_Debug("Server", "%i bytes of params", len);
+ if( len != hdr->NParams*sizeof(tRequestValue) ) {
+ // Oops.
+ perror("recv params");
+ Log_Warning("Sever", "Recieving params failed");
+ break ;
+ }
+ }
+ else
+ {
+// Log_Debug("Server", "No params?");
+ }
+
+ // Get buffer size
+ size_t hdrsize = sizeof(tRequestHeader) + hdr->NParams*sizeof(tRequestValue);
+ size_t bufsize = hdrsize;
+ int i;
+ for( i = 0; i < hdr->NParams; i ++ )
+ {
+ if( hdr->Params[i].Flags & ARG_FLAG_ZEROED )
+ ;
+ else {
+ bufsize += hdr->Params[i].Length;
+ }
+ }
+
+ // Allocate full buffer
+ hdr = malloc(bufsize);
+ memcpy(hdr, lbuf, hdrsize);
+ if( bufsize > hdrsize )
+ {
+ size_t rem = bufsize - hdrsize;
+ char *ptr = (void*)( hdr->Params + hdr->NParams );
+ while( rem )
+ {
+ len = recv(Client->Socket, ptr, rem, 0);
+// Log_Debug("Server", "%i bytes of data", len);
+ if( len == -1 ) {
+ // Oops?
+ perror("recv data");
+ Log_Warning("Sever", "Recieving data failed");
+ break ;
+ }
+ rem -= len;
+ ptr += len;
+ }
+ if( rem ) {
+ break;
+ }
+ }
+// else
+// Log_Debug("Server", "no data");
+
+ int retlen;
+ tRequestHeader *retHeader;
+ retHeader = SyscallRecieve(hdr, &retlen);
+ if( !retHeader ) {
+ // Some sort of error
+ Log_Warning("Server", "SyscallRecieve failed?");
+ continue ;
+ }
+
+ send(Client->Socket, (void*)retHeader, retlen, 0);
+
+ // Clean up
+ free(hdr);
+ }
+ }
+ #else
tRequestHeader *retHeader;
tRequestHeader errorHeader;
int retSize = 0;
int sentSize;
int cur_client_id = 0;
-
- #if USE_TCP
- #else
- for( ;; )
+ while( Client->ClientID != -1 )
{
// Wait for something to do
- while( Client->CurrentRequest == NULL )
+ if( Client->CurrentRequest == NULL )
SDL_CondWait(Client->WaitFlag, Client->Mutex);
+ if( Client->CurrentRequest == NULL )
+ continue ;
// Log_Debug("AcessSrv", "Worker got message %p", Client->CurrentRequest);
free( retHeader );
}
#endif
+ Log_Notice("Server", "Terminated Worker %p", ClientPtr);
+ return 0;
}
int SyscallServer(void)
return 0;
}
+int Server_Shutdown(void)
+{
+ close(gSocket);
+ for( int i = 0; i < MAX_CLIENTS; i ++ )
+ {
+ if( gaServer_Clients[i].ClientID == 0 )
+ continue ;
+ Threads_PostEvent( Threads_GetThread(gaServer_Clients[i].ClientID), 0 );
+ gaServer_Clients[i].ClientID = -1;
+ #if USE_TCP
+ close(gaServer_Clients[i].Socket);
+ #else
+ SDL_CondSignal(gaServer_Clients[i].WaitFlag);
+ #endif
+ }
+ return 0;
+}
+
int Server_ListenThread(void *Unused)
{
// Wait for something to do :)
for( ;; )
{
#if USE_TCP
- struct sockaddr_in client;
- uint clientSize = sizeof(client);
- int clientSock = accept(gSocket, (struct sockaddr*)&client, &clientSize);
+ struct sockaddr_in clientaddr;
+ socklen_t clientSize = sizeof(clientaddr);
+ int clientSock = accept(gSocket, (struct sockaddr*)&clientaddr, &clientSize);
if( clientSock < 0 ) {
perror("SyscallServer - accept");
break ;
}
+
+ char addrstr[4*8+8+1];
+ getnameinfo((struct sockaddr*)&clientaddr, sizeof(clientaddr),
+ addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+ Log_Debug("Server", "Client connection %s:%i", addrstr, ntohs(clientaddr.sin_port));
- Log("Client connection %x:%i\n",
- ntohl(client.sin_addr), ntohs(client.sin_port)
- );
+ // Perform auth
+ size_t len;
+ tRequestAuthHdr authhdr;
+ len = recv(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
+ if( len != sizeof(authhdr) ) {
+ // Some form of error?
+ Log_Warning("Server", "Client auth block bad size (%i != exp %i)",
+ len, sizeof(authhdr));
+ close(clientSock);
+ continue ;
+ }
+
+ Log_Debug("Server", "Client assumed PID %i", authhdr.pid);
+
+ tClient *client;
+ if( authhdr.pid == 0 ) {
+ // Allocate PID and client structure/thread
+ client = Server_GetClient(0);
+ client->Socket = clientSock;
+ authhdr.pid = client->ClientID;
+ }
+ else {
+ // Get client structure and make sure it's unused
+ // - Auth token / verifcation?
+ client = Server_GetClient(authhdr.pid);
+ if( !client ) {
+ Log_Warning("Server", "Can't allocate a client struct for %s:%i",
+ addrstr, clientaddr.sin_port);
+ close(clientSock);
+ continue ;
+ }
+ if( client->Socket != 0 ) {
+ Log_Warning("Server", "Client (%i)%p owned by FD%i but %s:%i tried to use it",
+ authhdr.pid, client, addrstr, clientaddr.sin_port);
+ close(clientSock);
+ continue;
+ }
+ else {
+ client->Socket = clientSock;
+ }
+ }
+ Log_Debug("Server", "Client given PID %i - info %p", authhdr.pid, client);
+ len = send(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
+ if( len != sizeof(authhdr) ) {
+ // Ok, this is an error
+ perror("Sending auth reply");
+ }
+
+ // All done, client thread should be watching now
+
#else
char data[BUFSIZ];
tRequestHeader *req = (void*)data;
#include <acess.h>
#include <threads.h>
#include <events.h>
+#if DEBUG == 0
+# define DONT_INCLUDE_SYSCALL_NAMES
+#endif
#include "../syscalls.h"
// === IMPORTS ===
extern int Threads_Fork(void); // AcessNative only function
+extern int Threads_Spawn(int nFD, int FDs[], const void *info);
// === TYPES ===
typedef int (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int *Sizes);
return -1;
return VFS_ReadDir(a0, a1);
);
-SYSCALL6(Syscall_select, "iddddi", int, fd_set *, fd_set *, fd_set *, time_t *, unsigned int,
+SYSCALL6(Syscall_select, "iddddi", int, fd_set *, fd_set *, fd_set *, tTime *, unsigned int,
return VFS_Select(a0, a1, a2, a3, a4, a5, 0);
);
SYSCALL3(Syscall_OpenChild, "isi", int, const char *, int,
return *a0;
);
+SYSCALL3(Syscall_AN_Spawn, "ddd", int *, int *, void *,
+ if(Sizes[0] < sizeof(int))
+ return -1;
+ *a0 = Threads_Spawn(Sizes[1] / sizeof(int), a1, a2);
+ return *a0;
+);
+
SYSCALL2(Syscall_SendMessage, "id", int, void *,
return Proc_SendMessage(a0, Sizes[1], a1);
);
Uint tmp;
int rv;
if( a0 ) {
- rv = Proc_GetMessage(&tmp, a1);
+ rv = Proc_GetMessage(&tmp, Sizes[1], a1);
*a0 = tmp;
}
else
- rv = Proc_GetMessage(NULL, a1);
+ rv = Proc_GetMessage(NULL, Sizes[1], a1);
return rv;
);
Syscall_Sleep,
Syscall_AN_Fork,
+ Syscall_AN_Spawn,
Syscall_SendMessage,
Syscall_GetMessage,
}
// Allocate the return
- ret = malloc(sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue)
- + retDataLen);
+ size_t msglen = sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue) + retDataLen;
+ ret = malloc(msglen);
ret->ClientID = Request->ClientID;
ret->CallID = Request->CallID;
ret->NParams = retValueCount;
+ ret->MessageLength = msglen;
inData = (char*)&ret->Params[ ret->NParams ];
// Static Uint64 return value
*(Uint64*)inData = retVal;
inData += sizeof(Uint64);
- Log_Debug("Syscalls", "Return 0x%llx", retVal);
+ //Log_Debug("Syscalls", "Return 0x%llx", retVal);
retValueCount = 1;
for( i = 0; i < Request->NParams; i ++ )
* threads.c
* - Thread and process handling
*/
-#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)
-#define off_t _acess_off_t
#include <arch.h>
-#undef NULL // Remove acess definition
#include <acess.h>
#include <mutex.h>
-#include <semaphore.h>
+#include "../../KernelLand/Kernel/include/semaphore.h"
+typedef signed long long int time_t;
+#include "../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/syscall_types.h"
+#include <rwlock.h>
#include <events.h>
#include <threads_int.h>
-
-#undef CLONE_VM // Such a hack
-#undef off_t
-
-// - Native headers
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include "/usr/include/signal.h"
-#include <SDL/SDL.h>
+#include <limits.h>
+#include "include/threads_glue.h"
#define THREAD_EVENT_WAKEUP 0x80000000
// === IMPORTS ===
-void VFS_CloneHandleList(int PID);
+extern void VFS_CloneHandleList(int PID);
+extern void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
// === STRUCTURES ===
-#if 0
-typedef struct sState
-{
- void *CurState;
- Uint SP, BP, IP;
-} tState;
-#endif
-
// === PROTOTYPES ===
int Threads_Wake(tThread *Thread);
ret->TID = giThreads_NextThreadID ++;
ret->ThreadName = strdup(TemplateThread->ThreadName);
- ret->EventSem = SDL_CreateSemaphore(0);
+ Threads_Glue_SemInit( &ret->EventSem, 0 );
ret->WaitingThreads = NULL;
ret->WaitingThreadsEnd = NULL;
void Threads_Sleep(void)
{
// TODO: Add to a sleeping queue
- pause();
+ //pause();
}
void Threads_Yield(void)
{
// Wait for the thread to be waited upon
while( gpCurrentThread->WaitingThreads == NULL )
- SDL_Delay(10);
+ Threads_Glue_Yield();
}
#endif
Threads_Wake(toWake);
while(gpCurrentThread->WaitingThreads == toWake)
- SDL_Delay(10);
+ Threads_Glue_Yield();
}
}
{
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;
}
+int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
+{
+ tThread *thread = Threads_CloneTCB(gpCurrentThread);
+ thread->PID = thread->TID;
+ if( info )
+ {
+ // TODO: PGID?
+ //if( info->flags & SPAWNFLAG_NEWPGID )
+ // thread->PGID = thread->PID;
+ if( info->gid && thread->UID == 0 )
+ thread->GID = info->gid;
+ if( info->uid && thread->UID == 0 ) // last because ->UID is used above
+ thread->UID = info->uid;
+ }
+
+ VFS_CloneHandlesFromList(thread->PID, nFD, FDs);
+
+ Log_Debug("Threads", "_spawn: %i", thread->PID);
+ return thread->PID;
+}
+
// --------------------------------------------------------------------
// Mutexes
// --------------------------------------------------------------------
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 );
+ Threads_Glue_AcquireMutex(&Mutex->Protector.Mutex);
return 0;
}
void Mutex_Release(tMutex *Mutex)
{
- pthread_mutex_unlock( &Mutex->Protector.Mutex );
+ Threads_Glue_ReleaseMutex(&Mutex->Protector.Mutex);
}
// --------------------------------------------------------------------
{
memset(Sem, 0, sizeof(tSemaphore));
// HACK: Use `Sem->Protector` as space for the semaphore pointer
- *(void**)(&Sem->Protector) = SDL_CreateSemaphore(InitValue);
+ Threads_Glue_SemInit( &Sem->Protector.Mutex, InitValue );
}
int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
{
- SDL_SemWait( *(void**)(&Sem->Protector) );
- return 1;
+ return Threads_Glue_SemWait( Sem->Protector.Mutex, MaxToTake );
}
int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
{
- int i;
- for( i = 0; i < AmmountToAdd; i ++ )
- SDL_SemPost( *(void**)(&Sem->Protector) );
- return AmmountToAdd;
+ return Threads_Glue_SemSignal( Sem->Protector.Mutex, AmmountToAdd );
}
// --------------------------------------------------------------------
{
Uint32 rv;
- Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
+ //Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
gpCurrentThread->WaitMask = Mask;
if( !(gpCurrentThread->Events & Mask) )
{
- SDL_SemWait( gpCurrentThread->EventSem );
+ if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
+ Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
+ gpCurrentThread, gpCurrentThread->EventSem);
+ }
+ //Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
}
rv = gpCurrentThread->Events & Mask;
gpCurrentThread->Events &= ~Mask;
gpCurrentThread->WaitMask = -1;
-
+
+ //Log_Debug("Threads", "- rv = %x", rv);
+
return rv;
}
void Threads_PostEvent(tThread *Thread, Uint32 Events)
{
Thread->Events |= Events;
- Log_Debug("Threads", "Trigger event %x (->Events = %p)", Events, Thread->Events);
-
- if( Thread->WaitMask & Events ) {
- SDL_SemPost( Thread->EventSem );
+// Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
+
+ if( Events == 0 || Thread->WaitMask & Events ) {
+ Threads_Glue_SemSignal( Thread->EventSem, 1 );
// Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
}
}
--- /dev/null
+/*
+ * Acess2 Native Kernel
+ * - Acess kernel emulation on another OS using SDL and UDP
+ *
+ * threads.c
+ * - Thread and process handling
+ */
+#include "include/threads_glue.h"
+
+#define _ACESS_H
+typedef void **tShortSpinlock;
+#include <rwlock.h>
+
+// - Native headers
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdint.h>
+//#include "/usr/include/signal.h"
+#include <SDL/SDL.h>
+#include <pthread.h>
+#include <assert.h>
+
+#include <logdebug.h> // Kernel land, but uses standards
+
+// === CODE ===
+void Threads_Glue_Yield(void)
+{
+ SDL_Delay(10);
+}
+
+void Threads_Glue_AcquireMutex(void **Lock)
+{
+ if(!*Lock) {
+ *Lock = malloc( sizeof(pthread_mutex_t) );
+ pthread_mutex_init( *Lock, NULL );
+ }
+ pthread_mutex_lock( *Lock );
+}
+
+void Threads_Glue_ReleaseMutex(void **Lock)
+{
+ pthread_mutex_unlock( *Lock );
+}
+
+void Threads_Glue_SemInit(void **Ptr, int Val)
+{
+ *Ptr = SDL_CreateSemaphore(Val);
+ if( !*Ptr ) {
+ Log_Warning("Threads", "Semaphore creation failed - %s", SDL_GetError());
+ }
+}
+
+int Threads_Glue_SemWait(void *Ptr, int Max)
+{
+ int have = 0;
+ assert(Ptr);
+ do {
+ if( SDL_SemWait( Ptr ) == -1 ) {
+ return -1;
+ }
+ have ++;
+ } while( SDL_SemValue(Ptr) && have < Max );
+ return have;
+}
+
+int Threads_Glue_SemSignal( void *Ptr, int AmmountToAdd )
+{
+ int i;
+ for( i = 0; i < AmmountToAdd; i ++ )
+ SDL_SemPost( Ptr );
+ return AmmountToAdd;
+}
+
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
+int RWLock_AcquireRead(tRWLock *Lock)
+{
+ if( !Lock->ReaderWaiting ) {
+ Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+ pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
+ }
+ pthread_rwlock_rdlock( (void*)Lock->ReaderWaiting );
+ return 0;
+}
+int RWLock_AcquireWrite(tRWLock *Lock)
+{
+ if( !Lock->ReaderWaiting ) {
+ Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+ pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
+ }
+ pthread_rwlock_wrlock( (void*)Lock->ReaderWaiting );
+ return 0;
+}
+void RWLock_Release(tRWLock *Lock)
+{
+ pthread_rwlock_unlock( (void*)Lock->ReaderWaiting );
+}
+
typedef void (*tUI_KeybardCallback)(Uint32 Key);
extern tUI_KeybardCallback gUI_KeyboardCallback;
+extern void Mouse_HandleEvent(Uint32 ButtonState, int *AxisDeltas, int *AxisValues);
#endif
return 0;
}
-Uint32 UI_GetAcessKeyFromSDL(SDLKey Sym, Uint16 Unicode)
+Uint32 UI_GetAcessKeyFromSDL(SDLKey Sym)
{
Uint8 *keystate = SDL_GetKeyState(NULL);
int shiftState = 0;
if( gUI_Keymap[shiftState][Sym] )
return gUI_Keymap[shiftState][Sym];
- // Enter key on acess returns \n, but SDL returns \r
- if( Sym == SDLK_RETURN )
- Unicode = '\n';
-
- // How nice of you, a unicode value
- if( Unicode )
- {
- ret = Unicode;
- }
- // Ok, we need to do work :(
- else
+ switch(Sym)
{
- switch(Sym)
- {
- case SDLK_UP: ret = KEY_UP; break;
- case SDLK_DOWN: ret = KEY_DOWN; break;
- case SDLK_LEFT: ret = KEY_LEFT; break;
- case SDLK_RIGHT:ret = KEY_RIGHT;break;
- case SDLK_CAPSLOCK: ret = KEY_CAPSLOCK; break;
- case SDLK_F1: ret = KEY_F1; break;
- case SDLK_F2: ret = KEY_F2; break;
- case SDLK_F3: ret = KEY_F3; break;
- case SDLK_F4: ret = KEY_F4; break;
- case SDLK_F5: ret = KEY_F5; break;
- case SDLK_F6: ret = KEY_F6; break;
- case SDLK_F7: ret = KEY_F7; break;
- case SDLK_F8: ret = KEY_F8; break;
- case SDLK_F9: ret = KEY_F9; break;
- case SDLK_F10: ret = KEY_F10; break;
- case SDLK_F11: ret = KEY_F11; break;
- case SDLK_F12: ret = KEY_F12; break;
- case SDLK_RETURN: ret = '\n'; break;
- default:
- printf("Unhandled key code %i\n", Sym);
- break;
- }
+ case SDLK_a ... SDLK_z:
+ ret = Sym - SDLK_a + KEYSYM_a;
+ break;
+ case SDLK_0 ... SDLK_9:
+ ret = Sym - SDLK_0 + KEYSYM_0;
+ break;
+ case SDLK_CAPSLOCK: ret = KEYSYM_CAPS; break;
+ case SDLK_TAB: ret = KEYSYM_TAB; break;
+ case SDLK_UP: ret = KEYSYM_UPARROW; break;
+ case SDLK_DOWN: ret = KEYSYM_DOWNARROW; break;
+ case SDLK_LEFT: ret = KEYSYM_LEFTARROW; break;
+ case SDLK_RIGHT:ret = KEYSYM_RIGHTARROW;break;
+ case SDLK_F1: ret = KEYSYM_F1; break;
+ case SDLK_F2: ret = KEYSYM_F2; break;
+ case SDLK_F3: ret = KEYSYM_F3; break;
+ case SDLK_F4: ret = KEYSYM_F4; break;
+ case SDLK_F5: ret = KEYSYM_F5; break;
+ case SDLK_F6: ret = KEYSYM_F6; break;
+ case SDLK_F7: ret = KEYSYM_F7; break;
+ case SDLK_F8: ret = KEYSYM_F8; break;
+ case SDLK_F9: ret = KEYSYM_F9; break;
+ case SDLK_F10: ret = KEYSYM_F10; break;
+ case SDLK_F11: ret = KEYSYM_F11; break;
+ case SDLK_F12: ret = KEYSYM_F12; break;
+ case SDLK_RETURN: ret = KEYSYM_RETURN; break;
+ case SDLK_LALT: ret = KEYSYM_LEFTALT; break;
+ case SDLK_LCTRL: ret = KEYSYM_LEFTCTRL; break;
+ case SDLK_LSHIFT: ret = KEYSYM_LEFTSHIFT; break;
+ case SDLK_LSUPER: ret = KEYSYM_LEFTGUI; break;
+ case SDLK_RALT: ret = KEYSYM_RIGHTALT; break;
+ case SDLK_RCTRL: ret = KEYSYM_RIGHTCTRL; break;
+ case SDLK_RSHIFT: ret = KEYSYM_RIGHTSHIFT; break;
+ case SDLK_RSUPER: ret = KEYSYM_RIGHTGUI; break;
+ default:
+ printf("Unhandled key code %i\n", Sym);
+ break;
}
gUI_Keymap[shiftState][Sym] = ret;
return ret;
}
+Uint32 UI_GetButtonBits(Uint8 sdlstate)
+{
+ Uint32 rv = 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_LEFT) ? (1 << 0) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_RIGHT) ? (1 << 1) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_MIDDLE) ? (1 << 2) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_X1) ? (1 << 3) : 0;
+ rv |= sdlstate & SDL_BUTTON(SDL_BUTTON_X2) ? (1 << 4) : 0;
+ return rv;
+}
+
void UI_MainLoop(void)
{
SDL_Event event;
return ;
case SDL_KEYDOWN:
- acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym,
- event.key.keysym.unicode);
-
+ acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym);
+ // Enter key on acess returns \n, but SDL returns \r
+ if(event.key.keysym.sym == SDLK_RETURN)
+ event.key.keysym.unicode = '\n';
+
if( gUI_KeyboardCallback ) {
- gUI_KeyboardCallback(KEY_ACTION_RAWSYM|event.key.keysym.sym);
- gUI_KeyboardCallback(KEY_ACTION_PRESS|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RAWSYM|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_PRESS|event.key.keysym.unicode);
}
break;
case SDL_KEYUP:
- acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym,
- event.key.keysym.unicode);
+ acess_sym = UI_GetAcessKeyFromSDL(event.key.keysym.sym);
if( gUI_KeyboardCallback ) {
- gUI_KeyboardCallback(KEY_ACTION_RAWSYM|event.key.keysym.sym);
- gUI_KeyboardCallback(KEY_ACTION_RELEASE|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RAWSYM|acess_sym);
+ gUI_KeyboardCallback(KEY_ACTION_RELEASE|0);
}
break;
case SDL_USEREVENT:
SDL_UpdateRect(gScreen, 0, 0, giUI_Width, giUI_Height);
SDL_Flip(gScreen);
- break;
+ break;
+
+ case SDL_MOUSEMOTION: {
+ int abs[] = {event.motion.x, event.motion.y};
+ int delta[] = {event.motion.xrel, event.motion.yrel};
+ Mouse_HandleEvent(UI_GetButtonBits(SDL_GetMouseState(NULL, NULL)), delta, abs);
+ break; }
+ case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEBUTTONDOWN: {
+ int abs[] = {event.button.x, event.button.y};
+ Mouse_HandleEvent(UI_GetButtonBits(SDL_GetMouseState(NULL, NULL)), NULL, abs);
+ break; }
default:
break;
tUserHandles *ent, *prev = NULL;
for( ent = gpUserHandles; ent; prev = ent, ent = ent->Next ) {
if( ent->PID == PID ) {
- if( bCreate )
- Log_Warning("VFS", "Process %i already has a handle list", PID);
+ //if( bCreate )
+ // Log_Warning("VFS", "Process %i already has a handle list", PID);
return ent;
}
if( ent->PID > PID ) break;
}
}
+void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[])
+{
+ tUserHandles *ent;
+ tUserHandles *cur;
+ int i, maxhandles;
+
+ 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);
+
+ maxhandles = *Threads_GetMaxFD();
+ if( nFD > maxhandles )
+ nFD = maxhandles;
+ for( i = 0; i < nFD; i ++ )
+ {
+ if( FDs[i] >= maxhandles ) {
+ ent->Handles[i].Node = NULL;
+ continue ;
+ }
+ memcpy(&ent->Handles[i], &cur->Handles[ FDs[i] ], sizeof(tVFS_Handle));
+ }
+ for( ; i < maxhandles; i ++ )
+ cur->Handles[i].Node = NULL;
+
+ for( i = 0; i < maxhandles; i ++ )
+ {
+ if(!cur->Handles[i].Node) continue;
+
+ if(ent->Handles[i].Node->Type->Reference)
+ ent->Handles[i].Node->Type->Reference(ent->Handles[i].Node);
+ }
+}
+
/**
* \fn tVFS_Handle *VFS_GetHandle(int FD)
* \brief Gets a pointer to the handle information structure
LOG("buffer = %p", Buffer);
+ Offset /= 4;
startX = Offset % giUI_Width;
startY = Offset / giUI_Width;
-
- if( Length + startX < giUI_Width )
+ Length /= 4;
+
+ if( startX + Length < giUI_Width )
{
// Single line
UI_BlitBitmap(
Length, 1,
Buffer);
}
+ else if( startX == 0 )
+ {
+ int lines = Length / giUI_Width;
+ int rem = Length % giUI_Width;
+ UI_BlitBitmap(0, startY, giUI_Width, lines, Buffer);
+ if( rem ) {
+ UI_BlitBitmap(0, startY + lines, rem, 1, (Uint32*)Buffer + lines*giUI_Width);
+ }
+ }
else
{
// First scanline (partial or full)
ifeq ($(PLATFORM),win)
BIN := ../ld-acess.exe
+ LDFLAGS += -lws2_32
endif
ifeq ($(PLATFORM),lin)
BIN := ../ld-acess
- LINKADDR := 0x200000
+ LINKADDR := 0x70000000
# LD += -m elf_i386
endif
$(RM) $(BIN) $(OBJ) $(DEPFILES) obj-$(PLATFORM)/link.ld
$(BIN): obj-$(PLATFORM)/link.ld $(OBJ)
- $(CC) $(LDFLAGS) -o $@ $(OBJ)
+ $(CC) -o $@ $(OBJ) $(LDFLAGS)
obj-$(PLATFORM)/%.o: %.c
@mkdir -p $(dir $@)
# Modify the default makefile to put the executable at 1MB instead
-obj-lin/link.ld:
+obj-lin/link.ld: Makefile
@mkdir -p $(dir $@)
@echo "Making Linker Script ($@)"
- $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x[048][0-9]*\b/$(LINKADDR)/g' | sed 's/CONSTANT (MAXPAGESIZE)/0x1000/g' > $@
+ $(LD) -g --verbose | awk '{ if( substr($$1,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x[048][0-9]*\b/$(LINKADDR)/g' | sed 's/CONSTANT (MAXPAGESIZE)/0x1000/g' > $@
+
+# Modify the default makefile to put the executable at 1MB instead
+obj-win/link.ld: Makefile
+ @mkdir -p $(dir $@)
+ @echo "Making Linker Script ($@)"
+ $(LD) -g --verbose | awk '{ if( substr($$1,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x[048][0-9]*\b/$(LINKADDR)/g' | sed 's/CONSTANT (MAXPAGESIZE)/0x1000/g' > $@
-include $(DEPFILES)
extern void Binary_SetReadyToUse(void *Base);
// HACKS - So this can share the usermode elf.c
-static inline void *GetSymbol(const char*sym, size_t*sz)
+static inline int GetSymbol(const char *sym, void **val, size_t *sz)
{
uintptr_t rv;
if( !Binary_GetSymbol(sym, &rv, sz) )
- return NULL;
- return (void*)rv;
+ return 0;
+ *val = (void*)rv;
+ return 1;
}
static inline void *LoadLibrary(const char *Name, const char *SearchPath, char **envp)
{
Binary_SetReadyToUse(Base);
}
+static inline int SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
+{
+ return 0;
+}
+
extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits);
+++ /dev/null
-../../Usermode/Libraries/ld-acess.so_src/elf.c
\ No newline at end of file
--- /dev/null
+#include "common.h"
+#define _COMMON_H
+// stops real ld-acess.so common.h being included
+#include "../../Usermode/Libraries/ld-acess.so_src/elf.c"
+++ /dev/null
-../../Usermode/Libraries/ld-acess.so_src/elf32.h
\ No newline at end of file
--- /dev/null
+#include "../../Usermode/Libraries/ld-acess.so_src/elf32.h"
+++ /dev/null
-../../Usermode/Libraries/ld-acess.so_src/elf64.h
\ No newline at end of file
--- /dev/null
+#include "../../Usermode/Libraries/ld-acess.so_src/elf64.h"
#include <stdio.h>\r
#include <string.h>\r
#include <unistd.h>\r
+#include <inttypes.h> // PRIx64\r
#include "common.h"\r
#include "elf32.h"\r
#include "elf64.h"\r
addr = phtab[i].p_vaddr + baseDiff;\r
\r
if( AllocateMemory( addr, phtab[i].p_memsz ) ) {\r
- fprintf(stderr, "Elf_Load: Unable to map memory at %llx (0x%llx bytes)\n",\r
- (long long)addr, (long long)phtab[i].p_memsz);\r
+ fprintf(stderr, "Elf_Load: Unable to map memory at %"PRIx64" (0x%"PRIx64" bytes)\n",\r
+ (uint64_t)addr, (uint64_t)phtab[i].p_memsz);\r
free( phtab );\r
return NULL;\r
}\r
#include <stdarg.h>
#include <stddef.h>
-#define DEBUG(v...) Debug(v)
+#define DEBUG(v...) do{}while(0)//Debug(v)
#define PAGE_SIZE 4096
typedef struct sFILE FILE;
-extern FILE *stderr;
extern void exit(int) __attribute__ ((noreturn));
extern int printf(const char *, ...);
extern int fprintf(FILE *,const char *, ...);
extern void _InitSyscalls(void);
extern void _CloseSyscalls(void);
+extern void Warning(const char *Format, ...);
extern void Debug(const char *Format, ...);
extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
// === CONSTANTS ===
#define NATIVE_FILE_MASK 0x40000000
+// === GLOBALS ===
+int acess__errno;
+char *gsExecutablePath = "./ld-acess";
+
// === CODE ===
// --- VFS Calls
int acess_chdir(const char *Path)
uint64_t acess_tell(int FD) {
if(FD & NATIVE_FILE_MASK)
return native_tell( FD & (NATIVE_FILE_MASK-1) );
+ DEBUG("tell(0x%x)", FD);
return _Syscall(SYS_TELL, ">i", FD);
}
);
}
-int acess_readdir(int fd, char *dest) {
- DEBUG("readdir(%i, %p)", fd, dest);
+int acess_SysReadDir(int fd, char *dest) {
+ DEBUG("SysReadDir(%i, %p)", fd, dest);
return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
}
int acess__SysOpenChild(int fd, char *name, int flags) {
+ DEBUG("_SysOpenChild(0x%x, '%s', 0x%x)", fd, name, flags);
return _Syscall(SYS_OPENCHILD, ">i >s >i", fd, name, flags);
}
int acess__SysGetACL(int fd, t_sysACL *dest) {
+ DEBUG("%s(0x%x, %p)", __func__, fd, dest);
return _Syscall(SYS_GETACL, ">i <d", fd, sizeof(t_sysACL), dest);
}
int acess__SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) {
+ DEBUG("%s('%s', '%s', '%s', '%s')", __func__, Device, Directory, Type, Options);
return _Syscall(SYS_MOUNT, ">s >s >s >s", Device, Directory, Type, Options);
}
// --- Process Management ---
int acess_clone(int flags, void *stack)
{
+ #ifdef __WIN32__
+ Warning("Win32 does not support anything like fork(2), cannot emulate");
+ exit(-1);
+ #else
extern int fork(void);
if(flags & CLONE_VM) {
int ret, newID, kernel_tid=0;
- printf("USERSIDE fork()\n");
+ Debug("USERSIDE fork()");
newID = _Syscall(SYS_AN_FORK, "<d", sizeof(int), &kernel_tid);
ret = fork();
if(ret == 0)
{
_CloseSyscalls();
- _InitSyscalls();
giSyscall_ClientID = newID;
+ _InitSyscalls();
return 0;
}
}
else
{
- fprintf(stderr, "ERROR: Threads currently unsupported\n");
+ Warning("ERROR: Threads currently unsupported\n");
exit(-1);
}
+ #endif
}
-int acess_execve(char *path, char **argv, char **envp)
+int acess_execve(char *path, char **argv, const char **envp)
{
int i, argc;
for( argc = 0; argv[argc]; argc ++ ) ;
DEBUG(" acess_execve: argc = %i", argc);
- char *new_argv[7+argc+1];
+ const char *new_argv[7+argc+1];
char client_id_str[11];
char socket_fd_str[11];
sprintf(client_id_str, "%i", giSyscall_ClientID);
return native_execve("./ld-acess", new_argv, envp);
}
+int acess__SysSpawn(const char *binary, const char **argv, const char **envp, int nfd, int fds[], struct s_sys_spawninfo *info)
+{
+ int argc = 0;
+ while( argv[argc++] );
+
+ Debug("_SysSpawn('%s', %p (%i), %p, %i, %p, %p)",
+ binary, argv, argc, envp, nfd, fds, info);
+
+ int kernel_tid;
+ int newID;
+ newID = _Syscall(SYS_AN_SPAWN, "<d >d >d", sizeof(int), &kernel_tid,
+ nfd*sizeof(int), fds,
+ info ? sizeof(*info) : 0, info);
+
+ const char *new_argv[5+argc+1];
+ int new_argc = 0, i;
+ char client_id_str[11];
+ sprintf(client_id_str, "%i", newID);
+ new_argv[new_argc++] = gsExecutablePath; // TODO: Get path to ld-acess executable
+ new_argv[new_argc++] = "--key";
+ new_argv[new_argc++] = client_id_str;
+ new_argv[new_argc++] = "--binary";
+ new_argv[new_argc++] = binary;
+ for( i = 0; argv[i]; i ++)
+ new_argv[new_argc++] = argv[i];
+ new_argv[new_argc++] = NULL;
+
+ // TODO: Debug output?
+
+ native_spawn(gsExecutablePath, new_argv, envp);
+
+ return kernel_tid;
+}
+
void acess_sleep(void)
{
+ DEBUG("%s()", __func__);
_Syscall(SYS_SLEEP, "");
}
int acess_waittid(int TID, int *ExitStatus)
{
+ DEBUG("%s(%i, %p)", __func__, TID, ExitStatus);
return _Syscall(SYS_WAITTID, ">i <d", TID, sizeof(int), &ExitStatus);
}
int acess_SysSendMessage(int DestTID, int Length, void *Data)
{
+ DEBUG("%s(%i, 0x%x, %p)", __func__, DestTID, Length, Data);
return _Syscall(SYS_SENDMSG, ">i >d", DestTID, Length, Data);
}
-int acess_SysGetMessage(int *SourceTID, void *Data)
+int acess_SysGetMessage(int *SourceTID, int BufLen, void *Data)
{
-// static __thread int lastlen = 1024;
- int lastlen;
-
- lastlen = _Syscall(SYS_GETMSG, "<d <d",
+ DEBUG("%s(%p, %p)", __func__, SourceTID, Data);
+ return _Syscall(SYS_GETMSG, "<d <d",
SourceTID ? sizeof(uint32_t) : 0, SourceTID,
- Data ? 1024 : 0, Data
+ BufLen, Data
);
- return lastlen;
}
int acess__SysWaitEvent(int Mask)
{
+ DEBUG("%s(%x)", __func__, Mask);
return _Syscall(SYS_WAITEVENT, ">i", Mask);
}
// === Symbol List ===
-#define DEFSYM(name) {#name, acess_##name}
+#define DEFSYM(name) {#name, &acess_##name}
const tSym caBuiltinSymbols[] = {
DEFSYM(_exit),
DEFSYM(tell),
DEFSYM(ioctl),
DEFSYM(finfo),
- DEFSYM(readdir),
+ DEFSYM(SysReadDir),
DEFSYM(select),
DEFSYM(_SysOpenChild),
DEFSYM(_SysGetACL),
DEFSYM(clone),
DEFSYM(execve),
+ DEFSYM(_SysSpawn),
DEFSYM(sleep),
DEFSYM(waittid),
+ DEFSYM(gettid),
DEFSYM(setuid),
DEFSYM(setgid),
- DEFSYM(gettid),
+ DEFSYM(getuid),
+ DEFSYM(getgid),
DEFSYM(SysSendMessage),
DEFSYM(SysGetMessage),
DEFSYM(_SysAllocate),
DEFSYM(_SysDebug),
DEFSYM(_SysSetFaultHandler),
- DEFSYM(_SysWaitEvent)
+ DEFSYM(_SysWaitEvent),
+
+ DEFSYM(_errno)
};
const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]);
#ifndef _EXPORTS_H_
#define _EXPORTS_H_
+#include <stddef.h>
+
// Syscall request (used by acess_*)
extern uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...);
extern int native_seek(int FD, int64_t Offset, int Dir);
extern uint64_t native_tell(int FD);
-extern int native_execve(const char *filename, char *const argv[], char *const envp[]);
+extern int native_execve(const char *filename, const char *const argv[], const char *const envp[]);
+extern int native_spawn(const char *filename, const char *const argv[], const char *const envp[]);
// Syscalls used by the linker
extern int acess_open(const char *Path, int Flags);
void Debug(const char *Format, ...)
{
va_list args;
- printf("[DEBUG %i] ", giSyscall_ClientID);
+ printf("[DEBUG ");
+ printf("%2i] ", giSyscall_ClientID);
va_start(args, Format);
vprintf(Format, args);
va_end(args);
size_t size = (VirtAddr & 0xFFF) + ByteCount;
void *tmp;
#if __WIN32__
- tmp = VirtualAlloc(base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ tmp = VirtualAlloc((void*)base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if( tmp == NULL ) {
- printf("ERROR: Unable to allocate memory (%i)\n", GetLastError());
+ printf("ERROR: Unable to allocate memory (0x%x)\n", (int)GetLastError());
return -1;
}
#else
uintptr_t FindFreeRange(size_t ByteCount, int MaxBits)
{
- #if __WIN32__
- # error "Windows FindFreeRange() unimplemented"
- #else
uintptr_t base, ofs, size;
uintptr_t end = -1;
static const int PAGE_SIZE = 0x1000;
for( base = end - size + 1; base > 0; base -= PAGE_SIZE )
{
for( ofs = 0; ofs < size; ofs += PAGE_SIZE ) {
+ #if __WIN32__
+ MEMORY_BASIC_INFORMATION info;
+ VirtualQuery( (void*)(base + ofs), &info, sizeof(info) );
+ if( info.State != MEM_FREE )
+ break;
+ #else
if( msync( (void*)(base+ofs), 1, 0) == 0 )
break;
if( errno != ENOMEM )
perror("FindFreeRange, msync");
+ #endif
}
if( ofs >= size ) {
return base;
}
}
return 0;
- #endif
}
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <inttypes.h>
#ifdef __WIN32__
# include <windows.h>
# include <winsock.h>
#include "request.h"
#include "../syscalls.h"
-#define USE_TCP 0
+#define USE_TCP 1
// === PROTOTYPES ===
void SendData(void *Data, int Length);
if( connect(gSocket, (struct sockaddr *)&gSyscall_ServerAddr, sizeof(struct sockaddr_in)) < 0 )
{
fprintf(stderr, "[ERROR -] Cannot connect to server (localhost:%i)\n", SERVER_PORT);
- fprintf(stderr, "[ERROR -] ", giSyscall_ClientID);
perror("_InitSyscalls");
#if __WIN32__
closesocket(gSocket);
}
#endif
- #if !USE_TCP
+ #if USE_TCP
+ {
+ tRequestAuthHdr auth;
+ auth.pid = giSyscall_ClientID;
+ auth.key = 0;
+ SendData(&auth, sizeof(auth));
+ int len = ReadData(&auth, sizeof(auth), 5);
+ if( len == 0 ) {
+ fprintf(stderr, "Timeout waiting for auth response\n");
+ exit(-1);
+ }
+ giSyscall_ClientID = auth.pid;
+ }
+ #else
// Ask server for a client ID
if( !giSyscall_ClientID )
{
printf("\n");
}
#endif
+ #if DEBUG
{
int i;
char *data = (char*)&Request->Params[Request->NParams];
data += sizeof(uint32_t);
break;
case ARG_TYPE_INT64:
- DEBUG_S(" 0x%016llx", *(uint64_t*)data);
+ DEBUG_S(" 0x%016"PRIx64"", *(uint64_t*)data);
data += sizeof(uint64_t);
break;
case ARG_TYPE_STRING:
}
DEBUG_S("\n");
}
+ #endif
// Send it off
SendData(Request, RequestSize);
if( Request->CallID == SYS_EXIT ) return 0;
// Wait for a response (no timeout)
- return ReadData(Request, ResponseSize, 0);
+ ReadData(Request, sizeof(*Request), 0);
+ // TODO: Sanity
+ size_t recvbytes = sizeof(*Request), expbytes = Request->MessageLength;
+ char *ptr = (void*)Request->Params;
+ while( recvbytes < expbytes )
+ {
+ size_t len = ReadData(ptr, expbytes - recvbytes, 1000);
+ if( len == -1 ) {
+ return -1;
+ }
+ recvbytes += len;
+ ptr += len;
+ }
+ if( recvbytes > expbytes ) {
+ // TODO: Warning
+ }
+ return recvbytes;
}
void SendData(void *Data, int Length)
int len;
#if USE_TCP
- len = send(Data, Length, 0);
+ len = send(gSocket, Data, Length, 0);
#else
len = sendto(gSocket, Data, Length, 0,
(struct sockaddr*)&gSyscall_ServerAddr, sizeof(gSyscall_ServerAddr));
if( !ret ) {
printf("[ERROR %i] Timeout reading from socket\n", giSyscall_ClientID);
- return 0; // Timeout
+ return -2; // Timeout
}
#if USE_TCP
perror("ReadData");
exit(-1);
}
+ if( ret == 0 ) {
+ fprintf(stderr, "[ERROR %i] Connection closed.\n", giSyscall_ClientID);
+ close(gSocket);
+ exit(0);
+ }
DEBUG_S("%i bytes read from socket\n", ret);
#include <string.h>
#include <stddef.h>
#include <unistd.h>
+#include <spawn.h> // posix_spawn
#include "request.h"
+#if SYSCALL_TRACE
#define DEBUG(str, x...) Debug(str, x)
+#else
+#define DEBUG(...) do{}while(0)
+#endif
#define MAX_FPS 16
break;
// Data (special handling)
case 'd':
- len = va_arg(*Args, int);
+ len = va_arg(*Args, size_t);
str = va_arg(*Args, char*);
// Save the pointer for later
// Create parameter block
Dest->Type = ARG_TYPE_DATA;
- Dest->Length = len;
+ Dest->Length = str ? len : 0;
Dest->Flags = 0;
if( direction & 2 )
Dest->Flags |= ARG_FLAG_RETURN;
// Has data?
if( direction & 1 )
{
- if( DataDest )
+ if( DataDest && str )
memcpy(DataDest, str, len);
}
else
req->ClientID = 0; //< Filled later
req->CallID = SyscallID;
req->NParams = paramCount;
+ req->MessageLength = dataLength;
dataPtr = &req->Params[paramCount];
// Fill `output` and `input`
}
// Write changes to buffers
+ if( req->NParams - 1 != retCount ) {
+ fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
+ req->NParams, retCount, SyscallID);
+ exit(127);
+ }
retCount = 0;
for( i = 1; i < req->NParams; i ++ )
{
free( req );
free( retPtrs );
- DEBUG(": %llx", retValue);
+ DEBUG(": %i 0x%llx", SyscallID, retValue);
return retValue;
}
return ftell( gaSyscall_LocalFPs[FD] );
}
-int native_execve(const char *filename, char *const argv[], char *const envp[])
+int native_execve(const char *filename, const char *const argv[], const char *const envp[])
{
int ret;
- ret = execve(filename, argv, envp);
+ ret = execve(filename, (void*)argv, (void*)envp);
perror("native_execve");
return ret;
}
+
+int native_spawn(const char *filename, const char *const argv[], const char *const envp[])
+{
+ int rv;
+
+ rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);
+
+ return rv;
+}
* uint8_t paramData[SUM(params[].Lengh)];
*/
+typedef struct {
+ uint32_t pid;
+ uint32_t key;
+} tRequestAuthHdr;
+
typedef struct sRequestValue {
/// \see eArgumentTypes
uint16_t Type;
uint16_t Flags;
- uint16_t Length;
+ uint32_t Length;
} tRequestValue;
typedef struct sRequestHeader {
uint16_t ClientID;
uint16_t CallID; //!< \see eSyscalls
+ uint32_t MessageLength;
uint16_t NParams;
tRequestValue Params[];
// IPC
SYS_SLEEP,
SYS_AN_FORK,
+ SYS_AN_SPAWN,
SYS_SENDMSG,
SYS_GETMSG,
SYS_SELECT,
ARM_CPUNAME = gerneric-armv7
-CC = arm-elf-gcc -mcpu=$(ARM_CPUNAME)
-AS = arm-elf-gcc -mcpu=$(ARM_CPUNAME) -c
-LD = arm-elf-ld
+CC = arm-eabi-gcc -mcpu=$(ARM_CPUNAME)
+AS = arm-eabi-gcc -mcpu=$(ARM_CPUNAME) -c
+LD = arm-eabi-ld
OBJDUMP = arm-elf-objdump
DISASM = $(OBJDUMP) -d -S
ARCHDIR = armv7
SAVED_CC_ := $(CC)
SAVED_LD_ := $(LD)
+ifeq ($(HOST_ARCH),)
+$(error Please set HOST_ARCH to the architecture to compile, e.g. x86)
+endif
+
include $(ACESSDIR)/BuildConf/$(HOST_ARCH)/Makefile.cfg
OBJDUMP := objdump -S
#
CC = i586-elf-gcc
+#CC = clang -m32
LD = i586-elf-ld
+#CC = gcc
+#LD = ld
AS = nasm
-OBJDUMP = i586-elf-objdump
+#OBJDUMP = i586-elf-objdump
+OBJDUMP = objdump
RM = @rm -f
STRIP = strip
MODULES += Input/PS2KbMouse
MODULES += x86/ISADMA x86/VGAText
-MODULES += USB/Core USB/UHCI USB/EHCI
+MODULES += USB/Core USB/UHCI
+#MODULES += USB/EHCI
#USB/OHCI
MODULES += USB/HID USB/MSC
#MODULES += Interfaces/UDI
LD := $(PREFIX)-ld
DISASM = $(PREFIX)-objdump -d -M x86-64 -S
-KERNEL_CFLAGS := -mcmodel=kernel -nostdlib -mno-red-zone -Wall
-DYNMOD_CFLAGS := -mcmodel=small -fPIC -mno-red-zone
+KERNEL_CFLAGS := -mcmodel=kernel -nostdlib -mno-red-zone -Wall -mno-sse
+DYNMOD_CFLAGS := -mcmodel=small -fPIC -mno-red-zone -mno-sse
ARCHDIR = x86_64
--- /dev/null
+acpica-unix-*
+include
--- /dev/null
+
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../Makefile.cfg
+
+BIN := ../bin-$(ARCH)/libacpica.a
+
+_VERS := $(patsubst acpica-unix-%.tar.gz,%,$(wildcard acpica-unix-*.tar.gz))
+_VERS := $(sort $(_VERS))
+_LATEST := $(lastword $(_VERS))
+
+ifeq ($(ACPICAVER),)
+ ifeq ($(_LATEST),)
+ $(warning Unable to find an archive matching acpica-unix-%.tar.gz)
+ $(warning Go to https://www.acpica.org/downloads/ to get it)
+ $(error No ACPICA archive found)
+ endif
+
+ ifneq ($(_LATEST),$(_VERS))
+ $(warning Multiple archvies found, picked $(_LATEST))
+ endif
+ ACPICAVER := $(_LATEST)
+endif
+
+ACPICAROOT := acpica-unix-$(ACPICAVER)/
+ACPICA_ARCHIVE := acpica-unix-$(ACPICAVER).tar.gz
+COMPDIR := $(ACPICAROOT)source/components/
+KERNELDIR := ../../KernelLand/Kernel/
+
+CPPFLAGS += -I $(KERNELDIR)include -I$(KERNELDIR)arch/$(ARCHDIR)/include -D_MODULE_NAME_=\"ACPICA\"
+CPPFLAGS += -I $(ACPICAROOT)source/include -D _ACESS -D __KERNEL__
+CPPFLAGS += -D ARCH=$(ARCH) -D ARCHDIR=$(ARCHDIR) -D PLATFORM=\"$(PLATFORM)\" -D ARCHDIR_IS_$(ARCHDIR)=1 -D PLATFORM_is_$(PLATFORM)=1
+CPPFLAGS += -D KERNEL_VERSION=$(KERNEL_VERSION) -ffreestanding
+CFLAGS += -Wall -fno-stack-protector -Wstrict-prototypes -std=gnu99 -g
+
+SRCS := $(wildcard $(COMPDIR)*/*.c)
+OBJS := $(SRCS:$(COMPDIR)%.c=obj-$(ARCH)/%.o)
+
+ACENV_H := $(ACPICAROOT)source/include/platform/acenv.h
+ACACESS_H := $(ACPICAROOT)source/include/platform/acacess.h
+
+.PHONY: all clean
+
+ifeq ($(words $(SRCS)),0)
+extract: $(ACPICAROOT)
+ @echo Re-run make to compile
+endif
+
+all: $(BIN) include
+
+clean:
+ $(RM) -r obj-$(ARCH)/ include
+
+purge: clean
+ $(RM) -r $(ACPICAROOT)
+
+$(BIN): $(OBJS)
+ @mkdir -p $(dir $@)
+ @echo [AR] $@
+ @ar rcu $@ $(OBJS)
+
+include:
+ ln -s $(ACPICAROOT)source/include
+
+$(ACPICAROOT): $(ACPICA_ARCHIVE)
+ tar -xf $(ACPICA_ARCHIVE)
+
+$(ACACESS_H): acacess.h
+ cp $< $@
+
+$(ACENV_H): $(ACPICA_ARCHIVE) Makefile
+ tar -x -O -f $(ACPICA_ARCHIVE) $(ACENV_H) | sed 's/aclinux/acacess/' | sed 's/_LINUX/_ACESS/' > $@
+
+obj-$(ARCH)/%.o: $(COMPDIR)%.c $(ACENV_H) $(ACACESS_H)
+ @mkdir -p $(dir $@)
+ @echo [CC] -o $@
+ @$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+-include $(OBJS:%=%.dep)
+
--- /dev/null
+CPPFLAGS += -I $(ACESSDIR)/Externals/ACPICA/include -D_ACESS -D__KERNEL__
+EXTERN_OBJS += $(ACESSDIR)/Externals/bin-$(ARCH)/libacpica.a
+
+$(ACESSDIR)/Externals/bin-$(ARCH)/libacpica.a:
+ @make -C $(ACESSDIR)/Externals/ACPICA
+ @make -C $(ACESSDIR)/Externals/ACPICA
+
+
--- /dev/null
+/******************************************************************************
+ *
+ * Name: aclinux.h - OS specific defines, etc. for Linux
+ *
+ *****************************************************************************/
+
+#ifndef _ACPICA__ACACESS_H_
+#define _ACPICA__ACACESS_H_
+
+#define ACPI_USE_SYSTEM_CLIBRARY
+#define ACPI_USE_DO_WHILE_0
+#define ACPI_MUTEX_TYPE ACPI_OSL_MUTEX
+
+//#define ACPI_DEBUG_OUTPUT 1
+
+#ifdef __KERNEL__
+
+#include <acess.h>
+
+/* Host-dependent types and defines for in-kernel ACPICA */
+
+#define ACPI_MACHINE_WIDTH BITS
+
+typedef struct sACPICache tACPICache;
+
+#define ACPI_CACHE_T tACPICache
+#define ACPI_SPINLOCK tShortSpinlock*
+#define ACPI_CPU_FLAGS unsigned long
+
+#define COMPILER_DEPENDENT_UINT64 Uint64
+#define COMPILER_DEPENDENT_INT64 Sint64
+
+#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) do { \
+ Uint64 rem; \
+ Sint64 num = ((Sint64)n_hi<<32)|n_lo; \
+ int sgn = 1; \
+ if(num < 0) {num = -num; sgn = -sgn; } \
+ if(d32 < 0) {d32 = -d32; sgn = -sgn; } \
+ q32 = sgn * DivMod64U( num, d32, &rem ); \
+ r32 = rem; \
+ }while(0)
+#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) do { \
+ n_lo >>= 1; \
+ if(n_hi & 1) n_lo |= (1 << 31); \
+ n_hi >>= 1; \
+ }while(0)
+
+#else /* !__KERNEL__ */
+
+#error "Kernel only"
+
+#endif /* __KERNEL__ */
+
+/* Linux uses GCC */
+
+#include "acgcc.h"
+
+
+#if 0
+#ifdef __KERNEL__
+#define ACPI_SYSTEM_XFACE
+#include <actypes.h>
+/*
+ * Overrides for in-kernel ACPICA
+ */
+static inline acpi_thread_id acpi_os_get_thread_id(void)
+{
+ return (ACPI_THREAD_ID) (unsigned long) current;
+}
+
+/*
+ * The irqs_disabled() check is for resume from RAM.
+ * Interrupts are off during resume, just like they are for boot.
+ * However, boot has (system_state != SYSTEM_RUNNING)
+ * to quiet __might_sleep() in kmalloc() and resume does not.
+ */
+static inline void *acpi_os_allocate(acpi_size size)
+{
+ return malloc(size);
+}
+
+static inline void *acpi_os_allocate_zeroed(acpi_size size)
+{
+ return calloc(size, 1);
+}
+
+static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
+{
+// return kmem_cache_zalloc(cache,
+// irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+}
+
+#define ACPI_ALLOCATE(a) acpi_os_allocate(a)
+#define ACPI_ALLOCATE_ZEROED(a) acpi_os_allocate_zeroed(a)
+#define ACPI_FREE(a) free(a)
+
+#ifndef CONFIG_PREEMPT
+/*
+ * Used within ACPICA to show where it is safe to preempt execution
+ * when CONFIG_PREEMPT=n
+ */
+#define ACPI_PREEMPTION_POINT() \
+ do { \
+ Threads_Yield(); \
+ } while (0)
+#endif
+
+/*
+ * When lockdep is enabled, the spin_lock_init() macro stringifies it's
+ * argument and uses that as a name for the lock in debugging.
+ * By executing spin_lock_init() in a macro the key changes from "lock" for
+ * all locks to the name of the argument of acpi_os_create_lock(), which
+ * prevents lockdep from reporting false positives for ACPICA locks.
+ */
+#define AcpiOsCreateLock(__handle) \
+({ \
+ tShortlock *lock = ACPI_ALLOCATE_ZEROED(sizeof(*lock)); \
+ \
+ if (lock) { \
+ *(__handle) = lock; \
+ } \
+ lock ? AE_OK : AE_NO_MEMORY; \
+})
+
+#endif /* __KERNEL__ */
+#endif
+
+#endif /* __ACLINUX_H__ */
CFLAGS += -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wuninitialized
CFLAGS += -O3
LDFLAGS += -T arch/$(ARCHDIR)/link.ld -g
+LIBGCC_PATH := $(shell $(CC) -print-libgcc-file-name)
ifeq ($(PLATFORM),default)
OBJDIR := obj-$(ARCH)/
OBJ += drvutil_video.o drvutil_disk.o
OBJ += messages.o modules.o syscalls.o system.o
OBJ += threads.o mutex.o semaphore.o workqueue.o events.o rwlock.o
-OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o
+OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o drv/vpci.o
OBJ += drv/vterm.o drv/vterm_font.o drv/vterm_vt100.o drv/vterm_output.o drv/vterm_input.o drv/vterm_termbuf.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
@$(RM) $(BIN) ../Acess2.$(ARCH).gz $(BIN).dsm ../Map.$(ARCH).txt LineCounts.$(ARCH).txt
@$(RM) -r $(OBJDIR) $(OBJ) $(DEPFILES) $(BUILDINFO_SRC)
+# Lower to avoid taking default target from 'all'
+-include $(addprefix ../../Externals/,$(addsuffix /Makefile.kinc, $(EXTERNS)))
+
+
# Creates a stripped and compressed copy of the kernel
# and installs it to the target
install: $(BIN)
# - Disassembles it
# - Increments the build count
# - Does whatever architecture defined rules
-$(BIN): $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile ../../BuildConf/$(ARCH)/Makefile.cfg ../../BuildConf/$(ARCH)/$(PLATFORM).mk
+$(BIN): $(EXTERN_OBJS) $(OBJ) $(MODS) arch/$(ARCHDIR)/link.ld Makefile ../../BuildConf/$(ARCH)/Makefile.cfg ../../BuildConf/$(ARCH)/$(PLATFORM).mk
@echo --- LD -o $(BIN)
- @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) $(LIBGCC_PATH) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt
+ @$(LD) $(LDFLAGS) -o $(BIN) $(OBJ) $(MODS) $(EXTERN_OBJS) $(LIBGCC_PATH) --defsym __buildnum=$$(( $(BUILD_NUM) + 1 )) -Map ../Map.$(ARCH).txt
@$(DISASM) -S $(BIN) > $(BIN).dsm
@echo BUILD_NUM = $$(( $(BUILD_NUM) + 1 )) > Makefile.BuildNum.$(ARCH)
$(POSTBUILD)
@cp $(BIN) $(BIN)_
- @-$(STRIP) $(BIN)_
+ @$(STRIP) $(BIN)_ || true
@gzip -c $(BIN)_ > $(GZBIN)
@$(RM) $(BIN)_
A_OBJ = start.ao main.o lib.o lib.ao time.o pci.o debug.o
A_OBJ += mm_phys.o mm_virt.o proc.o proc.ao
+A_OBJ += vpci_$(PLATFORM).o
#main.c: Makefile.BuildNum.$(ARCH)
// === PROTOTYPES ===
Uint64 __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem);
Uint32 __divmod32(Uint32 Num, Uint32 Den, Uint32 *Rem);
+#if 0
Uint64 __udivdi3(Uint64 Num, Uint64 Den);
Uint64 __umoddi3(Uint64 Num, Uint64 Den);
Uint32 __udivsi3(Uint32 Num, Uint32 Den);
Uint32 __umodsi3(Uint32 Num, Uint32 Den);
Sint32 __divsi3(Sint32 Num, Sint32 Den);
Sint32 __modsi3(Sint32 Num, Sint32 Den);
+#endif
+void abort(void);
// === CODE ===
void *memcpy(void *_dest, const void *_src, size_t _length)
val32 |= val32 << 16;
// Force alignment
- while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value;
+ while( (tVAddr)dst8 & 3 ) *dst8 ++ = _value, _length --;
dst = (void *)dst8;
// DWORD copies
return ret;
}
+#if 0
// Unsigned Divide 64-bit Integer
Uint64 __udivdi3(Uint64 Num, Uint64 Den)
{
DivMod32S(Num, Den, &rem);
return rem;
}
+#endif
+
+void abort(void)
+{
+ for(;;);
+}
*(.usertext)
}
. += gUsertextPhysStart + _kernel_base - _usertext_vbase;
-
+
+ /DISCARD/ : { *(.ARM.extab.init .ARM.exidx.init) }
+ .ARM.extab : AT( ADDR(.ARM.extab) - _kernel_base)
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ }
+ PROVIDE_HIDDEN ( __exidx_start = . );
+ .ARM.exidx : AT( ADDR(.ARM.exidx) - _kernel_base)
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ }
+ PROVIDE_HIDDEN ( __exidx_end = . );
+ .eh_frame_hdr : AT( ADDR(.eh_frame_hdr) - _kernel_base) {
+ *(.eh_frame_hdr)
+ }
+ .eh_frame : AT( ADDR(.eh_frame) - _kernel_base) ONLY_IF_RO
+ {
+ KEEP (*(.eh_frame))
+ }
+ .gcc_except_table : AT( ADDR(.gcc_except_table) - _kernel_base) ONLY_IF_RO
+ {
+ *(.gcc_except_table .gcc_except_table.*)
+ }
+
/* 0x4000 (4 pages) alignment needed for root table */
- .data ALIGN(0x4000) : AT( ADDR(.data) - _kernel_base )
+ . = ALIGN(0x4000);
+ .data : AT( ADDR(.data) - _kernel_base )
{
*(.padata)
*(.data*)
*(KMODULES)
gKernelModulesEnd = .;
}
- .bss : AT( ADDR(.bss) - _kernel_base )
+ .bss ALIGN(0x1000) : AT( ADDR(.bss) - _kernel_base )
{
bss_start = .;
*(.bss*)
#include <hal_proc.h>
#define TRACE_MAPS 0
+#define TRACE_COW 1
#define AP_KRW_ONLY 1 // Kernel page
#define AP_KRO_ONLY 5 // Kernel RO page
#define AP_RO_USER 2 // User RO Page
#define PADDR_MASK_LVL1 0xFFFFFC00
+const char * const caAPValueNames[] = {
+ "AP_NOACCESS", "AP_KRW_ONLY",
+ "AP_RO_USER", "AP_RW_BOTH",
+ "AP_???_4", "AP_KRO_ONLY",
+ "AP_???_6", "AP_RO_BOTH"
+};
+
// === IMPORTS ===
extern Uint32 kernel_table0[];
tVAddr MM_NewKStack(int bGlobal);
void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info);
//void MM_DumpTables(tVAddr Start, tVAddr End);
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch);
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR);
// === GLOBALS ===
tPAddr giMM_ZeroPage;
}
// --- Exports ---
-tPAddr MM_GetPhysAddr(tVAddr VAddr)
+tPAddr MM_GetPhysAddr(const void *Ptr)
{
tMM_PageInfo pi;
- if( MM_int_GetPageInfo(VAddr, &pi) )
+ if( MM_int_GetPageInfo((tVAddr)Ptr, &pi) )
return 0;
- return pi.PhysAddr | (VAddr & ((1 << pi.Size)-1));
+ return pi.PhysAddr | ((tVAddr)Ptr & ((1 << pi.Size)-1));
}
Uint MM_GetFlags(tVAddr VAddr)
tVAddr addr, ofs;
addr = USER_STACK_TOP - USER_STACK_SIZE;
- if( MM_GetPhysAddr(addr + PAGE_SIZE) ) {
+ if( MM_GetPhysAddr( (void*)(addr + PAGE_SIZE) ) ) {
Log_Error("MMVirt", "Unable to create initial user stack, addr %p taken",
addr + PAGE_SIZE
);
{
if( giMM_ZeroPage && Info->PhysAddr == giMM_ZeroPage )
{
- Debug("%p => %8s - 0x%7x %i %x %s",
+ Debug("%p => %8s - 0x%7x D%i %x %s %s",
Start, "ZERO", Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
else
{
- Debug("%p => %8x - 0x%7x %i %x %s",
+ Debug("%p => %8x - 0x%7x D%i %x %s %s",
Start, Info->PhysAddr-Len, Len,
Info->Domain, Info->AP,
- Info->bGlobal ? "G" : "nG"
+ Info->bExecutable ? " X" : "nX",
+ Info->bGlobal ? " G" : "nG"
);
}
}
}
// NOTE: Runs in abort context, not much difference, just a smaller stack
-void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch)
+void MM_PageFault(Uint32 PC, Uint32 Addr, Uint32 DFSR, int bPrefetch, Uint32 UserLR)
{
int rv;
tMM_PageInfo pi;
Log_Error("MMVirt", "Code at %p accessed %p (DFSR = 0x%x)%s", PC, Addr, DFSR,
(bPrefetch ? " - Prefetch" : "")
);
+ Log_Error("MMVirt", "- User LR = 0x%x", UserLR);
+ const char * const dfsr_errors[] = {
+ /* 00000 */ "-", "Alignment Fault",
+ /* 00010 */ "Debug event", "Access Flag (Section)",
+ /* 00100 */ "Instr Cache Maint", "Translation (Section)",
+ /* 00110 */ "Access Flag (Page)", "Translation (Page)",
+ /* 01000 */ "Sync. External abort", "Domain (Section)",
+ /* 01010 */ "-", "Domain (Page)",
+ /* 01100 */ "Table Walk sync ext (lvl 1)", "Permission (Section)",
+ /* 01110 */ "Table Walk sync ext (lvl 2)", "Permission (Page)",
+ // 0b10000
+ /* 10000 */ "-", "-",
+ /* 10010 */ "-", "-",
+ /* 10100 */ "IMPL (Lockdown)", "-",
+ /* 10110 */ "Async. Extern. Abort", "-",
+ /* 11000 */ "Mem. access async pairity error", "Mem. access async pairity error",
+ /* 11010 */ "IMPL (Coprocessor abort)", "-",
+ /* 11100 */ "Table Walk Sync parity (lvl 1)", "-",
+ /* 11110 */ "Table Walk Sync parity (lvl 2)", "-"
+ };
+ int errcode = (DFSR & 0xF) | (((DFSR >> 10) & 1) << 4);
+ Log_Error("MMVirt", "- Errcode 0b%05b", errcode);
+ Log_Error("MMVirt", "- Dom %i %s %s",
+ (DFSR >> 4) & 0xF, (DFSR & 0x800 ? "Write": "Read"),
+ dfsr_errors[errcode]
+ );
+ Log_Error("MMVirt", "- AP=%i(%s) %s", pi.AP, caAPValueNames[pi.AP], pi.bExecutable ? " Executable":"");
if( Addr < 0x80000000 )
MM_DumpTables(0, 0x80000000);
else
return new->TID;
}
-int Proc_SpawnWorker( void (*Fnc)(void*), void *Ptr )
+tThread *Proc_SpawnWorker( void (*Fnc)(void*), void *Ptr )
{
tThread *new;
Uint32 sp;
new = Threads_CloneThreadZero();
- if(!new) return -1;
+ if(!new) return NULL;
if(new->ThreadName) free(new->ThreadName);
new->ThreadName = NULL;
if(!new->KernelStack) {
// TODO: Delete thread
Log_Error("Proc", "Unable to allocate kernel stack");
- return -1;
+ return NULL;
}
sp = new->KernelStack;
Threads_AddActive(new);
- return new->TID;
+ return new;
}
tTID Proc_NewKThread( void (*Fnc)(void*), void *Ptr )
@ cpsid ifa, #19
PUSH_GPRS
+ @ Get the user's LR value (and push to stack)
+ cps #31 @ Go to system mode
+ mov r1, lr
+ cps #19 @ Go to supervisor
+ mov r0, lr
+ cps #23 @ back to exception
+ push {r0,r1}
+
mov r3, #0 @ not a prefetch abort
mrc p15, 0, r2, c5, c0, 0 @ Read DFSR (Data Fault Status Register) to R2
mrc p15, 0, r1, c6, c0, 0 @ Read DFAR (Data Fault Address Register) into R1
mov r0, lr @ PC
ldr r4, =MM_PageFault
blx r4
+ add sp, #8 @ Undo push of the user/system LR
POP_GPRS
rfeia sp! @ Pop state (actually RFEFD)
@ cpsid ifa, #19
PUSH_GPRS
- ldr r0, =csAbort_Tag
- ldr r1, =csPrefetchAbort_Fmt
-# mov r2, lr
- mrc p15, 0, r2, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3
- mrc p15, 0, r3, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3
- ldr r5, =Log_Error
- blx r5
-.loop:
- wfi
- b .loop
+ @ Get the user's LR value (and push to stack)
+ cps #31 @ Go to system mode
+ mov r0, lr
+ cps #23 @ back to supervisor
+ push {r0}
+
+ mrc p15, 0, r2, c5, c0, 1 @ Read IFSR (Instruction Fault Status Register) into R3
+ mrc p15, 0, r1, c6, c0, 2 @ Read IFAR (Instruction Fault Address Register) into R3
+ mov r0, r1
+ mov r3, #1 @ IS a prefetch abort
+ ldr r4, =MM_PageFault
+ blx r4
+ add sp, #4 @ Undo push of the user LR
+
+ POP_GPRS
+ rfeia sp! @ Pop state (actually RFEFD)
+
.globl Undef_Handler
Undef_Handler:
wfi
csDataAbort_Fmt:
.asciz "Data Abort - %p accessed %p, DFSR=%x Unk:%x Unk:%x"
csPrefetchAbort_Fmt:
- .asciz "Prefetch Abort at %p, IFSR=%x"
+ .asciz "Prefetch Abort at %p, IFSR=%x, UserLR:0x%x"
csSyscallPrintRetAddr:
.asciz "Syscall ret to %p"
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * vpci_realview_pb.c
+ * - Realview PB VPCI Definitions
+ */
+#include <virtual_pci.h>
+
+// === PROTOTYPES ===
+
+// === GLOBALS ===
+tVPCI_Device gaVPCI_Devices[] = {
+};
+int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]);
+
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * vpci_tegra2.c
+ * - Tegra2 VPCI Definitions
+ */
+#include <virtual_pci.h>
+
+// === PROTOTYPES ===
+
+// === GLOBALS ===
+tVPCI_Device gaVPCI_Devices[] = {
+ {
+ .Vendor=0x0ACE,.Device=0x1100,
+ .Class = 0x0C032000, // Serial, USB, ECHI
+ .BARs = {0xC5000000,0,0,0,0,0},
+ .IRQ = 0*32+20,
+ },
+ {
+ .Vendor=0x0ACE,.Device=0x1100,
+ .Class = 0x0C032000, // Serial, USB, ECHI
+ .BARs = {0xC5004000,0,0,0,0,0},
+ .IRQ = 0*32+21,
+ },
+ {
+ .Vendor=0x0ACE,.Device=0x1100,
+ .Class = 0x0C032000, // Serial, USB, ECHI
+ .BARs = {0xC5008000,0,0,0,0,0},
+ .IRQ = 4*32+1,
+ }
+};
+int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]);
+
AS_SUFFIX = asm
-CPPFLAGS =
+CPPFLAGS =
CFLAGS =
ASFLAGS = -f elf
A_OBJ = start.ao main.o mboot.o lib.o desctab.ao errors.o irq.o
A_OBJ += mm_phys.o mm_virt.o
A_OBJ += proc.o proc.ao time.o vm8086.o
-A_OBJ += kpanic.o pci.o
+A_OBJ += kpanic.o pci.o vpci.o
+#A_OBJ += acpica.o
+
+#EXTERNS += ACPICA
+
--- /dev/null
+/*
+ * Acess2 Kernel (x86 Core)
+ * - By John Hodge (thePowersGang)
+ *
+ * acpica.c
+ * - ACPICA Interface
+ */
+#define DEBUG 1
+#define _AcpiModuleName "Shim"
+#define _COMPONENT "Acess"
+#include <acpi.h>
+#include <timers.h>
+#include <mutex.h>
+#include <semaphore.h>
+
+#define ONEMEG (1024*1024)
+
+// === GLOBALS ===
+// - RSDP Address from uEFI
+tPAddr gACPI_RSDPOverride = 0;
+
+// === PROTOTYPES ===
+int ACPICA_Initialise(void);
+void ACPI_int_InterruptProxy(int IRQ, void *data);
+
+
+// === CODE ===
+int ACPICA_Initialise(void)
+{
+ ACPI_STATUS rv;
+
+ #ifdef ACPI_DEBUG_OUTPUT
+ AcpiDbgLevel = ACPI_DB_ALL;
+ #endif
+
+ rv = AcpiInitializeSubsystem();
+ if( ACPI_FAILURE(rv) )
+ {
+ Log_Error("ACPI", "AcpiInitializeSubsystem: %i", rv);
+ return -1;
+ }
+
+ rv = AcpiInitializeTables(NULL, 16, FALSE);
+ if( ACPI_FAILURE(rv) )
+ {
+ Log_Error("ACPI", "AcpiInitializeTables: %i", rv);
+ AcpiTerminate();
+ return -1;
+ }
+
+ // AcpiInitializeTables?
+ rv = AcpiLoadTables();
+ if( ACPI_FAILURE(rv) )
+ {
+ Log_Error("ACPI", "AcpiLoadTables: %i", rv);
+ AcpiTerminate();
+ return -1;
+ }
+
+ rv = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
+ if( ACPI_FAILURE(rv) )
+ {
+ Log_Error("ACPI", "AcpiEnableSubsystem: %i", rv);
+ AcpiTerminate();
+ return -1;
+ }
+
+ return 0;
+}
+
+// ---------------
+// --- Exports ---
+// ---------------
+ACPI_STATUS AcpiOsInitialize(void)
+{
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsTerminate(void)
+{
+ return AE_OK;
+}
+
+ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void)
+{
+ ACPI_SIZE val;
+ ACPI_STATUS rv;
+
+ if( gACPI_RSDPOverride )
+ return gACPI_RSDPOverride;
+
+ rv = AcpiFindRootPointer(&val);
+ if( ACPI_FAILURE(rv) )
+ return 0;
+
+ LOG("val=%x", val);
+
+ return val;
+ // (Or use EFI)
+}
+
+ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES *PredefinedObject, ACPI_STRING *NewValue)
+{
+ *NewValue = NULL;
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_TABLE_HEADER **NewTable)
+{
+ *NewTable = NULL;
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER *ExisitingTable, ACPI_PHYSICAL_ADDRESS *NewAddress, UINT32 *NewTableLength)
+{
+ *NewAddress = 0;
+ return AE_OK;
+}
+
+// -- Memory Management ---
+struct sACPICache
+{
+ Uint16 nObj;
+ Uint16 ObjectSize;
+ char *Name;
+ void *First;
+ char ObjectStates[];
+};
+
+ACPI_STATUS AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth, ACPI_CACHE_T **ReturnCache)
+{
+ tACPICache *ret;
+ int namelen = (CacheName ? strlen(CacheName) : 0) + 1;
+ LOG("CacheName=%s, ObjSize=%x, MaxDepth=%x", CacheName, ObjectSize, MaxDepth);
+
+ ret = malloc(sizeof(*ret) + MaxDepth*sizeof(char) + namelen + MaxDepth*ObjectSize);
+ if( !ret ) return AE_NO_MEMORY;
+
+ ret->nObj = MaxDepth;
+ ret->ObjectSize = ObjectSize;
+ ret->Name = (char*)(ret->ObjectStates + MaxDepth);
+ ret->First = ret->Name + namelen;
+ if( CacheName )
+ strcpy(ret->Name, CacheName);
+ else
+ ret->Name[0] = 0;
+ memset(ret->ObjectStates, 0, sizeof(char)*MaxDepth);
+
+ LOG("Allocated cache '%s' (%i x 0x%x)", CacheName, MaxDepth, ObjectSize);
+
+ *ReturnCache = ret;
+
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
+{
+ if( Cache == NULL )
+ return AE_BAD_PARAMETER;
+
+ free(Cache);
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
+{
+ if( Cache == NULL )
+ return AE_BAD_PARAMETER;
+
+ memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
+
+ return AE_OK;
+}
+
+void *AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
+{
+ LOG("(Cache=%p)", Cache);
+ for(int i = 0; i < Cache->nObj; i ++ )
+ {
+ if( !Cache->ObjectStates[i] ) {
+ Cache->ObjectStates[i] = 1;
+ return (char*)Cache->First + i*Cache->ObjectSize;
+ }
+ }
+ // TODO
+ return NULL;
+}
+
+ACPI_STATUS AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
+{
+ if( Cache == NULL || Object == NULL )
+ return AE_BAD_PARAMETER;
+
+ tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
+ delta /= Cache->ObjectSize;
+
+ if( delta > Cache->nObj )
+ return AE_BAD_PARAMETER;
+
+ Cache->ObjectStates[delta] = 0;
+
+ return AE_OK;
+}
+
+void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length)
+{
+ if( PhysicalAddress < ONEMEG )
+ return (void*)(KERNEL_BASE | PhysicalAddress);
+
+ Uint ofs = PhysicalAddress & (PAGE_SIZE-1);
+ int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
+ void *rv = ((char*)MM_MapHWPages(PhysicalAddress, npages)) + ofs;
+ LOG("Map (%P+%i pg) to %p", PhysicalAddress, npages, rv);
+ return rv;
+}
+
+void AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length)
+{
+ if( (tVAddr)LogicalAddress - KERNEL_BASE < ONEMEG )
+ return ;
+
+ LOG("%p", LogicalAddress);
+
+ Uint ofs = (tVAddr)LogicalAddress & (PAGE_SIZE-1);
+ int npages = (ofs + Length + (PAGE_SIZE-1)) / PAGE_SIZE;
+ // TODO: Validate `Length` is the same as was passed to AcpiOsMapMemory
+ MM_UnmapHWPages( (tVAddr)LogicalAddress, npages);
+}
+
+ACPI_STATUS AcpiOsGetPhysicalAddress(void *LogicalAddress, ACPI_PHYSICAL_ADDRESS *PhysicalAddress)
+{
+ if( LogicalAddress == NULL || PhysicalAddress == NULL )
+ return AE_BAD_PARAMETER;
+
+ tPAddr rv = MM_GetPhysAddr(LogicalAddress);
+ if( rv == 0 )
+ return AE_ERROR;
+ *PhysicalAddress = rv;
+ return AE_OK;
+}
+
+void *AcpiOsAllocate(ACPI_SIZE Size)
+{
+ return malloc(Size);
+}
+
+void AcpiOsFree(void *Memory)
+{
+ return free(Memory);
+}
+
+BOOLEAN AcpiOsReadable(void *Memory, ACPI_SIZE Length)
+{
+ return CheckMem(Memory, Length);
+}
+
+BOOLEAN AcpiOsWritable(void *Memory, ACPI_SIZE Length)
+{
+ // TODO: Actually check if it's writable
+ return CheckMem(Memory, Length);
+}
+
+
+// --- Threads ---
+ACPI_THREAD_ID AcpiOsGetThreadId(void)
+{
+ return Threads_GetTID() + 1;
+}
+
+ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
+{
+ // TODO: Need to store currently executing functions
+ if( Function == NULL )
+ return AE_BAD_PARAMETER;
+ Proc_SpawnWorker(Function, Context);
+ return AE_OK;
+}
+
+void AcpiOsSleep(UINT64 Milliseconds)
+{
+ Time_Delay(Milliseconds);
+}
+
+void AcpiOsStall(UINT32 Microseconds)
+{
+ // TODO: need a microsleep function
+ Microseconds += (1000-1);
+ Microseconds /= 1000;
+ Time_Delay(Microseconds);
+}
+
+void AcpiOsWaitEventsComplete(void)
+{
+ // TODO:
+}
+
+// --- Mutexes etc ---
+ACPI_STATUS AcpiOsCreateMutex(ACPI_MUTEX *OutHandle)
+{
+ LOG("()");
+ if( !OutHandle )
+ return AE_BAD_PARAMETER;
+ tMutex *ret = calloc( sizeof(tMutex), 1 );
+ if( !ret )
+ return AE_NO_MEMORY;
+ ret->Name = "AcpiOsCreateMutex";
+ *OutHandle = ret;
+
+ return AE_OK;
+}
+
+void AcpiOsDeleteMutex(ACPI_MUTEX Handle)
+{
+ Mutex_Acquire(Handle);
+ free(Handle);
+}
+
+ACPI_STATUS AcpiOsAcquireMutex(ACPI_MUTEX Handle, UINT16 Timeout)
+{
+ if( Handle == NULL )
+ return AE_BAD_PARAMETER;
+
+ Mutex_Acquire(Handle);
+
+ return AE_OK;
+}
+
+void AcpiOsReleaseMutex(ACPI_MUTEX Handle)
+{
+ Mutex_Release(Handle);
+}
+
+ACPI_STATUS AcpiOsCreateSemaphore(UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle)
+{
+ LOG("(MaxUnits=%i,InitialUnits=%i)", MaxUnits, InitialUnits);
+ if( !OutHandle )
+ return AE_BAD_PARAMETER;
+ tSemaphore *ret = calloc( sizeof(tSemaphore), 1 );
+ if( !ret )
+ return AE_NO_MEMORY;
+
+ Semaphore_Init(ret, InitialUnits, MaxUnits, "AcpiOsCreateSemaphore", "");
+ *OutHandle = ret;
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE Handle)
+{
+ if( !Handle )
+ return AE_BAD_PARAMETER;
+
+ free(Handle);
+
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units, UINT16 Timeout)
+{
+ if( !Handle )
+ return AE_BAD_PARAMETER;
+
+ // Special case
+ if( Timeout == 0 )
+ {
+ // NOTE: Possible race condition
+ if( Semaphore_GetValue(Handle) >= Units ) {
+ Semaphore_Wait(Handle, Units);
+ return AE_OK;
+ }
+ return AE_TIME;
+ }
+
+ tTime start = now();
+ UINT32 rem = Units;
+ while(rem && now() - start < Timeout)
+ {
+ rem -= Semaphore_Wait(Handle, rem);
+ }
+
+ if( rem ) {
+ Semaphore_Signal(Handle, Units - rem);
+ return AE_TIME;
+ }
+
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE Handle, UINT32 Units)
+{
+ if( !Handle )
+ return AE_BAD_PARAMETER;
+
+ // TODO: Support AE_LIMIT detection early (to avoid blocks)
+
+ // NOTE: Blocks
+ int rv = Semaphore_Signal(Handle, Units);
+ if( rv != Units )
+ return AE_LIMIT;
+
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK *OutHandle)
+{
+ LOG("()");
+ if( !OutHandle )
+ return AE_BAD_PARAMETER;
+ tShortSpinlock *lock = calloc(sizeof(tShortSpinlock), 1);
+ if( !lock )
+ return AE_NO_MEMORY;
+
+ *OutHandle = lock;
+ return AE_OK;
+}
+
+void AcpiOsDeleteLock(ACPI_SPINLOCK Handle)
+{
+ free(Handle);
+}
+
+ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK Handle)
+{
+ SHORTLOCK(Handle);
+ return 0;
+}
+
+void AcpiOsReleaseLock(ACPI_SPINLOCK Handle, ACPI_CPU_FLAGS Flags)
+{
+ SHORTREL(Handle);
+}
+
+// --- Interrupt handling ---
+#define N_INT_LEVELS 16
+ACPI_OSD_HANDLER gaACPI_InterruptHandlers[N_INT_LEVELS];
+void *gaACPI_InterruptData[N_INT_LEVELS];
+ int gaACPI_InterruptHandles[N_INT_LEVELS];
+
+void ACPI_int_InterruptProxy(int IRQ, void *data)
+{
+ if( !gaACPI_InterruptHandlers[IRQ] )
+ return ;
+ gaACPI_InterruptHandlers[IRQ](gaACPI_InterruptData[IRQ]);
+}
+
+ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, void *Context)
+{
+ if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
+ return AE_BAD_PARAMETER;
+ if( gaACPI_InterruptHandlers[InterruptLevel] )
+ return AE_ALREADY_EXISTS;
+
+ gaACPI_InterruptHandlers[InterruptLevel] = Handler;
+ gaACPI_InterruptData[InterruptLevel] = Context;
+
+ gaACPI_InterruptHandles[InterruptLevel] = IRQ_AddHandler(InterruptLevel, ACPI_int_InterruptProxy, NULL);
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler)
+{
+ if( InterruptLevel >= N_INT_LEVELS || Handler == NULL )
+ return AE_BAD_PARAMETER;
+ if( gaACPI_InterruptHandlers[InterruptLevel] != Handler )
+ return AE_NOT_EXIST;
+ gaACPI_InterruptHandlers[InterruptLevel] = NULL;
+ IRQ_RemHandler(gaACPI_InterruptHandles[InterruptLevel]);
+ return AE_OK;
+}
+
+// --- Memory Access ---
+ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 *Value, UINT32 Width)
+{
+ void *ptr;
+ if( Address < ONEMEG ) {
+ ptr = (void*)(KERNEL_BASE | Address);
+ }
+ else {
+ ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
+ }
+
+ switch(Width)
+ {
+ case 8: *Value = *(Uint8 *)ptr; break;
+ case 16: *Value = *(Uint16*)ptr; break;
+ case 32: *Value = *(Uint32*)ptr; break;
+ case 64: *Value = *(Uint64*)ptr; break;
+ }
+
+ if( Address >= ONEMEG ) {
+ MM_FreeTemp(ptr);
+ }
+
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS Address, UINT64 Value, UINT32 Width)
+{
+ void *ptr;
+ if( Address < ONEMEG ) {
+ ptr = (void*)(KERNEL_BASE | Address);
+ }
+ else {
+ ptr = (char*)MM_MapTemp(Address) + (Address & 0xFFF);
+ }
+
+ switch(Width)
+ {
+ case 8: *(Uint8 *)ptr = Value; break;
+ case 16: *(Uint16*)ptr = Value; break;
+ case 32: *(Uint32*)ptr = Value; break;
+ case 64: *(Uint64*)ptr = Value; break;
+ default:
+ return AE_BAD_PARAMETER;
+ }
+
+ if( Address >= 1024*1024 ) {
+ MM_FreeTemp(ptr);
+ }
+
+ return AE_OK;
+}
+
+// --- Port Input / Output ---
+ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
+{
+ switch(Width)
+ {
+ case 8: *Value = inb(Address); break;
+ case 16: *Value = inw(Address); break;
+ case 32: *Value = ind(Address); break;
+ default:
+ return AE_BAD_PARAMETER;
+ }
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
+{
+ switch(Width)
+ {
+ case 8: outb(Address, Value); break;
+ case 16: outw(Address, Value); break;
+ case 32: outd(Address, Value); break;
+ default:
+ return AE_BAD_PARAMETER;
+ }
+ return AE_OK;
+}
+
+// --- PCI Configuration Space Access ---
+ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value, UINT32 Width)
+{
+ UNIMPLEMENTED();
+ return AE_NOT_IMPLEMENTED;
+}
+
+ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 Value, UINT32 Width)
+{
+ UNIMPLEMENTED();
+ return AE_NOT_IMPLEMENTED;
+}
+
+// --- Formatted Output ---
+void AcpiOsPrintf(const char *Format, ...)
+{
+ va_list args;
+ va_start(args, Format);
+
+ LogFV(Format, args);
+
+ va_end(args);
+}
+
+void AcpiOsVprintf(const char *Format, va_list Args)
+{
+ LogFV(Format, Args);
+}
+
+void AcpiOsRedirectOutput(void *Destination)
+{
+ // TODO: Do I even need to impliment this?
+}
+
+// --- Miscellaneous ---
+UINT64 AcpiOsGetTimer(void)
+{
+ return now() * 10 * 1000;
+}
+
+ACPI_STATUS AcpiOsSignal(UINT32 Function, void *Info)
+{
+ switch(Function)
+ {
+ case ACPI_SIGNAL_FATAL: {
+ ACPI_SIGNAL_FATAL_INFO *finfo = Info;
+ Log_Error("ACPI AML", "Fatal %x %x %x", finfo->Type, finfo->Code, finfo->Argument);
+ break; }
+ case ACPI_SIGNAL_BREAKPOINT: {
+ Log_Notice("ACPI AML", "Breakpoint %s", Info);
+ break; };
+ }
+ return AE_OK;
+}
+
+ACPI_STATUS AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
+{
+ UNIMPLEMENTED();
+ return AE_NOT_IMPLEMENTED;
+}
+
#if LOCK_DISABLE_INTS
int IF; //!< Interrupt state on call to SHORTLOCK
#endif
+ void *LockedBy;
};
// === MACROS ===
typedef signed short Sint16;
typedef signed long Sint32;
typedef signed long long Sint64;
-typedef Uint size_t;
typedef char BOOL;
typedef Uint32 tPAddr;
Log_Log("IRQ", "Added IRQ%i Cb#%i %p", Num, i, Callback);
gIRQ_Handlers[Num][i] = Callback;
gaIRQ_DataPointers[Num][i] = Ptr;
- return 1;
+ return Num * MAX_CALLBACKS_PER_IRQ + i;
}
}
Log_Warning("IRQ", "No free callbacks on IRQ%i", Num);
- return 0;
+ return -1;
+}
+
+void IRQ_RemHandler(int Handle)
+{
+ int Num = Handle / MAX_CALLBACKS_PER_IRQ;
+ int id = Handle % MAX_CALLBACKS_PER_IRQ;
+ gIRQ_Handlers[Num][id] = NULL;
}
__ASM__ ("pushf;\n\tpop %0" : "=r"(IF));
IF &= 0x200; // AND out all but the interrupt flag
+ if( CPU_HAS_LOCK(Lock) )
+ {
+ Panic("Double lock of %p, %p req, %p has", Lock, __builtin_return_address(0), Lock->LockedBy);
+ for(;;);
+ }
+
#if TRACE_LOCKS
if( TRACE_LOCK_COND )
{
// Wait for another CPU to release
__AtomicTestSetLoop( (Uint*)&Lock->Lock, cpu );
Lock->IF = IF;
+ Lock->LockedBy = __builtin_return_address(0);
#if TRACE_LOCKS
if( TRACE_LOCK_COND )
* Linker Script
*/
-lowStart = start - 0xC0000000;
-ENTRY(lowStart)
+ENTRY(start)
OUTPUT_FORMAT(elf32-i386)
SECTIONS {
__load_addr = .;
.multiboot : AT(ADDR(.multiboot)) {
*(.multiboot)
+ *(.inittext)
}
. += 0xC0000000;
extern void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges);
extern void MM_InstallVirtual(void);
extern int Time_Setup(void);
+//extern int ACPICA_Initialise(void);
// === PROTOTYPES ===
int kmain(Uint MbMagic, void *MbInfoPtr);
gsBootCmdLine = (char*)(mbInfo->CommandLine + KERNEL_BASE);
// Adjust Multiboot structure address
- mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE );
+ mbInfo = (void*)( (tVAddr)MbInfoPtr + KERNEL_BASE );
nPMemMapEnts = Multiboot_LoadMemoryMap(mbInfo, KERNEL_BASE, pmemmap, MAX_PMEMMAP_ENTS,
KERNEL_LOAD, (tVAddr)&gKernelEnd - KERNEL_BASE);
MM_InstallVirtual(); // Clean up virtual address space
Heap_Install(); // Create initial heap
+ Time_Setup(); // Initialise timing
// Start Multitasking
Threads_Init();
-
- // Start Timers
- Time_Setup();
-
+
+ // Poke ACPICA
+// ACPICA_Initialise();
+
Log_Log("Arch", "Starting VFS...");
// Load Virtual Filesystem
VFS_Init();
* mboot.c
* - Multiboot Support
*/
-#define DEBUG 0
+#define DEBUG 1
#include <acess.h>
#include <mboot.h>
ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd",
MBInfo, MapOffset, Map, MapSize, KStart, KEnd);
- // Build up memory map
- nPMemMapEnts = 0;
- while( ent < last && nPMemMapEnts < MapSize )
+ // Check that the memory map is present
+ if( MBInfo->Flags & (1 << 6) )
{
- tPMemMapEnt *nent = &Map[nPMemMapEnts];
- nent->Start = ent->Base;
- nent->Length = ent->Length;
- switch(ent->Type)
+ // Build up memory map
+ nPMemMapEnts = 0;
+ while( ent < last && nPMemMapEnts < MapSize )
{
- case 1:
- nent->Type = PMEMTYPE_FREE;
- break;
- default:
- nent->Type = PMEMTYPE_RESERVED;
- break;
+ tPMemMapEnt *nent = &Map[nPMemMapEnts];
+ if( !MM_GetPhysAddr(ent) )
+ Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)",
+ nPMemMapEnts, ent);
+ LOG("%llx+%llx", ent->Base, ent->Length);
+
+ nent->Start = ent->Base;
+ nent->Length = ent->Length;
+ switch(ent->Type)
+ {
+ case 1:
+ nent->Type = PMEMTYPE_FREE;
+ break;
+ default:
+ nent->Type = PMEMTYPE_RESERVED;
+ break;
+ }
+ nent->NUMADomain = 0;
+
+ nPMemMapEnts ++;
+ ent = (void*)( (tVAddr)ent + ent->Size + 4 );
}
- nent->NUMADomain = 0;
-
- nPMemMapEnts ++;
- ent = (void*)( (tVAddr)ent + ent->Size + 4 );
+ }
+ else if( MBInfo->Flags & (1 << 0) )
+ {
+ Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper");
+ nPMemMapEnts = 2;
+ Map[0].Start = 0;
+ Map[0].Length = MBInfo->LowMem * 1024;
+ Map[0].Type = PMEMTYPE_FREE;
+ Map[0].NUMADomain = 0;
+
+ Map[1].Start = 0x100000;
+ Map[1].Length = MBInfo->HighMem * 1024;
+ Map[1].Type = PMEMTYPE_FREE;
+ Map[1].NUMADomain = 0;
+ }
+ else
+ {
+ Log_KernelPanic("MBoot", "Multiboot didn't pass memory information");
}
// Ensure it's valid
+ LOG("Validating");
nPMemMapEnts = PMemMap_ValidateMap(Map, nPMemMapEnts, MapSize);
// TODO: Error handling
// Replace kernel with PMEMTYPE_USED
+ LOG("Marking kernel");
nPMemMapEnts = PMemMap_MarkRangeUsed(
Map, nPMemMapEnts, MapSize,
KStart, KEnd - KStart
);
- // Replace modules with PMEMTYPE_USED
- nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize,
- MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module)
- );
- tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset);
- for( int i = 0; i < MBInfo->ModuleCount; i ++ )
+ LOG("Dumping");
+ PMemMap_DumpBlocks(Map, nPMemMapEnts);
+
+ // Check if boot modules were passed
+ if( MBInfo->Flags & (1 << 3) )
{
- nPMemMapEnts = PMemMap_MarkRangeUsed(
- Map, nPMemMapEnts, MapSize,
- mods->Start, mods->End - mods->Start
+ // Replace modules with PMEMTYPE_USED
+ nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize,
+ MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module)
);
+ LOG("MBInfo->Modules = %x", MBInfo->Modules);
+ tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset);
+ for( int i = 0; i < MBInfo->ModuleCount; i ++ )
+ {
+ LOG("&mods[%i] = %p", i, &mods[i]);
+ LOG("mods[i] = {0x%x -> 0x%x}", mods[i].Start, mods[i].End);
+ nPMemMapEnts = PMemMap_MarkRangeUsed(
+ Map, nPMemMapEnts, MapSize,
+ mods[i].Start, mods[i].End - mods[i].Start
+ );
+ }
}
-
+
// Debug - Output map
PMemMap_DumpBlocks(Map, nPMemMapEnts);
tBootModule *Multiboot_LoadModules(tMBoot_Info *MBInfo, tVAddr MapOffset, int *ModuleCount)
{
+ if( !(MBInfo->Flags & (1 << 3)) ) {
+ *ModuleCount = 0;
+ Log_Log("Arch", "No multiboot module information passed");
+ return NULL;
+ }
+
tMBoot_Module *mods = (void*)( MBInfo->Modules + MapOffset );
*ModuleCount = MBInfo->ModuleCount;
tBootModule *ret = malloc( MBInfo->ModuleCount * sizeof(*ret) );
gaPageReferences = (void*)MM_REFCOUNT_BASE;
+ Log_Debug("PMem", "maxAddr = %P", maxAddr);
Log_Log("PMem", "Physical memory set up (%lli pages of ~%lli MiB used)",
giPhysAlloc, (giTotalMemorySize*PAGE_SIZE)/(1024*1024)
);
Mutex_Release( &glPhysAlloc );
LEAVE('X', ret);
+ if( ret == 0x17FFE000 )
+ LogF("TRIP!\n");
#if TRACE_ALLOCS
if( now() > 4000 ) {
Log_Debug("PMem", "MM_AllocPhys: RETURN %P (%i free)", ret, giPageCount-giPhysAlloc);
*(Uint16*)(KERNEL_BASE|0x469) = 0xFFFF;
outb(0x70, 0x0F); outb(0x71, 0x0A); // Set warm reset flag
MP_SendIPI(gaCPUs[CPU].APICID, 0, 5); // Init IPI
-
- // Delay
- inb(0x80); inb(0x80); inb(0x80); inb(0x80);
-
+
+ // Take a quick nap (20ms)
+ Time_Delay(20);
+
// TODO: Use a better address, preferably registered with the MM
// - MM_AllocDMA mabye?
// Create a far jump
*(Uint8*)(KERNEL_BASE|0x11000) = 0xEA; // Far JMP
- *(Uint16*)(KERNEL_BASE|0x11001) = (Uint)&APStartup - (KERNEL_BASE|0xFFFF0); // IP
+ *(Uint16*)(KERNEL_BASE|0x11001) = (Uint16)&APStartup + 0x10; // IP
*(Uint16*)(KERNEL_BASE|0x11003) = 0xFFFF; // CS
+
+ giNumInitingCPUs ++;
+
// Send a Startup-IPI to make the CPU execute at 0x11000 (which we
// just filled)
MP_SendIPI(gaCPUs[CPU].APICID, 0x11, 6); // StartupIPI
- giNumInitingCPUs ++;
+ tTime timeout = now() + 2;
+ while( giNumInitingCPUs && now() > timeout )
+ HALT();
+
+ if( giNumInitingCPUs == 0 )
+ return ;
+
+ // First S-IPI failed, send again
+ MP_SendIPI(gaCPUs[CPU].APICID, 0x11, 6);
+ timeout = now() + 2;
+ while( giNumInitingCPUs && now() > timeout )
+ HALT();
+ if( giNumInitingCPUs == 0 )
+ return ;
+
+ Log_Notice("Proc", "CPU %i (APIC %x) didn't come up", CPU, gaCPUs[CPU].APICID);
+
+ // Oh dammit.
+ giNumInitingCPUs = 0;
}
void MP_SendIPIVector(int CPU, Uint8 Vector)
// Hi
val = (Uint)APICID << 24;
-// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[1], val);
gpMP_LocalAPIC->ICR[1].Val = val;
// Low (and send)
val = ((DeliveryMode & 7) << 8) | (Vector & 0xFF);
-// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[0], val);
gpMP_LocalAPIC->ICR[0].Val = val;
}
#endif
void Proc_Start(void)
{
#if USE_MP
- int i;
- #endif
+ // BSP still should run the current task
+ gaCPUs[giProc_BootProcessorID].Current = &gThreadZero;
+
+ __asm__ __volatile__ ("sti");
- #if USE_MP
// Start APs
- for( i = 0; i < giNumCPUs; i ++ )
+ for( int i = 0; i < giNumCPUs; i ++ )
{
- if(i) gaCPUs[i].Current = NULL;
-
+ if(i != giProc_BootProcessorID)
+ gaCPUs[i].Current = NULL;
+
// Create Idle Task
Proc_NewKThread(Proc_IdleThread, &gaCPUs[i]);
MP_StartAP( i );
}
}
-
- // BSP still should run the current task
- gaCPUs[0].Current = &gThreadZero;
-
- // Start interrupts and wait for APs to come up
- Log_Debug("Proc", "Waiting for APs to come up");
- __asm__ __volatile__ ("sti");
- while( giNumInitingCPUs ) __asm__ __volatile__ ("hlt");
#else
// Create Idle Task
Proc_NewKThread(Proc_IdleThread, &gaCPUs[0]);
* \fn int Proc_SpawnWorker(void)
* \brief Spawns a new worker thread
*/
-int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
+tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
tThread *new;
Uint stack_contents[4];
new = Threads_CloneThreadZero();
if(!new) {
Warning("Proc_SpawnWorker - Out of heap space!\n");
- return -1;
+ return NULL;
}
// Create the stack contents
new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
- return new->TID;
+ return new;
}
/**
; dd 8
;mboot2_end:
-[section .text]
+[section .inittext]
[extern kmain]
[extern Desctab_Install]
[global start]
; Load initial GDT
mov ax, 0xFFFF
mov ds, ax
- lgdt [DWORD ds:lGDTPtr-KERNEL_BASE-0xFFFF0]
+ lgdt [DWORD ds:lGDTPtr-0xFFFF0]
; Enable PMode in CR0
mov eax, cr0
or al, 1
mov cr0, eax
; Jump into PMode
- jmp 08h:DWORD .ProtectedMode-KERNEL_BASE
+ jmp 08h:DWORD .ProtectedMode
[bits 32]
.ProtectedMode:
; Load segment registers
jmp .hlt
%endif
+;
+;
+;
+[section .text]
[global GetEIP]
GetEIP:
mov eax, [esp]
--- /dev/null
+/*
+ * Acess2 Kernel x86 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * vpci.c
+ * - Virtual PCI Bus
+ */
+#include <virtual_pci.h>
+
+// === GLOBALS ===
+ int giVPCI_DeviceCount = 0;
+tVPCI_Device gaVPCI_Devices[0];
+
A_OBJ := start32.ao start64.ao desctab.ao proc.ao
A_OBJ += main.o lib.o proc.o mm_virt.o mm_phys.o
A_OBJ += kernelpanic.o errors.o time.o pci.o
-A_OBJ += vm8086.o
+A_OBJ += vm8086.o vpci.o
A_OBJ += ../x86/mboot.o
# rme.o
[BITS 64]
[extern Log]
+[extern Log_Debug]
[extern gGDTPtr]
[extern gGDT]
push rax
push rdx
sub rsp, 8
- mov rcx, rdi ; IRQ Number
- mov rdx, rsi ; Callback
- mov rsi, rax ; Pointer
- mov rdi, csIRQ_Assigned
- call Log
+ mov rcx, rsi ; IRQ Number
+ mov rdx, rdi ; Callback
+ mov rsi, csIRQ_Assigned
+ mov rdi, csIRQ_Tag
+ call Log_Debug
add rsp, 8
pop rdx
pop rax
[section .rodata]
csIRQ_Assigned:
- db "IRQ %p := %p (IRQ %i)",0
+ db "IRQ %i .= %p",0
csIRQ_Fired:
db "IRQ %i fired",0
+csIRQ_Tag:
+ db "IRQ",0
[section .text]
%macro ISR_NOERRNO 1
%assign i i+1
%endrep
+[extern Proc_int_SetIRQIP]
+
[global IrqCommon]
IrqCommon:
PUSH_GPR
push gs
push fs
-
+
+ mov rdi, [rsp+(16+2+2)*8] ; 2SReg + GPRs + Int/Errcode = RIP
+ call Proc_int_SetIRQIP
+ push rax
+
; mov rdi, csIRQ_Fired
; mov rsi, [rsp+(16+2)*8]
; call Log
- mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
+ mov ebx, [rsp+(1+2+16)*8] ; Get interrupt number (16 GPRS + 2 SRs)
shl ebx, 2 ; *4
mov rax, gaIRQ_Handlers
lea rbx, [rax+rbx*8]
test rax, rax ; Check if it exists
jz .skip.%[i]
; Set RDI to IRQ number
- mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1+1)*8] ; Get IRQ number
mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
call rax ; Call
.skip.%[i]:
; ACK
mov al, 0x20
- mov rdi, [rsp+(16+2)*8] ; Get IRQ number
+ mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
cmp rdi, 8
jb .skipAckSecondary
out 0xA0, al
.skipAckSecondary:
out 0x20, al
+
+ pop rdi
+ call Proc_int_SetIRQIP
pop fs
pop gs
mov [rsp+0x28], r10 ; Arg4
mov [rsp+0x30], r8 ; Arg5
mov [rsp+0x38], r9 ; Arg6
-
+
+ mov rdi, rcx
+ call Proc_int_SetIRQIP
+
mov rdi, rsp
sub rsp, 8
call SyscallHandler
extern int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
extern void Error_Backtrace(Uint IP, Uint BP);
extern void Proc_EnableSSE(void);
+extern void Threads_Dump(void);
extern void Proc_RestoreSSE(Uint32 Data);
// === PROTOTYPES ===
*(Uint8*)(Regs->RIP+2), *(Uint8*)(Regs->RIP+3)
);
break;
+ case 2: // NMI
+ Threads_Dump();
+ break;
}
__asm__ __volatile__ ("cli");
// === FUNCTIONS ===
void MM_FinishVirtualInit(void);
tVAddr MM_NewKStack(void);
-tVAddr MM_Clone(void);
+tVAddr MM_Clone(int bCopyUser);
tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize);
#endif
return ret;
}
+EXPORT(memcpy);
+EXPORT(memset);
+
// === CONSTANTS ===
#define KERNEL_LOAD 0x100000
#define MAX_PMEMMAP_ENTS 16
+#define MAX_ARGSTR_POS (0x200000-0x2000)
// === IMPORTS ===
extern void Desctab_Init(void);
// === GLOBALS ==
char *gsBootCmdLine = NULL;
+tBootModule *gaArch_BootModules;
+ int giArch_NumBootModules = 0;
// === CODE ===
void kmain(Uint MbMagic, void *MbInfoPtr)
// Adjust Multiboot structure address
mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE );
gsBootCmdLine = (char*)( (Uint)mbInfo->CommandLine + KERNEL_BASE);
+ // TODO: ref above?
nPMemMapEnts = Multiboot_LoadMemoryMap(mbInfo, KERNEL_BASE, pmemmap, MAX_PMEMMAP_ENTS,
KERNEL_LOAD, (tVAddr)&gKernelEnd - KERNEL_BASE
);
MM_InitPhys( nPMemMapEnts, pmemmap ); // Set up physical memory manager
Log("gsBootCmdLine = '%s'", gsBootCmdLine);
+ switch(MbMagic)
+ {
+ case MULTIBOOT_MAGIC:
+ MM_RefPhys( mbInfo->CommandLine );
+ break;
+ }
+
*(Uint16*)(KERNEL_BASE|0xB8000) = 0x1F00|'D';
Heap_Install();
Log_Log("Arch", "Starting VFS...");
VFS_Init();
+ gaArch_BootModules = Multiboot_LoadModules(mbInfo, KERNEL_BASE, &giArch_NumBootModules);
+
*(Uint16*)(KERNEL_BASE|0xB8000) = 0x1F00|'Z';
// Pass on to Independent Loader
void Arch_LoadBootModules(void)
{
-
+ int i, j, numPages;
+ Log("gsBootCmdLine = '%s'", gsBootCmdLine);
+ for( i = 0; i < giArch_NumBootModules; i ++ )
+ {
+ Log_Log("Arch", "Loading '%s'", gaArch_BootModules[i].ArgString);
+
+ if( !Module_LoadMem( gaArch_BootModules[i].Base,
+ gaArch_BootModules[i].Size, gaArch_BootModules[i].ArgString
+ ) )
+ {
+ Log_Warning("Arch", "Unable to load module");
+ }
+
+ // Unmap and free
+ numPages = (gaArch_BootModules[i].Size + ((Uint)gaArch_BootModules[i].Base&0xFFF) + 0xFFF) >> 12;
+ MM_UnmapHWPages( (tVAddr)gaArch_BootModules[i].Base, numPages );
+
+ for( j = 0; j < numPages; j++ )
+ MM_DerefPhys( gaArch_BootModules[i].PBase + (j << 12) );
+
+ if( (tVAddr) gaArch_BootModules[i].ArgString < KERNEL_BASE )
+ MM_UnmapHWPages( (tVAddr)gaArch_BootModules[i].ArgString, 2 );
+ }
+ Log_Log("Arch", "Boot modules loaded");
+ if( gaArch_BootModules )
+ free( gaArch_BootModules );
}
void StartupPrint(const char *String)
expected |= expected_pml4 & PF_NX;
expected |= expected_pdp & PF_NX;
expected |= expected_pd & PF_NX;
- Log("expected (pml4 = %x, pdp = %x, pd = %x)",
- expected_pml4, expected_pdp, expected_pd);
+// Log("expected (pml4 = %x, pdp = %x, pd = %x)",
+// expected_pml4, expected_pdp, expected_pd);
// Dump
MM_int_DumpTablesEnt( rangeStart, curPos - rangeStart, expected );
expected = CHANGEABLE_BITS;
Size += Addr & (PAGE_SIZE-1);
Addr &= ~(PAGE_SIZE-1);
- Addr &= ((1UL << 48)-1); // Clap to address space
+ // NC addr
+ if( ((Addr >> 47) & 1) != ((Addr>>48) == 0xFFFF))
+ return 0;
+ Addr &= ((1UL << 48)-1); // Clamp to address space
pml4 = Addr >> 39;
pdp = Addr >> 30;
dir = Addr >> 21;
tab = Addr >> 12;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
- if( !(PAGEDIR(dir) & 1) ) return 0;
- if( !(PAGETABLE(tab) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "PML4E %i NP", pml4);
+ return 0;
+ }
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "PDPE %i NP", pdp);
+ return 0;
+ }
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "PDE %i NP", dir);
+ return 0;
+ }
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "PTE %i NP", tab);
+ return 0;
+ }
bIsUser = !!(PAGETABLE(tab) & PF_USER);
while( Size >= PAGE_SIZE )
{
+ tab ++;
+ Size -= PAGE_SIZE;
+
if( (tab & 511) == 0 )
{
dir ++;
- if( ((dir >> 9) & 511) == 0 )
+ if( (dir & 511) == 0 )
{
pdp ++;
- if( ((pdp >> 18) & 511) == 0 )
+ if( (pdp & 511) == 0 )
{
pml4 ++;
- if( !(PAGEMAPLVL4(pml4) & 1) ) return 0;
+ if( !(PAGEMAPLVL4(pml4) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PML4E %x NP, Size=%x", pml4, Size);
+ return 0;
+ }
}
- if( !(PAGEDIRPTR(pdp) & 1) ) return 0;
+ if( !(PAGEDIRPTR(pdp) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDPE %x NP", pdp);
+ return 0;
+ }
+ }
+ if( !(PAGEDIR(dir) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PDE %x NP", dir);
+ return 0;
}
- if( !(PAGEDIR(dir) & 1) ) return 0;
}
- if( !(PAGETABLE(tab) & 1) ) return 0;
- if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0;
-
- tab ++;
- Size -= PAGE_SIZE;
+ if( !(PAGETABLE(tab) & 1) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x NP", tab);
+ return 0;
+ }
+ if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) {
+ Log_Debug("MMVirt", "IsValidBuffer - PTE %x Not user", tab);
+ return 0;
+ }
}
return 1;
}
// Allocated successfully, now map
ret = MM_MapHWPages(phys, Pages);
+ *PhysAddr = phys;
// MapHWPages references the pages, so deref them back down to 1
for(;Pages--;phys+=0x1000)
MM_DerefPhys(phys);
return 0;
}
- *PhysAddr = phys;
return ret;
}
// --- Address Space Clone --
-tPAddr MM_Clone(void)
+tPAddr MM_Clone(int bNoUserCopy)
{
tPAddr ret;
int i;
INVLPG_ALL();
// #3 Set Copy-On-Write to all user pages
- if( Threads_GetPID() != 0 )
+ if( Threads_GetPID() != 0 && !bNoUserCopy )
{
for( i = 0; i < 256; i ++)
{
tmp_addr = MM_MapTemp(phys);
dest = (char*)tmp_addr + (0x1000 - StackSize);
memcpy( dest, StackData, StackSize );
- Log_Debug("MM", "MM_NewWorkerStack: %p->%p %i bytes (i=%i)", StackData, dest, StackSize, i);
- Log_Debug("MM", "MM_NewWorkerStack: ret = %p", ret);
MM_FreeTemp(tmp_addr);
}
mov rdi, [rsp+0x10]
mov rax, [rsp+0x8]
add rsp, 0x10 ; Reclaim stack space (thread/fcn)
- xchg bx, bx
+ ;xchg bx, bx
call rax
; Quit thread with RAX as the return code
PUSH_GPR
; Save RSP
mov [rdi], rsp
+ ; Call MM_Clone (with bNoUserCopy flag)
+ mov rdi, rdx
call MM_Clone
; Save CR3
mov rsi, [rsp+0x30] ; Saved version of RSI
extern Uint GetRIP(void); // start.asm
extern Uint SaveState(Uint *RSP, Uint *Regs);
-extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3);
+extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM);
extern void NewTaskHeader(void); // Actually takes cdecl args
extern void Proc_InitialiseSSE(void);
extern void Proc_SaveSSE(Uint DestPtr);
//void Proc_DumpThreadCPUState(tThread *Thread);
//void Proc_Reschedule(void);
void Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
+Uint Proc_int_SetIRQIP(Uint RIP);
// === GLOBALS ===
//!\brief Used by desctab.asm in SyscallStub
if(!newThread) return -1;
// Save core machine state
- rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
+ rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
if(rip == 0) return 0; // Child
newThread->KernelStack = cur->KernelStack;
newThread->SavedState.RIP = rip;
* \fn int Proc_SpawnWorker(void)
* \brief Spawns a new worker thread
*/
-int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
+tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
tThread *new, *cur;
Uint stack_contents[3];
new = Threads_CloneThreadZero();
if(!new) {
Warning("Proc_SpawnWorker - Out of heap space!\n");
- return -1;
+ return NULL;
}
// Create the stack contents
new->Status = THREAD_STAT_PREINIT;
Threads_AddActive( new );
- return new->TID;
+ return new;
}
/**
void Proc_DumpThreadCPUState(tThread *Thread)
{
- Log(" At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ if( Thread->CurCPU == GetCPUNum() ) {
+ // TODO: Backtrace to IRQ
+ Log(" IRQ %016llx", Thread->SavedState.UserRIP);
+ }
+ else {
+ Log(" At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP);
+ Log(" User %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+ }
}
void Proc_Reschedule(void)
// Update CPU state
gaCPUs[cpu].Current = nextthread;
- gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
+ gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
__asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
if( curthread )
#endif
}
+Uint Proc_int_SetIRQIP(Uint RIP)
+{
+ int cpu = GetCPUNum();
+ tThread *thread = gaCPUs[cpu].Current;
+ Uint rv = thread->SavedState.UserRIP;
+ thread->SavedState.UserRIP = RIP;
+ return rv;
+}
+
// === EXPORTS ===
EXPORT(Proc_SpawnWorker);
--- /dev/null
+/*
+ * Acess2 Kernel x86 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * vpci.c
+ * - Virtual PCI Bus
+ */
+#include <virtual_pci.h>
+
+// === GLOBALS ===
+ int giVPCI_DeviceCount = 0;
+tVPCI_Device gaVPCI_Devices[0];
+
/*\r
- * Acess v0.1\r
- * ELF Executable Loader Code\r
+ * Acess2 Kernel\r
+ * - By John Hodge (thePowersGang)\r
+ *\r
+ * elf.c\r
+ * - ELF Executable Loader Code\r
*/\r
#define DEBUG 0\r
#include <acess.h>\r
#include <binary.h>\r
\r
+// ---- Import linking code from userland\r
#define _COMMON_H\r
#define SysDebug(v...) LOG(v)\r
-#define DISABLE_ELF64\r
-void *GetSymbol(const char *Name, size_t *Size);\r
-void *GetSymbol(const char *Name, size_t *Size) { Uint val; Binary_GetSymbol(Name, &val); if(Size)*Size=0; return (void*)val; };\r
+#if BITS <= 32\r
+# define DISABLE_ELF64\r
+#endif\r
+static int GetSymbol(const char *Name, void **Value, size_t *Size);\r
+static int GetSymbol(const char *Name, void **Value, size_t *Size) {\r
+ Uint val;\r
+ if(!Binary_GetSymbol(Name, &val)) {\r
+ Log_Notice("ELF", "Lookup of '%s' failed", Name);\r
+ return 0;\r
+ }\r
+ if(Size)\r
+ *Size=0;\r
+ *Value = (void*)val;\r
+ return 1;\r
+}\r
#define AddLoaded(a,b) do{}while(0)\r
#define LoadLibrary(a,b,c) (Log_Debug("ELF", "Module requested lib '%s'",a),0)\r
+#define _SysSetMemFlags(ad,f,m) do{}while(0)\r
#include "../../../Usermode/Libraries/ld-acess.so_src/elf.c"\r
+// ---- / ----\r
\r
#define DEBUG_WARN 1\r
\r
\r
int Elf_Relocate(void *Base)\r
{\r
- return ElfRelocate(Base, (char**){NULL}, "") != NULL;\r
+ return ElfRelocate(Base, (char**){NULL}, "") != NULL;\r
}\r
int Elf_GetSymbol(void *Base, const char *Name, Uint *ret)\r
{\r
Proc_Execve(Binary, ArgV, EnvP, size);
for(;;);
}
- if( ret < 0 )
+ if( ret == -1 )
{
VFS_FreeSavedHandles(nFD, handles);
+ free(cachebuf);
}
return ret;
tKernelBin *pKBin;
int numKSyms = ((Uint)&gKernelSymbolsEnd-(Uint)&gKernelSymbols)/sizeof(tKernelSymbol);
+ LOG("numKSyms = %i", numKSyms);
+
// Scan Kernel
for( i = 0; i < numKSyms; i++ )
{
+ LOG("KSym %s = %p", gKernelSymbols[i].Name, gKernelSymbols[i].Value);
if(strcmp(Name, gKernelSymbols[i].Name) == 0) {
*Value = gKernelSymbols[i].Value;
return 1;
SHORTREL(&glDebug_Lock);
#endif
}
-/**
- * \fn void Log(const char *Msg, ...)
- */
-void Log(const char *Fmt, ...)
+
+
+void LogFV(const char *Fmt, va_list args)
{
- va_list args;
+ #if LOCK_DEBUG_OUTPUT
+ SHORTLOCK(&glDebug_Lock);
+ #endif
+
+ Debug_Fmt(1, Fmt, args);
+ #if LOCK_DEBUG_OUTPUT
+ SHORTREL(&glDebug_Lock);
+ #endif
+}
+
+void LogV(const char *Fmt, va_list args)
+{
#if LOCK_DEBUG_OUTPUT
SHORTLOCK(&glDebug_Lock);
#endif
Debug_Puts(1, "Log: ");
- va_start(args, Fmt);
Debug_Fmt(1, Fmt, args);
- va_end(args);
Debug_Puts(1, "\r\n");
#if LOCK_DEBUG_OUTPUT
SHORTREL(&glDebug_Lock);
#endif
}
+
+/**
+ * \fn void Log(const char *Msg, ...)
+ */
+void Log(const char *Fmt, ...)
+{
+ va_list args;
+ va_start(args, Fmt);
+ LogV(Fmt, args);
+ va_end(args);
+}
+
void Warning(const char *Fmt, ...)
{
va_list args;
Debug_Putchar('\n');
Threads_Dump();
+ Heap_Dump();
for(;;) ;
}
#endif
}
-void Debug_HexDump(const char *Header, const void *Data, Uint Length)
+void Debug_HexDump(const char *Header, const void *Data, size_t Length)
{
const Uint8 *cdat = Data;
Uint pos = 0;
/*\r
- * AcessOS/AcessBasic v0.1\r
- * PCI Bus Driver\r
+ * Acess2 Kernel\r
+ * - By John Hodge (thePowersGang)\r
+ * \r
+ * drv/pci.c\r
+ * - PCI Enumeration and Arbitration\r
*/\r
#define DEBUG 0\r
#include <acess.h>\r
#include <fs_devfs.h>\r
#include <drv_pci.h>\r
#include <drv_pci_int.h>\r
+#include <virtual_pci.h>\r
\r
#define USE_PORT_BITMAP 0\r
#define LIST_DEVICES 1\r
+#define PCI_MAX_BUSSES 8\r
\r
// === STRUCTURES ===\r
typedef struct sPCIDevice\r
// === GLOBALS ===\r
MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL, NULL);\r
int giPCI_BusCount = 1;\r
+Uint8 gaPCI_BusNumbers[PCI_MAX_BUSSES];\r
int giPCI_InodeHandle = -1;\r
int giPCI_DeviceCount = 0;\r
tPCIDevice *gPCI_Devices = NULL;\r
#endif \r
\r
// Scan Bus (Bus 0, Don't fill gPCI_Devices)\r
+ giPCI_DeviceCount = 0;\r
+ giPCI_BusCount = 1;\r
+ gaPCI_BusNumbers[0] = 0;\r
for( bus = 0; bus < giPCI_BusCount; bus ++ )\r
{\r
- ret = PCI_ScanBus(bus, 0);\r
+ ret = PCI_ScanBus(gaPCI_BusNumbers[bus], 0);\r
if(ret != MODULE_ERR_OK) return ret;\r
}\r
- \r
+ // TODO: PCIe\r
+ // - Add VPCI Devices\r
+ giPCI_DeviceCount += giVPCI_DeviceCount;\r
+ \r
if(giPCI_DeviceCount == 0) {\r
Log_Notice("PCI", "No devices were found");\r
return MODULE_ERR_NOTNEEDED;\r
// Rescan, filling the PCI device array\r
for( bus = 0; bus < giPCI_BusCount; bus ++ )\r
{\r
- PCI_ScanBus(bus, 1);\r
+ PCI_ScanBus(gaPCI_BusNumbers[bus], 1);\r
+ }\r
+ // Insert VPCI Devices\r
+ for( int i = 0; i < giVPCI_DeviceCount; i ++ )\r
+ {\r
+ tPCIDevice *devinfo = &gPCI_Devices[giPCI_DeviceCount];\r
+ \r
+ devinfo->bus = -1;\r
+ devinfo->slot = i;\r
+ devinfo->fcn = 0;\r
+ devinfo->vendor = gaVPCI_Devices[i].Vendor;\r
+ devinfo->device = gaVPCI_Devices[i].Device;\r
+ devinfo->revision = gaVPCI_Devices[i].Class & 0xFF;\r
+ devinfo->class = gaVPCI_Devices[i].Class >> 8;\r
+ snprintf(devinfo->Name, sizeof(devinfo->Name), "%02x.%02x:%x", 0xFF, i, 0);\r
+\r
+ for(int j = 0; j < 256/4; j ++ )\r
+ devinfo->ConfigCache[i] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4);\r
+\r
+ memset(&devinfo->Node, 0, sizeof(devinfo->Node));\r
+ devinfo->Node.Inode = giPCI_DeviceCount;\r
+ devinfo->Node.Size = 256;\r
+ devinfo->Node.NumACLs = 1;\r
+ devinfo->Node.ACLs = &gVFS_ACL_EveryoneRO;\r
+ devinfo->Node.Type = &gPCI_DevNodeType;\r
+\r
+ giPCI_DeviceCount ++;\r
}\r
\r
// Complete Driver Structure\r
if(!PCI_int_EnumDevice(BusID, dev, fcn, &devInfo))\r
continue;\r
\r
- if(devInfo.class == PCI_OC_PCIBRIDGE)\r
- {\r
- #if LIST_DEVICES\r
- if( !bFill )\r
- Log_Log("PCI", "Bridge @ %i,%i:%i (0x%x:0x%x)",\r
- BusID, dev, fcn, devInfo.vendor, devInfo.device);\r
- #endif\r
- //TODO: Handle PCI-PCI Bridges\r
- //PCI_ScanBus(devInfo.???, bFill);\r
- giPCI_BusCount ++;\r
- }\r
- else\r
- {\r
- #if LIST_DEVICES\r
- if( !bFill )\r
- Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i",\r
- BusID, dev, fcn, devInfo.class,\r
- devInfo.vendor, devInfo.device, devInfo.revision);\r
- #endif\r
- }\r
+ #if LIST_DEVICES\r
+ if( !bFill )\r
+ Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i",\r
+ BusID, dev, fcn, devInfo.class,\r
+ devInfo.vendor, devInfo.device, devInfo.revision);\r
+ #endif\r
\r
if( bFill ) {\r
devInfo.Node.Inode = giPCI_DeviceCount;\r
}\r
giPCI_DeviceCount ++;\r
\r
- // If bit 23 of (soemthing) is set, there are sub-functions\r
+ switch(devInfo.ConfigCache[3] & 0x007F0000)\r
+ {\r
+ case 0x00: // Normal device\r
+ break;\r
+ case 0x01: // PCI-PCI Bridge\r
+ {\r
+ // TODO: Add to list of busses?\r
+ Uint8 sec = (devInfo.ConfigCache[6] & 0x0000FF00) >> 8;\r
+ #if LIST_DEVICES\r
+ if( !bFill ) {\r
+ Uint8 pri = (devInfo.ConfigCache[6] & 0x000000FF) >> 0;\r
+ Log_Log("PCI", "- PCI-PCI Bridge %02x=>%02x", pri, sec);\r
+ }\r
+ #endif\r
+ gaPCI_BusNumbers[giPCI_BusCount++] = sec;\r
+ }\r
+ break;\r
+ case 0x02: // PCI-CardBus Bridge\r
+ break;\r
+ }\r
+\r
+ // If bit 8 of the Header Type register is set, there are sub-functions\r
if(fcn == 0 && !(devInfo.ConfigCache[3] & 0x00800000) )\r
break;\r
}\r
*/\r
tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename)\r
{\r
- int bus,slot,fcn;\r
int i;\r
- // Validate Filename (Pointer and length)\r
- if(!filename || strlen(filename) != 7)\r
- return NULL;\r
- // Check for spacers\r
- if(filename[2] != '.' || filename[5] != ':')\r
- return NULL;\r
- \r
- // Get Information\r
- if(filename[0] < '0' || filename[0] > '9') return NULL;\r
- bus = (filename[0] - '0')*10;\r
- if(filename[1] < '0' || filename[1] > '9') return NULL;\r
- bus += filename[1] - '0';\r
- if(filename[3] < '0' || filename[3] > '9') return NULL;\r
- slot = (filename[3] - '0')*10;\r
- if(filename[4] < '0' || filename[4] > '9') return NULL;\r
- slot += filename[4] - '0';\r
- if(filename[6] < '0' || filename[6] > '9') return NULL;\r
- fcn = filename[6] - '0';\r
\r
// Find Match\r
for(i=0;i<giPCI_DeviceCount;i++)\r
{\r
- if(gPCI_Devices[i].bus != bus) continue;\r
- if(gPCI_Devices[i].slot != slot) continue;\r
- if(gPCI_Devices[i].fcn != fcn) continue;\r
- \r
- return &gPCI_Devices[i].Node;\r
+ int cmp = strcmp(gPCI_Devices[i].Name, filename);\r
+ if( cmp > 0 ) // Sorted list\r
+ break;\r
+ if( cmp == 0 )\r
+ return &gPCI_Devices[i].Node;\r
}\r
\r
// Error Return\r
if( Offset & (Size - 1) ) return 0;\r
\r
dev = &gPCI_Devices[ID];\r
+ // Detect VPCI devices\r
+ if( dev->bus == -1 ) {\r
+ return VPCI_Read(&gaVPCI_Devices[dev->slot], Offset, Size);\r
+ }\r
+\r
addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset);\r
\r
dword = PCI_CfgReadDWord(addr);\r
tPCIDevice *dev;\r
Uint32 dword, addr;\r
int shift;\r
+\r
if( ID < 0 || ID >= giPCI_DeviceCount ) return ;\r
if( Offset < 0 || Offset > 256 ) return ;\r
- \r
+\r
dev = &gPCI_Devices[ID];\r
+\r
+ // Detect VPCI devices\r
+ if( dev->bus == -1 ) {\r
+ VPCI_Write(&gaVPCI_Devices[dev->slot], Offset, Size, Value);\r
+ return ;\r
+ }\r
+\r
addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset);\r
\r
if(Size != 4)\r
vendor_dev = PCI_CfgReadDWord( addr );\r
if((vendor_dev & 0xFFFF) == 0xFFFF) // Invalid Device\r
return 0;\r
+ \r
+ info->bus = bus;\r
+ info->slot = slot;\r
+ info->fcn = fcn;\r
\r
+ // Read configuration\r
info->ConfigCache[0] = vendor_dev;\r
for( i = 1, addr += 4; i < 256/4; i ++, addr += 4 )\r
{\r
info->ConfigCache[i] = PCI_CfgReadDWord(addr);\r
} \r
\r
- info->bus = bus;\r
- info->slot = slot;\r
- info->fcn = fcn;\r
info->vendor = vendor_dev & 0xFFFF;\r
info->device = vendor_dev >> 16;\r
tmp = info->ConfigCache[2];\r
// #endif\r
\r
// Make node name\r
- info->Name[0] = '0' + bus/10;\r
- info->Name[1] = '0' + bus%10;\r
- info->Name[2] = '.';\r
- info->Name[3] = '0' + slot/10;\r
- info->Name[4] = '0' + slot%10;\r
- info->Name[5] = ':';\r
- info->Name[6] = '0' + fcn;\r
- info->Name[7] = '\0';\r
+ snprintf(info->Name, 8, "%02x.%02x:%x", bus, slot, fcn);\r
\r
// Create VFS Node\r
memset( &info->Node, 0, sizeof(tVFS_Node) );\r
tSysFS_Ent *ent, *parent, *prev;
prev = NULL;
- for( ent = gSysFS_FileList; ent; prev = ent, ent = ent->Next )
+ for( ent = gSysFS_FileList; ent; prev = ent, ent = ent->ListNext )
{
// It's a reverse sorted list
- if(ent->Node.Inode < (Uint64)ID) return 0;
- if(ent->Node.Inode == (Uint64)ID) break;
+ if(ent->Node.Inode <= (Uint64)ID) break;
+ }
+ if( !ent || ent->Node.Inode != (Uint64)ID) {
+ Log_Notice("SysFS", "ID %i not present", ID);
+ return 0;
}
-
- if(!ent) return 0;
// Set up for next part
file = ent;
file->Node.Size = 0;
file->Node.ImplPtr = NULL;
- // Search parent directory
- for( ent = parent->Node.ImplPtr; ent; prev = ent, ent = ent->Next )
+ // Clean out of parent directory
+ while(parent)
{
- if( ent == file ) break;
- }
- if(!ent) {
- Log_Warning("SysFS", "Bookkeeping Error: File in list, but not in directory");
- return 0;
+ for( ent = parent->Node.ImplPtr; ent; prev = ent, ent = ent->Next )
+ {
+ if( ent == file ) break;
+ }
+ if(!ent) {
+ Log_Warning("SysFS", "Bookkeeping Error: File in list, but not in directory");
+ return 0;
+ }
+
+ // Remove from parent directory
+ if(prev)
+ prev->Next = ent->Next;
+ else
+ parent->Node.ImplPtr = ent->Next;
+
+ // Free if not in use
+ if(file->Node.ReferenceCount == 0) {
+ free(file);
+ }
+
+ if( parent->Node.ImplPtr )
+ break;
+
+ // Remove parent from the tree
+ file = parent;
+ parent = parent->Parent;
}
- // Remove from parent directory
- if(prev)
- prev->Next = ent->Next;
- else
- parent->Node.ImplPtr = ent->Next;
-
- // Free if not in use
- if(file->Node.ReferenceCount == 0)
- free(file);
-
return 1;
}
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/vpci.c
+ * - Virtual PCI Bus
+ */
+#include <virtual_pci.h>
+
+// === CODE ===
+Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size)
+{
+ Uint32 tmp_dword = 0;
+
+ if( Size > 4 || Size == 3 || Size == 0 )
+ return 0;
+ if( Offset & (Size - 1) )
+ return 0;
+
+ switch( Offset >> 2 )
+ {
+ case 0: // Vendor[0:15], Device[16:31]
+ tmp_dword = (Dev->Vendor) | (Dev->Device << 16);
+ break;
+ case 2: // Class Code
+ tmp_dword = Dev->Class;
+ break;
+ // 1: Command[0:15], Status[16:31]
+ // 3: Cache Line Size, Latency Timer, Header Type, BIST
+ // 4-9: BARs
+ // 10: Unused (Cardbus CIS Pointer)
+ // 11: Subsystem Vendor ID, Subsystem ID
+ // 12: Expansion ROM Address
+ // 13: Capabilities[0:8], Reserved[9:31]
+ // 14: Reserved
+ // 15: Interrupt Line, Interrupt Pin, Min Grant, Max Latency
+ default:
+ tmp_dword = Dev->Read(Dev->Ptr, Offset >> 2);
+ break;
+ }
+
+ tmp_dword >>= 8*(Offset & 3);
+ switch(Size)
+ {
+ case 4: break;
+ case 2: tmp_dword &= 0xFFFF; break;
+ case 1: tmp_dword &= 0xFF;
+ }
+
+ return tmp_dword;
+}
+
+void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data)
+{
+ Uint32 tmp_dword;
+ if( Size > 4 || Size == 3 || Size == 0 )
+ return ;
+ if( Offset & (Size - 1) )
+ return ;
+
+ switch(Offset >> 2)
+ {
+ case 0: // Vendor / Device IDs
+ case 2: // Class Code
+ // READ ONLY
+ return ;
+ }
+
+ tmp_dword = Dev->Read(Dev->Ptr, Offset>>2);
+ switch(Size)
+ {
+ case 4: tmp_dword = 0; break;
+ case 2:
+ tmp_dword &= ~(0xFFFF << ((Offset&2)*16));
+ Data |= 0xFFFF;
+ break;
+ case 1:
+ tmp_dword &= ~(0xFF << ((Offset&3)*8));
+ Data |= 0xFF;
+ break;
+ }
+ tmp_dword |= Data << ((Offset&3)*8);
+ Dev->Write(Dev->Ptr, Offset>>2, tmp_dword);
+}
Codepoint &= KEY_CODEPOINT_MASK;
- // Ignore Modifer Keys
- if(Codepoint > KEY_MODIFIERS) return;
-
// Get UTF-8/ANSI Encoding
if( Codepoint == 0 )
{
{
tHeapHead *head, *badHead;
tHeapFoot *foot = NULL;
+ static int in_heap_dump;
+ if( in_heap_dump ) return;
+
+ in_heap_dump = 1;
+
head = gHeapStart;
while( (Uint)head < (Uint)gHeapEnd )
{
}
// If the heap is valid, ok!
- if( (tVAddr)head == (tVAddr)gHeapEnd )
+ if( (tVAddr)head == (tVAddr)gHeapEnd ) {
+ in_heap_dump = 0;
return ;
+ }
// Check for a bad return
- if( (tVAddr)head >= (tVAddr)gHeapEnd )
+ if( (tVAddr)head >= (tVAddr)gHeapEnd ) {
+ in_heap_dump = 0;
return ;
+ }
#if !VERBOSE_DUMP
Log_Log("Heap", "%p (%P): 0x%08lx %i %4C",
* \brief Acess2 Kernel API Core
*/
-//! NULL Pointer
-#define NULL ((void*)0)
+#include <stddef.h>
+#include <arch.h>
+
//! Pack a structure
#define PACKED __attribute__((packed))
//! Mark a function as not returning
#define NORETURN __attribute__((noreturn))
+//! Mark a function that its return value should be used
+#define WARN_UNUSED_RET __attribute__((warn_unused_result))
//! Mark a function (or variable) as deprecated
#define DEPRECATED __attribute__((deprecated))
//! Mark a parameter as unused
#define UNUSED(x) UNUSED_##x __attribute__((unused))
-//! Get the offset of a member in a structure
-#define offsetof(st, m) ((Uint)((char *)&((st *)(0))->m - (char *)0 ))
/**
* \name Boolean constants
* \}
*/
-#include <arch.h>
#include <stdarg.h>
#include "errno.h"
* \}
*/
-// --- Logging ---
-/**
- * \name Logging to kernel ring buffer
- * \{
- */
-extern void Log_KernelPanic(const char *Ident, const char *Message, ...);
-extern void Log_Panic(const char *Ident, const char *Message, ...);
-extern void Log_Error(const char *Ident, const char *Message, ...);
-extern void Log_Warning(const char *Ident, const char *Message, ...);
-extern void Log_Notice(const char *Ident, const char *Message, ...);
-extern void Log_Log(const char *Ident, const char *Message, ...);
-extern void Log_Debug(const char *Ident, const char *Message, ...);
-/**
- * \}
- */
-
-// --- Debug ---
-/**
- * \name Debugging and Errors
- * \{
- */
-extern void Debug_KernelPanic(void); //!< Initiate a kernel panic
-extern void Panic(const char *Msg, ...); //!< Print a panic message (initiates a kernel panic)
-extern void Warning(const char *Msg, ...); //!< Print a warning message
-extern void LogF(const char *Fmt, ...); //!< Print a log message without a trailing newline
-extern void Log(const char *Fmt, ...); //!< Print a log message
-extern void Debug(const char *Fmt, ...); //!< Print a debug message (doesn't go to KTerm)
-extern void LogV(const char *Fmt, va_list Args); //!< va_list Log message
-extern void Debug_Enter(const char *FuncName, const char *ArgTypes, ...);
-extern void Debug_Log(const char *FuncName, const char *Fmt, ...);
-extern void Debug_Leave(const char *FuncName, char RetType, ...);
-extern void Debug_HexDump(const char *Header, const void *Data, Uint Length);
-#define UNIMPLEMENTED() Warning("'%s' unimplemented", __func__)
-#if DEBUG
-# define ENTER(_types...) Debug_Enter((char*)__func__, _types)
-# define LOG(_fmt...) Debug_Log((char*)__func__, _fmt)
-# define LEAVE(_t...) Debug_Leave((char*)__func__, _t)
-# define LEAVE_RET(_t,_v...) do{LEAVE(_t,_v);return _v;}while(0)
-# define LEAVE_RET0() do{LEAVE('-');return;}while(0)
-#else
-# define ENTER(...)
-# define LOG(...)
-# define LEAVE(...)
-# define LEAVE_RET(_t,_v...) return (_v)
-# define LEAVE_RET0() return
-#endif
-#if SANITY
-# define ASSERT(expr) do{if(!(expr))Panic("%s:%i - %s: Assertion '"#expr"' failed",__FILE__,__LINE__,(char*)__func__);}while(0)
-#else
-# define ASSERT(expr)
-#endif
-/**
- * \}
- */
+#include "logdebug.h"
// --- IO ---
#if NO_IO_BUS
* \name Threads and Processes
* \{
*/
-extern int Proc_SpawnWorker(void (*Fcn)(void*), void *Data);
+extern struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data);
extern int Proc_Spawn(const char *Path);
extern int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int nFD, int *FDs);
extern int Proc_Execve(const char *File, const char **ArgV, const char **EnvP, int DataSize);
* \}\r
*/\r
\r
-/**\r
- * \brief Symbolic key codes\r
- * \r
- * These key codes represent non-pritable characters and are placed above\r
- * the Unicode character space.\r
- * If the using driver recieves a key code with the 31st bit set, it means\r
- * that that key has been released.\r
- */\r
-enum eTplKeyboard_KeyCodes {\r
- KEY_ESC = 0x1B, //!< Escape Character\r
- \r
- KEY_NP_MASK = 0x20000000, //! Mask for non-printable characters\r
- \r
- /**\r
- * \name Special Keys\r
- * \brief These keys are usually used on their own\r
- * \{\r
- */\r
- KEY_CAPSLOCK,\r
- KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,\r
- KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, \r
- KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,\r
- KEY_NUMLOCK, KEY_SCROLLLOCK,\r
- KEY_HOME, KEY_END, KEY_INS, KEY_DEL,\r
- KEY_PAUSE, KEY_BREAK,\r
- KEY_PGUP, KEY_PGDOWN,\r
- KEY_KPENTER, KEY_KPSLASH, KEY_KPMINUS, KEY_KPPLUS, KEY_KPSTAR,\r
- KEY_KPHOME, KEY_KPUP, KEY_KPPGUP, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT,\r
- KEY_KPEND, KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL,\r
- KEY_LWIN, KEY_RWIN,\r
- KEY_MENU,\r
- /**\r
- * \}\r
- */\r
- \r
- // Modifiers\r
- /**\r
- * \name Modifiers\r
- * \brief These keye usually alter the character stream sent to the user\r
- * \{\r
- */\r
- KEY_MODIFIERS = 0x30000000,\r
- KEY_LCTRL, KEY_RCTRL,\r
- KEY_LALT, KEY_RALT,\r
- KEY_LSHIFT, KEY_RSHIFT,\r
- /**\r
- * \}\r
- */\r
-};\r
-\r
#include "keysyms.h"\r
\r
#endif\r
#ifndef _ERRNO_H
#define _ERRNO_H
-enum eErrorNums
-{
- EOK,
-
- ENOSYS, // Invalid Instruction
- EINVAL, // Invalid Paramater
- ENOMEM, // No free memory
- EACCES, // Not permitted
- EBUSY, // Resource is busy
- ENOTFOUND, // Item not found
- EREADONLY, // Read only
- ENOTIMPL, // Not implemented
- ENOENT, // No entry?
- EEXIST, // Already exists
- ENFILE, // Too many open files
- ENOTDIR, // Not a directory
- EIO, // IO Error
-
- EALREADY, // Operation was a NOP
- EINTERNAL, // Internal Error
-
- NUM_ERRS
-};
+#include "../../../Usermode/Libraries/libc.so_src/include_exp/errno.enum.h"
#endif
#include <threads.h>
+/**
+ * \name Event Values
+ * \{
+ */
+//! Fired when a VFS wait is ready [used in select(2)]
#define THREAD_EVENT_VFS 0x00000001
+//! Fired when an IPC Message arrives
#define THREAD_EVENT_IPCMSG 0x00000002
+//! Fired when a signal (e.g. SIGINT) is asserted
#define THREAD_EVENT_SIGNAL 0x00000004
+//! Timer event fire
#define THREAD_EVENT_TIMER 0x00000008
+//! General purpose event for short waits
+//! e.g. waiting for an IRQ in a Read() call
#define THREAD_EVENT_SHORTWAIT 0x00000010
+#define THREAD_EVENT_USER1 0x10000000
+#define THREAD_EVENT_USER2 0x20000000
+#define THREAD_EVENT_USER3 0x40000000
+#define THREAD_EVENT_USER4 0x80000000
+/**
+ * \}
+ */
+
// === FUNCTIONS ===
extern void Threads_PostEvent(tThread *Thread, Uint32 EventMask);
extern void Threads_ClearEvent(Uint32 EventMask);
* \brief Achitecture defined thread/process management functions
*/
+#include <threads.h>
#include <threads_int.h>
/**
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * logdebug.h
+ * - Logging / Debug printing functions
+ */
+#ifndef _KERNEL__LOGDEBUG_H_
+#define _KERNEL__LOGDEBUG_H_
+
+#include <stdarg.h>
+
+// --- Logging ---
+/**
+ * \name Logging to kernel ring buffer
+ * \{
+ */
+extern void Log_KernelPanic(const char *Ident, const char *Message, ...);
+extern void Log_Panic(const char *Ident, const char *Message, ...);
+extern void Log_Error(const char *Ident, const char *Message, ...);
+extern void Log_Warning(const char *Ident, const char *Message, ...);
+extern void Log_Notice(const char *Ident, const char *Message, ...);
+extern void Log_Log(const char *Ident, const char *Message, ...);
+extern void Log_Debug(const char *Ident, const char *Message, ...);
+/**
+ * \}
+ */
+
+// --- Debug ---
+/**
+ * \name Debugging and Errors
+ * \{
+ */
+extern void Debug_KernelPanic(void); //!< Initiate a kernel panic
+extern void Panic(const char *Msg, ...); //!< Print a panic message (initiates a kernel panic)
+extern void Warning(const char *Msg, ...); //!< Print a warning message
+extern void LogF(const char *Fmt, ...); //!< Print a log message without a trailing newline
+extern void Log(const char *Fmt, ...); //!< Print a log message
+extern void Debug(const char *Fmt, ...); //!< Print a debug message (doesn't go to KTerm)
+extern void LogV(const char *Fmt, va_list Args); //!< va_list Log message
+extern void Debug_Enter(const char *FuncName, const char *ArgTypes, ...);
+extern void Debug_Log(const char *FuncName, const char *Fmt, ...);
+extern void Debug_Leave(const char *FuncName, char RetType, ...);
+extern void Debug_HexDump(const char *Header, const void *Data, size_t Length);
+#define UNIMPLEMENTED() Warning("'%s' unimplemented", __func__)
+#if DEBUG
+# define ENTER(_types...) Debug_Enter((char*)__func__, _types)
+# define LOG(_fmt...) Debug_Log((char*)__func__, _fmt)
+# define LEAVE(_t...) Debug_Leave((char*)__func__, _t)
+# define LEAVE_RET(_t,_v...) do{LEAVE(_t,_v);return _v;}while(0)
+# define LEAVE_RET0() do{LEAVE('-');return;}while(0)
+#else
+# define ENTER(...)
+# define LOG(...)
+# define LEAVE(...)
+# define LEAVE_RET(_t,_v...) return (_v)
+# define LEAVE_RET0() return
+#endif
+#if !DISABLE_ASSERTS
+# define ASSERT(expr) do{if(!(expr))Panic("%s:%i - %s: Assertion '"#expr"' failed",__FILE__,__LINE__,(char*)__func__);}while(0)
+#else
+# define ASSERT(expr)
+#endif
+/**
+ * \}
+ */
+
+#endif
+
*/
extern int RWLock_AcquireRead(tRWLock *Lock);
-extern int RWLock_AcquireWrite(tRWLock *LOck);
+extern int RWLock_AcquireWrite(tRWLock *Lock);
/**
* \brief Release a held mutex
#define SYS_SETGID 42 // Set current Group ID
#define SYS_OPEN 64 // Open a file
#define SYS_REOPEN 65 // Close a file and reuse its handle
-#define SYS_CLOSE 66 // Close a file
-#define SYS_READ 67 // Read from an open file
-#define SYS_WRITE 68 // Write to an open file
-#define SYS_IOCTL 69 // Perform an IOCtl Call
-#define SYS_SEEK 70 // Seek to a new position in the file
-#define SYS_READDIR 71 // Read from an open directory
-#define SYS_OPENCHILD 72 // Open a child entry in a directory
-#define SYS_GETACL 73 // Get an ACL Value
-#define SYS_SETACL 74 // Set an ACL Value
-#define SYS_FINFO 75 // Get file information
-#define SYS_MKDIR 76 // Create a new directory
-#define SYS_LINK 77 // Create a new link to a file
-#define SYS_SYMLINK 78 // Create a symbolic link
-#define SYS_UNLINK 79 // Delete a file
-#define SYS_TELL 80 // Return the current file position
-#define SYS_CHDIR 81 // Change current directory
-#define SYS_GETCWD 82 // Get current directory
-#define SYS_MOUNT 83 // Mount a filesystem
-#define SYS_SELECT 84 // Wait for file handles
+#define SYS_OPENCHILD 66 // Open a child entry in a directory
+#define SYS_OPENPIPE 67 // Open a FIFO pipe pair
+#define SYS_CLOSE 68 // Close a file
+#define SYS_COPYFD 69 // Create a copy of a file handle
+#define SYS_FDCTL 70 // Modify properties of a file descriptor
+#define SYS_READ 71 // Read from an open file
+#define SYS_WRITE 72 // Write to an open file
+#define SYS_IOCTL 73 // Perform an IOCtl Call
+#define SYS_SEEK 74 // Seek to a new position in the file
+#define SYS_READDIR 75 // Read from an open directory
+#define SYS_GETACL 76 // Get an ACL Value
+#define SYS_SETACL 77 // Set an ACL Value
+#define SYS_FINFO 78 // Get file information
+#define SYS_MKDIR 79 // Create a new directory
+#define SYS_LINK 80 // Create a new link to a file
+#define SYS_SYMLINK 81 // Create a symbolic link
+#define SYS_UNLINK 82 // Delete a file
+#define SYS_TELL 83 // Return the current file position
+#define SYS_CHDIR 84 // Change current directory
+#define SYS_GETCWD 85 // Get current directory
+#define SYS_MOUNT 86 // Mount a filesystem
+#define SYS_SELECT 87 // Wait for file handles
-#define NUM_SYSCALLS 85
+#define NUM_SYSCALLS 88
#define SYS_DEBUG 0x100
#ifndef __ASSEMBLER__
"",
"SYS_OPEN",
"SYS_REOPEN",
+ "SYS_OPENCHILD",
+ "SYS_OPENPIPE",
"SYS_CLOSE",
+ "SYS_COPYFD",
+ "SYS_FDCTL",
"SYS_READ",
"SYS_WRITE",
"SYS_IOCTL",
"SYS_SEEK",
"SYS_READDIR",
- "SYS_OPENCHILD",
"SYS_GETACL",
"SYS_SETACL",
"SYS_FINFO",
%define SYS_SETGID 42 ;Set current Group ID
%define SYS_OPEN 64 ;Open a file
%define SYS_REOPEN 65 ;Close a file and reuse its handle
-%define SYS_CLOSE 66 ;Close a file
-%define SYS_READ 67 ;Read from an open file
-%define SYS_WRITE 68 ;Write to an open file
-%define SYS_IOCTL 69 ;Perform an IOCtl Call
-%define SYS_SEEK 70 ;Seek to a new position in the file
-%define SYS_READDIR 71 ;Read from an open directory
-%define SYS_OPENCHILD 72 ;Open a child entry in a directory
-%define SYS_GETACL 73 ;Get an ACL Value
-%define SYS_SETACL 74 ;Set an ACL Value
-%define SYS_FINFO 75 ;Get file information
-%define SYS_MKDIR 76 ;Create a new directory
-%define SYS_LINK 77 ;Create a new link to a file
-%define SYS_SYMLINK 78 ;Create a symbolic link
-%define SYS_UNLINK 79 ;Delete a file
-%define SYS_TELL 80 ;Return the current file position
-%define SYS_CHDIR 81 ;Change current directory
-%define SYS_GETCWD 82 ;Get current directory
-%define SYS_MOUNT 83 ;Mount a filesystem
-%define SYS_SELECT 84 ;Wait for file handles
+%define SYS_OPENCHILD 66 ;Open a child entry in a directory
+%define SYS_OPENPIPE 67 ;Open a FIFO pipe pair
+%define SYS_CLOSE 68 ;Close a file
+%define SYS_COPYFD 69 ;Create a copy of a file handle
+%define SYS_FDCTL 70 ;Modify properties of a file descriptor
+%define SYS_READ 71 ;Read from an open file
+%define SYS_WRITE 72 ;Write to an open file
+%define SYS_IOCTL 73 ;Perform an IOCtl Call
+%define SYS_SEEK 74 ;Seek to a new position in the file
+%define SYS_READDIR 75 ;Read from an open directory
+%define SYS_GETACL 76 ;Get an ACL Value
+%define SYS_SETACL 77 ;Set an ACL Value
+%define SYS_FINFO 78 ;Get file information
+%define SYS_MKDIR 79 ;Create a new directory
+%define SYS_LINK 80 ;Create a new link to a file
+%define SYS_SYMLINK 81 ;Create a symbolic link
+%define SYS_UNLINK 82 ;Delete a file
+%define SYS_TELL 83 ;Return the current file position
+%define SYS_CHDIR 84 ;Change current directory
+%define SYS_GETCWD 85 ;Get current directory
+%define SYS_MOUNT 86 ;Mount a filesystem
+%define SYS_SELECT 87 ;Wait for file handles
extern char **Threads_GetChroot(void);
extern int Proc_SendMessage(Uint Dest, int Length, void *Data);
-extern int Proc_GetMessage(Uint *Source, void *Buffer);
+extern int Proc_GetMessage(Uint *Source, Uint BufSize, void *Buffer);
#endif
/*
- * Internal Threading header
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * include/threads_int.h
+ * - Internal Threading header
* - Only for use by stuff that needs access to the thread type.
*/
#ifndef _THREADS_INT_H_
#include <threads.h>
#include <proc.h>
+#include <timers_int.h>
typedef struct sProcess tProcess;
// --- event.c
Uint32 EventState;
+ // --- timer.c
+ tTimer ThreadTimer;
};
-enum {
+enum eThreadStatus {
THREAD_STAT_NULL, // Invalid process
THREAD_STAT_ACTIVE, // Running and schedulable process
THREAD_STAT_SLEEPING, // Message Sleep
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * include/timers_int.h
+ * - Timer internal header
+ * - Only for use by code that needs access to timer internals
+ */
+#ifndef _KERNEL__TIMERS_INT_H_
+#define _KERNEL__TIMERS_INT_H_
+
+#include <timers.h>
+
+// === TYPEDEFS ===
+struct sTimer {
+ tTimer *Next;
+ Sint64 FiresAfter;
+ void (*Callback)(void*);
+ void *Argument;
+// tMutex Lock;
+ BOOL bActive;
+};
+
+#endif
+
extern tVFS_Driver *gVFS_Drivers;
// === PROTOTYPES ===
+extern void VFS_Deinit(void);
// --- open.c ---
extern char *VFS_GetAbsPath(const char *Path);
extern tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath, tVFS_Mount **MountPoint);
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * virtual_pci.h
+ * - Virtual PCI bus definitions
+ */
+#ifndef _VIRTUAL_PCI_H_
+#define _VIRTUAL_PCI_H_
+#include <acess.h>
+
+typedef struct sVPCI_Device tVPCI_Device;
+
+struct sVPCI_Device
+{
+ void *Ptr;
+
+ // Vendor/Device is defined at runtime as 0x0ACE:0x[ARCH][ARCH][IDX][IDX]
+ Uint16 Vendor;
+ Uint16 Device;
+ // Class code (Class, Subclass, Programming Interface, Revision)
+ Uint32 Class;
+
+ Uint32 BARs[6];
+ Uint8 IRQ;
+
+ /**
+ * \param Ptr Value in sVPCI_Device.Ptr
+ * \param Data Data to write to the specified address
+ */
+ void (*Write)(void *Ptr, Uint8 DWord, Uint32 Data);
+ Uint32 (*Read)(void *Ptr, Uint8 DWord);
+};
+
+extern int giVPCI_DeviceCount;
+extern tVPCI_Device gaVPCI_Devices[];
+
+extern Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size);
+extern void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data);
+#endif
+
}
// Four Byte
- if( (*str & 0xF1) == 0xF0 ) {
+ if( (*str & 0xF8) == 0xF0 ) {
outval = (*str & 0x07) << 18; // Upper 3 Bits
str ++;
if( (*str & 0xC0) != 0x80) return 2; // Validity check
return stamp * 1000;
}
+static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R);
+
+static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R)
+{
+ int sign = (N < 0) != (D < 0);
+ if(N < 0) N = -N;
+ if(D < 0) D = -D;
+ if(sign)
+ return -DivMod64U(N, D, (Uint64*)R);
+ else
+ return DivMod64U(N, D, (Uint64*)R);
+}
+
void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms)
{
int is_leap = 0, i;
- auto Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R);
-
- Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R)
- {
- int sign = (N < 0) != (D < 0);
- if(N < 0) N = -N;
- if(D < 0) D = -D;
- if(sign)
- return -DivMod64U(N, D, (Uint64*)R);
- else
- return DivMod64U(N, D, (Uint64*)R);
- }
-
// Get time
// TODO: Leap-seconds?
{
#define RANDOM_SPRUCE 0xf12b039
// === PROTOTYPES ===
+unsigned long long strtoull(const char *str, char **end, int base);
+unsigned long strtoul(const char *str, char **end, int base);
+signed long long strtoll(const char *str, char **end, int base);
+signed long strtol(const char *str, char **end, int base);
#if 0
int atoi(const char *string);
int ParseInt(const char *string, int *Val);
EXPORT(CheckMem);
// === CODE ===
-/**
- * \brief Convert a string into an integer
- */
-int atoi(const char *string)
-{
- int ret = 0;
- ParseInt(string, &ret);
- return ret;
-}
+// - Import userland stroi.c file
+#define _LIB_H_
+#include "../../Usermode/Libraries/libc.so_src/strtoi.c"
+
int ParseInt(const char *string, int *Val)
{
int ret = 0;
/**
* \brief Append a character the the vsnprintf output
*/
-#define PUTCH(c) _putch(c)
+#define PUTCH(ch) do { \
+ if(pos < __maxlen) { \
+ if(__s) __s[pos] = ch; \
+ } else { \
+ (void)ch;\
+ } \
+ pos ++; \
+ } while(0)
#define GETVAL() do {\
if(isLongLong) val = va_arg(args, Uint64);\
else val = va_arg(args, unsigned int);\
size_t pos = 0;
// Flags
int bPadLeft = 0;
-
- auto void _putch(char ch);
-
- void _putch(char ch)
- {
- if(pos < __maxlen)
- {
- if(__s) __s[pos] = ch;
- }
- pos ++;
- }
while((c = *__format++) != 0)
{
if(c == 'p') {
Uint ptr = va_arg(args, Uint);
PUTCH('*'); PUTCH('0'); PUTCH('x');
- for( len = BITS/4; len --; )
- PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
+ for( len = BITS/4; len -- && ((ptr>>(len*4))&15) == 0; )
+ ;
+ len ++;
+ if( len == 0 )
+ PUTCH( '0' );
+ else
+ while( len -- )
+ PUTCH( cUCDIGITS[ (ptr>>(len*4))&15 ] );
continue ;
}
if(!p) p = "(null)";
len = strlen(p);
if( !bPadLeft ) while(len++ < minSize) PUTCH(pad);
- while(*p && precision--) PUTCH(*p++);
+ while(*p && precision--) { PUTCH(*p); p++;}
if( bPadLeft ) while(len++ < minSize) PUTCH(pad);
break;
p = va_arg(args, char*);
if( !CheckMem(p, minSize) ) continue; // No #PFs please
if(!p) goto printString;
- while(minSize--) PUTCH(*p++);
+ while(minSize--) {
+ PUTCH(*p);
+ p ++;
+ }
break;
// Single Character
}
-// NOTE: Strictly not libc, but lib.c is used by userland code too
+// NOTE: Strictly not libc, but lib.c is used by userland code too and hence these two
+// can't be in it.
/**
* \name Memory Validation
* \{
va_list args_tmp;
if( Level >= NUM_LOG_LEVELS ) return;
-
+
va_copy(args_tmp, Args);
len = vsnprintf(NULL, 256, Format, args_tmp);
- //Log("len = %i", len);
-
#if USE_RING_BUFFER || !CACHE_MESSAGES
{
char buf[sizeof(tLogEntry)+len+1];
if( CPU_HAS_LOCK(&glLogOutput) )
return ; // TODO: Error?
SHORTLOCK( &glLogOutput );
- LogF("%s%014lli%s [%-8s] %i - %s",
+ LogF("%s%014lli",
csaLevelColours[Entry->Level],
- Entry->Time,
+ Entry->Time
+ );
+ LogF("%s [%-8s] %i - %s",
csaLevelCodes[Entry->Level],
Entry->Ident,
Threads_GetTID(),
* \fn int Proc_GetMessage(Uint *Source, void *Buffer)
* \brief Gets a message
* \param Source Where to put the source TID
+ * \param BufSize Size of \a Buffer, only this many bytes will be copied
* \param Buffer Buffer to place the message data (set to NULL to just get message length)
* \return Message length
*/
-int Proc_GetMessage(Uint *Source, void *Buffer)
+int Proc_GetMessage(Uint *Source, Uint BufSize, void *Buffer)
{
int ret;
void *tmp;
// Get message
if(Buffer != GETMSG_IGNORE)
{
- if( !CheckMem( Buffer, cur->Messages->Length ) )
+ if( !CheckMem( Buffer, BufSize ) )
{
LOG("Invalid buffer");
errno = -EINVAL;
LEAVE('i', -1);
return -1;
}
+ if( BufSize < cur->Messages->Length )
+ Log_Notice("Threads", "Buffer of 0x%x passed, but 0x%x long message, truncated",
+ BufSize, cur->Messages->Length);
+ else if( BufSize < cur->Messages->Length )
+ BufSize = cur->Messages->Length;
+ else
+ ; // equal
LOG("Copied to buffer");
- memcpy(Buffer, cur->Messages->Data, cur->Messages->Length);
+ memcpy(Buffer, cur->Messages->Data, BufSize);
}
ret = cur->Messages->Length;
// Remove from list
tmp = cur->Messages;
cur->Messages = cur->Messages->Next;
+ // - Removed last message? Clear the end-of-list pointer
if(cur->Messages == NULL) cur->LastMessage = NULL;
+ // > Otherwise, re-mark the IPCMSG event flag
+ else cur->EventState |= THREAD_EVENT_IPCMSG;
SHORTREL( &cur->IsLocked );
-
+
free(tmp); // Free outside of lock
LEAVE('i', ret);
// TODO: I need a way of relocating the dependencies before everything else, so
// they can be resolved before any other link errors
if( !Binary_Relocate(base) ) {
- Log_Warning("Relocation of module %s failed", Path);
+ Log_Warning("Module", "Relocation of module %s failed", Path);
Binary_Unload(base);
return 0;
}
}
if( !Module_int_ResolveDeps(info) ) {
- Log_Warning("Dependencies not met for '%s'", Path);
+ Log_Warning("Module", "Dependencies not met for '%s'", Path);
Binary_Unload(base);
return 0;
}
{
for( int i = 0; i < NEnts; i ++ )
{
- Log_Debug("PMemMap", "%i: %i 0x%02x %08llx+%llx",
+ Log_Debug("PMemMap", "%i: %i 0x%02x %08llx+%llx (end %llx)",
i, map[i].Type, map[i].NUMADomain,
- map[i].Start, map[i].Length
+ map[i].Start, map[i].Length,
+ map[i].Start + map[i].Length
);
}
}
toWake->RetStatus = given;
// Wake the sleeper
- SHORTLOCK( &glThreadListLock );
if( toWake->Status != THREAD_STAT_ACTIVE )
Threads_AddActive(toWake);
- SHORTREL( &glThreadListLock );
}
SHORTREL( &Sem->Protector );
#include <threads.h>
#include <events.h>
+#if 1
+# define MERR(f,v...) Log_Debug("Syscalls", "0x%x "f, callNum ,## v)
+#else
+# define MERR(v...) do{}while(0)
+#endif
+
#define CHECK_NUM_NULLOK(v,size) \
- if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NULLOK(v) \
- if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if((v)&&!Syscall_ValidString((v))){MERR("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_NUM_NONULL(v,size) \
- if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_NONULL(v) \
- if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+ if(!(v)||!Syscall_ValidString((v))){MERR("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
void SyscallHandler(tSyscallRegs *Regs);
int Syscall_ValidString(const char *Addr);
int Syscall_Valid(int Size, const void *Addr);
+ int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask);
// === CODE ===
// TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel
// -- Unmap an address
case SYS_UNMAP: MM_Deallocate(Regs->Arg1); break;
+ // -- Change the protection on an address
+ case SYS_SETFLAGS:
+ ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3);
+ break;
+
// -- Get Thread/Process IDs
case SYS_GETTID: ret = Threads_GetTID(); break;
case SYS_GETPID: ret = Threads_GetPID(); break;
// -- Check for messages
case SYS_GETMSG:
CHECK_NUM_NULLOK( (Uint*)Regs->Arg1, sizeof(Uint) );
- // NOTE: Can't do range checking as we don't know the size
- // - Should be done by Proc_GetMessage
- if( Regs->Arg2 && Regs->Arg2 != -1 && !MM_IsUser(Regs->Arg2) ) {
- err = -EINVAL; ret = -1; break;
- }
+ if( Regs->Arg3 != -1 )
+ CHECK_NUM_NULLOK((void*)Regs->Arg3, Regs->Arg2);
// *Source, *Data
- ret = Proc_GetMessage((Uint*)Regs->Arg1, (void*)Regs->Arg2);
+ ret = Proc_GetMessage((Uint*)Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
break;
// -- Get the current timestamp
CHECK_STR_NONULL((const char*)Regs->Arg1);
CHECK_STR_ARRAY((const char**)Regs->Arg2);
CHECK_STR_ARRAY((const char**)Regs->Arg3);
- CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+ CHECK_NUM_NULLOK((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
ret = Proc_SysSpawn(
(const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
Regs->Arg4, (int*)Regs->Arg5
case SYS_IOCTL:
// All sanity checking should be done by the driver
if( Regs->Arg3 && !MM_IsUser(Regs->Arg3) ) {
+ MERR("IOCtl Invalid arg %p", Regs->Arg3);
err = -EINVAL; ret = -1; break;
}
ret = VFS_IOCtl( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
ret = -1;
break;
}
- // Sanity check the paths
- if(!Syscall_ValidString((char*)Regs->Arg1)
- || !Syscall_ValidString((char*)Regs->Arg2)
- || !Syscall_ValidString((char*)Regs->Arg3)
- || !Syscall_ValidString((char*)Regs->Arg4) ) {
- err = -EINVAL;
- ret = -1;
- break;
+
+ if( !Regs->Arg1 )
+ {
+ if( !Syscall_ValidString((char*)Regs->Arg2) ) {
+ err = -EINVAL;
+ ret = -1;
+ break;
+ }
+
+ ret = VFS_Unmount((char*)Regs->Arg2);
+ }
+ else
+ {
+ // Sanity check the paths
+ if(!Syscall_ValidString((char*)Regs->Arg1)
+ || !Syscall_ValidString((char*)Regs->Arg2)
+ || (Regs->Arg3 && !Syscall_ValidString((char*)Regs->Arg3))
+ || !Syscall_ValidString((char*)Regs->Arg4) ) {
+ err = -EINVAL;
+ ret = -1;
+ break;
+ }
+ ret = VFS_Mount(
+ (char*)Regs->Arg1, // Device
+ (char*)Regs->Arg2, // Mount point
+ (char*)Regs->Arg3, // Filesystem
+ (char*)Regs->Arg4 // Options
+ );
}
- ret = VFS_Mount(
- (char*)Regs->Arg1, // Device
- (char*)Regs->Arg2, // Mount point
- (char*)Regs->Arg3, // Filesystem
- (char*)Regs->Arg4 // Options
- );
break;
// Wait on a set of handles
*/
int Syscall_Valid(int Size, const void *Addr)
{
- if(!MM_IsUser( (tVAddr)Addr )) return 0;
+ if(!MM_IsUser( (tVAddr)Addr )) {
+ Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr);
+ return 0;
+ }
return CheckMem( Addr, Size );
}
+
+int Syscall_MM_SetFlags(const void *Addr, Uint Flags, Uint Mask)
+{
+ tPAddr paddr = MM_GetPhysAddr(Addr);
+ Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+ Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC;
+
+ //Log_Debug("Syscalls", "SYS_SETFLAGS: %p %x %x", Addr, Flags, Mask);
+
+ // Enable write?
+ if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) {
+ void *node;
+ // HACK - Assume that RO mmap'd files are immutable
+ if( MM_GetPageNode(paddr, &node) == 0 && node ) {
+ Flags |= MM_PFLAG_COW;
+ Mask |= MM_PFLAG_COW;
+ }
+ }
+ MM_SetFlags((tVAddr)Addr, Flags, Mask);
+ return 0;
+}
64
SYS_OPEN Open a file
SYS_REOPEN Close a file and reuse its handle
+SYS_OPENCHILD Open a child entry in a directory
+SYS_OPENPIPE Open a FIFO pipe pair
SYS_CLOSE Close a file
+SYS_COPYFD Create a copy of a file handle
+SYS_FDCTL Modify properties of a file descriptor
SYS_READ Read from an open file
SYS_WRITE Write to an open file
SYS_IOCTL Perform an IOCtl Call
SYS_SEEK Seek to a new position in the file
SYS_READDIR Read from an open directory
-SYS_OPENCHILD Open a child entry in a directory
SYS_GETACL Get an ACL Value
SYS_SETACL Set an ACL Value
SYS_FINFO Get file information
* system.c
* - Architecture Independent System Init
*/
-#define DEBUG 0
+#define DEBUG 1
#include <acess.h>
#include <hal_proc.h>
return -EALREADY;
case THREAD_STAT_SLEEPING:
- SHORTLOCK( &glThreadListLock );
// Remove from sleeping queue
+ SHORTLOCK( &glThreadListLock );
Threads_int_DelFromQueue(&gSleepingThreads, Thread);
-
SHORTREL( &glThreadListLock );
+
Threads_AddActive( Thread );
#if DEBUG_TRACE_STATE
return -ENOTIMPL;
default:
- Warning("Threads_Wake - Unknown process status (%i)\n", Thread->Status);
+ Log_Warning("Threads", "Threads_Wake - Unknown process status (%i)", Thread->Status);
return -EINTERNAL;
}
}
default: break;
}
Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum);
- Log(" KStack 0x%x", thread->KernelStack);
+ Log(" KStack %p", thread->KernelStack);
if( thread->bInstrTrace )
Log(" Tracing Enabled");
Proc_DumpThreadCPUState(thread);
#define DEBUG 0
#include <acess.h>
#include <timers.h>
+#include <timers_int.h>
#include <events.h>
#include <hal_proc.h> // Proc_GetCurThread
#include <workqueue.h>
-
-// === TYPEDEFS ===
-struct sTimer {
- tTimer *Next;
- Sint64 FiresAfter;
- void (*Callback)(void*);
- void *Argument;
-// tMutex Lock;
- BOOL bActive;
-};
+#include <threads_int.h> // Used to get thread timer
// === PROTOTYPES ===
void Timer_CallbackThread(void *Unused);
*/
void Time_Delay(int Delay)
{
- tTimer *t;
- t = Time_AllocateTimer(NULL, NULL);
+ tTimer *t = &Proc_GetCurThread()->ThreadTimer;
+ Time_InitTimer(t, NULL, NULL);
Time_ScheduleTimer(t, Delay);
Threads_WaitEvents(THREAD_EVENT_TIMER);
- Time_FreeTimer(t);
}
// === EXPORTS ===
* Acess2 VFS
* - Directory Management Functions
*/
+#define SANITY 1
#define DEBUG 0
#include <acess.h>
#include <vfs.h>
LOG("parent = %p", parent);
if(!parent) {
- LEAVE('i', -1);
- return -1; // Error Check
+ errno = ENOENT;
+ goto _error;
}
// Permissions Check
if( !VFS_CheckACL(parent, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) {
- _CloseNode(parent);
- mountpt->OpenHandleCount --;
- free(absPath);
- LEAVE('i', -1);
- return -1;
+ errno = EACCES;
+ goto _error;
}
LOG("parent = %p", parent);
if(!parent->Type || !parent->Type->MkNod) {
Log_Warning("VFS", "VFS_MkNod - Directory has no MkNod method");
- mountpt->OpenHandleCount --;
- LEAVE('i', -1);
- return -1;
+ errno = ENOTDIR;
+ goto _error;
}
// Create node
free(absPath);
// Free Parent
+ ASSERT(mountpt->OpenHandleCount>0);
mountpt->OpenHandleCount --;
_CloseNode(parent);
// Return whatever the driver said
LEAVE('i', ret==NULL);
return ret==NULL;
+
+_error:
+ _CloseNode(parent);
+ ASSERT(mountpt->OpenHandleCount>0);
+ mountpt->OpenHandleCount --;
+ free(absPath);
+ LEAVE('i', -1);
+ return -1;
}
/**
realLink = VFS_GetAbsPath( Link );
if(!realLink) {
Log_Warning("VFS", "Path '%s' is badly formed", Link);
+ errno = EINVAL;
LEAVE('i', -1);
return -1;
}
if( VFS_MkNod(Name, VFS_FFLAG_SYMLINK) != 0 ) {
Log_Warning("VFS", "Unable to create link node '%s'", Name);
free(realLink);
+ // errno is set by VFS_MkNod
LEAVE('i', -2);
return -2; // Make link node
}
// Write link address
fp = VFS_Open(Name, VFS_OPENFLAG_WRITE|VFS_OPENFLAG_NOLINK);
+ if( fp == -1 ) {
+ Log_Warning("VFS", "Unable to open newly created symlink '%s'", Name);
+ free(realLink);
+ LEAVE('i', -3);
+ return -3;
+ }
VFS_Write(fp, strlen(realLink), realLink);
VFS_Close(fp);
* Acess2 VFS
* - AllocHandle, GetHandle
*/
+#define SANITY 1
#define DEBUG 0
#include <acess.h>
#include <mm_virt.h>
tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
// === CODE ===
+inline void _ReferenceNode(tVFS_Node *Node)
+{
+ if( !MM_GetPhysAddr(Node->Type) ) {
+ Log_Error("VFS", "Node %p's type is invalid (%p bad pointer) - %P corrupted",
+ Node, Node->Type, MM_GetPhysAddr(&Node->Type));
+ return ;
+ }
+ if( Node->Type && Node->Type->Reference )
+ Node->Type->Reference( Node );
+ else
+ Node->ReferenceCount ++;
+}
+
/**
* \fn tVFS_Handle *VFS_GetHandle(int FD)
* \brief Gets a pointer to the handle information structure
h = &gaUserHandles[i];
if( !h->Node )
continue ;
- if( h->Node->Type && h->Node->Type->Reference )
- h->Node->Type->Reference( h->Node );
+ _ReferenceNode(h->Node);
+ h->Mount->OpenHandleCount ++;
}
}
h = &gaUserHandles[i];
if( !h->Node )
continue ;
- if( h->Node->Type && h->Node->Type->Close )
- h->Node->Type->Close( h->Node );
+ _CloseNode(h->Node);
}
}
// Reference node
if( !h->Node )
continue ;
- if( h->Node->Type && h->Node->Type->Reference )
- h->Node->Type->Reference( h->Node );
+ _ReferenceNode(h->Node);
h->Mount->OpenHandleCount ++;
}
if( !h->Node )
continue ;
- if( h->Node->Type && h->Node->Type->Reference )
- h->Node->Type->Reference( h->Node );
+ _ReferenceNode(h->Node);
h->Mount->OpenHandleCount ++;
}
}
if( !h->Node )
continue ;
- if( h->Node->Type && h->Node->Type->Close )
- h->Node->Type->Close( h->Node );
+ _CloseNode(h->Node);
+
+ ASSERT(h->Mount->OpenHandleCount > 0);
+ LOG("dec. mntpt '%s' to %i", h->Mount->MountPoint, h->Mount->OpenHandleCount-1);
h->Mount->OpenHandleCount --;
}
free( Handles );
return 0;
}
+void VFS_Deinit(void)
+{
+ SysFS_RemoveFile(giVFS_MountFileID);
+ free(gsVFS_MountFile);
+ SysFS_RemoveFile(giVFS_DriverFileID);
+ free(gsVFS_DriverFile);
+}
+
/**
* \fn char *VFS_GetTruePath(const char *Path)
* \brief Gets the true path (non-symlink) of a file
if(gsVFS_DriverFile) free(gsVFS_DriverFile);
gsVFS_DriverFile = buf;
}
+
+void VFS_CleanupNode(tVFS_Node *Node)
+{
+
+}
+
PAGE_SIZE - (mapping_base & (PAGE_SIZE-1))
);
memset( (void*)(mapping_base + ofs), 0, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1)));
+ LOG("dune");
}
else {
LOG("New empty page");
/*
* Acess Micro - VFS Server version 1
*/
+#define SANITY 1
#define DEBUG 0
#include <acess.h>
#include <vfs.h>
// Create mount information
mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 );
if(!mnt) {
+ ASSERT(parent_mnt->OpenHandleCount > 0);
parent_mnt->OpenHandleCount --;
return -2;
}
mnt->RootNode = fs->InitDevice(Device, (const char **)args);
if(!mnt->RootNode) {
free(mnt);
+ ASSERT(parent_mnt->OpenHandleCount>0);
parent_mnt->OpenHandleCount --;
return -2;
}
break;
}
if(mpmnt) {
- mpmnt->OpenHandleCount -= 1;
+ ASSERT(mpmnt->OpenHandleCount>0);
+ mpmnt->OpenHandleCount --;
}
else {
Log_Notice("VFS", "Mountpoint '%s' has no parent", Mount->MountPoint);
if( mount->OpenHandleCount ) {
LOG("Mountpoint busy");
RWLock_Release(&glVFS_MountList);
+ Log_Log("VFS", "Unmount of '%s' deferred, still busy (%i open handles)",
+ Mountpoint, mount->OpenHandleCount);
return EBUSY;
}
if(prev)
// If we've unmounted the final filesystem, all good
if( gVFS_Mounts == NULL) {
RWLock_Release( &glVFS_MountList );
+
+ // Final unmount means VFS completely deinited
+ VFS_Deinit();
return -1;
}
for( mount = gVFS_Mounts; mount; prev = mount, mount = next )
{
next = mount->Next;
+
+ ASSERT(mount->OpenHandleCount >= 0);
+
// Can't unmount stuff with open handles
if( mount->OpenHandleCount > 0 ) {
LOG("%p (%s) has open handles (%i of them)",
tVFS_Node *Inode_CacheNode(int Handle, tVFS_Node *Node)
{
tInodeCache *cache;
- tCachedInode *newEnt, *ent, *prev;
+ tCachedInode *newEnt, *ent, *prev = NULL;
cache = Inode_int_GetFSCache(Handle);
if(!cache) return NULL;
// Search Cache
ent = cache->FirstNode;
- prev = (tCachedInode*) &cache->FirstNode;
for( ; ent; prev = ent, ent = ent->Next )
{
if(ent->Node.Inode < Node->Inode) continue;
newEnt = malloc(sizeof(tCachedInode));
newEnt->Next = ent;
memcpy(&newEnt->Node, Node, sizeof(tVFS_Node));
- prev->Next = newEnt;
+ if( prev )
+ prev->Next = newEnt;
+ else
+ cache->FirstNode = newEnt;
newEnt->Node.ReferenceCount = 1;
LOG("Cached %llx as %p", Node->Inode, &newEnt->Node);
* Acess2 VFS
* - Open, Close and ChDir
*/
+#define SANITY 1
#define DEBUG 0
#include <acess.h>
#include "vfs.h"
extern tVFS_Node *VFS_MemFile_Create(const char *Path);
// === PROTOTYPES ===
+void _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag);
+void _DereferenceMount(tVFS_Mount *Mount, const char *DebugTag);
int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode );
// === CODE ===
+void _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag)
+{
+// Log_Debug("VFS", "%s: inc. mntpt '%s' to %i", DebugTag, Mount->MountPoint, Mount->OpenHandleCount+1);
+ Mount->OpenHandleCount ++;
+}
+void _DereferenceMount(tVFS_Mount *Mount, const char *DebugTag)
+{
+// Log_Debug("VFS", "%s: dec. mntpt '%s' to %i", DebugTag, Mount->MountPoint, Mount->OpenHandleCount-1);
+ ASSERT(Mount->OpenHandleCount > 0);
+ Mount->OpenHandleCount --;
+}
/**
* \fn char *VFS_GetAbsPath(const char *Path)
* \brief Create an absolute path from a relative one
*TruePath = malloc( gVFS_RootMount->MountPointLen+1 );
strcpy(*TruePath, gVFS_RootMount->MountPoint);
}
- gVFS_RootMount->OpenHandleCount ++;
+ _ReferenceMount(gVFS_RootMount, "ParsePath - Fast Tree Root");
if(MountPoint) *MountPoint = gVFS_RootMount;
LEAVE('p', gVFS_RootMount->RootNode);
return gVFS_RootMount->RootNode;
*MountPoint = mnt;
RWLock_Release( &glVFS_MountList );
LOG("Mount %p root", mnt);
+ _ReferenceMount(mnt, "ParsePath - Mount Root");
LEAVE('p', mnt->RootNode);
return mnt->RootNode;
}
#endif
longestMount = mnt;
}
- longestMount->OpenHandleCount ++; // Increment assuimg it worked
+ if(!longestMount) {
+ Log_Panic("VFS", "VFS_ParsePath - No mount for '%s'", Path);
+ return NULL;
+ }
+
+ _ReferenceMount(longestMount, "ParsePath");
RWLock_Release( &glVFS_MountList );
// Save to shorter variable
// EVIL: Goto :)
LOG("Symlink -> '%s', restart", Path);
- mnt->OpenHandleCount --; // Not in this mountpoint
+ _DereferenceMount(mnt, "ParsePath - sym");
goto restart_parse;
}
*TruePath = NULL;
}
// Open failed, so decrement the open handle count
- mnt->OpenHandleCount --;
+ _DereferenceMount(mnt, "ParsePath - error");
LEAVE('n');
return NULL;
errno = EACCES;
LEAVE_RET('i', -1);
}
+
+ if( MM_GetPhysAddr(Node->Type) == 0 ) {
+ Log_Error("VFS", "Node %p from mount '%s' (%s) has a bad type (%p)",
+ Node, Mount->MountPoint, Mount->Filesystem->Name, Node->Type);
+ errno = EINTERNAL;
+ LEAVE_RET('i', -1);
+ }
i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), Node, Mode );
if( i < 0 ) {
LEAVE_RET('i', -1);
}
- // TODO: Check ACLs on the parent
+ // Check ACLs on the parent
if( !VFS_CheckACL(pnode, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) {
- _CloseNode(pnode);
- pmnt->OpenHandleCount --;
- free(absPath);
- LEAVE('i', -1);
- return -1;
+ errno = EACCES;
+ goto _pnode_err;
}
// Check that there's a MkNod method
if( !pnode->Type || !pnode->Type->MkNod ) {
Log_Warning("VFS", "VFS_Open - Directory has no MkNod method");
errno = EINVAL;
- LEAVE_RET('i', -1);
+ goto _pnode_err;
}
node = pnode->Type->MkNod(pnode, file, new_flags);
+ if( !node ) {
+ LOG("Cannot create node '%s' in '%s'", file, absPath);
+ errno = ENOENT;
+ goto _pnode_err;
+ }
+ // Set mountpoint (and increment open handle count)
+ mnt = pmnt;
+ _ReferenceMount(mnt, "Open - create");
// Fall through on error check
_CloseNode(pnode);
- pmnt->OpenHandleCount --;
+ _DereferenceMount(pmnt, "Open - create");
+ goto _pnode_ok;
+
+ _pnode_err:
+ if( pnode ) {
+ _CloseNode(pnode);
+ _DereferenceMount(pmnt, "Open - create,fail");
+ free(absPath);
+ }
+ LEAVE('i', -1);
+ return -1;
}
+ _pnode_ok:
// Free generated path
free(absPath);
{
LOG("Cannot find node");
errno = ENOENT;
- LEAVE_RET('i', -1);
+ goto _error;
}
// Check for symlinks
char tmppath[node->Size+1];
if( node->Size > MAX_PATH_LEN ) {
Log_Warning("VFS", "VFS_Open - Symlink is too long (%i)", node->Size);
- LEAVE_RET('i', -1);
+ goto _error;
}
if( !node->Type || !node->Type->Read ) {
Log_Warning("VFS", "VFS_Open - No read method on symlink");
- LEAVE_RET('i', -1);
+ goto _error;
}
// Read symlink's path
node->Type->Read( node, 0, node->Size, tmppath );
tmppath[ node->Size ] = '\0';
_CloseNode( node );
+ _DereferenceMount(mnt, "Open - symlink");
// Open the target
node = VFS_ParsePath(tmppath, NULL, &mnt);
if(!node) {
LOG("Cannot find symlink target node (%s)", tmppath);
errno = ENOENT;
- LEAVE_RET('i', -1);
+ goto _error;
}
}
- LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, Flags));
+ int ret = VFS_int_CreateHandle(node, mnt, Flags);
+ LEAVE_RET('x', ret);
+_error:
+ if( node )
+ {
+ _DereferenceMount(mnt, "Open - error");
+ _CloseNode(node);
+ }
+ LEAVE_RET('i', -1);
}
}
// Increment open handle count, no problems with the mount going away as `h` is already open on it
- h->Mount->OpenHandleCount ++;
+ _ReferenceMount(h->Mount, "OpenChild");
LEAVE_RET('x', VFS_int_CreateHandle(node, h->Mount, Mode));
}
Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x", FD);
return;
}
-
+
+ if( h->Node == NULL ) {
+ Log_Warning("VFS", "Non-open handle passed to VFS_Close, 0x%x", FD);
+ return ;
+ }
+
#if VALIDATE_VFS_FUNCTIPONS
if(h->Node->Close && !MM_GetPhysAddr(h->Node->Close)) {
Log_Warning("VFS", "Node %p's ->Close method is invalid (%p)",
}
#endif
+ LOG("Handle %x", FD);
_CloseNode(h->Node);
- if( h->Mount )
- h->Mount->OpenHandleCount --;
+ if( h->Mount ) {
+ _DereferenceMount(h->Mount, "Close");
+ }
h->Node = NULL;
}
VBE_DISPI_INDEX_Y_OFFSET\r
};\r
\r
-extern void MM_DumpTables(tVAddr Start, tVAddr End);\r
-\r
// === PROTOTYPES ===\r
// Driver\r
int BGA_Install(char **Arguments);\r
gBGA_CursorPos.x, gBGA_CursorPos.y\r
);\r
break;\r
+\r
+ case VIDEO_IOCTL_SETCURSORBITMAP:\r
+ DrvUtil_Video_SetCursor( &gBGA_DrvUtil_BufInfo, Data );\r
+ return 0;\r
\r
default:\r
LEAVE('i', -2);\r
* dir.c
* - Directory Handling
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERBOSE 0
#include "ext2_common.h"
tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int Ext2_Unlink(tVFS_Node *Node, const char *OldName);
int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
-// --- Helpers ---
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId);
// === GLOBALS ===
tVFS_NodeType gExt2_DirType = {
*/
int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
{
- #if 1
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
tExt2_DirEnt *dirent;
Mutex_Release(&Node->Lock);
LEAVE('i', 0);
return 0;
- #else
- Log_Warning("Ext2", "TODO: Impliment Ext2_Link");
- return 1;
- #endif
-}
-
-// ---- INTERNAL FUNCTIONS ----
-/**
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)
- * \brief Create a new VFS Node
- */
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)
-{
- tExt2_Inode inode;
- tVFS_Node retNode;
- tVFS_Node *tmpNode;
-
- if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
- return NULL;
-
- if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
- return tmpNode;
-
- memset(&retNode, 0, sizeof(retNode));
-
- // Set identifiers
- retNode.Inode = InodeID;
- retNode.ImplPtr = Disk;
- retNode.ImplInt = inode.i_links_count;
-
- // Set file length
- retNode.Size = inode.i_size;
-
- // Set Access Permissions
- retNode.UID = inode.i_uid;
- retNode.GID = inode.i_gid;
- retNode.NumACLs = 3;
- retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
-
- // Set Function Pointers
- retNode.Type = &gExt2_FileType;
-
- switch(inode.i_mode & EXT2_S_IFMT)
- {
- // Symbolic Link
- case EXT2_S_IFLNK:
- retNode.Flags = VFS_FFLAG_SYMLINK;
- break;
- // Regular File
- case EXT2_S_IFREG:
- retNode.Flags = 0;
- retNode.Size |= (Uint64)inode.i_dir_acl << 32;
- break;
- // Directory
- case EXT2_S_IFDIR:
- retNode.Type = &gExt2_DirType;
- retNode.Flags = VFS_FFLAG_DIRECTORY;
- retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );
- break;
- // Unknown, Write protect it to be safe
- default:
- retNode.Flags = VFS_FFLAG_READONLY;
- break;
- }
-
- // Set Timestamps
- retNode.ATime = inode.i_atime * 1000;
- retNode.MTime = inode.i_mtime * 1000;
- retNode.CTime = inode.i_ctime * 1000;
-
- // Save in node cache and return saved node
- return Inode_CacheNode(Disk->CacheID, &retNode);
-}
-
-int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)
-{
- Log_Warning("Ext2","TODO: Impliment Ext2_int_WritebackNode");
- return 0;
}
#define MIN_BLOCKS_PER_GROUP 2\r
#define MAX_BLOCK_LOG_SIZE 10 // 1024 << 10 = 1MiB\r
\r
-// === IMPORTS ===\r
-extern tVFS_NodeType gExt2_DirType;\r
-\r
// === PROTOTYPES ===\r
int Ext2_Install(char **Arguments);\r
int Ext2_Cleanup(void);\r
if( Node->Flags & VFS_FFLAG_DIRTY )\r
{\r
// Commit changes\r
- Log_Warning("Ext2", "TODO: Commit node changes");\r
+ Ext2_int_WritebackNode(disk, Node);\r
+ Node->Flags &= ~VFS_FFLAG_DIRTY;\r
}\r
\r
int was_not_referenced = (Node->ImplInt == 0);\r
{\r
LOG("Removng inode");\r
// Remove inode\r
- Log_Warning("Ext2", "TODO: Remove inode when not referenced");\r
+ Log_Warning("Ext2", "TODO: Remove inode when not referenced (%x)", (Uint32)Node->Inode);\r
}\r
if( acls != &gVFS_ACL_EveryoneRW ) {\r
free(acls);\r
return 1;\r
}\r
\r
+/**\r
+ * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)\r
+ * \brief Create a new VFS Node\r
+ */\r
+tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)\r
+{\r
+ tExt2_Inode inode;\r
+ tVFS_Node retNode;\r
+ tVFS_Node *tmpNode;\r
+ \r
+ if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )\r
+ return NULL;\r
+ \r
+ if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
+ return tmpNode;\r
+\r
+ memset(&retNode, 0, sizeof(retNode)); \r
+ \r
+ // Set identifiers\r
+ retNode.Inode = InodeID;\r
+ retNode.ImplPtr = Disk;\r
+ retNode.ImplInt = inode.i_links_count;\r
+ if( inode.i_links_count == 0 ) {\r
+ Log_Notice("Ext2", "Inode %p:%x is not referenced, bug?", Disk, InodeID);\r
+ }\r
+ \r
+ // Set file length\r
+ retNode.Size = inode.i_size;\r
+ \r
+ // Set Access Permissions\r
+ retNode.UID = inode.i_uid;\r
+ retNode.GID = inode.i_gid;\r
+ retNode.NumACLs = 3;\r
+ retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);\r
+ \r
+ // Set Function Pointers\r
+ retNode.Type = &gExt2_FileType;\r
+ \r
+ switch(inode.i_mode & EXT2_S_IFMT)\r
+ {\r
+ // Symbolic Link\r
+ case EXT2_S_IFLNK:\r
+ retNode.Flags = VFS_FFLAG_SYMLINK;\r
+ break;\r
+ // Regular File\r
+ case EXT2_S_IFREG:\r
+ retNode.Flags = 0;\r
+ retNode.Size |= (Uint64)inode.i_dir_acl << 32;\r
+ break;\r
+ // Directory\r
+ case EXT2_S_IFDIR:\r
+ retNode.Type = &gExt2_DirType;\r
+ retNode.Flags = VFS_FFLAG_DIRECTORY;\r
+ retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );\r
+ break;\r
+ // Unknown, Write protect it to be safe \r
+ default:\r
+ retNode.Flags = VFS_FFLAG_READONLY;\r
+ break;\r
+ }\r
+ \r
+ // Set Timestamps\r
+ retNode.ATime = inode.i_atime * 1000;\r
+ retNode.MTime = inode.i_mtime * 1000;\r
+ retNode.CTime = inode.i_ctime * 1000;\r
+ \r
+ // Save in node cache and return saved node\r
+ return Inode_CacheNode(Disk->CacheID, &retNode);\r
+}\r
+\r
+int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)\r
+{\r
+ tExt2_Inode inode;\r
+\r
+ if( Disk != Node->ImplPtr ) {\r
+ Log_Error("Ext2", "Ext2_int_WritebackNode - Disk != Node->ImplPtr");\r
+ return -1;\r
+ }\r
+ \r
+ if( Node->Flags & VFS_FFLAG_SYMLINK ) {\r
+ inode.i_mode = EXT2_S_IFLNK;\r
+ }\r
+ else if( Node->Flags & VFS_FFLAG_DIRECTORY ) {\r
+ inode.i_mode = EXT2_S_IFDIR;\r
+ }\r
+ else if( Node->Flags & VFS_FFLAG_READONLY ) {\r
+ Log_Notice("Ext2", "Not writing back readonly inode %p:%x", Disk, Node->Inode);\r
+ return 1;\r
+ }\r
+ else {\r
+ inode.i_mode = EXT2_S_IFREG;\r
+ inode.i_dir_acl = Node->Size >> 32;\r
+ }\r
+\r
+ inode.i_size = Node->Size & 0xFFFFFFFF;\r
+ inode.i_links_count = Node->ImplInt;\r
+\r
+ inode.i_uid = Node->UID;\r
+ inode.i_gid = Node->GID;\r
+\r
+ inode.i_atime = Node->ATime / 1000;\r
+ inode.i_mtime = Node->MTime / 1000;\r
+ inode.i_ctime = Node->CTime / 1000;\r
+\r
+ // TODO: Compact ACLs into unix mode\r
+ Log_Warning("Ext2", "TODO: Support converting Acess ACLs into unix modes");\r
+\r
+ Ext2_int_WriteInode(Disk, Node->Inode, &inode);\r
+\r
+ return 0;\r
+}\r
+\r
/**\r
* \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
* \brief Get the address of a block from an inode's list\r
tExt2_Group Groups[];
} tExt2_Disk;
+// === GLOBALS ===
+extern tVFS_NodeType gExt2_FileType;
+extern tVFS_NodeType gExt2_DirType;
+
// === FUNCTIONS ===
// --- Common ---
extern void Ext2_CloseFile(tVFS_Node *Node);
extern tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
extern tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
extern int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
+extern tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId);
+extern int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node);
// --- Read ---
extern size_t Ext2_Read(tVFS_Node *node, off_t offset, size_t length, void *buffer);
// --- Write ---
extern void FAT_int_ClearNodeCache(tFAT_VolInfo *Disk);
// --- FAT Access ---
+#define GETFATVALUE_EOC 0xFFFFFFFF
extern Uint32 FAT_int_GetFatValue(tFAT_VolInfo *Disk, Uint32 Cluster);
#if SUPPORT_WRITE
extern Uint32 FAT_int_AllocateCluster(tFAT_VolInfo *Disk, Uint32 Previous);
fat_filetable fileinfo[ents_per_sector];
int i, sector;
- Mutex_Acquire(&DirNode->Lock);
+ if( Mutex_Acquire(&DirNode->Lock) ) {
+ return -EINTR;
+ }
+
sector = 0;
for( i = 0; ; i ++ )
{
}
Mutex_Release(&DirNode->Lock);
- return -1;
+ return -ENOENT;
}
/*
tFAT_LFNCache *cache;
int i, firstFree;
- Mutex_Acquire( &Node->Lock );
+ if( Mutex_Acquire( &Node->Lock ) ) {
+ return NULL;
+ }
// TODO: Thread Safety (Lock things)
cache = Node->Data;
if( ret ) {
if( (ret->Inode >> 32) != 0 ) {
LOG("Node in cache, quick return");
+ LEAVE('p', ret);
return ret;
}
else {
const int eps = 512 / sizeof(fat_filetable);
fat_filetable fileinfo[eps];
- Mutex_Acquire( &DirNode->Lock );
+ if( Mutex_Acquire( &DirNode->Lock ) ) {
+ return EINTR;
+ }
// -- Ensure duplicates aren't created --
if( FAT_int_GetEntryByName(DirNode, NewName, &ft) >= 0 ) {
tVFS_Node *child;
fat_filetable ft;
- Mutex_Acquire(&Node->Lock);
+ if( Mutex_Acquire(&Node->Lock) ) {
+ return EINTR;
+ }
int id = FAT_int_GetEntryByName(Node, OldName, &ft);
if(id == -1) {
\r
if(bs.bps == 0 || bs.spc == 0)\r
return 0;\r
- \r
+\r
+ Log_Debug("FAT", "_Detect: Media type = %02x", bs.mediaDesc);\r
+ if( bs.mediaDesc < 0xF0 )\r
+ return 0;\r
+\r
return 1;\r
}\r
/**\r
if(Cluster) *Cluster = cluster;\r
cluster = FAT_int_GetFatValue(disk, cluster);\r
// Check for end of cluster chain\r
- if(cluster == 0xFFFFFFFF) { LEAVE('i', 1); return 1;}\r
+ if(cluster == GETFATVALUE_EOC) { LEAVE('i', 1); return 1; }\r
}\r
if(Cluster) *Cluster = cluster;\r
}\r
for(i = preSkip; i--; )\r
{\r
cluster = FAT_int_GetFatValue(disk, cluster);\r
- if(cluster == -1) {\r
+ if(cluster == GETFATVALUE_EOC) {\r
Log_Warning("FAT", "Offset is past end of cluster chain mark");\r
LEAVE('i', 0);\r
return 0;\r
LOG("pos = %i, Reading the rest of the clusters");\r
// Get next cluster in the chain\r
cluster = FAT_int_GetFatValue(disk, cluster);\r
- if(cluster == -1) {\r
+ if(cluster == GETFATVALUE_EOC) {\r
Log_Warning("FAT", "Read past End of Cluster Chain (Align)");\r
LEAVE('X', pos);\r
return pos;\r
// Read the rest of the cluster data\r
for( ; count; count -- )\r
{\r
- if(cluster == -1) {\r
+ if(cluster == GETFATVALUE_EOC) {\r
Log_Warning("FAT", "Read past End of Cluster Chain (Bulk)");\r
LEAVE('X', pos);\r
return pos;\r
while( Offset > disk->BytesPerCluster )\r
{\r
cluster = FAT_int_GetFatValue( disk, cluster );\r
- if(cluster == -1) {\r
+ if(cluster == GETFATVALUE_EOC) {\r
Log_Warning("FAT", "EOC Unexpectedly Reached");\r
LEAVE('i', 0);\r
return 0;\r
\r
// Get next cluster (allocating if needed)\r
tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
- if(tmpCluster == -1) {\r
+ if(tmpCluster == GETFATVALUE_EOC) {\r
tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
if( tmpCluster == 0 )\r
goto ret_incomplete;\r
\r
// Get next cluster (allocating if needed)\r
tmpCluster = FAT_int_GetFatValue(disk, cluster);\r
- if(tmpCluster == -1) {\r
+ if(tmpCluster == GETFATVALUE_EOC) {\r
bNewCluster = 1;\r
tmpCluster = FAT_int_AllocateCluster(disk, cluster);\r
if( tmpCluster == 0 )\r
Uint32 val = 0;
Uint32 ofs;
ENTER("pDisk xCluster", Disk, cluster);
+
Mutex_Acquire( &Disk->lFAT );
#if CACHE_FAT
if( Disk->ClusterCount <= giFAT_MaxCachedClusters )
{
val = Disk->FATCache[cluster];
- if(Disk->type == FAT12 && val == EOC_FAT12) val = -1;
- if(Disk->type == FAT16 && val == EOC_FAT16) val = -1;
- if(Disk->type == FAT32 && val == EOC_FAT32) val = -1;
+ if(Disk->type == FAT12 && val == EOC_FAT12) val = GETFATVALUE_EOC;
+ if(Disk->type == FAT16 && val == EOC_FAT16) val = GETFATVALUE_EOC;
+ if(Disk->type == FAT32 && val == EOC_FAT32) val = GETFATVALUE_EOC;
}
else
{
VFS_ReadAt(Disk->fileHandle, ofs+(cluster/2)*3, 3, &val);
LOG("3 bytes at 0x%x are (Uint32)0x%x", ofs+(cluster/2)*3, val);
val = (cluster & 1) ? (val>>12) : (val & 0xFFF);
- if(val == EOC_FAT12) val = -1;
+ if(val == EOC_FAT12) val = GETFATVALUE_EOC;
} else if(Disk->type == FAT16) {
VFS_ReadAt(Disk->fileHandle, ofs+cluster*2, 2, &val);
- if(val == EOC_FAT16) val = -1;
+ if(val == EOC_FAT16) val = GETFATVALUE_EOC;
} else {
VFS_ReadAt(Disk->fileHandle, ofs+cluster*4, 4, &val);
- if(val == EOC_FAT32) val = -1;
+ if(val == EOC_FAT32) val = GETFATVALUE_EOC;
}
#if CACHE_FAT
}
// Already out of the list :)
if(cnode->Node.Data)
free(cnode->Node.Data);
+ VFS_CleanupNode(&cnode->Node);
free(cnode);
bFreed = 1;
}
<?php
+date_default_timezone_set("UTC");
+
$lGenDate = date("Y-m-d H:i");
$gOutput = <<<EOF
/*
File "ld-acess.so" "__BIN__/Libs/ld-acess.so"
File "libld-acess.so" "__BIN__/Libs/libld-acess.so"
File "libc.so" "__BIN__/Libs/libc.so"
- File "libgcc.so" "__BIN__/Libs/libgcc.so"
File "libreadline.so" "__BIN__/Libs/libreadline.so"
File "libnet.so" "__BIN__/Libs/libnet.so"
File "liburi.so" "__BIN__/Libs/liburi.so"
File "libimage_sif.so" "__BIN__/Libs/libimage_sif.so"
File "libaxwin3.so" "__BIN__/Libs/libaxwin3.so"
+ File "libposix.so" "__BIN__/Libs/libposix.so"
+ File "libpsocket.so" "__BIN__/Libs/libpsocket.so"
}
Dir "Conf" {
File "BootConf.cfg" "__FS__/Conf/BootConf.cfg"
Dir "3.0" {
File "AxWinWM" "__BIN__/Apps/AxWin/3.0/AxWinWM"
File "AxWinUI" "__BIN__/Apps/AxWin/3.0/AxWinUI"
+ File "ate" "__BIN__/Apps/AxWin/3.0/ate"
File "AcessLogoSmall.sif" "__SRC__/Usermode/Applications/axwin3_src/AcessLogoSmall.sif"
}
}
Mutex_Release( &glIP_Adapters );
// Watch the adapter for incoming packets
- tTID tid = Proc_SpawnWorker(Adapter_int_WatchThread, ret);
- if(tid < 0) {
+ void *worker = Proc_SpawnWorker(Adapter_int_WatchThread, ret);
+ if(!worker) {
Log_Warning("IPStack", "Unable to create watcher thread for %p", ret);
}
const tUDPEndpoint *ep;
const void *data;
int ofs;
- if(chan->LocalPort == 0) return 0;
+
+ if(chan->LocalPort == 0) {
+ Log_Notice("UDP", "Write to channel %p with zero local port", chan);
+ return 0;
+ }
ep = Buffer;
ofs = 2 + 2 + IPStack_GetAddressSize( ep->AddrType );
/**
* \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
*/
-int ATA_ReadRaw(void *Ptr, Uint64 Address, Uint Count, void *Buffer)
+int ATA_ReadRaw(void *Ptr, Uint64 Address, size_t Count, void *Buffer)
{
int Disk = (tVAddr)Ptr;
int ret;
/**
* \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, const void *Buffer, Uint Disk)
*/
-int ATA_WriteRaw(void *Ptr, Uint64 Address, Uint Count, const void *Buffer)
+int ATA_WriteRaw(void *Ptr, Uint64 Address, size_t Count, const void *Buffer)
{
int Disk = (tVAddr)Ptr;
int ret;
OBJ = main.o
OBJ += usb.o usb_lowlevel.o usb_devinit.o usb_io.o usb_poll.o usb_info.o
-OBJ += hub.o
+OBJ += hub.o portctl.o
CPPFLAGS = -Iinclude
NAME = Core
// resvd
#define SET_FEATURE 3
-#define PORT_CONNECTION 0
-#define PORT_ENABLE 1
-#define PORT_SUSPEND 2
-#define PORT_OVER_CURRENT 3
-#define PORT_RESET 4
-#define PORT_POWER 8
-#define PORT_LOW_SPEED 9
-#define C_PORT_CONNECTION 16
-#define C_PORT_ENABLE 17
-#define C_PORT_SUSPEND 18
-#define C_PORT_OVER_CURRENT 19
-#define C_PORT_RESET 20
-#define PORT_TEST 21
-#define PORT_INDICATOR 21
-
struct sHubDescriptor
{
Uint8 DescLength;
void Hub_Disconnected(tUSBInterface *Dev);
void Hub_PortStatusChange(tUSBInterface *Dev, int Endpoint, int Length, void *Data);
void Hub_int_HandleChange(tUSBInterface *Dev, int Port);
+void Hub_SetPortFeature(tUSBInterface *Dev, int Port, int Feat);
+void Hub_ClearPortFeature(tUSBInterface *HubDev, int Port, int Feat);
+int Hub_GetPortStatus(tUSBInterface *HubDev, int Port, int Flag);
// === GLOBALS ===
tUSBDriver gUSBHub_Driver = {
// - Power on port
USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_POWER, Port, 0, NULL);
Time_Delay(info->PowerOnDelay);
- // - Reset
- USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_RESET, Port, 0, NULL);
- Time_Delay(20); // Spec says 10ms after reset, but how long is reset?
- // - Enable
- USB_Request(Dev, 0, 0x23, SET_FEATURE, PORT_ENABLE, Port, 0, NULL);
- // - Poke USB Stack
- USB_DeviceConnected(info->HubPtr, Port);
+ // - Start reset process
+ USB_PortCtl_BeginReset(info->HubPtr, Port);
}
else {
// Disconnected
USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, C_PORT_RESET, Port, 0, NULL);
}
}
+
+void Hub_SetPortFeature(tUSBInterface *Dev, int Port, int Feat)
+{
+ USB_Request(Dev, 0, 0x23, SET_FEATURE, Feat, Port, 0, NULL);
+}
+
+void Hub_ClearPortFeature(tUSBInterface *Dev, int Port, int Feat)
+{
+ USB_Request(Dev, 0, 0x23, CLEAR_FEATURE, Feat, Port, 0, NULL);
+}
+
+int Hub_GetPortStatus(tUSBInterface *Dev, int Port, int Flag)
+{
+ Uint16 status[2]; // Status, Change
+ USB_Request(Dev, 0, 0xA3, GET_STATUS, 0, Port, 4, status);
+ return !!(status[0] & (1 << Flag));
+}
tUSBBulkOp SendBulk;
void (*FreeOp)(void *Ptr, void *Handle);
+ // Root hub stuff
void (*CheckPorts)(void *Ptr);
+ void (*SetPortFeature)(void *Ptr, int PortNum, int Feat);
+ void (*ClearPortFeature)(void *Ptr, int PortNum, int Feat);
+ int (*GetPortStatus)(void *Ptr, int PortNum, int Flag);
};
extern tUSBHub *USB_RegisterHost(tUSBHostDef *HostDef, void *ControllerPtr, int nPorts);
extern void USB_DeviceConnected(tUSBHub *Hub, int Port);
extern void USB_DeviceDisconnected(tUSBHub *Hub, int Port);
+#define PORT_CONNECTION 0
+#define PORT_ENABLE 1
+#define PORT_SUSPEND 2
+#define PORT_OVER_CURRENT 3
+#define PORT_RESET 4
+#define PORT_POWER 8
+#define PORT_LOW_SPEED 9
+#define C_PORT_CONNECTION 16
+#define C_PORT_ENABLE 17
+#define C_PORT_SUSPEND 18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET 20
+#define PORT_TEST 21
+#define PORT_INDICATOR 21
+
+extern void Hub_SetPortFeature(tUSBInterface *HubDev, int Port, int Feat);
+extern void Hub_ClearPortFeature(tUSBInterface *HubDev, int Port, int Feat);
+extern int Hub_GetPortStatus(tUSBInterface *HubDev, int Port, int Flag);
+
+extern void USB_PortCtl_BeginReset(tUSBHub *Hub, int Port);
+
#endif
// === IMPORTS ===
extern void USB_PollThread(void *unused);
extern void USB_AsyncThread(void *Unused);
+extern void USB_PortCtl_Init(void);
// === PROTOTYPES ===
int USB_Install(char **Arguments);
*/
int USB_Install(char **Arguments)
{
+ USB_PortCtl_Init();
Proc_SpawnWorker(USB_PollThread, NULL);
Proc_SpawnWorker(USB_AsyncThread, NULL);
--- /dev/null
+/*
+ * Acess2 USB Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * portctl.c
+ * - Port control code
+ */
+#define DEBUG 1
+#define SANITY 1
+#include <acess.h>
+#include "usb.h"
+#include <workqueue.h>
+#include <timers.h>
+#include <usb_hub.h>
+
+// === PROTOTYPES ===
+void USB_PortCtl_Init(void);
+void USB_PortCtl_Worker(void *Unused);
+void USB_PortCtl_SetPortFeature(tUSBHub *Hub, int Port, int Feat);
+void USB_PortCtl_ClearPortFeature(tUSBHub *Hub, int Port, int Feat);
+ int USB_PortCtl_GetPortStatus(tUSBHub *Hub, int Port, int Flag);
+
+// === GLOBALS ===
+tWorkqueue gUSB_PortCtl_WorkQueue;
+
+// === CODE ===
+void USB_PortCtl_Init(void)
+{
+ Workqueue_Init(&gUSB_PortCtl_WorkQueue, "USB Port Reset Work Queue", offsetof(tUSBHubPort, ListNext));
+ Proc_SpawnWorker(USB_PortCtl_Worker, NULL);
+}
+
+void USB_PortCtl_Worker(void *Unused)
+{
+ Threads_SetName("USB PortCtl Worker");
+ for(;;)
+ {
+ tUSBHubPort *port;
+ tUSBHub *hub;
+
+ port = Workqueue_GetWork(&gUSB_PortCtl_WorkQueue);
+ if( !port ) {
+ Log_Warning("USB", "PortCtl Workqueue returned NULL");
+ break;
+ }
+ hub = (tUSBHub*)(port - port->PortNum) - 1;
+
+ LOG("port = %p, hub = %p", port, hub);
+
+ switch(port->Status)
+ {
+ case 1:
+ // Assert reset
+ USB_PortCtl_SetPortFeature(hub, port->PortNum, PORT_RESET);
+ LOG("Port reset starting");
+ // Wait 50 ms
+ Time_Delay(50);
+ USB_PortCtl_ClearPortFeature(hub, port->PortNum, PORT_RESET);
+ Time_Delay(10); // May take up to 2ms for reset to clear
+ // Enable port
+ LOG("Port enabling");
+ USB_PortCtl_SetPortFeature(hub, port->PortNum, PORT_ENABLE);
+ // Begin connect processing
+ port->Status = 2;
+ USB_DeviceConnected(hub, port->PortNum);
+ break;
+ }
+ }
+}
+
+void USB_PortCtl_BeginReset(tUSBHub *Hub, int Port)
+{
+ LOG("Starting %p %i", Hub, Port);
+ // Set status field in hub structure
+ Hub->Ports[Port].Status = 1;
+ Hub->Ports[Port].PortNum = Port;
+ // Add to the work queue
+ Workqueue_AddWork(&gUSB_PortCtl_WorkQueue, &Hub->Ports[Port]);
+}
+
+void USB_PortCtl_SetPortFeature(tUSBHub *Hub, int Port, int Feat)
+{
+ if( Hub->Interface->Driver == NULL ) {
+ // - Host Port
+ tUSBHost *host = Hub->Interface->Dev->Host;
+ ASSERT(host->HostDef->SetPortFeature);
+ host->HostDef->SetPortFeature(host->Ptr, Port, Feat);
+ }
+ else {
+ // - Hub Port
+ Hub_SetPortFeature(Hub->Interface, Port, Feat);
+ }
+}
+
+void USB_PortCtl_ClearPortFeature(tUSBHub *Hub, int Port, int Feat)
+{
+ if( Hub->Interface->Driver == NULL ) {
+ // - Host Port
+ tUSBHost *host = Hub->Interface->Dev->Host;
+ ASSERT(host->HostDef->ClearPortFeature);
+ host->HostDef->ClearPortFeature(host->Ptr, Port, Feat);
+ }
+ else {
+ // - Hub Port
+ Hub_ClearPortFeature(Hub->Interface, Port, Feat);
+ }
+}
+
+int USB_PortCtl_GetPortStatus(tUSBHub *Hub, int Port, int Flag)
+{
+ if( Hub->Interface->Driver == NULL ) {
+ // - Host Port
+ tUSBHost *host = Hub->Interface->Dev->Host;
+ ASSERT(host->HostDef->GetPortStatus);
+ return host->HostDef->GetPortStatus(host->Ptr, Port, Flag);
+ }
+ else {
+ // - Hub Port
+ return Hub_GetPortStatus(Hub->Interface, Port, Flag);
+ }
+ return 0;
+}
+
{
tUSBHost *host;
- host = malloc(sizeof(tUSBHost) + nPorts*sizeof(void*));
+ host = malloc(sizeof(tUSBHost) + nPorts*sizeof(tUSBHubPort) + sizeof(tUSBDevice) + sizeof(tUSBInterface));
if(!host) {
// Oh, bugger.
return NULL;
host->Ptr = ControllerPtr;
memset(host->AddressBitmap, 0, sizeof(host->AddressBitmap));
- host->RootHubDev.ParentHub = NULL;
- host->RootHubDev.Host = host;
- host->RootHubDev.Address = 0;
- host->RootHubDev.EndpointHandles[0] = HostDef->InitControl(ControllerPtr, 0, 64);
+ host->RootHubDev = (void*)(host->RootHub.Ports + nPorts);
+ host->RootHubDev->ParentHub = NULL;
+ host->RootHubDev->Host = host;
+ host->RootHubDev->Address = 0;
+ ASSERT(HostDef->InitControl);
+ host->RootHubDev->EndpointHandles[0] = HostDef->InitControl(ControllerPtr, 0, 64);
+ host->RootHubDev->nInterfaces = 0;
-// host->RootHubIf.Next = NULL;
- host->RootHubIf.Dev = &host->RootHubDev;
- host->RootHubIf.Driver = NULL;
- host->RootHubIf.Data = NULL;
- host->RootHubIf.nEndpoints = 0;
+ host->RootHubIf = (void*)(host->RootHubDev + 1);
+ host->RootHubIf->Dev = host->RootHubDev;
+ host->RootHubIf->Driver = NULL;
+ host->RootHubIf->Data = NULL;
+ host->RootHubIf->nEndpoints = 0;
- host->RootHub.Interface = &host->RootHubIf;
+ host->RootHub.Interface = host->RootHubIf;
host->RootHub.nPorts = nPorts;
- memset(host->RootHub.Devices, 0, sizeof(void*)*nPorts);
+ memset(host->RootHub.Ports, 0, sizeof(tUSBHubPort)*nPorts);
// Append to list
Mutex_Acquire( &glUSB_Hosts );
{
tUSBHub *ret;
- ret = malloc(sizeof(tUSBHub) + sizeof(ret->Devices[0])*PortCount);
+ ret = malloc(sizeof(tUSBHub) + sizeof(ret->Ports[0])*PortCount);
ret->Interface = Device;
ret->nPorts = PortCount;
- memset(ret->Devices, 0, sizeof(ret->Devices[0])*PortCount);
+ memset(ret->Ports, 0, sizeof(ret->Ports[0])*PortCount);
return ret;
}
{
for( int i = 0; i < Hub->nPorts; i ++ )
{
- if( Hub->Devices[i] )
+ if( Hub->Ports[i].Dev )
{
USB_DeviceDisconnected( Hub, i );
}
#include <usb_host.h>
#include "usb_proto.h"
+typedef struct sUSBHubPort tUSBHubPort;
typedef struct sUSBHost tUSBHost;
typedef struct sUSBDevice tUSBDevice;
typedef struct sUSBEndpoint tUSBEndpoint;
// === STRUCTURES ===
+struct sUSBHubPort
+{
+ void *ListNext;
+ char Status;
+ char PortNum;
+ tUSBDevice *Dev;
+};
+
/**
* \brief USB Hub data
*/
tUSBInterface *Interface;
int nPorts;
- tUSBDevice *Devices[];
+ struct sUSBHubPort Ports[];
};
struct sUSBEndpoint
Uint8 AddressBitmap[128/8];
- tUSBDevice RootHubDev;
- tUSBInterface RootHubIf;
+ tUSBDevice *RootHubDev;
+ tUSBInterface *RootHubIf;
tUSBHub RootHub;
};
tUSBDevice tmpdev;
tUSBDevice *dev = &tmpdev;
if( Port >= Hub->nPorts ) return ;
- if( Hub->Devices[Port] ) return ;
+ if( Hub->Ports[Port].Dev ) return ;
ENTER("pHub iPort", Hub, Port);
free(full_buf);
}
- Hub->Devices[Port] = dev;
+ Hub->Ports[Port].Dev = dev;
// Done.
LEAVE('-');
void USB_DeviceDisconnected(tUSBHub *Hub, int Port)
{
tUSBDevice *dev;
- if( !Hub->Devices[Port] ) {
+ if( !Hub->Ports[Port].Dev ) {
Log_Error("USB", "Non-registered device disconnected");
return;
}
- dev = Hub->Devices[Port];
+ dev = Hub->Ports[Port].Dev;
// TODO: Free related resources
// - Endpoint registrations
// - Bus Address
USB_int_DeallocateAddress(dev->Host, dev->Address);
// - Inform handler
- // - Allocate memory
+ // - Release memory
free(dev);
+ Hub->Ports[Port].Dev = NULL;
}
void *USB_GetDeviceDataPtr(tUSBInterface *Dev) { return Dev->Data; }
int USB_int_AllocateAddress(tUSBHost *Host)
{
int i;
+ ASSERT(Host);
for( i = 1; i < 128; i ++ )
{
if(Host->AddressBitmap[i/8] & (1 << (i%8)))
int USB_int_SendSetupSetAddress(tUSBHost *Host, int Address)
{
- USB_int_Request(&Host->RootHubDev, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
+ USB_int_Request(Host->RootHubDev, 0, 0x00, 5, Address & 0x7F, 0, 0, NULL);
return 0;
}
// Check hosts
for( tUSBHost *host = gUSB_Hosts; host; host = host->Next )
{
- host->HostDef->CheckPorts(host->Ptr);
+ if( host->HostDef->CheckPorts )
+ host->HostDef->CheckPorts(host->Ptr);
}
Time_Delay(100);
#include "ehci.h"
#include <drv_pci.h>
#include <limits.h>
+#include <events.h>
+#include <timers.h>
// === CONSTANTS ===
#define EHCI_MAX_CONTROLLERS 4
+#define EHCI_THREADEVENT_IOC THREAD_EVENT_USER1
+#define EHCI_THREADEVENT_PORTSC THREAD_EVENT_USER2
// === PROTOTYPES ===
int EHCI_Initialise(char **Arguments);
);
void *EHCI_SendBulk(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, int Dir, void *Data, size_t Length);
void EHCI_FreeOp(void *Ptr, void *Handle);
+Uint32 EHCI_int_RootHub_FeatToMask(int Feat);
+void EHCI_RootHub_SetPortFeature(void *Ptr, int Port, int Feat);
+void EHCI_RootHub_ClearPortFeature(void *Ptr, int Port, int Feat);
+ int EHCI_RootHub_GetPortStatus(void *Ptr, int Port, int Flag);
// --- Internals ---
tEHCI_qTD *EHCI_int_AllocateTD(tEHCI_Controller *Cont, int PID, void *Data, size_t Length, tUSBHostCb Cb, void *CbData);
void EHCI_int_DeallocateTD(tEHCI_Controller *Cont, tEHCI_qTD *TD);
-void EHCI_int_AppendTD(tEHCI_QH *QH, tEHCI_qTD *TD);
+void EHCI_int_AppendTD(tEHCI_Controller *Cont, tEHCI_QH *QH, tEHCI_qTD *TD);
tEHCI_QH *EHCI_int_AllocateQH(tEHCI_Controller *Cont, int Endpoint, size_t MaxPacketSize);
void EHCI_int_DeallocateQH(tEHCI_Controller *Cont, tEHCI_QH *QH);
+void EHCI_int_InterruptThread(void *ControllerPtr);
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, USB_EHCI, EHCI_Initialise, NULL, "USB_Core", NULL);
tUSBHostDef gEHCI_HostDef = {
.InitInterrupt = EHCI_InitInterrupt,
.InitIsoch = EHCI_InitIsoch,
+ .InitControl = EHCI_InitControl,
.InitBulk = EHCI_InitBulk,
.RemEndpoint = EHCI_RemEndpoint,
.SendIsoch = NULL,
.SendControl = EHCI_SendControl,
.SendBulk = EHCI_SendBulk,
- .FreeOp = EHCI_FreeOp
+ .FreeOp = EHCI_FreeOp,
+
+ .CheckPorts = NULL, // No need
+ .SetPortFeature = EHCI_RootHub_SetPortFeature,
+ .ClearPortFeature = EHCI_RootHub_ClearPortFeature,
+ .GetPortStatus = EHCI_RootHub_GetPortStatus,
};
// === CODE ===
// TODO: The same
}
- if( EHCI_InitController(addr, irq) ) {
+ Log_Log("ECHI", "Controller at PCI %i 0x%x IRQ 0x%x",
+ id, addr, irq);
+
+ if( EHCI_InitController(addr, irq) )
+ {
// TODO: Detect other forms of failure than "out of slots"
break ;
}
+
+ // TODO: Register with the USB stack
}
return 0;
}
break;
}
}
-
if(!cont) {
+ Log_Notice("EHCI", "Too many controllers (EHCI_MAX_CONTROLLERS=%i)",
+ EHCI_MAX_CONTROLLERS);
return 1;
}
+ // - Nuke a couple of fields so error handling code doesn't derp
+ cont->CapRegs = NULL;
+ cont->PeriodicQueue = NULL;
+ cont->TDPool = NULL;
+
// -- Build up structure --
cont->CapRegs = (void*)MM_MapHWPages(BaseAddress, 1);
+ if( !cont->CapRegs ) {
+ Log_Warning("EHCI", "Can't map 1 page at %P into kernel space", BaseAddress);
+ goto _error;
+ }
// TODO: Error check
+ if( (cont->CapRegs->CapLength & 3) ) {
+ Log_Warning("EHCI", "Controller at %P non-aligned op regs", BaseAddress);
+ goto _error;
+ }
cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
// - Allocate periodic queue
- cont->PeriodicQueue = (void*)MM_AllocDMA(1, 32, NULL);
+ tPAddr unused;
+ cont->PeriodicQueue = (void*)MM_AllocDMA(1, 32, &unused);
+ if( !cont->PeriodicQueue ) {
+ Log_Warning("ECHI", "Can't allocate 1 32-bit page for periodic queue");
+ goto _error;
+ }
+ for( int i = 0; i < 1024; i ++ )
+ cont->PeriodicQueue[i] = 1;
// TODO: Error check
// > Populate queue
+ // - Allocate TD pool
+ cont->TDPool = (void*)MM_AllocDMA(1, 32, &unused);
+ if( !cont->TDPool ) {
+ Log_Warning("ECHI", "Can't allocate 1 32-bit page for qTD pool");
+ goto _error;
+ }
+ for( int i = 0; i < TD_POOL_SIZE; i ++ ) {
+ cont->TDPool[i].Token = 3 << 8;
+ }
+
+ // Get port count
+ cont->nPorts = cont->CapRegs->HCSParams & 0xF;
+
// -- Bind IRQ --
IRQ_AddHandler(InterruptNum, EHCI_InterruptHandler, cont);
+ cont->InterruptThread = Proc_SpawnWorker(EHCI_int_InterruptThread, cont);
+ if( !cont->InterruptThread ) {
+ Log_Warning("EHCI", "Can't spawn interrupt worker thread");
+ goto _error;
+ }
+ LOG("cont->InterruptThread = %p", cont->InterruptThread);
// -- Initialisation procedure (from ehci-r10) --
// - Reset controller
cont->OpRegs->USBCmd = (0x40 << 16) | USBCMD_PeriodicEnable | USBCMD_Run;
// - Route all ports
cont->OpRegs->ConfigFlag = 1;
-
+
+ cont->DeadTD = EHCI_int_AllocateTD(cont, 0, NULL, 0, NULL, NULL);
+ cont->DeadTD->Link = 1;
+ cont->DeadTD->Link2 = 1;
+ cont->DeadTD->Token = 0;
+
+ // -- Register with USB Core --
+ cont->RootHub = USB_RegisterHost(&gEHCI_HostDef, cont, cont->nPorts);
+
return 0;
+_error:
+ cont->PhysBase = 0;
+ if( cont->CapRegs )
+ MM_Deallocate( (tVAddr)cont->CapRegs );
+ if( cont->PeriodicQueue )
+ MM_Deallocate( (tVAddr)cont->PeriodicQueue );
+ if( cont->TDPool )
+ MM_Deallocate( (tVAddr)cont->TDPool );
+ return 2;
}
void EHCI_InterruptHandler(int IRQ, void *Ptr)
{
- tEHCI_Controller *cont = Ptr;
- Uint32 sts = cont->OpRegs->USBSts;
+ tEHCI_Controller *Cont = Ptr;
+ Uint32 sts = Cont->OpRegs->USBSts;
// Clear interrupts
- cont->OpRegs->USBSts = sts;
+ Cont->OpRegs->USBSts = sts;
+
+ if( sts & 0xFFFF0FC0 ) {
+ LOG("Oops, reserved bits set (%08x), funny hardware?", sts);
+ sts &= ~0xFFFF0FFC0;
+ }
+
+ // Unmask read-only bits
+ sts &= ~(0xF000);
if( sts & USBINTR_IOC ) {
// IOC
+ Threads_PostEvent(Cont->InterruptThread, EHCI_THREADEVENT_IOC);
sts &= ~USBINTR_IOC;
}
if( sts & USBINTR_PortChange ) {
// Port change, determine what port and poke helper thread
+ LOG("Port status change");
+ Threads_PostEvent(Cont->InterruptThread, EHCI_THREADEVENT_PORTSC);
sts &= ~USBINTR_PortChange;
}
if( sts & USBINTR_FrameRollover ) {
// Frame rollover, used to aid timing (trigger per-second operations)
+ LOG("Frame rollover");
sts &= ~USBINTR_FrameRollover;
}
if( sts ) {
// Unhandled interupt bits
// TODO: Warn
+ LOG("WARN - Bitmask %x unhandled", sts);
}
+
+
}
// --------------------------------------------------------------------
tEHCI_QH *qh = EHCI_int_AllocateQH(Cont, Endpoint, Length);
qh->Impl.IntPeriodPow = period_pow;
+ Mutex_Acquire(&Cont->PeriodicListLock);
+
// Choose an interrupt slot to use
int minslot = 0, minslot_load = INT_MAX;
for( int slot = 0; slot < Period; slot ++ )
}
}
// Increase loading on the selected slot
- for( int i = 0; i < PERIODIC_SIZE; i += Period )
- Cont->InterruptLoad[i+minslot] += Length;
+ for( int i = minslot; i < PERIODIC_SIZE; i += Period )
+ Cont->InterruptLoad[i] += Length;
qh->Impl.IntOfs = minslot;
// Allocate TD for the data
tEHCI_qTD *td = EHCI_int_AllocateTD(Cont, (bOutbound ? PID_OUT : PID_IN), Buf, Length, Cb, CbData);
- EHCI_int_AppendTD(qh, td);
+ EHCI_int_AppendTD(Cont, qh, td);
// Insert into the periodic list
+ for( int i = 0; i < PERIODIC_SIZE; i += Period )
+ {
+ // Walk list until
+ // - the end is reached
+ // - this QH is found
+ // - A QH with a lower period is encountered
+ tEHCI_QH *pqh = NULL;
+ tEHCI_QH *nqh;
+ for( nqh = Cont->PeriodicQueueV[i]; nqh; pqh = nqh, nqh = nqh->Impl.Next )
+ {
+ if( nqh == qh )
+ break;
+ if( nqh->Impl.IntPeriodPow < period_pow )
+ break;
+ }
+
+ // Somehow, we've already been added to this queue.
+ if( nqh && nqh == qh )
+ continue ;
+
+ if( qh->Impl.Next && qh->Impl.Next != nqh ) {
+ Log_Warning("EHCI", "Suspected bookkeeping error on %p - int list %i+%i overlap",
+ Cont, period_pow, minslot);
+ break;
+ }
+
+ if( nqh ) {
+ qh->Impl.Next = nqh;
+ qh->HLink = MM_GetPhysAddr(nqh) | 2;
+ }
+ else {
+ qh->Impl.Next = NULL;
+ qh->HLink = 2|1; // QH, Terminate
+ }
+
+ if( pqh ) {
+ pqh->Impl.Next = qh;
+ pqh->HLink = MM_GetPhysAddr(qh) | 2;
+ }
+ else {
+ Cont->PeriodicQueueV[i] = qh;
+ Cont->PeriodicQueue[i] = MM_GetPhysAddr(qh) | 2;
+ }
+ }
+ Mutex_Release(&Cont->PeriodicListLock);
return qh;
}
// Allocate a QH
tEHCI_QH *qh = EHCI_int_AllocateQH(Cont, Endpoint, MaxPacketSize);
+ qh->CurrentTD = MM_GetPhysAddr(Cont->DeadTD);
// Append to async list
if( Cont->LastAsyncHead ) {
Cont->LastAsyncHead->HLink = MM_GetPhysAddr(qh)|2;
Cont->LastAsyncHead->Impl.Next = qh;
+ LOG("- Placed after %p", Cont->LastAsyncHead);
}
- else
+ else {
Cont->OpRegs->AsyncListAddr = MM_GetPhysAddr(qh)|2;
+ }
+ qh->HLink = Cont->OpRegs->AsyncListAddr;
+ Cont->OpRegs->USBCmd |= USBCMD_AsyncEnable;
Cont->LastAsyncHead = qh;
+ LOG("Created %p for %p Ep 0x%x - %i bytes MPS", qh, Ptr, Endpoint, MaxPacketSize);
+
return qh;
}
void *EHCI_InitBulk(void *Ptr, int Endpoint, size_t MaxPacketSize)
else if( (tVAddr)Handle <= 256*16 )
return ; // Isoch
else {
+ tEHCI_QH *qh = Ptr;
+
// Remove QH from list
// - If it's a polling endpoint, need to remove from all periodic lists
+ if( qh->Impl.IntPeriodPow != 0xFF) {
+ // Poll
+ }
+ else {
+ // GP
+ }
// Deallocate QH
EHCI_int_DeallocateQH(Ptr, Handle);
td_setup = EHCI_int_AllocateTD(Cont, PID_SETUP, (void*)SetupData, SetupLength, NULL, NULL);
if( isOutbound )
{
- td_data = EHCI_int_AllocateTD(Cont, PID_OUT, (void*)OutData, OutLength, NULL, NULL);
+ td_data = OutData ? EHCI_int_AllocateTD(Cont, PID_OUT, (void*)OutData, OutLength, NULL, NULL) : NULL;
td_status = EHCI_int_AllocateTD(Cont, PID_IN, InData, InLength, Cb, CbData);
}
else
{
- td_data = EHCI_int_AllocateTD(Cont, PID_IN, InData, InLength, NULL, NULL);
+ td_data = InData ? EHCI_int_AllocateTD(Cont, PID_IN, InData, InLength, NULL, NULL) : NULL;
td_status = EHCI_int_AllocateTD(Cont, PID_OUT, (void*)OutData, OutLength, Cb, CbData);
+ td_status->Token |= (1 << 15); // IOC
}
// Append TDs
- EHCI_int_AppendTD(Dest, td_setup);
- EHCI_int_AppendTD(Dest, td_data);
- EHCI_int_AppendTD(Dest, td_status);
+ if( td_data ) {
+ td_setup->Link = MM_GetPhysAddr(td_data);
+ td_data->Link = MM_GetPhysAddr(td_status) | 1;
+ td_data->Token |= (1 << 8); // Active
+ }
+ else {
+ td_setup->Link = MM_GetPhysAddr(td_status) | 1;
+ }
+ td_setup->Token |= (1 << 8); // Active
+ td_status->Token |= (1 << 8);
+ EHCI_int_AppendTD(Cont, Dest, td_setup);
return td_status;
}
// Allocate single TD
tEHCI_qTD *td = EHCI_int_AllocateTD(Cont, (Dir ? PID_OUT : PID_IN), Data, Length, Cb, CbData);
- EHCI_int_AppendTD(Dest, td);
+ EHCI_int_AppendTD(Cont, Dest, td);
return td;
}
EHCI_int_DeallocateTD(Cont, Handle);
}
+Uint32 EHCI_int_RootHub_FeatToMask(int Feat)
+{
+ switch(Feat)
+ {
+ case PORT_RESET: return PORTSC_PortReset;
+ case PORT_ENABLE: return PORTSC_PortEnabled;
+ default:
+ Log_Warning("EHCI", "Unknown root hub port feature %i", Feat);
+ return 0;
+ }
+}
+
+void EHCI_RootHub_SetPortFeature(void *Ptr, int Port, int Feat)
+{
+ tEHCI_Controller *Cont = Ptr;
+ if(Port >= Cont->nPorts) return;
+
+ Cont->OpRegs->PortSC[Port] |= EHCI_int_RootHub_FeatToMask(Feat);
+}
+
+void EHCI_RootHub_ClearPortFeature(void *Ptr, int Port, int Feat)
+{
+ tEHCI_Controller *Cont = Ptr;
+ if(Port >= Cont->nPorts) return;
+
+ Cont->OpRegs->PortSC[Port] &= ~EHCI_int_RootHub_FeatToMask(Feat);
+}
+
+int EHCI_RootHub_GetPortStatus(void *Ptr, int Port, int Flag)
+{
+ tEHCI_Controller *Cont = Ptr;
+ if(Port >= Cont->nPorts) return 0;
+
+ return !!(Cont->OpRegs->PortSC[Port] & EHCI_int_RootHub_FeatToMask(Flag));
+}
+
// --------------------------------------------------------------------
// Internals
// --------------------------------------------------------------------
+tEHCI_qTD *EHCI_int_GetTDFromPhys(tEHCI_Controller *Cont, Uint32 Addr)
+{
+ if( Addr == 0 ) return NULL;
+ LOG("%p + (%x - %x)", Cont->TDPool, Addr, MM_GetPhysAddr(Cont->TDPool));
+ return Cont->TDPool + (Addr - MM_GetPhysAddr(Cont->TDPool))/sizeof(tEHCI_qTD);
+}
+
tEHCI_qTD *EHCI_int_AllocateTD(tEHCI_Controller *Cont, int PID, void *Data, size_t Length, tUSBHostCb Cb, void *CbData)
{
+// Semaphore_Wait(&Cont->TDSemaphore, 1);
+ Mutex_Acquire(&Cont->TDPoolMutex);
+ for( int i = 0; i < TD_POOL_SIZE; i ++ )
+ {
+ if( ((Cont->TDPool[i].Token >> 8) & 3) != 3 )
+ continue ;
+ Cont->TDPool[i].Token = (PID << 8) | (Length << 16);
+ // NOTE: Assumes that `Length` is <= PAGE_SIZE
+ Cont->TDPool[i].Pages[0] = MM_GetPhysAddr(Data);
+ if( (Cont->TDPool[i].Pages[0] & (PAGE_SIZE-1)) + Length - 1 > PAGE_SIZE )
+ Cont->TDPool[i].Pages[1] = MM_GetPhysAddr((char*)Data + Length - 1) & ~(PAGE_SIZE-1);
+ Mutex_Release(&Cont->TDPoolMutex);
+ LOG("Allocated %p for PID %i on %p", &Cont->TDPool[i], PID, Cont);
+ return &Cont->TDPool[i];
+ }
+
+ Mutex_Release(&Cont->TDPoolMutex);
return NULL;
}
void EHCI_int_DeallocateTD(tEHCI_Controller *Cont, tEHCI_qTD *TD)
{
+ UNIMPLEMENTED();
}
-void EHCI_int_AppendTD(tEHCI_QH *QH, tEHCI_qTD *TD)
+void EHCI_int_AppendTD(tEHCI_Controller *Cont, tEHCI_QH *QH, tEHCI_qTD *TD)
{
+ tEHCI_qTD *ptd = NULL;
+ Uint32 link = QH->CurrentTD;
+
+ // TODO: Need locking and validation here
+ while( link && !(link & 1) )
+ {
+ ptd = EHCI_int_GetTDFromPhys(Cont, link);
+ link = ptd->Link;
+ }
+ // TODO: Figure out how to follow this properly
+ if( !ptd ) {
+ QH->CurrentTD = MM_GetPhysAddr(TD);
+ LOG("Appended %p to beginning of %p", TD, QH);
+ }
+ else {
+ ptd->Link = MM_GetPhysAddr(TD);
+ LOG("Appended %p to end of %p", TD, QH);
+ }
}
tEHCI_QH *EHCI_int_AllocateQH(tEHCI_Controller *Cont, int Endpoint, size_t MaxPacketSize)
{
+ tEHCI_QH *ret;
+ Mutex_Acquire(&Cont->QHPoolMutex);
+ for( int i = 0; i < QH_POOL_SIZE; i ++ )
+ {
+ if( !MM_GetPhysAddr( Cont->QHPools[i/QH_POOL_NPERPAGE] ) ) {
+ tPAddr tmp;
+ Cont->QHPools[i/QH_POOL_NPERPAGE] = (void*)MM_AllocDMA(1, 32, &tmp);
+ memset(Cont->QHPools[i/QH_POOL_NPERPAGE], 0, PAGE_SIZE);
+ }
+
+ ret = &Cont->QHPools[i/QH_POOL_NPERPAGE][i%QH_POOL_NPERPAGE];
+ if( ret->HLink == 0 ) {
+ ret->HLink = 1;
+ ret->Overlay.Link = 1;
+ ret->Endpoint = (Endpoint >> 4) | 0x80 | ((Endpoint & 0xF) << 8)
+ | (MaxPacketSize << 16);
+ // TODO: Endpoint speed (13:12) 0:Full, 1:Low, 2:High
+ // TODO: Control Endpoint Flag (27) 0:*, 1:Full/Low Control
+ Mutex_Release(&Cont->QHPoolMutex);
+ return ret;
+ }
+ }
+ Mutex_Release(&Cont->QHPoolMutex);
return NULL;
}
void EHCI_int_DeallocateQH(tEHCI_Controller *Cont, tEHCI_QH *QH)
{
+ // TODO: Ensure it's unused (somehow)
+ QH->HLink = 0;
}
+void EHCI_int_HandlePortConnectChange(tEHCI_Controller *Cont, int Port)
+{
+ // Connect Event
+ if( Cont->OpRegs->PortSC[Port] & PORTSC_CurrentConnectStatus )
+ {
+ // Is the device low-speed?
+ if( (Cont->OpRegs->PortSC[Port] & PORTSC_LineStatus_MASK) == PORTSC_LineStatus_Kstate )
+ {
+ LOG("Low speed device on %p Port %i, giving to companion", Cont, Port);
+ Cont->OpRegs->PortSC[Port] |= PORTSC_PortOwner;
+ }
+ // not a low-speed device, EHCI reset
+ else
+ {
+ LOG("Device connected on %p #%i", Cont, Port);
+ // Reset procedure.
+ USB_PortCtl_BeginReset(Cont->RootHub, Port);
+ }
+ }
+ // Disconnect Event
+ else
+ {
+ if( Cont->OpRegs->PortSC[Port] & PORTSC_PortOwner ) {
+ LOG("Companion port %i disconnected, taking it back", Port);
+ Cont->OpRegs->PortSC[Port] &= ~PORTSC_PortOwner;
+ }
+ else {
+ LOG("Port %i disconnected", Port);
+ USB_DeviceDisconnected(Cont->RootHub, Port);
+ }
+ }
+}
+
+void EHCI_int_InterruptThread(void *ControllerPtr)
+{
+ tEHCI_Controller *Cont = ControllerPtr;
+ while(Cont->OpRegs)
+ {
+ Uint32 events;
+
+ LOG("sleeping for events");
+ events = Threads_WaitEvents(EHCI_THREADEVENT_IOC|EHCI_THREADEVENT_PORTSC);
+ if( !events ) {
+ // TODO: Should this cause a termination?
+ }
+ LOG("events = 0x%x", events);
+
+ if( events & EHCI_THREADEVENT_IOC )
+ {
+ // IOC, Do whatever it is you do
+ }
+
+ // Port status change interrupt
+ if( events & EHCI_THREADEVENT_PORTSC )
+ {
+ // Check for port status changes
+ for(int i = 0; i < Cont->nPorts; i ++ )
+ {
+ Uint32 sts = Cont->OpRegs->PortSC[i];
+ LOG("Port %i: sts = %x", i, sts);
+ Cont->OpRegs->PortSC[i] = sts;
+ if( sts & PORTSC_ConnectStatusChange )
+ EHCI_int_HandlePortConnectChange(Cont, i);
+
+ if( sts & PORTSC_PortEnableChange )
+ {
+ // Handle enable/disable
+ }
+
+ if( sts & PORTSC_OvercurrentChange )
+ {
+ // Handle over-current change
+ }
+ }
+ }
+
+ LOG("Going back to sleep");
+ }
+}
#ifndef _EHCI_H_
#define _EHCI_H_
+#include <threads.h>
+
#define PERIODIC_SIZE 1024
typedef struct sEHCI_CapRegs tEHCI_CapRegs;
* 15 = Asynchronous Schedule Status
* 16:31 = Reserved ?(Zero)
*/
- Uint32 USBSts;
+ volatile Uint32 USBSts;
/**
* USB Interrupt Enable Register
*
*
* Bits 14:3 are used as n index into PeridocListBase
*/
- Uint32 FrIndex;
+ volatile Uint32 FrIndex;
/**
* Control Data Structure Segment Register
*
* 22 = Wake on Over-current Enable
* 23:31 = Reserved (ZERO)
*/
- Uint32 PortSC[15];
+ volatile Uint32 PortSC[15];
};
#define USBCMD_Run 0x0001
#define USBINTR_HostSystemError 0x0010
#define USBINTR_AsyncAdvance 0x0020
+#define PORTSC_CurrentConnectStatus 0x0001
+#define PORTSC_ConnectStatusChange 0x0002
+#define PORTSC_PortEnabled 0x0004
+#define PORTSC_PortEnableChange 0x0008
+#define PORTSC_OvercurrentActive 0x0010
+#define PORTSC_OvercurrentChange 0x0020
+#define PORTSC_ForcePortResume 0x0040
+#define PORTSC_Suspend 0x0080
+#define PORTSC_PortReset 0x0100
+#define PORTSC_Reserved1 0x0200
+#define PORTSC_LineStatus_MASK 0x0C00
+#define PORTSC_LineStatus_SE0 0x0000
+#define PORTSC_LineStatus_Jstate 0x0400
+#define PORTSC_LineStatus_Kstate 0x0800
+#define PORTSC_LineStatus_Undef 0x0C00
+#define PORTSC_PortPower 0x1000
+#define PORTSC_PortOwner 0x2000
+#define PORTSC_PortIndicator_MASK 0xC000
+#define PORTSC_PortIndicator_Off 0x0000
+#define PORTSC_PortIndicator_Amber 0x4000
+#define PORTSC_PortIndicator_Green 0x800
+
// Isochronous (High-Speed) Transfer Descriptor
struct sEHCI_iTD
{
Uint32 Endpoint;
Uint32 EndpointExt;
Uint32 CurrentTD;
- tEHCI_qTD Overlay;
+ struct {
+ Uint32 Link;
+ Uint32 Link2;
+ Uint32 Token;
+ Uint32 Pages[5];
+ } Overlay;
struct {
Uint8 IntOfs;
Uint8 IntPeriodPow;
tEHCI_QH *Next;
} Impl;
} __attribute__((aligned(32)));
-// sizeof = 48 (64)
+// sizeof = 48 (round up to 64)
#define PID_OUT 0
#define PID_IN 1
#define PID_SETUP 2
+#define TD_POOL_SIZE (PAGE_SIZE/sizeof(tEHCI_qTD))
+// - 256 addresses * 16 endpoints
+#define QH_POOL_SIZE (256*16)
+#define QH_POOL_PAGES (QH_POOL_SIZE*sizeof(tEHCI_QH)/PAGE_SIZE)
+#define QH_POOL_NPERPAGE (PAGE_SIZE/sizeof(tEHCI_QH))
+
struct sEHCI_Controller
{
+ tUSBHub *RootHub;
+ tThread *InterruptThread;
+ int nPorts;
+
tPAddr PhysBase;
tEHCI_CapRegs *CapRegs;
tEHCI_OpRegs *OpRegs;
+ tEHCI_qTD *DeadTD;
+
int InterruptLoad[PERIODIC_SIZE];
tEHCI_QH *LastAsyncHead;
- Uint32 *PeriodicQueue;
- tEHCI_QH PeriodicQueueV[PERIODIC_SIZE];
+ tMutex PeriodicListLock;
+ Uint32 *PeriodicQueue;
+ tEHCI_QH *PeriodicQueueV[PERIODIC_SIZE];
- tEHCI_QH *QHPools[(256*16)*sizeof(tEHCI_QH)/PAGE_SIZE]; // [PAGE_SIZE/64]
- tEHCI_qTD *TDPool[PAGE_SIZE/sizeof(tEHCI_qTD)];
+ tMutex QHPoolMutex;
+ tEHCI_QH *QHPools[QH_POOL_PAGES]; // [PAGE_SIZE/64]
+ tMutex TDPoolMutex;
+ tEHCI_qTD *TDPool; // [TD_POOL_SIZE]
};
#endif
int ret;
ENTER("");
-
+
+ if( Arguments && *Arguments && strcmp(*Arguments, "0") == 0 )
+ {
+ LOG("Disabled by argument");
+ LEAVE('i', MODULE_ERR_NOTNEEDED);
+ return MODULE_ERR_NOTNEEDED;
+ }
+
// Initialise with no maximum value
Semaphore_Init( &gUHCI_InterruptSempahore, 0, 0, "UHCI", "Interrupt Queue");
tPAddr tmp;
gaUHCI_TDPool = (void *) MM_AllocDMA(1, 32, &tmp);
memset(gaUHCI_TDPool, 0, PAGE_SIZE);
+ LOG("gaUHCI_TDPool = %p (%P)", gaUHCI_TDPool, tmp);
}
// Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices
+ // Class:SubClass:Protocol = 0xC (Serial) : 0x3 (USB) : 0x00 (UHCI)
while( (id = PCI_GetDeviceByClass(0x0C0300, 0xFFFFFF, id)) >= 0 && i < MAX_CONTROLLERS )
{
tUHCI_Controller *cinfo = &gUHCI_Controllers[i];
Uint32 base_addr;
- // NOTE: Check "protocol" from PCI?
cinfo->PciId = id;
base_addr = PCI_GetBAR(id, 4);
LEAVE('i', -1);
return -1;
}
+ LOG("->FrameList = %p (%P)", Host->FrameList, Host->PhysFrameList);
Host->TDQHPage = (void *) MM_AllocDMA(1, 32, &Host->PhysTDQHPage);
if( !Host->TDQHPage ) {
LEAVE('i', -1);
return -1;
}
+ LOG("->TDQHPage = %p (%P)", Host->TDQHPage, Host->PhysTDQHPage);
// Fill frame list
// - The numbers 0...31, but bit reversed (16 (0b1000) = 1 (0b00001)
0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30,
1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31
};
+ // Fill all slots (but every 4th will be changed below
for( int i = 0; i < 1024; i ++ ) {
Uint32 addr = MM_GetPhysAddr( &Host->TDQHPage->ControlQH );
Host->FrameList[i] = addr | 2;
Host->FrameList[768 + i*4] = addr | 2;
}
- // Build up interrupt binary tree
+ // Build up interrupt binary tree
{
tUHCI_QH *dest = Host->TDQHPage->InterruptQHs;
Uint32 destphys = Host->PhysTDQHPage;
// Set up next pointer to index to i/2 in the next step
for( int _count = 64; _count > 1; _count /= 2 )
{
+ LOG("count=%i, dest=%p, destphys=%P", _count, dest, destphys);
for( int i = 0; i < _count; i ++ ) {
+ LOG(" %i-%i: %P==%P", _count, i, MM_GetPhysAddr(dest+i), destphys+i*sizeof(tUHCI_QH));
dest[i].Next = destphys + (_count + i/2) * sizeof(tUHCI_QH) + 2;
dest[i].Child = 1;
}
PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 );
// Enable processing
+ LOG("Processing enabling");
_OutWord( Host, USBCMD, 0x0001 );
LEAVE('i', 0);
TD->Control |= (TD->Token >> 21) & 0x7FF;
// Stop controller
+ tPAddr tdaddr = MM_GetPhysAddr( TD );
+ ASSERT(tdaddr);
_OutWord( Cont, USBCMD, 0x0000 );
// Add
TD->Link = 1;
if( QH->Child & 1 ) {
- QH->Child = MM_GetPhysAddr( TD );
+ QH->Child = tdaddr;
}
else {
// Depth first
- QH->_LastItem->Link = MM_GetPhysAddr( TD ) | 4;
+ QH->_LastItem->Link = tdaddr | 4;
}
QH->_LastItem = TD;
void *InData, size_t InLength
)
{
- ENTER("pPtr pEndpt ibOutbound", Ptr, Endpt, bOutbound);
+ ENTER("pPtr pEndpt bOutbound", Ptr, Endpt, bOutbound);
tUHCI_Controller *Cont = Ptr;
tUHCI_QH *qh = &Cont->TDQHPage->ControlQH;
// Update toggle value
epi->Tgl = tgl;
-
+
+ // --- HACK!!!
+// for( int i = 0; i < 1024; i ++ )
+// {
+// LOG("- FrameList[%i] = %x", i, Cont->FrameList[i]);
+// }
+ // --- /HACK
+
LEAVE('p', td);
return td;
}
int dest, tgl;
size_t mps;
- ENTER("pPtr pEndpt pCb pCbData bOutbound pData iLength", Ptr, Dest, Cb, CbData, bOutbound, Data, Length);
+ ENTER("pPtr pEndpt pCb pCbData bOutbound pData iLength", Ptr, Endpt, Cb, CbData, bOutbound, Data, Length);
if( Endpt == NULL ) {
Log_Error("UHCI", "_SendBulk passed a NULL endpoint handle");
continue ;
}
- LOG("Removed %p from QH %p", td, QH);
+ LOG("Removed %p from QH %p", td, QH);
+ ASSERT(td->Link);
if( !prev )
QH->Child = td->Link;
// USB Error Interrupt
if( status & 2 )
{
-
+ Log_Notice("UHCI", "USB Error");
}
// Resume Detect
// - Fired if in suspend state and a USB device sends the RESUME signal
if( status & 4 )
{
-
+ Log_Notice("UHCI", "Resume Detect");
}
// Host System Error
if( status & 8 )
{
-
+ Log_Notice("UHCI", "Host System Error");
}
// Host Controller Process Error
if( status & 0x10 )
{
Log_Error("UHCI", "Host controller process error on controller %p", Ptr);
+ // Spam Tree
+ //for( int i = 0; i < 1024; i += 4 ) {
+ // LOG("%4i: %x", i, Host->FrameList[i]);
+ //}
+
+ tPAddr phys = Host->TDQHPage->ControlQH.Child;
+ while( !(phys & 1) && MM_GetRefCount(phys & ~15))
+ {
+ tUHCI_TD *td = UHCI_int_GetTDFromPhys(Host, phys);
+ LOG("%08P: %08x %08x %08x", phys, td->Control, td->Token, td->BufferPointer);
+ phys = td->Link;
+ }
}
_OutWord(Host, USBSTS, status);
SUBMAKE = $(MAKE) --no-print-directory
-USRLIBS := crt0.o acess.ld ld-acess.so libgcc.so libc.so
+USRLIBS := crt0.o acess.ld ld-acess.so libc.so libposix.so
USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
USRLIBS += libimage_sif.so
USRAPPS := init login CLIShell cat ls mount
USRAPPS += bomb lspci
USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3
+USRAPPS += axwin3 gui_ate
ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
ALL_MODULES := $(addprefix all-,$(MODULES))
AI_USRAPPS := $(addprefix allinstall-,$(USRAPPS))
.PHONY: all clean install \
+ kmode all-kmode clean-kmode \
+ all-user clean-user \
$(ALL_MODULES) all-Kernel $(ALL_USRLIBS) $(ALL_USRAPPS) \
$(AI_MODULES) allinstall-Kernel $(AI_USRLIBS) $(AI_USRAPPS) \
$(CLEAN_MODULES) clean-Kernel $(CLEAN_USRLIBS) $(CLEAN_USRAPPS) \
kmode: $(AI_MODULES) $(AI_DYNMODS) allinstall-Kernel
all-kmode: $(ALL_MODULES) $(ALL_DYNMODS) all-Kernel
+clean-kmode: $(CLEAN_MODULES) $(CLEAN_DYNMODS) clean-Kernel
all-user: $(ALL_USRLIBS) $(ALL_USRAPPS)
clean-user: $(CLEAN_USRLIBS) $(CLEAN_USRAPPS)
# Acess2 Build Configuration
#
+ACESSDIR := $(dir $(lastword $(MAKEFILE_LIST)))
+ACESSDIR := $(shell cd $(ACESSDIR) && pwd)
+
# Install destination configuration
-DISTROOT := a:/Acess2
+DISTROOT := -i $(ACESSDIR)/Acess2.img ::/Acess2
xCP := mcopy -D o
xMKDIR := mmd -D s
-ACESSDIR := $(dir $(lastword $(MAKEFILE_LIST)))
-ACESSDIR := $(shell cd $(ACESSDIR) && pwd)
-
-include $(ACESSDIR)/Makefile.Version.cfg
# Default build programs
--- /dev/null
+Rationale:
+- Provides a method for ARM SoCs to use existing device drivers (e.g. USB ECHI) with minimal modifcation.
+
+Method possibilities
+# Hook in Kernel/drv/pci.c that enumerates the virtual bus using a fixed format.
_kfile="KernelLand/Acess2.$1-$2.bin"
fi
BOOTOPT="-kernel $_kfile"
- BOOTOPT=$BOOTOPT" -initrd KernelLand/Modules/Filesystems/FS_InitRD.kmd.$1 -append $3"
+ BOOTOPT=$BOOTOPT" -initrd KernelLand/Modules/Filesystems/FS_InitRD.kmd.$1 -append \"$3\""
shift
shift
;;
-dbgbin)
QEMU=/home/tpg/apps/bin/qemu-system-x86_64
;;
+ -bin)
+ shift
+ QEMU=$1
+ ;;
+ -dbgscript)
+ QEMU="echo $QEMU"
+ ;;
-extramem)
QEMU_PARAMS=$QEMU_PARAMS" -m 768"
;;
-notee)
_NOTEE="yes"
;;
+ -nographic)
+ _NOGRAPHIC="yes"
+ ;;
esac
shift
done
if [ "x$_NOUSB" != "xyes" ] ; then
QEMU_PARAMS=$QEMU_PARAMS" -usb"
+# QEMU_PARAMS=$QEMU_PARAMS" -device usb-ehci"
QEMU_PARAMS=$QEMU_PARAMS" -drive id=test_usb_image,file=USB_Test_Image.img,if=none"
QEMU_PARAMS=$QEMU_PARAMS" -device usb-storage,drive=test_usb_image"
QEMU_PARAMS=$QEMU_PARAMS" -usbdevice mouse"
# /home/tpg/apps/bin/qemu-system-x86_64 $QEMU_PARAMS -serial stdio -serial file:QemuLog.txt
# qemu-system-x86_64 $QEMU_PARAMS -serial stdio | tee QemuLog.txt
#echo $QEMU $BOOTOPT $QEMU_PARAMS
-if [ "x$_NOTEE" != "xyes" ] ; then
- $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
-else
+if [ "x$_NOGRAPHIC" = "xyes" ] ; then
+ $QEMU $BOOTOPT $QEMU_PARAMS -nographic
+ exit
+fi
+
+if [ "x$_NOTEE" = "xyes" ] ; then
$QEMU $BOOTOPT $QEMU_PARAMS -serial stdio
+ exit
fi
+
+eval $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
TODO:
+
+=== Hardware ===
- E1000 Driver (stubbed)
> Find specs
http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
- Sound Stack
> Intel 82801AA AC97 Audio (qemu)
+
+=== General Features ===
- Init Scripts
> With an argument to init passed from the kernel?
- Signals
> Add return value to mutexs and semaphores, and add warn_unused_ret
+
+=== Kernel Core ===
- Virtual PCI bus for system configuration
> Hook in drv_pci.c, with an arch-defined array of devices
> Allow hooks on PCI config accesses (to emulate power management etc)
- LVM Usablity
> /Devices/LVM/by-id/ and /Devices/LVM/by-label
+=== Userland ===
- AxWin3
> Text editor (with a GP formatted text field?)
> Maybe a basic web browser using the surface support?
char name[256];
while( VFS_ReadDir(fd, name) )
{
- Log("- %s", name);
+ tFInfo fi;
+ int child = VFS_OpenChild(fd, name, 0);
+ if( child != -1 )
+ {
+ VFS_FInfo(child, &fi, 0);
+ VFS_Close(child);
+ }
+ Log("- %02x %6lli %s", fi.flags, fi.size, name);
}
VFS_Close(fd);
fprintf(stderr, "[HexDump ]d %s:", Prefix);
for( ; ofs < Length; ofs ++ )
{
- if( ofs % 16 == 8 ) fprintf(stderr, " ");
+ if( ofs % 8 == 0 ) fprintf(stderr, " ");
fprintf(stderr, " %02x", data[ofs%16]);
}
fprintf(stderr, "\n");
--- /dev/null
+#!/bin/bash
+
+# Get invocation path (which could be a symlink in $PATH)
+fullpath=`which "$0"`
+if [[ !$? ]]; then
+ fullpath="$0"
+fi
+
+# Resolve symlink
+fullpath=`readlink -f "$fullpath"`
+
+# Get base directory
+BASEDIR=`dirname "$fullpath"`
+
+cfgfile=`mktemp`
+make --no-print-directory -f $BASEDIR/getconfig.mk ARCH=x86 > $cfgfile
+#echo $cfgfile
+#cat $cfgfile
+. $cfgfile
+rm $cfgfile
+
+_miscargs=""
+_compile=0
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -E)
+ _preproc=1
+ ;;
+ -c)
+ _compile=1
+ ;;
+ -o)
+ shift
+ _outfile="-o $1"
+ ;;
+ -I)
+ shift
+ _cflags=$_cflags" -I$1"
+ ;;
+ -I*|-D*|-O*)
+ _cflags=$_cflags" $1"
+ ;;
+ -Wl,*)
+ arg=$1
+ arg=${arg#-Wl}
+ arg=${arg/,/ }
+ _ldflags=$_ldflags" ${arg}"
+ ;;
+ -l)
+ shift
+ _libs=$_libs" -l$1"
+ ;;
+ -l*|-L*)
+ _libs=$_libs" $1"
+ ;;
+ *)
+ _miscargs=$_miscargs" $1"
+ ;;
+ esac
+ shift
+done
+
+run() {
+# echo $*
+ $*
+}
+
+if [[ $_preproc -eq 1 ]]; then
+ run $_CC -E $CFLAGS $_cflags $_miscargs $_outfile
+ exit $?
+fi
+if [[ $_compile -eq 1 ]]; then
+ run $_CC $CFLAGS $_cflags $_miscargs -c $_outfile
+ exit $?
+fi
+
+if echo " $_miscargs" | grep '\.c' >/dev/null; then
+ tmpout=`mktemp acess_gccproxy.XXXXXXXXXX.o --tmpdir`
+ run $_CC $CFLAGS $_miscargs -c -o $tmpout
+ run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile
+ rm $tmpout
+else
+ run $_LD $LDFLAGS $_ldflags $_miscargs $_outfile $LIBGCC_PATH
+fi
+
--- /dev/null
+include $(dir $(lastword $(MAKEFILE_LIST)))../../Usermode/Applications/Makefile.cfg
+
+.PHONY: shellvars
+
+shellvars:
+ @echo '_CC="$(CC)"'
+ @echo '_LD="$(LD)"'
+ @echo 'LDFLAGS="$(LDFLAGS)"'
+ @echo 'CFLAGS="$(CFLAGS)"'
+ @echo 'LIBGCC_PATH="$(LIBGCC_PATH)"'
{\r
GeneratePath(exefile, gsCurrentDirectory, sTmpBuffer);\r
// Check file existence\r
- fd = open(sTmpBuffer, OPENFLAG_EXEC);\r
+ fd = _SysOpen(sTmpBuffer, OPENFLAG_EXEC);\r
if(fd == -1) {\r
printf("Unknown Command: `%s'\n", Args[0]); // Error Message\r
return ;\r
}\r
\r
// Get File info and close file\r
- finfo( fd, &info, 0 );\r
- close( fd );\r
+ _SysFInfo( fd, &info, 0 );\r
+ _SysClose( fd );\r
\r
// Check if the file is a directory\r
if(info.flags & FILEFLAG_DIRECTORY) {\r
for( i = 0; i < giNumPathDirs; i++ )\r
{\r
GeneratePath(exefile, gasPathDirs[i], sTmpBuffer);\r
- fd = open(sTmpBuffer, OPENFLAG_EXEC);\r
+ fd = _SysOpen(sTmpBuffer, OPENFLAG_EXEC);\r
if(fd == -1) continue;\r
- finfo( fd, &info, 0 );\r
- close( fd );\r
+ _SysFInfo( fd, &info, 0 );\r
+ _SysClose( fd );\r
if(info.flags & FILEFLAG_DIRECTORY) continue;\r
// Woohoo! We found a valid command\r
break;\r
}\r
\r
// Create new process\r
- pid = clone(CLONE_VM, 0);\r
- // Start Task\r
- if(pid == 0) {\r
- execve(sTmpBuffer, Args, gasEnvironment);\r
- printf("Execve returned, ... oops\n");\r
- exit(-1);\r
- }\r
+ int fds[] = {0, 1, 2};\r
+ pid = _SysSpawn(sTmpBuffer, (const char **)Args, (const char **)gasEnvironment, 3, fds, NULL);\r
if(pid <= 0) {\r
printf("Unable to create process: `%s'\n", sTmpBuffer); // Error Message\r
}\r
else {\r
int status;\r
- waittid(pid, &status);\r
+ _SysWaitTID(pid, &status);\r
}\r
}\r
\r
*/\r
void Command_Clear(int argc, char **argv)\r
{\r
- write(_stdout, "\x1B[2J", 4); //Clear Screen\r
+ _SysWrite(_stdout, "\x1B[2J", 4); //Clear Screen\r
}\r
\r
/**\r
\r
GeneratePath(argv[1], gsCurrentDirectory, tmpPath);\r
\r
- fp = open(tmpPath, 0);\r
+ fp = _SysOpen(tmpPath, 0);\r
if(fp == -1) {\r
printf("Directory does not exist\n");\r
return;\r
}\r
- finfo(fp, &stats, 0);\r
- close(fp);\r
+ _SysFInfo(fp, &stats, 0);\r
+ _SysClose(fp);\r
\r
if( !(stats.flags & FILEFLAG_DIRECTORY) ) {\r
printf("Not a Directory\n");\r
strcpy(gsCurrentDirectory, tmpPath);\r
\r
// Register change with kernel\r
- chdir( gsCurrentDirectory );\r
+ _SysChdir( gsCurrentDirectory );\r
}\r
\r
/**\r
dirLen = strlen(tmpPath);\r
\r
// Open Directory\r
- dp = open(tmpPath, OPENFLAG_READ);\r
+ dp = _SysOpen(tmpPath, OPENFLAG_READ);\r
// Check if file opened\r
if(dp == -1)\r
{\r
return;\r
}\r
// Get File Stats\r
- if( finfo(dp, &info, 0) == -1 )\r
+ if( _SysFInfo(dp, &info, 0) == -1 )\r
{\r
- close(dp);\r
+ _SysClose(dp);\r
printf("stat Failed, Bad File Descriptor\n");\r
return;\r
}\r
// Check if it's a directory\r
if(!(info.flags & FILEFLAG_DIRECTORY))\r
{\r
- close(dp);\r
+ _SysClose(dp);\r
printf("Unable to open directory `%s', Not a directory\n", tmpPath);\r
return;\r
}\r
\r
fileName = (char*)(tmpPath+dirLen);\r
// Read Directory Content\r
- while( (fp = SysReadDir(dp, fileName)) )\r
+ while( (fp = _SysReadDir(dp, fileName)) )\r
{\r
if(fp < 0)\r
{\r
break;\r
}\r
// Open File\r
- fp = open(tmpPath, 0);\r
+ fp = _SysOpen(tmpPath, 0);\r
if(fp == -1) continue;\r
// Get File Stats\r
- finfo(fp, &info, 0);\r
+ _SysFInfo(fp, &info, 0);\r
\r
if(info.flags & FILEFLAG_DIRECTORY)\r
printf("d");\r
if(acl.perms & 2) modeStr[7] = 'w'; else modeStr[7] = '-';\r
if(acl.perms & 8) modeStr[8] = 'x'; else modeStr[8] = '-';\r
printf(modeStr);\r
- close(fp);\r
+ _SysClose(fp);\r
\r
// Colour Code\r
if(info.flags & FILEFLAG_DIRECTORY) // Directory: Green\r
printf("\n");\r
}\r
// Close Directory\r
- close(dp);\r
+ _SysClose(dp);\r
}\r
CPPFLAGS = -ffreestanding -I$(ACESSUSERDIR)/include/ -DARCHDIR_is_$(ARCHDIR)
CPPFLAGS += $(addprefix -I,$(wildcard $(ACESSUSERDIR)Libraries/*/include_exp/))
CFLAGS = -fno-stack-protector $(CPPFLAGS)
-LDFLAGS = -T $(OUTPUTDIR)Libs/acess.ld -rpath-link $(OUTPUTDIR)Libs -L $(OUTPUTDIR)Libs -I /Acess/Libs/ld-acess.so -lld-acess -lc $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o
+LDFLAGS = -T $(OUTPUTDIR)Libs/acess.ld -rpath-link $(OUTPUTDIR)Libs -L $(OUTPUTDIR)Libs -I /Acess/Libs/ld-acess.so -lld-acess -lc $(OUTPUTDIR)Libs/crtbegin.o $(OUTPUTDIR)Libs/crtend.o -lposix
LIBGCC_PATH = $(shell $(CC) -print-libgcc-file-name)
# Extra-verbose errors!
@mkdir -p $(dir $@)
endif
@$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
- @$(CC) -M -MT $@ $(CPPFLAGS) $< -o $(_OBJPREFIX)$*.dep
+ @$(CC) -M -MP -MT $@ $(CPPFLAGS) $< -o $(_OBJPREFIX)$*.dep
$(OUTPUTDIR)Libs/libld-acess.so:
@make -C $(ACESSDIR)/Usermode/Libraries/ld-acess.so_src/
void create_mainmenu(void);
void create_run_dialog(void);
void mainmenu_run_dialog(void *unused);
+void mainmenu_app_terminal(void *unused);
+void mainmenu_app_textedit(void *unused);
// === GLOBALS ===
tHWND gSidebar;
tAxWin3_Widget *gRunInput;
int giScreenWidth;
int giScreenHeight;
+char **gEnvion;
// === CODE ===
int systembutton_fire(tAxWin3_Widget *Widget)
return 0;
}
-int main(int argc, char *argv[])
+int main(int argc, char *argv[], char **envp)
{
+ gEnvion = envp;
// Connect to AxWin3 Server
AxWin3_Connect(NULL);
create_run_dialog();
AxWin3_RegisterAction(gSidebar, "Interface>Run", (tAxWin3_HotkeyCallback)mainmenu_run_dialog);
-// AxWin3_RegisterAction(gSidebar, "Interface>Terminal", mainmenu_app_terminal);
-// AxWin3_RegisterAction(gSidebar, "Interface>TextEdit", mainmenu_app_textedit);
+ AxWin3_RegisterAction(gSidebar, "Interface>Terminal", (tAxWin3_HotkeyCallback)mainmenu_app_terminal);
+ AxWin3_RegisterAction(gSidebar, "Interface>TextEdit", (tAxWin3_HotkeyCallback)mainmenu_app_textedit);
// Idle loop
AxWin3_MainLoop();
void mainmenu_app_textedit(void *unused)
{
- _SysDebug("TODO: Launch text editor");
+ const char *args[] = {"ate",NULL};
+// _SysDebug("TODO: Launch text editor");
+ _SysSpawn("/Acess/Apps/AxWin/3.0/ate", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_app_terminal(void *unused)
OBJ := main.o input.o video.o ipc.o image.o utf-8.o
OBJ += wm.o wm_input.o wm_render.o wm_render_text.o wm_hotkeys.o
OBJ += decorator.o
-OBJ += renderers/passthru.o
+OBJ += renderers/framebuffer.o
OBJ += renderers/background.o
OBJ += renderers/menu.o
+OBJ += renderers/richtext.o
# TODO: Move to a lower makefile
OBJ += renderers/widget.o
OBJ += renderers/widget/button.o
OBJ += renderers/widget/disptext.o
OBJ += renderers/widget/textinput.o
OBJ += renderers/widget/spacer.o
+OBJ += renderers/widget/subwin.o
LDFLAGS += -limage_sif -luri -lnet
int Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data)
{
+ static tWindow *btn1_down;
switch(Message)
{
case WNDMSG_MOUSEMOVE: {
const struct sWndMsg_MouseMove *msg = Data;
+
+ if( btn1_down == Window ) {
+ WM_MoveWindow(Window, Window->X + msg->dX, Window->Y + msg->dY);
+ return 0;
+ }
+
if(msg->Y >= 0) return 1; // Pass
-
+
// TODO: Handle
return 0; }
case WNDMSG_MOUSEBTN: {
const struct sWndMsg_MouseButton *msg = Data;
+ if( msg->Button == 0 && !msg->bPressed )
+ btn1_down = 0;
+
if(msg->Y >= 0) return 1; // Pass
-
+
+ if( msg->Button == 0 && msg->bPressed )
+ btn1_down = Window;
+
// TODO: Handle
return 0; }
default: // Anything unhandled is passed on
#define WINFLAG_NODECORATE 0x00000002
//! Window takes up all of screen
#define WINFLAG_MAXIMIZED 0x00000004
+//! Window is contained within the parent
+#define WINFLAG_RELATIVE 0x00000008
//! Window contents are valid
#define WINFLAG_CLEAN 0x00000040
//! All child windows are un-changed
// === FUNCTIONS ===
// --- Management
extern tWindow *WM_CreateWindow(tWindow *Parent, tIPC_Client *Client, uint32_t ID, int Flags, const char *Renderer);
+extern tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID);
extern void WM_Invalidate(tWindow *Window);
extern void WM_SetWindowTitle(tWindow *Window, const char *Title);
extern void WM_FocusWindow(tWindow *Destination);
extern void WM_RaiseWindow(tWindow *Window);
extern void WM_ShowWindow(tWindow *Window, int bShow);
extern void WM_DecorateWindow(tWindow *Window, int bDecorate);
+extern void WM_SetRelative(tWindow *Window, int bRelativeToParent);
extern int WM_ResizeWindow(tWindow *Window, int W, int H);
extern int WM_MoveWindow(tWindow *Window, int X, int Y);
extern int WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Length, const void *Data);
// Position and dimensions
int X, Y;
- int RealW, RealH;
int W, H;
+ int RealX, RealY;
+ int RealW, RealH;
void *RenderBuffer; //!< Cached copy of the rendered window
};
* \return Boolean failure (0: Handled, 1: Unhandled)
*/
int (*HandleMessage)(tWindow *Window, int MessageID, int Length, const void *Data);
+
+ int nIPCHandlers;
+
+ /**
+ * \brief IPC Message handler
+ */
+ int (*IPCHandlers[])(tWindow *Window, size_t Length, const void *Data);
};
extern void WM_RegisterRenderer(tWMRenderer *Renderer);
extern tWindow *WM_CreateWindowStruct(size_t ExtraBytes);
+extern int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Data);
#endif
#include <common.h>
#include <acess/sys.h>
#include <wm_input.h>
+#include <stddef.h>
// TODO: Move out to a common header
typedef struct
tNumValue num_value;
// Open mouse for RW
- giMouseFD = open(gsMouseDevice, 3);
+ giMouseFD = _SysOpen(gsMouseDevice, 3);
// Set mouse limits
// TODO: Update these if the screen resolution changes
num_value.Num = 0; num_value.Value = giScreenWidth;
- ioctl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value);
+ _SysIOCtl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value);
num_value.Value = giScreenWidth/2;
giInput_MouseX = giScreenWidth/2;
- ioctl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value);
+ _SysIOCtl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value);
num_value.Num = 1; num_value.Value = giScreenHeight;
- ioctl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value);
+ _SysIOCtl(giMouseFD, JOY_IOCTL_GETSETAXISLIMIT, &num_value);
num_value.Value = giScreenHeight/2;
giInput_MouseY = giScreenHeight/2;
- ioctl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value);
+ _SysIOCtl(giMouseFD, JOY_IOCTL_GETSETAXISPOSITION, &num_value);
return 0;
}
static uint32_t scancode;
#define KEY_CODEPOINT_MASK 0x3FFFFFFF
- size_t readlen = read(giTerminalFD_Input, &codepoint, sizeof(codepoint));
+ size_t readlen = _SysRead(giTerminalFD_Input, &codepoint, sizeof(codepoint));
if( readlen != sizeof(codepoint) )
{
// oops, error
mouseinfo = (void*)data;
- seek(giMouseFD, 0, SEEK_SET);
- i = read(giMouseFD, data, sizeof(data));
+ _SysSeek(giMouseFD, 0, SEEK_SET);
+ i = _SysRead(giMouseFD, data, sizeof(data));
i -= sizeof(*mouseinfo);
if( i < 0 ) {
_SysDebug("Mouse data undersized (no header)");
#include <stdio.h>
#include <wm.h>
#include <wm_internals.h>
-#include <wm_hotkeys.h>
+#include <wm_hotkeys.h> // Hotkey registration
+#include <wm_renderer.h> // Renderer IPC messages
#define AXWIN_PORT 4101
{
int tmp;
// TODO: Check this
- giNetworkFileHandle = open("/Devices/ip/loop/udp", OPENFLAG_READ);
+ giNetworkFileHandle = _SysOpen("/Devices/ip/loop/udp", OPENFLAG_READ);
if( giNetworkFileHandle != -1 )
{
tmp = AXWIN_PORT;
- ioctl(giNetworkFileHandle, 4, &tmp); // TODO: Don't hard-code IOCtl number
+ _SysIOCtl(giNetworkFileHandle, 4, &tmp); // TODO: Don't hard-code IOCtl number
}
}
int readlen, identlen;
char *msg;
- readlen = read(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
+ readlen = _SysRead(giNetworkFileHandle, staticBuf, sizeof(staticBuf));
identlen = 4 + Net_GetAddressSize( ((uint16_t*)staticBuf)[1] );
msg = staticBuf + identlen;
}
}
- while(SysGetMessage(NULL, NULL))
+ size_t len;
+ int tid;
+ while( (len = _SysGetMessage(&tid, 0, NULL)) )
{
- pid_t tid;
- int len = SysGetMessage(&tid, NULL);
char data[len];
- SysGetMessage(NULL, data);
+ _SysGetMessage(NULL, len, data);
IPC_Handle(&gIPC_Type_SysMessage, &tid, len, (void*)data);
// _SysDebug("IPC_HandleSelect: Message handled");
memcpy(tmpbuf, Ident, identlen); // Header
memcpy(tmpbuf + identlen, Data, Length); // Data
// TODO: Handle fragmented packets
- write(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
+ _SysWrite(giNetworkFileHandle, tmpbuf, sizeof(tmpbuf));
}
int IPC_Type_Sys_GetSize(const void *Ident)
void IPC_Type_Sys_Send(const void *Ident, size_t Length, const void *Data)
{
- SysSendMessage( *(const tid_t*)Ident, Length, Data );
+ _SysSendMessage( *(const tid_t*)Ident, Length, Data );
}
// --- Client -> Window Mappings
return NULL;
if( WindowID >= Client->nWindows ) {
-// _SysDebug("Window %i out of range for %p (%i)", WindowID, Client, Client->nWindows);
return NULL;
}
tIPC_Client *client;
int rv = 0;
- _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
- IPCType, Ident, MsgLen, Msg);
+// _SysDebug("IPC_Handle: (IPCType=%p, Ident=%p, MsgLen=%i, Msg=%p)",
+// IPCType, Ident, MsgLen, Msg);
if( MsgLen < sizeof(tAxWin_IPCMessage) )
return ;
return ;
client = IPC_int_GetClient(IPCType, Ident);
-
- if( Msg->ID >= giIPC_NumMessageHandlers ) {
- fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
- _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
- return ;
+ if( !client ) {
+ // Oops?
}
- if( !gIPC_MessageHandlers[ Msg->ID ] ) {
- fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
- _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
- return ;
+ if( Msg->Flags & IPCMSG_FLAG_RENDERER )
+ {
+ tWindow *win = IPC_int_GetWindow(client, Msg->Window);
+ if( !win ) {
+ _SysDebug("WARNING: NULL window in message %i", Msg->ID);
+ return ;
+ }
+ tWMRenderer *renderer = win->Renderer;
+ if( Msg->ID >= renderer->nIPCHandlers ) {
+ _SysDebug("WARNING: Message %i out of range in %s", Msg->ID, renderer->Name);
+ return ;
+ }
+ if( !renderer->IPCHandlers[Msg->ID] ) {
+ _SysDebug("WARNING: Message %i has no handler in %s", Msg->ID, renderer->Name);
+ return ;
+ }
+ _SysDebug("IPC_Handle: Call %s-%i", renderer->Name, Msg->ID);
+ rv = renderer->IPCHandlers[Msg->ID](win, Msg->Size, Msg->Data);
+ if( rv )
+ _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
+ }
+ else
+ {
+ if( Msg->ID >= giIPC_NumMessageHandlers ) {
+ fprintf(stderr, "WARNING: Unknown message %i (%p)\n", Msg->ID, IPCType);
+ _SysDebug("WARNING: Unknown message %i (%p)", Msg->ID, IPCType);
+ return ;
+ }
+
+ if( !gIPC_MessageHandlers[ Msg->ID ] ) {
+ fprintf(stderr, "WARNING: Message %i does not have a handler\n", Msg->ID);
+ _SysDebug("WARNING: Message %i does not have a handler", Msg->ID);
+ return ;
+ }
+
+ _SysDebug("IPC_Handle: Call WM-%i", Msg->ID);
+ rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
+ if( rv )
+ _SysDebug("IPC_Handle: rv != 0 (%i)", rv);
}
-
- _SysDebug("IPC_Handle: Msg->ID = %i", Msg->ID);
- rv = gIPC_MessageHandlers[Msg->ID](client, Msg);
- _SysDebug("IPC_Handle: rv = %i", rv);
}
-// --- Server->Client replies
+// Dispatch a message to the client
void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int MsgID, int Len, void *Data)
{
tAxWin_IPCMessage *hdr;
Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
}
+// --- Server->Client replies
+void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data)
+{
+ tAxWin_IPCMessage *hdr;
+ char buf[sizeof(*hdr)+Len];
+
+ hdr = (void*)buf;
+
+ hdr->ID = MsgID;
+ hdr->Flags = IPCMSG_FLAG_RENDERER;
+ hdr->Size = Len;
+ hdr->Window = WinID;
+
+ memcpy(hdr->Data, Data, Len);
+ Client->IPCType->SendMessage(Client->Ident, sizeof(buf), buf);
+}
+
extern int Renderer_Widget_Init(void);
extern int Renderer_Background_Init(void);
extern int Renderer_Framebuffer_Init(void);
+extern int Renderer_RichText_Init(void);
extern void WM_Update(void);
extern void WM_Hotkey_Register(int nKeys, uint32_t *Keys, const char *ActionName);
*/
int main(int argc, char *argv[])
{
- int server_tid = gettid();
-
ParseCommandline(argc, argv);
if( gsTerminalDevice == NULL ) {
Renderer_Widget_Init();
Renderer_Background_Init();
Renderer_Framebuffer_Init();
+ Renderer_RichText_Init();
WM_Initialise();
// TODO: Config
WM_Hotkey_Register(2, keys, "Interface>Run");
// Spawn interface root
- if( clone(CLONE_VM, 0) == 0 )
{
+ int server_tid = gettid();
+ _SysDebug("server_tid = %i", server_tid);
static char csInterfaceApp[] = __INSTALL_ROOT"/AxWinUI";
char server_info[] = "AXWIN3_SERVER=00000";
- char *envp[] = {server_info, NULL};
- char *argv[] = {csInterfaceApp, NULL};
+ const char *envp[] = {server_info, NULL};
+ const char *argv[] = {csInterfaceApp, NULL};
_SysDebug("server_tid = %i, &server_tid = %p", server_tid, &server_tid);
sprintf(server_info, "AXWIN3_SERVER=%i", server_tid);
- execve(csInterfaceApp, argv, envp);
- exit(1);
+ // TODO: Does the client need FDs?
+ int rv = _SysSpawn(csInterfaceApp, argv, envp, 0, NULL, NULL);
+ if( rv ) {
+ _SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
+ }
}
// Main Loop
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer_passthru.c
+ * - Passthrough window render (framebuffer essentially)
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <string.h>
+#include <framebuffer_messages.h>
+#include <wm_messages.h>
+
+// === TYPES ===
+typedef struct
+{
+ short W, H;
+ void *Data;
+ char _data[];
+} tFBBuffer;
+typedef struct
+{
+ tFBBuffer BackBuffer;
+ int MaxBufferCount;
+ tFBBuffer *Buffers[];
+} tFBWin;
+
+// === PROTOTYPES ===
+tWindow *Renderer_Framebuffer_Create(int Flags);
+void Renderer_Framebuffer_Redraw(tWindow *Window);
+ int _Handle_Commit(tWindow *Target, size_t Len, const void *Data);
+ int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data);
+ int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer gRenderer_Framebuffer = {
+ .Name = "FrameBuffer",
+ .CreateWindow = Renderer_Framebuffer_Create,
+ .Redraw = Renderer_Framebuffer_Redraw,
+ .HandleMessage = Renderer_Framebuffer_HandleMessage,
+ .nIPCHandlers = N_IPC_FB,
+ .IPCHandlers = {
+ [IPC_FB_COMMIT] = _Handle_Commit,
+ [IPC_FB_NEWBUF] = _Handle_CreateBuf,
+ }
+};
+
+// === CODE ===
+int Renderer_Framebuffer_Init(void)
+{
+ WM_RegisterRenderer(&gRenderer_Framebuffer);
+ return 0;
+}
+
+tWindow *Renderer_Framebuffer_Create(int Flags)
+{
+ tWindow *ret;
+ tFBWin *info;
+ const int max_buffers = 10; // TODO: Have this be configurable
+
+ ret = WM_CreateWindowStruct( sizeof(*info) + max_buffers*sizeof(tFBBuffer*) );
+ info = ret->RendererInfo;
+
+ info->BackBuffer.W = 0;
+ info->BackBuffer.H = 0;
+ info->BackBuffer.Data = NULL;
+ info->MaxBufferCount = max_buffers;
+ memset( info->Buffers, 0, sizeof(tFBBuffer*) * max_buffers );
+
+ return ret;
+}
+
+void Renderer_Framebuffer_Redraw(tWindow *Window)
+{
+
+}
+
+// --- ---
+tFBBuffer *_GetBuffer(tWindow *Win, uint16_t ID)
+{
+ tFBWin *info = Win->RendererInfo;
+ if( ID == 0xFFFF )
+ return &info->BackBuffer;
+ else if( ID >= info->MaxBufferCount )
+ return NULL;
+ else
+ return info->Buffers[ ID ];
+}
+
+void _Blit(
+ tFBBuffer *Dest, uint16_t DX, uint16_t DY,
+ const tFBBuffer *Src, uint16_t SX, uint16_t SY,
+ uint16_t W, uint16_t H
+ )
+{
+ uint32_t *dest_data = Dest->Data;
+ const uint32_t *src_data = Src->Data;
+ // First, some sanity
+ if( DX > Dest->W ) return ;
+ if( DY > Dest->H ) return ;
+ if( SX > Src->W ) return ;
+ if( SY > Src->H ) return ;
+
+ if( DX + W > Dest->W ) W = Dest->W - DX;
+ if( SX + W > Src->W ) W = Src->W - SX;
+ if( DY + H > Dest->H ) H = Dest->H - DY;
+ if( SY + H > Src->H ) H = Src->H - SY;
+
+ dest_data += (DY * Dest->W) + DX;
+ src_data += (SY * Src->W ) + SX;
+ for( int i = 0; i < H; i ++ )
+ {
+ memcpy( dest_data, src_data, W * 4 );
+ dest_data += Dest->W;
+ src_data += Src->W;
+ }
+}
+
+void _Fill(tFBBuffer *Buf, uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint32_t Colour)
+{
+ uint32_t *data = Buf->Data;
+
+ if( X > Buf->W ) return ;
+ if( Y > Buf->H ) return ;
+ if( X + W > Buf->W ) W = Buf->W - X;
+ if( Y + H > Buf->H ) H = Buf->H - Y;
+
+ data += (Y * Buf->W) + X;
+ for( int i = 0; i < H; i ++ )
+ {
+ for( int j = 0; j < W; j ++ )
+ *data++ = Colour;
+ data += Buf->W - W;
+ }
+}
+
+// --- ---
+int _Handle_Commit(tWindow *Target, size_t Len, const void *Data)
+{
+ // Do a window invalidate
+ return 0;
+}
+
+int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_NewBuf *msg = Data;
+ tFBBuffer *buf;
+ tFBWin *info = Target->RendererInfo;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ if( msg->Buffer == -1 || msg->Buffer >= info->MaxBufferCount ) {
+ // Can't reallocate -1
+ return 1;
+ }
+
+ if( info->Buffers[msg->Buffer] ) {
+ free(info->Buffers[msg->Buffer]);
+ info->Buffers[msg->Buffer] = NULL;
+ }
+
+ buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
+ buf->W = msg->W;
+ buf->H = msg->H;
+ buf->Data = buf->_data;
+
+ info->Buffers[msg->Buffer] = buf;
+
+ return 0;
+}
+
+int _Handle_Upload(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Transfer *msg = Data;
+ tFBBuffer *dest, src;
+
+ if( Len < sizeof(*msg) ) return -1;
+ if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return -1;
+
+ dest = _GetBuffer(Target, msg->Buffer);
+
+ src.W = msg->W;
+ src.H = msg->H;
+ src.Data = (void*)msg->ImageData;
+
+ _Blit( dest, msg->X, msg->Y, &src, 0, 0, msg->W, msg->H );
+ return 0;
+}
+
+int _Handle_Download(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Transfer *msg = Data;
+ tFBBuffer dest, *src;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ src = _GetBuffer(Target, msg->Buffer);
+
+ tFBIPC_Transfer *ret;
+ int retlen = sizeof(*ret) + msg->W*msg->H*4;
+ ret = malloc( retlen );
+
+ dest.W = ret->W = msg->W;
+ dest.H = ret->H = msg->H;
+ dest.Data = ret->ImageData;
+
+ _Blit( &dest, 0, 0, src, msg->X, msg->Y, msg->W, msg->H );
+
+ WM_SendIPCReply(Target, IPC_FB_DOWNLOAD, retlen, ret);
+
+ free(ret);
+
+ return 0;
+}
+
+int _Handle_LocalBlit(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Blit *msg = Data;
+ tFBBuffer *dest, *src;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ src = _GetBuffer(Target, msg->Source);
+ dest = _GetBuffer(Target, msg->Dest);
+
+ _Blit( dest, msg->DstX, msg->DstY, src, msg->SrcX, msg->SrcY, msg->W, msg->H );
+ return 0;
+}
+
+int _Handle_FillRect(tWindow *Target, size_t Len, const void *Data)
+{
+ const tFBIPC_Fill *msg = Data;
+ tFBBuffer *dest;
+
+ if( Len < sizeof(*msg) ) return -1;
+
+ dest = _GetBuffer(Target, msg->Buffer);
+
+ _Fill( dest, msg->X, msg->Y, msg->W, msg->H, msg->Colour );
+ return 0;
+}
+
+int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+ switch(Msg)
+ {
+ case WNDMSG_RESIZE:
+ // Resize the framebuffer
+ return 1; // Pass on
+
+ // Messages that get passed on
+ case WNDMSG_MOUSEBTN:
+ return 1;
+ }
+ return 1;
+}
+
+
void Renderer_Menu_Init(void);
tWindow *Renderer_Menu_Create(int Argument);
void Renderer_Menu_Redraw(tWindow *Window);
+ int Renderer_Menu_HandleIPC_AddItem(tWindow *Window, size_t Length, const void *Data);
+ int Renderer_Menu_HandleIPC_SetFlags(tWindow *Window, size_t Length, const void *Data);
int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, const void *Data);
// === CONSTANTS ===
.Name = "Menu",
.CreateWindow = Renderer_Menu_Create,
.Redraw = Renderer_Menu_Redraw,
- .HandleMessage = Renderer_Menu_HandleMessage
+ .HandleMessage = Renderer_Menu_HandleMessage,
+ .nIPCHandlers = 2,
+ .IPCHandlers = {
+ Renderer_Menu_HandleIPC_AddItem,
+// Renderer_Menu_HandleIPC_SetFlags
+ }
};
tFont *gMenu_Font = NULL; // System monospace
}
}
-int Renderer_Menu_int_AddItem(tWindow *Window, int Length, const tMenuMsg_AddItem *Msg)
+int Renderer_Menu_HandleIPC_AddItem(tWindow *Window, size_t Length, const void *Data)
{
+ const tMenuIPC_AddItem *Msg = Data;
tMenuWindowInfo *info = Window->RendererInfo;
tMenuItem *item;
return 0; }
- // Manipulation messages
- case MSG_MENU_ADDITEM:
-// _SysDebug("MSG_MENU_ADDITEM");
- return Renderer_Menu_int_AddItem(Window, Length, Data);
-
// Only message to pass to client
case MSG_MENU_SELECT:
return 1;
+++ /dev/null
-/*
- * Acess2 Window Manager v3
- * - By John Hodge (thePowersGang)
- *
- * renderer_passthru.c
- * - Passthrough window render (framebuffer essentially)
- */
-#include <common.h>
-#include <wm_renderer.h>
-#include <string.h>
-#include <framebuffer_messages.h>
-#include <wm_messages.h>
-
-// === TYPES ===
-typedef struct
-{
- short W, H;
- void *Data;
- char _data[];
-} tFBBuffer;
-typedef struct
-{
- tFBBuffer BackBuffer;
- int MaxBufferCount;
- tFBBuffer *Buffers[];
-} tFBWin;
-
-// === PROTOTYPES ===
-tWindow *Renderer_Framebuffer_Create(int Flags);
-void Renderer_Framebuffer_Redraw(tWindow *Window);
- int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
-
-// === GLOBALS ===
-tWMRenderer gRenderer_Framebuffer = {
- .Name = "FrameBuffer",
- .CreateWindow = Renderer_Framebuffer_Create,
- .Redraw = Renderer_Framebuffer_Redraw,
- .HandleMessage = Renderer_Framebuffer_HandleMessage
-};
-
-// === CODE ===
-int Renderer_Framebuffer_Init(void)
-{
- WM_RegisterRenderer(&gRenderer_Framebuffer);
- return 0;
-}
-
-tWindow *Renderer_Framebuffer_Create(int Flags)
-{
- tWindow *ret;
- tFBWin *info;
- const int max_buffers = 10; // TODO: Have this be configurable
-
- ret = WM_CreateWindowStruct( sizeof(*info) + max_buffers*sizeof(tFBBuffer*) );
- info = ret->RendererInfo;
-
- info->BackBuffer.W = 0;
- info->BackBuffer.H = 0;
- info->BackBuffer.Data = NULL;
- info->MaxBufferCount = max_buffers;
- memset( info->Buffers, 0, sizeof(tFBBuffer*) * max_buffers );
-
- return ret;
-}
-
-void Renderer_Framebuffer_Redraw(tWindow *Window)
-{
-
-}
-
-// --- ---
-tFBBuffer *_GetBuffer(tWindow *Win, uint16_t ID)
-{
- tFBWin *info = Win->RendererInfo;
- if( ID == 0xFFFF )
- return &info->BackBuffer;
- else if( ID >= info->MaxBufferCount )
- return NULL;
- else
- return info->Buffers[ ID ];
-}
-
-void _Blit(
- tFBBuffer *Dest, uint16_t DX, uint16_t DY,
- const tFBBuffer *Src, uint16_t SX, uint16_t SY,
- uint16_t W, uint16_t H
- )
-{
- uint32_t *dest_data = Dest->Data;
- const uint32_t *src_data = Src->Data;
- // First, some sanity
- if( DX > Dest->W ) return ;
- if( DY > Dest->H ) return ;
- if( SX > Src->W ) return ;
- if( SY > Src->H ) return ;
-
- if( DX + W > Dest->W ) W = Dest->W - DX;
- if( SX + W > Src->W ) W = Src->W - SX;
- if( DY + H > Dest->H ) H = Dest->H - DY;
- if( SY + H > Src->H ) H = Src->H - SY;
-
- dest_data += (DY * Dest->W) + DX;
- src_data += (SY * Src->W ) + SX;
- for( int i = 0; i < H; i ++ )
- {
- memcpy( dest_data, src_data, W * 4 );
- dest_data += Dest->W;
- src_data += Src->W;
- }
-}
-
-void _Fill(tFBBuffer *Buf, uint16_t X, uint16_t Y, uint16_t W, uint16_t H, uint32_t Colour)
-{
- uint32_t *data = Buf->Data;
-
- if( X > Buf->W ) return ;
- if( Y > Buf->H ) return ;
- if( X + W > Buf->W ) W = Buf->W - X;
- if( Y + H > Buf->H ) H = Buf->H - Y;
-
- data += (Y * Buf->W) + X;
- for( int i = 0; i < H; i ++ )
- {
- for( int j = 0; j < W; j ++ )
- *data++ = Colour;
- data += Buf->W - W;
- }
-}
-
-// --- ---
-void _Handle_Commit(tWindow *Target, size_t Len, const void *Data)
-{
- // Do a window invalidate
-}
-
-void _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_NewBuf *msg = Data;
- tFBBuffer *buf;
- tFBWin *info = Target->RendererInfo;
-
- if( Len < sizeof(*msg) ) return ;
-
- if( msg->Buffer == -1 || msg->Buffer >= info->MaxBufferCount ) {
- // Can't reallocate -1
- return ;
- }
-
- if( info->Buffers[msg->Buffer] ) {
- free(info->Buffers[msg->Buffer]);
- info->Buffers[msg->Buffer] = NULL;
- }
-
- buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
- buf->W = msg->W;
- buf->H = msg->H;
- buf->Data = buf->_data;
-
- info->Buffers[msg->Buffer] = buf;
-}
-
-void _Handle_Upload(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Transfer *msg = Data;
- tFBBuffer *dest, src;
-
- if( Len < sizeof(*msg) ) return ;
- if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return ;
-
- dest = _GetBuffer(Target, msg->Buffer);
-
- src.W = msg->W;
- src.H = msg->H;
- src.Data = (void*)msg->ImageData;
-
- _Blit( dest, msg->X, msg->Y, &src, 0, 0, msg->W, msg->H );
-}
-
-void _Handle_Download(tWindow *Target, size_t Len, const void *Data)
-{
- #if 0
- const tFBMsg_Transfer *msg = Data;
- tFBBuffer dest, *src;
-
- if( Len < sizeof(*msg) ) return ;
- if( Len < sizeof(*msg) + msg->W * msg->H * 4 ) return ;
-
- src = _GetBuffer(Target, msg->Buffer);
-
- dest.W = msg->W;
- dest.H = msg->H;
- dest.Data = msg->ImageData;
-
- _Blit( &dest, 0, 0, src, msg->X, msg->Y, msg->W, msg->H );
- #endif
-}
-
-void _Handle_LocalBlit(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Blit *msg = Data;
- tFBBuffer *dest, *src;
-
- if( Len < sizeof(*msg) ) return ;
-
- src = _GetBuffer(Target, msg->Source);
- dest = _GetBuffer(Target, msg->Dest);
-
- _Blit( dest, msg->DstX, msg->DstY, src, msg->SrcX, msg->SrcY, msg->W, msg->H );
-}
-
-void _Handle_FillRect(tWindow *Target, size_t Len, const void *Data)
-{
- const tFBMsg_Fill *msg = Data;
- tFBBuffer *dest;
-
- if( Len < sizeof(*msg) ) return ;
-
- dest = _GetBuffer(Target, msg->Buffer);
-
- _Fill( dest, msg->X, msg->Y, msg->W, msg->H, msg->Colour );
-}
-
-int Renderer_Framebuffer_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
-{
- switch(Msg)
- {
- case WNDMSG_RESIZE:
- // Resize the framebuffer
- return 1; // Pass on
-
- // Messages that get passed on
- case WNDMSG_MOUSEBTN:
- return 1;
-
- // --- Local messages ---
- // - Drawing completed, do an update
- case MSG_FB_COMMIT:
- _Handle_Commit(Target, Len, Data);
- return 0;
- // - New Buffer (create a new server-side buffer)
- case MSG_FB_NEWBUF:
- _Handle_CreateBuf(Target, Len, Data);
- return 0;
- // - Upload (Transfer data from client to server)
- case MSG_FB_UPLOAD:
- _Handle_Upload(Target, Len, Data);
- return 0;
- // - Download (Transfer image data from server to client)
- case MSG_FB_DOWNLOAD:
- _Handle_Download(Target, Len, Data);
- return 0;
- // - Local Blit (Transfer from server to server)
- case MSG_FB_BLIT:
- _Handle_LocalBlit(Target, Len, Data);
- return 0;
- // - Fill a rectangle
- case MSG_FB_FILL:
- _Handle_FillRect(Target, Len, Data);
- return 0;
- }
- return 1;
-}
-
-
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render/richtext.c
+ * - Formatted Line Editor
+ */
+#include <common.h>
+#include <wm_renderer.h>
+#include <wm_messages.h>
+#include <richtext_messages.h>
+#include <stdio.h> // sscanf
+#include <string.h> // memcpy
+
+#define LINES_PER_BLOCK 30
+
+// === TYPES ===
+typedef struct sRichText_Line
+{
+ struct sRichText_Line *Next;
+ struct sRichText_Line *Prev;
+ int Num;
+ // TODO: Pre-rendered cache?
+ short ByteLength;
+ short Space;
+ char Data[];
+} tRichText_Line;
+typedef struct sRichText_Window
+{
+ int DispLines, DispCols;
+ int FirstVisRow, FirstVisCol;
+ int nLines, nCols;
+ int CursorRow, CursorCol;
+ tRichText_Line *FirstLine;
+ tRichText_Line *FirstVisLine;
+ tColour DefaultFG;
+ tColour DefaultBG;
+ tFont *Font;
+
+ short LineHeight;
+} tRichText_Window;
+
+// === PROTOTYPES ===
+ int Renderer_RichText_Init(void);
+tWindow *Renderer_RichText_Create(int Flags);
+void Renderer_RichText_Redraw(tWindow *Window);
+ int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data);
+ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data);
+ int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
+
+// === GLOBALS ===
+tWMRenderer gRenderer_RichText = {
+ .Name = "RichText",
+ .CreateWindow = Renderer_RichText_Create,
+ .Redraw = Renderer_RichText_Redraw,
+ .HandleMessage = Renderer_RichText_HandleMessage,
+ .nIPCHandlers = N_IPC_RICHTEXT,
+ .IPCHandlers = {
+ [IPC_RICHTEXT_SETATTR] = Renderer_RichText_HandleIPC_SetAttr,
+ [IPC_RICHTEXT_WRITELINE] = Renderer_RichText_HandleIPC_WriteLine
+ }
+};
+
+// === CODE ===
+int Renderer_RichText_Init(void)
+{
+ WM_RegisterRenderer(&gRenderer_RichText);
+ return 0;
+}
+
+tWindow *Renderer_RichText_Create(int Flags)
+{
+ tRichText_Window *info;
+ tWindow *ret = WM_CreateWindowStruct( sizeof(*info) );
+ if(!ret) return NULL;
+ info = ret->RendererInfo;
+
+ // Initialise font (get an idea of dimensions)
+ int h;
+ WM_Render_GetTextDims(NULL, "yY!", 3, NULL, &h);
+ info->LineHeight = h;
+
+ return ret;
+}
+
+static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Window *info, int X, int Row, const char *Text, int Bytes, tColour FG, tColour BG, int Flags)
+{
+ int rwidth;
+ // TODO: Fill only what is needed? What about the rest of the line?
+ WM_Render_DrawRect(Window, X, Row*info->LineHeight,
+ Window->W - X, info->LineHeight,
+ BG
+ );
+ // TODO: Bold, Italic, Underline
+ rwidth = WM_Render_DrawText(Window,
+ X, Row*info->LineHeight,
+ Window->W - X, info->LineHeight,
+ info->Font, FG,
+ Text, Bytes
+ );
+ return rwidth;
+}
+
+void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ tColour fg = info->DefaultFG;
+ tColour bg = info->DefaultBG;
+ int flagset = 0;
+ int bRender = 0;
+ int curx = 0;
+ const char *oldtext = Text;
+
+ for( int i = 0; curx < Window->W; i ++ )
+ {
+ char ch, flags;
+ int len;
+
+ if( i == info->FirstVisCol )
+ bRender = 1;
+
+ ch = *Text++;
+ if( ch == 0 ) break;
+
+ // Not an escape - move along
+ if( ch > 4 )
+ continue ;
+
+ if( bRender ) {
+ // Render previous characters
+ curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line,
+ oldtext, Text - oldtext - 1, fg, bg, flagset);
+ if( curx >= Window->W )
+ break;
+ }
+ oldtext = Text;
+ switch(ch)
+ {
+ case 1: // FG Select (\1 RRGGBB)
+ if( sscanf(Text, "%6x%n", &fg, &len) != 1 || len != 6 ) {
+ // Bad client
+ _SysDebug("foreground scanf failed - len=%i", len);
+ len = 0;
+ }
+ Text += len;
+ oldtext = Text;
+ _SysDebug("FG update to %x", fg);
+ break ;
+ case 2: // BG Select (\2 RRGGBB)
+ if( sscanf(Text, "%6x%n", &bg, &len) != 1 || len != 6 ) {
+ // Bad client
+ _SysDebug("background scanf failed - len=%i", len);
+ len = 0;
+ }
+ Text += len;
+ oldtext = Text;
+ _SysDebug("BG update to %x", bg);
+ break ;
+ case 3: // Flagset (0,it,uline,bold)
+ if( sscanf(Text, "%1hhx%n", &flags, &len) != 1 || len != 1 ) {
+ // Bad client
+ _SysDebug("Flagset scanf failed - len=%i", len);
+ }
+ flagset = flags & 7;
+ Text += len;
+ oldtext = Text;
+ break ;
+ case 4: // Escape (do nothing)
+ Text ++;
+ // NOTE: No update to oldtext
+ break;
+ default: // Error.
+ break;
+ }
+ }
+ curx += Renderer_RichText_RenderText_Act(Window, info, curx,
+ Line, oldtext, Text - oldtext + 1, fg, bg, flagset);
+ WM_Render_DrawRect(Window, curx, Line * info->LineHeight,
+ Window->W - curx, info->LineHeight, info->DefaultBG);
+}
+
+void Renderer_RichText_Redraw(tWindow *Window)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ int i;
+ tRichText_Line *line = info->FirstVisLine;
+
+ if( !line ) {
+ line = info->FirstLine;
+ while(line && line->Num < info->FirstVisRow )
+ line = line->Next;
+ info->FirstVisLine = line;
+ }
+ while( line && line->Prev && line->Prev->Num > info->FirstVisRow )
+ line = line->Prev;
+
+ for( i = 0; i < info->DispLines && line; i ++ )
+ {
+ if( i >= info->nLines - info->FirstVisRow )
+ break;
+ // TODO: Dirty rectangles?
+ WM_Render_FillRect(Window,
+ 0, i*info->LineHeight,
+ Window->W, info->LineHeight,
+ info->DefaultBG
+ );
+ if( line->Num > info->FirstVisRow + i )
+ continue ;
+ // TODO: Horizontal scrolling?
+ // TODO: Formatting
+
+ // Formatted text out
+ Renderer_RichText_RenderText(Window, i, line->Data);
+ _SysDebug("RichText: %p - Render %i '%.*s'", Window,
+ line->Num, line->ByteLength, line->Data);
+
+ line = line->Next;
+ }
+ // Clear out i -- info->DispLines
+ _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i",
+ Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight);
+ WM_Render_FillRect(Window,
+ 0, i*info->LineHeight,
+ Window->W, (info->DispLines-i)*info->LineHeight,
+ info->DefaultBG
+ );
+}
+
+int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ const struct sRichTextIPC_SetAttr *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ _SysDebug("RichText Attr %i set to %x", msg->Attr, msg->Value);
+ switch(msg->Attr)
+ {
+ case _ATTR_DEFBG:
+ info->DefaultBG = msg->Value;
+ break;
+ case _ATTR_DEFFG:
+ info->DefaultFG = msg->Value;
+ break;
+ case _ATTR_SCROLL:
+ // TODO: Set scroll flag
+ break;
+ case _ATTR_LINECOUNT:
+ info->nLines = msg->Value;
+ break;
+ }
+
+ return 0;
+}
+
+int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data)
+{
+ tRichText_Window *info = Window->RendererInfo;
+ const struct sRichTextIPC_WriteLine *msg = Data;
+ if( Len < sizeof(*msg) ) return -1;
+ if( msg->Line >= info->nLines ) return 1; // Bad count
+
+ tRichText_Line *line = info->FirstLine;
+ tRichText_Line *prev = NULL;
+ while(line && line->Num < msg->Line)
+ prev = line, line = line->Next;
+ if( !line || line->Num > msg->Line )
+ {
+ // New line!
+ // Round up to 32
+ int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
+ tRichText_Line *new = malloc(sizeof(*line) + space);
+ // TODO: Bookkeeping on how much memory each window uses
+ new->Next = line;
+ new->Prev = prev;
+ new->Num = msg->Line;
+ new->Space = space;
+ if(new->Prev) new->Prev->Next = new;
+ else info->FirstLine = new;
+ if(new->Next) new->Next->Prev = new;
+ line = new;
+ }
+ else if( line->Space < Len - sizeof(*msg) )
+ {
+ // Need to allocate more space
+ int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
+ tRichText_Line *new = realloc(line, space);
+ // TODO: Bookkeeping on how much memory each window uses
+ new->Space = space;
+
+ if(new->Prev) new->Prev->Next = new;
+ else info->FirstLine = new;
+ if(new->Next) new->Next->Prev = new;
+ line = new;
+ }
+ else
+ {
+ // It fits :)
+ }
+ line->ByteLength = Len - sizeof(*msg);
+ memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
+
+ return 0;
+}
+
+int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
+{
+ tRichText_Window *info = Target->RendererInfo;
+ switch(Msg)
+ {
+ case WNDMSG_RESIZE: {
+ const struct sWndMsg_Resize *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+ info->DispLines = msg->H / info->LineHeight;
+ return 1; }
+ }
+ return 0;
+}
void Widget_UpdatePosition(tElement *Element);
// --- Messages
tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg);
-void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg);
-void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg);
-void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg);
+ int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_Delete(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data);
+ int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_SetColour(tWindow *Win, size_t Len, const void *Data);
int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
// === GLOBALS ===
.Name = "Widget",
.CreateWindow = Renderer_Widget_Create,
.Redraw = Renderer_Widget_Redraw,
- .HandleMessage = Renderer_Widget_HandleMessage
+ .HandleMessage = Renderer_Widget_HandleMessage,
+ .nIPCHandlers = N_IPC_WIDGET,
+ .IPCHandlers = {
+ [IPC_WIDGET_CREATE] = Widget_IPC_Create,
+ [IPC_WIDGET_CREATESUBWIN] = Widget_IPC_NewWidgetSubwin,
+ [IPC_WIDGET_SETFOCUS] = Widget_IPC_SetFocus,
+ [IPC_WIDGET_SETFLAGS] = Widget_IPC_SetFlags,
+ [IPC_WIDGET_SETSIZE] = Widget_IPC_SetSize,
+ [IPC_WIDGET_SETTEXT] = Widget_IPC_SetText,
+ [IPC_WIDGET_GETTEXT] = Widget_IPC_GetText,
+ }
};
// --- Element callbacks
tWidgetWin *info;
int eletable_size = DEFAULT_ELETABLE_SIZE;
- _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+ //_SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
// TODO: Use `Flags` as default element count?
// - Actaully, it's taken by the root ele flags
else
fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
- _SysDebug("%i (p=%i) - WxH=%ix%i",
- Element->ID, (Element->Parent ? Element->Parent->ID : -1),
- Element->CachedW, Element->CachedH
- );
- _SysDebug(" %s dynWith = %i, fullCross = %i",
- (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
- dynWith, fullCross
- );
+ //_SysDebug("%i (p=%i) - WxH=%ix%i",
+ // Element->ID, (Element->Parent ? Element->Parent->ID : -1),
+ // Element->CachedW, Element->CachedH
+ // );
+ //_SysDebug(" %s dynWith = %i, fullCross = %i",
+ // (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
+ // dynWith, fullCross
+ // );
// Pass 2 - Set sizes and recurse
for( child = Element->FirstChild; child; child = child->NextSibling )
return ele;
}
-// --- Message Handlers ---
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
+tElement *Widget_int_Create(tWidgetWin *Info, tElement *Parent, int ID, int Type, int Flags)
{
- const int max_debugname_len = Len - sizeof(tWidgetMsg_Create);
- tElement *parent, *new;
-
- // Sanity check
- if( Len < sizeof(*Msg) )
- return ;
- if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
- return ;
-
- _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
- Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
-
- if(Msg->Type >= ciWM_NumWidgetTypes)
- {
- _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
- return ;
- }
-
- // Create
- parent = Widget_GetElementById(Info, Msg->Parent);
- if(!parent)
- {
- _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
- return ;
- }
-
- // Check if the ID is already in use
- if( Widget_GetElementById(Info, Msg->NewID) )
- return ;
+ if( Widget_GetElementById(Info, ID) )
+ return NULL;
// Create new element
- new = calloc(sizeof(tElement), 1);
- new->Window = parent->Window;
- new->ID = Msg->NewID;
- new->Type = Msg->Type;
- new->Parent = parent;
- new->Flags = Msg->Flags;
+ tElement *new = calloc(sizeof(tElement), 1);
+ new->Window = Parent->Window;
+ new->ID = ID;
+ new->Type = Type;
+ new->Parent = Parent;
+ new->Flags = Flags;
new->PaddingT = 2;
new->PaddingB = 2;
new->PaddingL = 2;
new->PaddingR = 2;
new->CachedX = -1;
- if( gaWM_WidgetTypes[new->Type]->Init )
- gaWM_WidgetTypes[new->Type]->Init(new);
+ if( gaWM_WidgetTypes[Type]->Init )
+ gaWM_WidgetTypes[Type]->Init(new);
// Add to parent's list
- if(parent->LastChild)
- parent->LastChild->NextSibling = new;
+ if(Parent->LastChild)
+ Parent->LastChild->NextSibling = new;
else
- parent->FirstChild = new;
- parent->LastChild = new;
+ Parent->FirstChild = new;
+ Parent->LastChild = new;
// Add to info
{
else
Info->ElementTable[new->ID % Info->TableSize] = new;
}
-
- Widget_UpdateMinDims(parent);
+
+ return new;
}
void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
Info->FocusedElement = Ele;
}
-void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
+
+// --- Message Handlers ---
+int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_Create *Msg = Data;
+ const int max_debugname_len = Len - sizeof(*Msg);
+ tElement *parent;
+
+ // Sanity check
+ if( Len < sizeof(*Msg) )
+ return -1;
+ if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+ return -1;
+
+ _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
+ Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
+
+ if(Msg->Type >= ciWM_NumWidgetTypes)
+ {
+ _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
+ return 1;
+ }
+
+ // Create
+ parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent)
+ {
+ _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
+ return 1;
+ }
+
+ Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+
+ Widget_UpdateMinDims(parent);
+ return 0;
+}
+
+int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_CreateSubWin *Msg = Data;
+ const int max_debugname_len = Len - sizeof(*Msg);
+ tElement *parent, *new;
+
+ // Sanity check
+ if( Len < sizeof(*Msg) )
+ return -1;
+ if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+ return -1;
+
+ parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent) return 1;
+ if( Widget_GetElementById(Info, Msg->NewID) ) return 1;
+
+ new = Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+ new->Data = WM_GetWindowByID(parent->Window, Msg->WindowHandle);
+ Widget_UpdateMinDims(parent);
+ return 0;
+}
+
+// TODO: Widget_IPC_Delete
+
+int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data)
+{
+ tWidgetWin *info = Win->RendererInfo;
+ tElement *ele;
+ const tWidgetIPC_SetFocus *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ ele = Widget_GetElementById(info, msg->WidgetID);
+ Widget_SetFocus(info, ele);
+ return 0;
+}
+
+int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetFlags *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) )
- return ;
+ return -1;
_SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return;
+ if(!ele) return 1;
ele->Flags &= ~Msg->Mask;
ele->Flags |= Msg->Value & Msg->Mask;
+
+ return 0;
}
-void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg)
+int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetSize *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) )
- return ;
+ return -1;
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return ;
+ if(!ele) return 1;
ele->FixedWith = Msg->Value;
+ return 0;
}
-void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetText *Msg = Data;
tElement *ele;
if( Len < sizeof(*Msg) + 1 )
- return ;
+ return -1;
if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' )
- return ;
+ return -1;
ele = Widget_GetElementById(Info, Msg->WidgetID);
- if(!ele) return ;
-
+ if(!ele) return 1;
if( gaWM_WidgetTypes[ele->Type]->UpdateText )
{
// if(ele->Text) free(ele->Text);
// ele->Text = strdup(Msg->Text);
// }
+ return 0;
}
-int Widget_GetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data)
{
+ tWidgetWin *Info = Win->RendererInfo;
+ const tWidgetIPC_SetText *Msg = Data;
if( Len < sizeof(*Msg) )
- return 0;
- if( Len > sizeof(*Msg) )
- return 1; // Pass to user
+ return -1;
const char *text = NULL;
tElement *ele = Widget_GetElementById(Info, Msg->WidgetID);
if(ele)
text = ele->Text;
- char buf[sizeof(tWidgetMsg_SetText) + strlen(text?text:"") + 1];
- tWidgetMsg_SetText *omsg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText) + strlen(text?text:"") + 1];
+ tWidgetIPC_SetText *omsg = (void*)buf;
if( text ) {
omsg->WidgetID = Msg->WidgetID;
omsg->Text[0] = 0;
}
- WM_SendMessage(Info->RootElement.Window, Info->RootElement.Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+ WM_SendIPCReply(Win, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
return 0;
}
}
return 0; }
- // New Widget
- case MSG_WIDGET_CREATE:
- Widget_NewWidget(info, Len, Data);
- return 0;
-
- // Delete a widget
- case MSG_WIDGET_DELETE:
- _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
- return 0;
-
- // Set focused widget
- case MSG_WIDGET_SETFOCUS: {
- tElement *ele;
- const tWidgetMsg_SetFocus *msg = Data;
- if(Len < sizeof(*msg)) return -1;
-
- ele = Widget_GetElementById(info, msg->WidgetID);
- Widget_SetFocus(info, ele);
- return 0; }
-
- // Set Flags
- case MSG_WIDGET_SETFLAGS:
- Widget_SetFlags(info, Len, Data);
- return 0;
-
- // Set length
- case MSG_WIDGET_SETSIZE:
- Widget_SetSize(info, Len, Data);
- return 0;
-
- // Set text
- case MSG_WIDGET_SETTEXT:
- Widget_SetText(info, Len, Data);
- return 0;
- case MSG_WIDGET_GETTEXT:
- return Widget_GetText(info, Len, Data);
-
//
default:
return 1; // Unhandled, pass to user
{
tWidgetMsg_Fire msg;
msg.WidgetID = Element->ID;
+ _SysDebug("Widget_Fire: Fire on %p %i", Element->Window, Element->ID);
WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
}
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * renderer/widget/subwin.c
+ * - Embedded Window Widget Type
+ */
+#include <common.h>
+#include "./common.h"
+#include "./colours.h"
+
+void Widget_SubWin_Render(tWindow *Window, tElement *Element)
+{
+ // Ensure that child window is positioned relative to this window
+ WM_SetRelative(Element->Data, 1);
+ // Note: Doesn't actually render, but does poke the child window
+ WM_MoveWindow(Element->Data, Element->CachedX, Element->CachedY);
+ WM_ResizeWindow(Element->Data, Element->CachedW, Element->CachedH);
+}
+
+DEFWIDGETTYPE(ELETYPE_SUBWIN,
+ WIDGETTYPE_FLAG_NOCHILDREN,
+ .Render = Widget_SubWin_Render
+ )
}
// Four Byte
- if( (*str & 0xF1) == 0xF0 ) {
+ if( (*str & 0xF8) == 0xF0 ) {
*Val = (*str & 0x07) << 18; // Upper 3 Bits
str ++;
if( (*str & 0xC0) != 0x80) return -1; // Validity check
// Open terminal
#if 0
- giTerminalFD = open(gsTerminalDevice, OPENFLAG_READ|OPENFLAG_WRITE);
+ giTerminalFD = _SysOpen(gsTerminalDevice, OPENFLAG_READ|OPENFLAG_WRITE);
if( giTerminalFD == -1 )
{
fprintf(stderr, "ERROR: Unable to open '%s' (%i)\n", gsTerminalDevice, _errno);
giTerminalFD = 1;
giTerminalFD_Input = 0;
// Check that the console is a VT
- // - ioctl(..., 0, NULL) returns the type, which should be 2
- if( ioctl(1, 0, NULL) != 2 )
+ // - _SysIOCtl(..., 0, NULL) returns the type, which should be 2
+ if( _SysIOCtl(1, 0, NULL) != 2 )
{
fprintf(stderr, "stdout is not an Acess VT, can't start");
_SysDebug("stdout is not an Acess VT, can't start");
// Set mode to video
tmpInt = TERM_MODE_FB;
- ioctl( giTerminalFD, TERM_IOCTL_MODETYPE, &tmpInt );
+ _SysIOCtl( giTerminalFD, TERM_IOCTL_MODETYPE, &tmpInt );
// Get dimensions
- giScreenWidth = ioctl( giTerminalFD, TERM_IOCTL_WIDTH, NULL );
- giScreenHeight = ioctl( giTerminalFD, TERM_IOCTL_HEIGHT, NULL );
+ giScreenWidth = _SysIOCtl( giTerminalFD, TERM_IOCTL_WIDTH, NULL );
+ giScreenHeight = _SysIOCtl( giTerminalFD, TERM_IOCTL_HEIGHT, NULL );
giVideo_LastDirtyLine = giScreenHeight;
// Force VT to be shown
- ioctl( giTerminalFD, TERM_IOCTL_FORCESHOW, NULL );
+ _SysIOCtl( giTerminalFD, TERM_IOCTL_FORCESHOW, NULL );
// Create local framebuffer (back buffer)
gpScreenBuffer = malloc( giScreenWidth*giScreenHeight*4 );
// Set cursor position and bitmap
- ioctl(giTerminalFD, TERM_IOCTL_SETCURSORBITMAP, &cCursorBitmap);
+ _SysIOCtl(giTerminalFD, TERM_IOCTL_SETCURSORBITMAP, &cCursorBitmap);
Video_SetCursorPos( giScreenWidth/2, giScreenHeight/2 );
}
_SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
- seek(giTerminalFD, ofs*4, 1);
- _SysDebug("Video_Update - Sending");
- write(giTerminalFD, gpScreenBuffer+ofs, size*4);
+ _SysSeek(giTerminalFD, ofs*4, 1);
+ _SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4);
+ _SysWrite(giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysDebug("Video_Update - Done");
giVideo_FirstDirtyLine = 0;
giVideo_LastDirtyLine = 0;
} pos;
pos.x = giVideo_CursorX = X;
pos.y = giVideo_CursorY = Y;
- ioctl(giTerminalFD, TERM_IOCTL_GETSETCURSOR, &pos);
+ _SysIOCtl(giTerminalFD, TERM_IOCTL_GETSETCURSOR, &pos);
}
void Video_FillRect(int X, int Y, int W, int H, uint32_t Colour)
void Video_Blit(uint32_t *Source, short DstX, short DstY, short W, short H)
{
uint32_t *buf;
+ short drawW = W;
if( DstX >= giScreenWidth) return ;
if( DstY >= giScreenHeight) return ;
- // TODO: Handle -ve X/Y by clipping
- if( DstX < 0 || DstY < 0 ) return ;
- // TODO: Handle out of bounds by clipping too
- if( DstX + W > giScreenWidth ) return;
+ // Drawing oob to left/top, clip
+ if( DstX < 0 ) {
+ Source += -DstX;
+ drawW -= -DstX;
+ DstX = 0;
+ }
+ if( DstY < 0 ) {
+ Source += (-DstY)*W;
+ H -= -DstY;
+ DstY = 0;
+ }
+ if( drawW < 0 ) return ;
+ // Drawing oob to the right, clip
+ if( DstX + drawW > giScreenWidth ) {
+ //int oldw = drawW;
+ drawW = giScreenWidth - DstX;
+ }
if( DstY + H > giScreenHeight )
- H = giScreenWidth - DstY;
+ H = giScreenHeight - DstY;
if( W <= 0 || H <= 0 ) return;
- if( DstX < giVideo_FirstDirtyLine )
+ if( DstY < giVideo_FirstDirtyLine )
giVideo_FirstDirtyLine = DstY;
if( DstY + H > giVideo_LastDirtyLine )
giVideo_LastDirtyLine = DstY + H;
buf = gpScreenBuffer + DstY*giScreenWidth + DstX;
- if(W != giScreenWidth)
+ if(drawW != giScreenWidth || W != giScreenWidth)
{
while( H -- )
{
- memcpy(buf, Source, W*4);
+ memcpy(buf, Source, drawW*4);
Source += W;
buf += giScreenWidth;
}
}
else
{
+ // Only valid if copying full scanlines on both ends
memcpy(buf, Source, giScreenWidth*H*4);
}
}
// === IMPORTS ===
extern void IPC_SendWMMessage(tIPC_Client *Client, uint32_t Src, uint32_t Dst, int Msg, int Len, const void *Data);
+extern void IPC_SendReply(tIPC_Client *Client, uint32_t WinID, int MsgID, size_t Len, const void *Data);
+extern tWindow *IPC_int_GetWindow(tIPC_Client *Client, uint32_t ID);
// === GLOBALS ===
tWMRenderer *gpWM_Renderers;
return ret;
}
+tWindow *WM_GetWindowByID(tWindow *Requester, uint32_t ID)
+{
+ return IPC_int_GetWindow(Requester->Client, ID);
+}
+
tWindow *WM_CreateWindowStruct(size_t ExtraSize)
{
tWindow *ret;
Window->PrevSibling = parent->LastChild;
Window->NextSibling = NULL;
parent->LastChild = Window;
+
+ _SysDebug("Raised %p", Window);
+}
+
+/*
+void WM_RaiseWindow(tWindow *Window)
+{
+ // Move to the last render position (move to top)
+ while(Window && Window->Parent)
+ {
+ if( Window->NextSibling )
+ {
+ // remove
+ if( Window->PrevSibling )
+ Window->PrevSibling->NextSibling = Window->NextSibling;
+ Window->NextSibling->PrevSibling = Window->PrevSibling;
+ // Mutate self
+ Window->PrevSibling = Window->Parent->LastChild;
+ Window->NextSibling = NULL;
+ // re-add
+ Window->PrevSibling->NextSibling = Window;
+ Window->Parent->LastChild = Window;
+ }
+ _SysDebug("WM_RaiseWindow: Raised %p", Window);
+ Window = Window->Parent;
+ }
}
+*/
void WM_FocusWindow(tWindow *Destination)
{
if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
return ;
- _msg.Val = 0;
- WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
- _msg.Val = 1;
- WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
-
+ if( gpWM_FocusedWindow )
+ {
+ _msg.Val = 0;
+ WM_SendMessage(NULL, gpWM_FocusedWindow, WNDMSG_FOCUS, sizeof(_msg), &_msg);
+ }
+ if( Destination )
+ {
+ _msg.Val = 1;
+ WM_SendMessage(NULL, Destination, WNDMSG_FOCUS, sizeof(_msg), &_msg);
+ }
+
WM_Invalidate(gpWM_FocusedWindow);
WM_Invalidate(Destination);
- gpWM_FocusedWindow = Destination;
-
- // Get the owner of the focused window
-// while(Destination && Destination->Owner) Destination = Destination->Owner;
-// gpWM_HilightedWindow = Destination;
+ gpWM_FocusedWindow = Destination;
}
WM_SendMessage(NULL, Window, WNDMSG_SHOW, sizeof(_msg), &_msg);
// Update the flag
- if(bShow)
+ if(bShow) {
Window->Flags |= WINFLAG_SHOW;
+ _SysDebug("Window %p shown", Window);
+ }
else
{
Window->Flags &= ~WINFLAG_SHOW;
free(Window->RenderBuffer);
Window->RenderBuffer = NULL;
}
+ _SysDebug("Window %p hidden", Window);
}
WM_Invalidate(Window);
WM_Invalidate(Window);
}
+void WM_SetRelative(tWindow *Window, int bRelativeToParent)
+{
+// _SysDebug("WM_SetRelative: (%p{Parent=%p},%i)", Window, Window->Parent, bRelativeToParent);
+ // No meaning if no parent
+ if( !Window->Parent )
+ return ;
+
+ // Check that the flag is changing
+ if( !!bRelativeToParent == !!(Window->Flags & WINFLAG_RELATIVE) )
+ return ;
+
+ if( bRelativeToParent ) {
+ // Set
+ Window->Flags |= WINFLAG_RELATIVE;
+ WM_MoveWindow(Window, Window->X, Window->Y);
+ }
+ else {
+ // Clear
+ Window->Flags &= ~WINFLAG_RELATIVE;
+ WM_MoveWindow(Window, Window->X - Window->Parent->X, Window->Y - Window->Parent->Y);
+ }
+}
+
int WM_MoveWindow(tWindow *Window, int X, int Y)
{
+// _SysDebug("Move %p to (%i,%i)", Window, X, Y);
// Clip coordinates
if(X + Window->W < 0) X = -Window->W + 1;
if(Y + Window->H < 0) Y = -Window->H + 1;
if(X >= giScreenWidth) X = giScreenWidth - 1;
if(Y >= giScreenHeight) Y = giScreenHeight - 1;
+ // If relative to the parent, extra checks
+ if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
+ {
+ if( X > Window->Parent->W ) return 1;
+ if( Y > Window->Parent->H ) return 1;
+ }
+ // TODO: Re-sanitise
+
+ _SysDebug("WM_MoveWindow: (%i,%i)", X, Y);
Window->X = X; Window->Y = Y;
- WM_Invalidate(Window);
+ // Mark up the tree that a child window has changed
+ while( (Window = Window->Parent) )
+ Window->Flags &= ~WINFLAG_CHILDCLEAN;
return 0;
}
if(Window->X + W < 0) Window->X = -W + 1;
if(Window->Y + H < 0) Window->Y = -H + 1;
+ if( Window->W == W && Window->H == H )
+ return 0;
+
+ _SysDebug("WM_Resizeindow: %ix%i", W, H);
Window->W = W; Window->H = H;
if(Window->RenderBuffer) {
int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, const void *Data)
{
- if(Dest == NULL) return -2;
- if(Length > 0 && Data == NULL) return -1;
+// _SysDebug("WM_SendMessage: (%p, %p, %i, %i, %p)", Source, Dest, Message, Length, Data);
+ if(Dest == NULL) {
+ _SysDebug("WM_SendMessage: NULL destination from %p", __builtin_return_address(0));
+ return -2;
+ }
+ if(Length > 0 && Data == NULL) {
+ _SysDebug("WM_SendMessage: non-zero length and NULL data");
+ return -1;
+ }
if( Decorator_HandleMessage(Dest, Message, Length, Data) != 1 )
{
// TODO: Catch errors from ->HandleMessage
+// _SysDebug("WM_SendMessage: Decorator grabbed message?");
return 0;
}
if( Dest->Renderer->HandleMessage(Dest, Message, Length, Data) != 1 )
{
// TODO: Catch errors from ->HandleMessage
+// _SysDebug("WM_SendMessage: Renderer grabbed message?");
return 0;
}
// TODO: Implement message masking
+ // Dispatch to client
if(Dest->Client)
{
uint32_t src_id;
src_id = Source->ID;
}
+// _SysDebug("WM_SendMessage: IPC Dispatch");
IPC_SendWMMessage(Dest->Client, src_id, Dest->ID, Message, Length, Data);
}
return 1;
}
+int WM_SendIPCReply(tWindow *Window, int Message, size_t Length, const void *Data)
+{
+ IPC_SendReply(Window->Client, Window->ID, Message, Length, Data);
+ return 0;
+}
+
void WM_Invalidate(tWindow *Window)
{
if(!Window) return ;
- _SysDebug("Invalidating %p", Window);
+// _SysDebug("Invalidating %p", Window);
// Don't invalidate twice (speedup)
// if( !(Window->Flags & WINFLAG_CLEAN) ) return;
if( !(Window->Flags & WINFLAG_SHOW) )
return ;
+ if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
+ {
+ Window->RealX = Window->Parent->RealX + Window->Parent->BorderL + Window->X;
+ Window->RealY = Window->Parent->RealY + Window->Parent->BorderT + Window->Y;
+ }
+ else
+ {
+ Window->RealX = Window->X;
+ Window->RealY = Window->Y;
+ }
+
// Render
if( !(Window->Flags & WINFLAG_CLEAN) )
{
// Calculate RealW/RealH
if( !(Window->Flags & WINFLAG_NODECORATE) )
{
- _SysDebug("Applying decorations to %p", Window);
+ //_SysDebug("Applying decorations to %p", Window);
Decorator_UpdateBorderSize(Window);
Window->RealW = Window->BorderL + Window->W + Window->BorderR;
Window->RealH = Window->BorderT + Window->H + Window->BorderB;
Window->RealW = Window->W;
Window->RealH = Window->H;
}
-
+
Window->Renderer->Redraw(Window);
Window->Flags |= WINFLAG_CLEAN;
}
// Ignore hidden windows
if( !(Window->Flags & WINFLAG_SHOW) )
return ;
+
+ // Duplicated position update to handle window moving
+ if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent )
+ {
+ Window->RealX = Window->Parent->RealX + Window->Parent->BorderL + Window->X;
+ Window->RealY = Window->Parent->RealY + Window->Parent->BorderT + Window->Y;
+ }
+ else
+ {
+ Window->RealX = Window->X;
+ Window->RealY = Window->Y;
+ }
-// _SysDebug("Blit %p to (%i,%i) %ix%i", Window, Window->X, Window->Y, Window->RealW, Window->RealH);
- Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH);
+// _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer,
+// Window->RealX, Window->RealY, Window->RealW, Window->RealH);
+ Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH);
if( Window == gpWM_FocusedWindow && Window->CursorW )
{
Video_FillRect(
- Window->X + Window->BorderL + Window->CursorX,
- Window->Y + Window->BorderT + Window->CursorY,
+ Window->RealX + Window->BorderL + Window->CursorX,
+ Window->RealY + Window->BorderT + Window->CursorY,
Window->CursorW, Window->CursorH,
0x000000
);
-
}
for( child = Window->FirstChild; child; child = child->NextSibling )
for(win = ret->FirstChild; win; win = win->NextSibling)
{
if( !(win->Flags & WINFLAG_SHOW) ) continue ;
- if( X < win->X || X >= win->X + win->RealW ) continue;
- if( Y < win->Y || Y >= win->Y + win->RealH ) continue;
+ if( X < win->RealX || X >= win->RealX + win->RealW ) continue;
+ if( Y < win->RealY || Y >= win->RealY + win->RealH ) continue;
next_win = win; // Overwrite as we want the final rendered window
}
}
struct sWndMsg_MouseMove msg;
win = WM_int_GetWindowAtPos(OldX, OldY);
- msg.X = NewX - win->X - win->BorderL;
- msg.Y = NewY - win->Y - win->BorderT;
+ msg.X = NewX - win->RealX - win->BorderL;
+ msg.Y = NewY - win->RealY - win->BorderT;
msg.dX = NewX - OldX;
msg.dY = NewY - OldY;
WM_SendMessage(NULL, win, WNDMSG_MOUSEMOVE, sizeof(msg), &msg);
// TODO: Send mouseup to match mousedown if the cursor moves out of a window?
win = newWin;
- msg.X = NewX - win->X - win->BorderL;
- msg.Y = NewY - win->Y - win->BorderT;
+ msg.X = NewX - win->RealX - win->BorderL;
+ msg.Y = NewY - win->RealY - win->BorderT;
msg.dX = NewX - OldX;
msg.dY = NewY - OldY;
WM_SendMessage(NULL, win, WNDMSG_MOUSEMOVE, sizeof(msg), &msg);
{
struct sWndMsg_MouseButton msg;
- msg.X = X - Win->X - Win->BorderL;
- msg.Y = Y - Win->Y - Win->BorderT;
+ msg.X = X - Win->RealX - Win->BorderL;
+ msg.Y = Y - Win->RealY - Win->BorderT;
msg.Button = Index;
msg.bPressed = !!Pressed;
{
// _SysDebug("Gave focus to %p", win);
WM_FocusWindow(win);
- WM_RaiseWindow(win);
+ tWindow *tmpwin = win;
+ while( tmpwin )
+ {
+ WM_RaiseWindow(tmpwin);
+ tmpwin = tmpwin->Parent;
+ }
}
// Make sure that even if the mouse has moved out of the original window,
#include <wm_internals.h>
#include <stdlib.h>
#include <utf8.h>
+#include <limits.h> // INT_MAX
// === TYPES ===
typedef struct sGlyph tGlyph;
#ifndef _AXWIN3__FRAMEBUFFER_MESSAGES_H_
#define _AXWIN3__FRAMEBUFFER_MESSAGES_H_
-enum
+enum eFrameBuffer_IPCCalls
{
- MSG_FB_COMMIT = 0x1000,
- MSG_FB_NEWBUF,
- MSG_FB_UPLOAD,
- MSG_FB_DOWNLOAD,
- MSG_FB_BLIT,
- MSG_FB_FILL
+ IPC_FB_COMMIT,
+ IPC_FB_NEWBUF,
+ IPC_FB_UPLOAD,
+ IPC_FB_DOWNLOAD, // Replies with requested data
+ IPC_FB_BLIT,
+ IPC_FB_FILL,
+ N_IPC_FB
};
typedef struct
{
uint16_t Buffer;
uint16_t W, H;
-} tFBMsg_NewBuf;
+} tFBIPC_NewBuf;
typedef struct
{
uint16_t W, H;
uint16_t X, Y;
uint32_t ImageData[];
-} tFBMsg_Transfer;
+} tFBIPC_Transfer;
typedef struct
{
uint16_t SrcX, SrcY;
uint16_t DstX, DstY;
uint16_t W, H;
-} tFBMsg_Blit;
+} tFBIPC_Blit;
typedef struct
{
uint16_t X, Y;
uint16_t W, H;
uint32_t Colour;
-} tFBMsg_Fill;
+} tFBIPC_Fill;
#endif
*/
//! Request a return value
#define IPCMSG_FLAG_RETURN 0x01
+//! IPC Message for renderer
+#define IPCMSG_FLAG_RENDERER 0x80
/**
* \}
*/
#include "ipcmessages.h"
-enum eMenuMessages
+// Client->Server IPC methods
+enum eMenuIPCCalls
{
- MSG_MENU_ADDITEM = 0x1000,
- MSG_MENU_SETFLAGS,
-
- MSG_MENU_SELECT
+ IPC_MENU_ADDITEM,
+ IPC_MENU_SETFLAGS
};
typedef struct
uint16_t Flags;
uint32_t SubMenuID;
char Label[];
-} tMenuMsg_AddItem;
+} tMenuIPC_AddItem;
typedef struct
{
uint16_t ID;
uint16_t Value;
uint16_t Mask;
-} tMenuMsg_SetFlags;
+} tMenuIPC_SetFlags;
+
+// Server->Client messages
+enum eMenuMessages
+{
+ MSG_MENU_SELECT = 0x1000
+};
typedef struct
{
--- /dev/null
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * richtext_messages.h
+ * - Formatted Text Field
+ */
+#ifndef _RICHTEXT_MESSAGES_H_
+#define _RICHTEXT_MESSAGES_H_
+
+enum eRichText_Attrs {
+ _ATTR_DEFBG,
+ _ATTR_DEFFG,
+ _ATTR_SCROLL,
+ _ATTR_LINECOUNT,
+ _ATTR_COLCOUNT,
+ _ATTR_CURSOR,
+ _ATTR_CURSORBLINK,
+ _ATTR_CURSORPOS,
+};
+
+enum eRichText_IPCCalls
+{
+ IPC_RICHTEXT_SETATTR,
+ IPC_RICHTEXT_SETFONT,
+ IPC_RICHTEXT_DELLINE,
+ IPC_RICHTEXT_ADDLINE,
+ IPC_RICHTEXT_WRITELINE, // Set line contents
+ IPC_RICHTEXT_READLINE, // Request line contents
+ N_IPC_RICHTEXT
+};
+
+struct sRichTextIPC_SetAttr
+{
+ uint32_t Attr;
+ uint32_t Value;
+};
+
+struct sRichTextIPC_SetFont
+{
+ uint16_t Size;
+ char Name[];
+};
+
+struct sRichTextIPC_AddDelLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextIPC_ReadLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextIPC_WriteLine
+{
+ uint32_t Line;
+ char LineData[];
+};
+
+enum
+{
+ // Events
+ MSG_RICHTEXT_KEYPRESS = 0x1000,
+ MSG_RICHTEXT_MOUSEBTN,
+
+ // Sent by server to get a line that is not cached (expects IPC WRITELINE)
+ MSG_RICHTEXT_REQLINE,
+ // Response to IPC READLINE
+ MSG_RICHTEXT_LINEDATA,
+};
+
+struct sRichTextMsg_ReqLine
+{
+ uint32_t Line;
+};
+
+struct sRichTextMsg_LineData
+{
+ uint32_t Line;
+ char LineData[];
+};
+
+#endif
+
#ifndef _WIDGET_MESSAGES_H_
#define _WIDGET_MESSAGES_H_
-enum
+enum eWidgetIPCCalls
{
// Control (Client->Server) messages
- MSG_WIDGET_CREATE = 0x1000,
- MSG_WIDGET_DELETE,
- MSG_WIDGET_SETFOCUS,
- MSG_WIDGET_SETFLAGS,
- MSG_WIDGET_SETSIZE,
- MSG_WIDGET_SETTEXT,
- MSG_WIDGET_SETCOLOUR,
+ IPC_WIDGET_CREATE,
+ IPC_WIDGET_CREATESUBWIN,
+ IPC_WIDGET_DELETE,
+ IPC_WIDGET_SETFOCUS,
+ IPC_WIDGET_SETFLAGS,
+ IPC_WIDGET_SETSIZE,
+ IPC_WIDGET_SETTEXT,
+ IPC_WIDGET_SETCOLOUR,
-
- // Request (Client->Server->Client) messages
- MSG_WIDGET_GETTEXT,
-
- // Event (Server->Client) messages
- MSG_WIDGET_FIRE,
- MSG_WIDGET_KEYPRESS,
- MSG_WIDGET_MOUSEBTN,
+ IPC_WIDGET_GETTEXT,
+
+ N_IPC_WIDGET
};
+typedef struct
+{
+ uint32_t Parent;
+ uint32_t NewID;
+ uint32_t Type;
+ uint32_t Flags;
+ char DebugName[];
+} tWidgetIPC_Create;
typedef struct
{
uint32_t NewID;
uint32_t Type;
uint32_t Flags;
+ uint32_t WindowHandle;
char DebugName[];
-} tWidgetMsg_Create;
+} tWidgetIPC_CreateSubWin;
typedef struct
{
uint32_t WidgetID;
-} tWidgetMsg_Delete;
+} tWidgetIPC_Delete;
typedef struct
{
uint32_t WidgetID;
-} tWidgetMsg_SetFocus;
+} tWidgetIPC_SetFocus;
typedef struct
{
uint32_t WidgetID;
uint32_t Value;
uint32_t Mask;
-} tWidgetMsg_SetFlags;
+} tWidgetIPC_SetFlags;
typedef struct
{
uint32_t WidgetID;
uint32_t Value;
-} tWidgetMsg_SetSize;
+} tWidgetIPC_SetSize;
typedef struct
{
uint32_t WidgetID;
char Text[];
-} tWidgetMsg_SetText;
+} tWidgetIPC_SetText;
typedef struct
{
uint32_t WidgetID;
uint32_t Index;
uint32_t Colour;
-} tWidgetMsg_SetColour;
+} tWidgetIPC_SetColour;
+
+enum eWidgetMessages
+{
+ // Event (Server->Client) messages
+ MSG_WIDGET_FIRE = 0x1000,
+ MSG_WIDGET_KEYPRESS,
+ MSG_WIDGET_MOUSEBTN,
+};
+
+
typedef struct
{
LDFLAGS += -lc -soname libaxwin3.so
OBJ = main.o msg.o wm.o r_widget.o r_menu.o
+OBJ += r_richtext.o
BIN = libaxwin3.so
include ../../../Libraries/Makefile.tpl
extern void *AxWin3_int_GetDataPtr(tHWND Window);
extern uint32_t AxWin3_int_GetWindowID(tHWND Window);
+extern void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data);
+extern void *AxWin3_WaitIPCMessage(tHWND Window, int Message, size_t *Length);
#endif
extern tAxWin_IPCMessage *AxWin3_int_AllocateIPCMessage(tHWND Window, int Message, int Flags, int ExtraBytes);
extern void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg);
-extern tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(void);
+extern tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *FDs);
extern tAxWin_IPCMessage *AxWin3_int_WaitIPCMessage(int WantedID);
extern void AxWin3_int_HandleMessage(tAxWin_IPCMessage *Msg);
while(!bExit)
{
- msg = AxWin3_int_GetIPCMessage();
+ msg = AxWin3_int_GetIPCMessage(0, NULL);
if(!msg) continue;
- _SysDebug("oh look, a message (Type=%i, Window=%i, Len=%i)",
+ _SysDebug("AxWin3_MainLoop - Message (Type=%i, Window=%i, Len=%i)",
msg->ID, msg->Window, msg->Size);
AxWin3_int_HandleMessage( msg );
-
- free(msg);
}
}
+void AxWin3_MessageSelect(int nFD, fd_set *FDs)
+{
+ tAxWin_IPCMessage *msg;
+ msg = AxWin3_int_GetIPCMessage(nFD, FDs);
+ if( msg )
+ AxWin3_int_HandleMessage( msg );
+}
+
// === CODE ===
void AxWin3_Connect(const char *ServerDesc)
{
- _SysDebug("ServerDesc = %s", ServerDesc);
- if( !ServerDesc )
- {
+ _SysDebug("ServerDesc (argument) = %s", ServerDesc);
+ if( !ServerDesc ) {
ServerDesc = gsAxWin3_int_ServerDesc;
}
_SysDebug("ServerDesc = %s", ServerDesc);
case '6': case '7': case '8': case '9': case '0':
giConnectionType = CONNTYPE_SENDMESSAGE;
giConnectionNum = atoi(ServerDesc);
+ if( giConnectionNum == 0 ) {
+ _SysDebug("Invalid server PID");
+ exit(-1);
+ }
break;
case 'u':
while(*ServerDesc && *ServerDesc != ':') ServerDesc ++;
switch(giConnectionType)
{
case CONNTYPE_SENDMESSAGE:
- SysSendMessage(giConnectionNum, size, Msg);
+ _SysSendMessage(giConnectionNum, size, Msg);
break;
case CONNTYPE_UDP: {
// Create UDP header
char tmpbuf[giAxWin3_int_UDPHeaderLen + size];
memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen);
memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size);
- write(giConnectionNum, tmpbuf, sizeof(tmpbuf));
+ _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf));
}
break;
case CONNTYPE_TCP:
- write(giConnectionNum, Msg, size);
+ _SysWrite(giConnectionNum, Msg, size);
break;
default:
break;
}
}
-tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(void)
+tAxWin_IPCMessage *AxWin3_int_GetIPCMessage(int nFD, fd_set *fds)
{
int len;
tAxWin_IPCMessage *ret = NULL;
- switch(giConnectionType)
+ int tid;
+
+ _SysSelect(nFD, fds, NULL, NULL, NULL, THREAD_EVENT_IPCMSG);
+
+ // Clear out IPC messages
+ while( (len = _SysGetMessage(&tid, 0, NULL)) )
{
- case CONNTYPE_SENDMESSAGE:
- for( ;; )
+ if( giConnectionType != CONNTYPE_SENDMESSAGE || tid != giConnectionNum )
{
- pid_t tid;
+ _SysDebug("%i byte message from %i", len, tid);
+ // If not, pass the buck (or ignore)
+ if( gAxWin3_MessageCallback )
+ gAxWin3_MessageCallback(tid, len);
+ else
+ _SysGetMessage(NULL, 0, GETMSG_IGNORE);
+ continue ;
+ }
- // Wait for a message to arrive
- while( !(len = SysGetMessage(&tid, NULL)) )
- {
- _SysWaitEvent(THREAD_EVENT_IPCMSG);
- }
-
- // Check if the message came from the server
- if(tid != giConnectionNum)
- {
- _SysDebug("%i byte message from %i", len, tid);
- // If not, pass the buck (or ignore)
- if( gAxWin3_MessageCallback )
- gAxWin3_MessageCallback(tid, len);
- else
- SysGetMessage(NULL, GETMSG_IGNORE);
- continue ;
- }
-
- // If it's from the server, allocate a buffer and return it
- ret = malloc(len);
- if(ret == NULL) {
- _SysDebug("malloc() failed, ignoring message");
- SysGetMessage(NULL, GETMSG_IGNORE);
- return NULL;
- }
- SysGetMessage(NULL, ret);
- break;
+ // Using CONNTYPE_SENDMESSAGE and server message has arrived
+ ret = malloc(len);
+ if(ret == NULL) {
+ _SysDebug("malloc() failed, ignoring message");
+ _SysGetMessage(NULL, 0, GETMSG_IGNORE);
+ return NULL;
}
- break;
- default:
- // TODO: Implement
- _SysDebug("TODO: Implement AxWin3_int_GetIPCMessage for TCP/UDP");
+ _SysGetMessage(NULL, len, ret);
break;
}
- // No message?
- if( ret == NULL )
- return NULL;
-
- // TODO: Sanity checks, so a stupid server can't crash us
+ if( giConnectionType == CONNTYPE_TCP || giConnectionType == CONNTYPE_UDP )
+ {
+ // Check fds
+ }
return ret;
}
tAxWin_IPCMessage *msg;
for(;;)
{
- msg = AxWin3_int_GetIPCMessage();
+ msg = AxWin3_int_GetIPCMessage(0, NULL);
if(msg->ID == WantedID) return msg;
AxWin3_int_HandleMessage( msg );
- free(msg);
}
}
if(msg->ID >= info->nItems) return -1;
item = &info->Items[msg->ID];
if(item->Callback) item->Callback(item->CbPtr);
- return 0; }
+ return 1; }
}
- return 1;
+ return 0;
}
tHWND AxWin3_Menu_Create(tHWND Parent)
ret->SubMenu = SubMenu;
{
- tMenuMsg_AddItem *req;
+ tMenuIPC_AddItem *req;
int data_size;
if(!Label) Label = "";
data_size = sizeof(*req)+strlen(Label)+1;
req->Flags = Flags;
req->SubMenuID = AxWin3_int_GetWindowID(SubMenu);
strcpy(req->Label, Label);
- AxWin3_SendMessage(Menu, Menu, MSG_MENU_ADDITEM, data_size, req);
+ AxWin3_SendIPC(Menu, IPC_MENU_ADDITEM, data_size, req);
free(req);
}
--- /dev/null
+/*
+ * AxWin3 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * r_richtext.c
+ * - Formatted Text window type
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+#include "include/internal.h"
+#include <richtext_messages.h>
+#include <string.h>
+//#include <alloca.h>
+
+// === TYPES ===
+typedef struct sRichText_Window
+{
+ tAxWin3_RichText_KeyHandler KeyCallback;
+ tAxWin3_RichText_MouseHandler MouseCallback;
+ tAxWin3_RichText_LineHandler LineHandler;
+} tRichText_Window;
+
+// === CODE ===
+int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
+{
+ return 0;
+}
+
+static void _SendAttrib(tHWND Window, int Attr, uint32_t Value)
+{
+ struct sRichTextIPC_SetAttr msg;
+ msg.Attr = Attr;
+ msg.Value = Value;
+ AxWin3_SendIPC(Window, IPC_RICHTEXT_SETATTR, sizeof(msg), &msg);
+}
+
+tHWND AxWin3_RichText_CreateWindow(tHWND Parent, int Flags)
+{
+ tHWND ret = AxWin3_CreateWindow(Parent, "RichText", Flags, sizeof(tRichText_Window), AxWin3_RichText_MessageHandler);
+// tRichText_Window *info = AxWin3_int_GetDataPtr(ret);
+ return ret;
+}
+
+void AxWin3_RichText_SetKeyHandler(tHWND Window, tAxWin3_RichText_KeyHandler Handler)
+{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ info->KeyCallback = Handler;
+}
+
+void AxWin3_RichText_SetMouseHandler(tHWND Window, tAxWin3_RichText_MouseHandler Handler)
+{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ info->MouseCallback = Handler;
+}
+
+void AxWin3_RichText_EnableScroll(tHWND Window, int bEnable)
+{
+ _SendAttrib(Window, _ATTR_SCROLL, bEnable);
+}
+void AxWin3_RichText_SetLineCount(tHWND Window, int Lines)
+{
+ _SendAttrib(Window, _ATTR_LINECOUNT, Lines);
+}
+void AxWin3_RichText_SetColCount(tHWND Window, int Cols)
+{
+ _SendAttrib(Window, _ATTR_COLCOUNT, Cols);
+}
+void AxWin3_RichText_SetBackground(tHWND Window, uint32_t ARGB_Colour)
+{
+ _SendAttrib(Window, _ATTR_DEFBG, ARGB_Colour);
+}
+void AxWin3_RichText_SetDefaultColour(tHWND Window, uint32_t ARGB_Colour)
+{
+ _SendAttrib(Window, _ATTR_DEFFG, ARGB_Colour);
+}
+void AxWin3_RichText_SetFont(tHWND Window, const char *FontName, int PointSize)
+{
+ // TODO: Send message
+}
+void AxWin3_RichText_SetCursorType(tHWND Window, int Type)
+{
+ _SendAttrib(Window, _ATTR_CURSOR, Type);
+}
+void AxWin3_RichText_SetCursorBlink(tHWND Window, int bBlink)
+{
+ _SendAttrib(Window, _ATTR_CURSORBLINK, bBlink);
+}
+void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column)
+{
+ if(Row < 0 || Row > 0xFFFFF || Column > 0xFFF || Column < 0)
+ return ;
+ _SendAttrib(Window, _ATTR_CURSORPOS, ((Row & 0xFFFFF) << 12) | (Column & 0xFFF));
+}
+
+void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text)
+{
+ // TODO: Local sanity check on `Line`?
+ struct sRichTextIPC_WriteLine *msg;
+ size_t len = sizeof(*msg) + strlen(Text) + 1;
+ char buffer[len];
+ msg = (void*)buffer;
+ msg->Line = Line;
+ strcpy(msg->LineData, Text);
+ AxWin3_SendIPC(Window, IPC_RICHTEXT_WRITELINE, len, msg);
+}
+
return info->Elements[ID];
}
+uint32_t AxWin3_Widget_int_AllocateID(tWidgetWindowInfo *Info)
+{
+ uint32_t newID;
+ // BUG BUG BUG - Double Allocations! (citation needed)
+ // TODO: Atomicity
+ for( newID = Info->FirstFreeID; newID < Info->nElements; newID ++ )
+ {
+ if( Info->Elements[newID] == NULL )
+ break;
+ }
+ if( newID == Info->nElements )
+ {
+ const int size_step = 4;
+ Info->nElements += 4;
+ Info->Elements = realloc(Info->Elements, sizeof(*Info->Elements)*Info->nElements);
+ newID = Info->nElements - 4;
+ memset( &Info->Elements[newID+1], 0, (size_step-1)*sizeof(Info->Elements));
+ _SysDebug("Widget: Expanded to %i and allocated %i", Info->nElements, newID);
+ }
+ else
+ _SysDebug("Widget: Allocated %i", newID);
+ Info->Elements[newID] = (void*)-1;
+
+ return newID;
+
+}
+
int AxWin3_Widget_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
{
tAxWin3_Widget *widget;
widget = AxWin3_Widget_int_GetElementByID(Window, msg->WidgetID);
if(widget->Fire) widget->Fire(widget);
- return 0; }
+ return 1; }
default:
return 0;
}
info = AxWin3_int_GetDataPtr(Parent->Window);
- // Assign ID
- // BUG BUG BUG - Double Allocations!
- // TODO: Atomicity
- for( newID = info->FirstFreeID; newID < info->nElements; newID ++ )
- {
- if( info->Elements[newID] == NULL )
- break;
- }
- if( newID == info->nElements )
- {
- const int size_step = 4;
- info->nElements += 4;
- info->Elements = realloc(info->Elements, sizeof(*info->Elements)*info->nElements);
- newID = info->nElements - 4;
- memset( &info->Elements[newID+1], 0, (size_step-1)*sizeof(info->Elements));
- _SysDebug("Expanded to %i and allocated %i", info->nElements, newID);
- }
- else
- _SysDebug("Allocated %i", newID);
- info->Elements[newID] = (void*)-1;
+ newID = AxWin3_Widget_int_AllocateID(info);
// Create new widget structure
ret = calloc(sizeof(tAxWin3_Widget), 1);
// Send create widget message
{
- char tmp[sizeof(tWidgetMsg_Create)+1];
- tWidgetMsg_Create *msg = (void*)tmp;
+ char tmp[sizeof(tWidgetIPC_Create)+1];
+ tWidgetIPC_Create *msg = (void*)tmp;
msg->Parent = Parent->ID;
msg->NewID = newID;
msg->Type = Type;
msg->Flags = Flags;
msg->DebugName[0] = '\0';
- AxWin3_SendMessage(ret->Window, ret->Window, MSG_WIDGET_CREATE, sizeof(tmp), tmp);
+ AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATE, sizeof(tmp), tmp);
+ }
+
+ return ret;
+}
+
+tAxWin3_Widget *AxWin3_Widget_AddWidget_SubWindow(tAxWin3_Widget *Parent, tHWND Window, int Flags, const char *DbgName)
+{
+ tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Parent->Window);
+ int newID = AxWin3_Widget_int_AllocateID(info);
+
+ tAxWin3_Widget *ret = calloc(sizeof(tAxWin3_Widget), 1);
+ ret->Window = Parent->Window;
+ ret->ID = newID;
+ info->Elements[newID] = ret;
+
+ // Send message
+ {
+ char tmp[sizeof(tWidgetIPC_CreateSubWin)+1];
+ tWidgetIPC_CreateSubWin *msg = (void*)tmp;
+ msg->Parent = Parent->ID;
+ msg->NewID = newID;
+ msg->Type = ELETYPE_SUBWIN;
+ msg->Flags = Flags; // TODO: Flags
+ msg->WindowHandle = AxWin3_int_GetWindowID(Window);
+ msg->DebugName[0] = '\0';
+ AxWin3_SendIPC(ret->Window, IPC_WIDGET_CREATESUBWIN, sizeof(tmp), tmp);
}
return ret;
}
+
void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget)
{
- tWidgetMsg_Delete msg;
+ tWidgetIPC_Delete msg;
tWidgetWindowInfo *info = AxWin3_int_GetDataPtr(Widget->Window);
msg.WidgetID = Widget->ID;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_DELETE, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_DELETE, sizeof(msg), &msg);
info->Elements[Widget->ID] = NULL;
if(Widget->ID < info->FirstFreeID)
// --- Manipulation
void AxWin3_Widget_SetFlags(tAxWin3_Widget *Widget, int FlagSet, int FlagMask)
{
- tWidgetMsg_SetFlags msg;
+ tWidgetIPC_SetFlags msg;
msg.WidgetID = Widget->ID;
msg.Value = FlagSet;
msg.Mask = FlagMask;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETFLAGS, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETFLAGS, sizeof(msg), &msg);
}
void AxWin3_Widget_SetSize(tAxWin3_Widget *Widget, int Size)
{
- tWidgetMsg_SetSize msg;
+ tWidgetIPC_SetSize msg;
msg.WidgetID = Widget->ID;
msg.Value = Size;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETSIZE, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETSIZE, sizeof(msg), &msg);
}
void AxWin3_Widget_SetText(tAxWin3_Widget *Widget, const char *Text)
{
- char buf[sizeof(tWidgetMsg_SetText) + strlen(Text) + 1];
- tWidgetMsg_SetText *msg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText) + strlen(Text) + 1];
+ tWidgetIPC_SetText *msg = (void*)buf;
msg->WidgetID = Widget->ID;
strcpy(msg->Text, Text);
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETTEXT, sizeof(buf), buf);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETTEXT, sizeof(buf), buf);
}
char *AxWin3_Widget_GetText(tAxWin3_Widget *Widget)
{
- char buf[sizeof(tWidgetMsg_SetText)];
- tWidgetMsg_SetText *msg = (void*)buf;
+ char buf[sizeof(tWidgetIPC_SetText)];
+ tWidgetIPC_SetText *msg = (void*)buf;
size_t retmsg_size;
msg->WidgetID = Widget->ID;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
- msg = AxWin3_WaitMessage(Widget->Window, MSG_WIDGET_GETTEXT, &retmsg_size);
+ msg = AxWin3_WaitIPCMessage(Widget->Window, IPC_WIDGET_GETTEXT, &retmsg_size);
if( retmsg_size < sizeof(*msg) ) {
free(msg);
return NULL;
void AxWin3_Widget_SetColour(tAxWin3_Widget *Widget, int Index, tAxWin3_Colour Colour)
{
- tWidgetMsg_SetColour msg;
+ tWidgetIPC_SetColour msg;
msg.WidgetID = Widget->ID;
msg.Index = Index;
msg.Colour = Colour;
- AxWin3_SendMessage(Widget->Window, Widget->Window, MSG_WIDGET_SETCOLOUR, sizeof(msg), &msg);
+ AxWin3_SendIPC(Widget->Window, IPC_WIDGET_SETCOLOUR, sizeof(msg), &msg);
}
ret = (void*)msg->Data;
if(X) *X = ret->X;
- if(X) *X = ret->Y;
+ if(Y) *Y = ret->Y;
if(Width) *Width = ret->W;
if(Height) *Height = ret->H;
AxWin3_int_SendIPCMessage(msg);
free(msg);
+ _SysDebug("AxWin3_CreateWindow: %i :: '%s'", newWinID, Renderer);
+
// TODO: Detect and handle possible errors
// Return success
gAxWin3_Hotkeys[mi->ID]();
}break;
default:
- _SysDebug("--- Unhandled SENDMSG %i", info->ID);
+ _SysDebug("--- Unhandled SENDMSG 0x%x win %i", info->ID, Msg->Window);
break;
}
}
_SysDebug("Unknow message ID %i", Msg->ID);
break;
}
+
+ free(Msg);
}
void AxWin3_SetWindowTitle(tHWND Window, const char *Title)
}
}
+void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data)
+{
+ tAxWin_IPCMessage *msg;
+
+ msg = AxWin3_int_AllocateIPCMessage(Window, Message, IPCMSG_FLAG_RENDERER, Length);
+ memcpy(msg->Data, Data, Length);
+ AxWin3_int_SendIPCMessage(msg);
+ free(msg);
+}
+
+void *AxWin3_WaitIPCMessage(tHWND Window, int MessageID, size_t *Length)
+{
+ tAxWin_IPCMessage *msg;
+ for( ;; )
+ {
+ msg = AxWin3_int_WaitIPCMessage(MessageID);
+ if( !(msg->Flags & IPCMSG_FLAG_RENDERER) || msg->Window != AxWin3_int_GetWindowID(Window) ) {
+ AxWin3_int_HandleMessage(msg);
+ continue ;
+ }
+
+ *Length = msg->Size;
+ void *ret = malloc(msg->Size);
+ memcpy(ret, msg->Data, msg->Size);
+ free(msg);
+
+ return ret;
+ }
+}
+
void AxWin3_FocusWindow(tHWND Window)
{
tAxWin_IPCMessage *msg;
if( gbForkBomb )
{
- for(;;) clone(CLONE_VM, 0);
+ for(;;) _SysClone(CLONE_VM, 0);
}
else {
for(;;)
printf("Outta heap space!\n");
return 0;
}
- tid = clone(0, stack+stackSize-stackOffset);
+ tid = _SysClone(0, stack+stackSize-stackOffset);
//_SysDebug("tid = %i", tid);
if( tid == 0 )
{
// Sleep forever (TODO: Fix up the stack so it can nuke)
- for(;;) sleep();
+ for(;;) _SysWaitEvent(THREAD_EVENT_SIGNAL);
}
if( tid < 0 ) {
printf("Clone failed\n");
/*
* Acess2 CAT command
*/
-#include <acess/sys.h>
#include <stdlib.h>
#include <stdio.h>
*/
int main(int argc, char *argv[])
{
- int fd;
int num;
char buf[BUF_SIZE];
return -1;
}
- fd = open(argv[1], OPENFLAG_READ);
- if(fd == -1) {
+ FILE *fp = fopen(argv[1], "r");
+ if(!fp) {
printf("Unable to open '%s' for reading\n", argv[1]);
return -1;
}
do {
- num = read(fd, buf, BUF_SIZE);
+ num = fread(buf, BUF_SIZE, 1, fp);
if(num < 0) break;
- write(1, buf, num);
+ fwrite(buf, num, 1, stdout);
} while(num == BUF_SIZE);
- close(fd);
+ fclose(fp);
printf("\n");
return 0;
*
* http://www.ietf.org/rfc/rfc2131.txt
*/
-#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <net.h>
+#include <acess/sys.h>
#define FILENAME_MAX 255
// --- Translation functions ---
STATE_PREINIT,
STATE_DISCOVER_SENT,
STATE_REQUEST_SENT,
- STATE_COMPLETE
+ STATE_COMPLETE,
};
// === STRUCTURES ===
char HWAddr[6];
int64_t Timeout;
+ int nTimeouts;
} tInterface;
// === PROTOTYPES ===
int Start_Interface(tInterface *Iface);
void Send_DHCPDISCOVER(tInterface *Iface);
void Send_DHCPREQUEST(tInterface *Iface, void *OfferBuffer, int TypeOffset);
-int Handle_Packet(tInterface *Iface);
-void Handle_Timeout(tInterface *Iface);
+ int Handle_Packet(tInterface *Iface);
+ int Handle_Timeout(tInterface *Iface);
void Update_State(tInterface *Iface, int newState);
void SetAddress(tInterface *Iface, void *Addr, void *Mask, void *Router);
if( FD_ISSET(i->SocketFD, &fds) )
{
if( Handle_Packet( i ) )
- {
- close(i->SocketFD);
- close(i->IfaceFD);
- p->Next = i->Next;
- free(i);
- i = p;
- }
+ goto _remove;
}
if( _SysTimestamp() > i->Timeout )
{
- Handle_Timeout(i);
+ if( Handle_Timeout(i) )
+ {
+ fprintf(stderr, "%s timed out\n", i->Adapter);
+ goto _remove;
+ }
}
+ continue ;
+ _remove:
+ _SysClose(i->SocketFD);
+ _SysClose(i->IfaceFD);
+ p->Next = i->Next;
+ free(i);
+ i = p;
}
}
return 0;
void Scan_Dir(tInterface **IfaceList, const char *Directory)
{
- int dp = open(Directory, OPENFLAG_READ);
+ int dp = _SysOpen(Directory, OPENFLAG_READ);
char filename[FILENAME_MAX];
if( dp == -1 ) {
fprintf(stderr, "Unable to open directory '%s'\n", Directory);
+ return ;
}
- while( SysReadDir(dp, filename) )
+ while( _SysReadDir(dp, filename) )
{
if( filename[0] == '.' ) continue ;
if( strcmp(filename, "lo") == 0 ) continue ;
new->Next = *IfaceList;
*IfaceList = new;
}
- close(dp);
+ _SysClose(dp);
}
// RETURN: Client FD
{
char path[] = "/Devices/ip/adapters/ethXXXX";
sprintf(path, "/Devices/ip/adapters/%s", Iface->Adapter);
- fd = open(path, 0);
+ fd = _SysOpen(path, 0);
if(fd == -1) {
_SysDebug("Unable to open adapter %s", path);
return -1;
}
- ioctl(fd, 4, Iface->HWAddr);
+ _SysIOCtl(fd, 4, Iface->HWAddr);
// TODO: Check if ioctl() failed
- close(fd);
+ _SysClose(fd);
}
// Initialise an interface, with a dummy IP address (zero)
- fd = open("/Devices/ip", 0);
+ fd = _SysOpen("/Devices/ip", 0);
if( fd == -1 ) {
fprintf(stderr, "ERROR: Unable to open '/Devices/ip'\n");
return -1;
}
- Iface->Num = ioctl(fd, 4, (void*)Iface->Adapter); // Create interface
+ Iface->Num = _SysIOCtl(fd, 4, (void*)Iface->Adapter); // Create interface
if( Iface->Num == -1 ) {
fprintf(stderr, "ERROR: Unable to create new interface\n");
return -1;
}
- close(fd);
+ _SysClose(fd);
// Open new interface
snprintf(path, sizeof(path), "/Devices/ip/%i", Iface->Num);
- Iface->IfaceFD = fd = open(path, 0);
+ Iface->IfaceFD = fd = _SysOpen(path, 0);
if( fd == -1 ) {
fprintf(stderr, "ERROR: Unable to open '%s'\n", path);
return -1;
}
- tmp = 4; ioctl(fd, 4, &tmp); // Set to IPv4
- ioctl(fd, 6, addr); // Set address to 0.0.0.0
- tmp = 0; ioctl(fd, 7, &tmp); // Set subnet mask to 0
+ tmp = 4; _SysIOCtl(fd, 4, &tmp); // Set to IPv4
+ _SysIOCtl(fd, 6, addr); // Set address to 0.0.0.0
+ tmp = 0; _SysIOCtl(fd, 7, &tmp); // Set subnet mask to 0
// Open UDP Client
snprintf(path, sizeof(path), "/Devices/ip/%i/udp", Iface->Num);
- Iface->SocketFD = fd = open(path, O_RDWR);
+ Iface->SocketFD = fd = _SysOpen(path, OPENFLAG_READ|OPENFLAG_WRITE);
if( fd == -1 ) {
fprintf(stderr, "ERROR: Unable to open '%s'\n", path);
return -1;
}
- tmp = 68; ioctl(fd, 4, &tmp); // Local port
- tmp = 67; ioctl(fd, 5, &tmp); // Remote port
- tmp = 0; ioctl(fd, 7, &tmp); // Remote addr mask bits - we don't care where the reply comes from
+ tmp = 68; _SysIOCtl(fd, 4, &tmp); // Local port
+ tmp = 67; _SysIOCtl(fd, 5, &tmp); // Remote port
+ tmp = 0; _SysIOCtl(fd, 7, &tmp); // Remote addr mask bits - we don't care where the reply comes from
addr[0] = addr[1] = addr[2] = addr[3] = 255; // 255.255.255.255
- ioctl(fd, 8, addr); // Remote address
+ _SysIOCtl(fd, 8, addr); // Remote address
return 0;
}
data[2] = 4; data[3] = 0; // AddrType
data[4] = 255; data[5] = 255; data[6] = 255; data[7] = 255;
- write(Iface->SocketFD, data, sizeof(data));
+ i = _SysWrite(Iface->SocketFD, data, sizeof(data));
+ if( i != sizeof(data) ) {
+ _SysDebug("_SysWrite failed (%i != %i)", i, sizeof(data));
+ }
Update_State(Iface, STATE_DISCOVER_SENT);
}
((uint8_t*)OfferPacket)[6] = 255;
((uint8_t*)OfferPacket)[7] = 255;
- write(Iface->SocketFD, OfferPacket, 8 + sizeof(*msg) + i);
+ _SysWrite(Iface->SocketFD, OfferPacket, 8 + sizeof(*msg) + i);
Update_State(Iface, STATE_REQUEST_SENT);
}
void *subnet_mask = NULL;
_SysDebug("Doing read on %i", Iface->SocketFD);
- len = read(Iface->SocketFD, data, sizeof(data));
+ len = _SysRead(Iface->SocketFD, data, sizeof(data));
_SysDebug("len = %i", len);
_SysDebug("*msg = {");
return 0;
}
-void Handle_Timeout(tInterface *Iface)
+int Handle_Timeout(tInterface *Iface)
{
+ if( Iface->nTimeouts == 3 )
+ return 1;
switch(Iface->State)
{
case STATE_DISCOVER_SENT:
_SysDebug("Timeout with state = %i", Iface->State);
break;
}
+ return 0;
}
void Update_State(tInterface *Iface, int newState)
{
Iface->Timeout = _SysTimestamp() + 500;
Iface->State = newState;
+ Iface->nTimeouts = 0;
}
else
{
// TODO: Exponential backoff
Iface->Timeout = _SysTimestamp() + 3000;
+ Iface->nTimeouts ++;
_SysDebug("State %i repeated, timeout is 3000ms now", newState);
}
}
);
}
- ioctl(Iface->IfaceFD, 6, Addr);
- ioctl(Iface->IfaceFD, 7, &mask_bits);
+ _SysIOCtl(Iface->IfaceFD, 6, Addr);
+ _SysIOCtl(Iface->IfaceFD, 7, &mask_bits);
if( Router );
{
// Set default route
int fd;
- fd = open("/Devices/ip/routes/4:00000000:0:0", OPENFLAG_CREATE);
+ fd = _SysOpen("/Devices/ip/routes/4:00000000:0:0", OPENFLAG_CREATE);
if(fd == -1) {
fprintf(stderr, "ERROR: Unable to open default route\n");
}
else {
char ifname[snprintf(NULL,0,"%i",Iface->Num)+1];
sprintf(ifname, "%i", Iface->Num);
- ioctl(fd, ioctl(fd, 3, "set_nexthop"), Router);
- ioctl(fd, ioctl(fd, 3, "set_interface"), ifname);
- close(fd);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_nexthop"), Router);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_interface"), ifname);
+ _SysClose(fd);
}
}
}
--- /dev/null
+# Project: [GUI] Acess Text Editor (ATE)
+
+-include ../Makefile.cfg
+
+LDFLAGS += -laxwin3
+
+OBJ = main.o
+BIN = ate
+DIR := Apps/AxWin/3.0
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * edit.c
+ * - File Loading / Manipulation
+ */
+#include <stdio.h>
+#include "include/file.h"
+#include "include/syntax.h"
+
+// === CODE ===
+tFile *File_New(void)
+{
+ tFile *ret = malloc(sizeof(tFile) + 1);
+ ret->Handle = NULL;
+ ret->nLines = 0;
+ ret->Lines = NULL;
+ ret->NameOfs = 0;
+ ret->Path[0] = 0;
+ return ret;
+}
+
+tFile *File_Load(const char *Path)
+{
+ return NULL;
+}
+
+int File_Save(tFile *File)
+{
+
+ //file->bIsDirty = 0;
+ return -1;
+}
+
+int File_Close(tFile *File, int bDiscard)
+{
+ //if( file->bIsDirty && !bDiscard )
+ // return 1;
+ if( file->Handle )
+ fclose(File->Handle);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * include/file.h
+ * - In-memory file structures
+ */
+#ifndef _ATE__FILE_H_
+#define _ATE__FILE_H_
+#include <stdio.h>
+
+typedef struct sFileLine
+{
+ int Num;
+
+ // State data for hilighting
+ int HilightState;
+ char *Rendered;
+
+ int Space;
+ int Length;
+ char Data[];
+} tFileLine;
+
+typedef struct sFile
+{
+ FILE *Handle;
+ int nLines;
+ tFileLine **Lines; // TODO: Handle very large files?
+ int NameOfs;
+ const char Path[];
+} tFile;
+
+#endif
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * include/syntax.h
+ * - Syntax Hilighting / Rendering structures
+ */
+#ifndef _ATE__SYNTAX_H_
+#define _ATE__SYNTAX_H_
+
+#endif
+
--- /dev/null
+/*
+ * Acess Text Editor (ATE)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/widget.h>
+#include <axwin3/menu.h>
+#include <axwin3/richtext.h>
+#include <stdio.h>
+#include "strings.h"
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[]);
+ int TextArea_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
+ int TextArea_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+void add_toolbar_button(tAxWin3_Widget *Toolbar, const char *Ident, tAxWin3_Widget_FireCb Callback);
+ int Toolbar_New(tAxWin3_Widget *Widget);
+ int Toolbar_Open(tAxWin3_Widget *Widget);
+ int Toolbar_Save(tAxWin3_Widget *Widget);
+
+// === GLOBALS ===
+tHWND gMainWindow;
+tAxWin3_Widget *gMainWindow_Root;
+tHWND gMainWindow_MenuBar;
+tAxWin3_Widget *gMainWindow_Toolbar;
+tHWND gMainWindow_TextArea;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+ AxWin3_Connect(NULL);
+
+ // --- Build up window
+ gMainWindow = AxWin3_Widget_CreateWindow(NULL, 700, 400, ELEFLAG_VERTICAL);
+ AxWin3_SetWindowTitle(gMainWindow, "Acess Text Editor"); // TODO: Update title with other info
+ gMainWindow_Root = AxWin3_Widget_GetRoot(gMainWindow);
+
+ //gMainWindow_MenuBar = AxWin3_Menu_Create(gMainWindow);
+ //AxWin3_Widget_AddWidget_SubWindow(gMainWindow_Root, gMainWindow_MenuBar);
+ // TODO: Populate menu
+
+ // Create toolbar
+ gMainWindow_Toolbar = AxWin3_Widget_AddWidget(gMainWindow_Root, ELETYPE_TOOLBAR, ELEFLAG_NOSTRETCH, "Toolbar");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnNew", Toolbar_New);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnOpen", Toolbar_Open);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnSave", Toolbar_Save);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnUndo", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnRedo", NULL);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnCut", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnCopy", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnPaste", NULL);
+ AxWin3_Widget_AddWidget(gMainWindow_Toolbar, ELETYPE_SPACER, 0, "");
+ add_toolbar_button(gMainWindow_Toolbar, "BtnSearch", NULL);
+ add_toolbar_button(gMainWindow_Toolbar, "BtnReplace", NULL);
+
+ // TODO: Tab control?
+
+ gMainWindow_TextArea = AxWin3_RichText_CreateWindow(gMainWindow, 0);
+ AxWin3_Widget_AddWidget_SubWindow(gMainWindow_Root, gMainWindow_TextArea, 0, "TextArea");
+ AxWin3_RichText_SetKeyHandler (gMainWindow_TextArea, TextArea_KeyHandler);
+ AxWin3_RichText_SetMouseHandler (gMainWindow_TextArea, TextArea_MouseHandler);
+ AxWin3_RichText_SetBackground (gMainWindow_TextArea, 0xFFFFFF);
+ AxWin3_RichText_SetDefaultColour(gMainWindow_TextArea, 0x000000);
+ AxWin3_RichText_SetFont (gMainWindow_TextArea, "#monospace", 10);
+ AxWin3_RichText_SetCursorPos (gMainWindow_TextArea, 0, 0);
+ AxWin3_RichText_SetCursorType (gMainWindow_TextArea, AXWIN3_RICHTEXT_CURSOR_VLINE);
+ AxWin3_RichText_SetCursorBlink (gMainWindow_TextArea, 1);
+
+ // <testing>
+ AxWin3_RichText_SetLineCount(gMainWindow_TextArea, 3);
+ AxWin3_RichText_SendLine(gMainWindow_TextArea, 0, "First line!");
+ AxWin3_RichText_SendLine(gMainWindow_TextArea, 2, "Third line! \x01""ff0000A red");
+ // </testing>
+
+ AxWin3_ShowWindow(gMainWindow_TextArea, 1);
+ // TODO: Status Bar?
+
+ AxWin3_MoveWindow(gMainWindow, 50, 50);
+ AxWin3_ShowWindow(gMainWindow, 1);
+ AxWin3_FocusWindow(gMainWindow);
+
+ // Main loop
+ AxWin3_MainLoop();
+
+ return 0;
+}
+
+int TextArea_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
+{
+ return 0;
+}
+
+int TextArea_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
+{
+ return 0;
+}
+
+void add_toolbar_button(tAxWin3_Widget *Toolbar, const char *Ident, tAxWin3_Widget_FireCb Callback)
+{
+ tAxWin3_Widget *btn = AxWin3_Widget_AddWidget(Toolbar, ELETYPE_BUTTON, ELEFLAG_NOSTRETCH, Ident);
+ tAxWin3_Widget *txt = AxWin3_Widget_AddWidget(btn, ELETYPE_TEXT, 0, Ident);
+ // TODO: Get image / text using `Ident` as a lookup key
+ AxWin3_Widget_SetText(txt, Ident);
+ AxWin3_Widget_SetFireHandler(btn, Callback);
+}
+
+int Toolbar_New(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+int Toolbar_Open(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+int Toolbar_Save(tAxWin3_Widget *Widget)
+{
+ return 0;
+}
+
--- /dev/null
+# Project: [GUI] Terminal
+
+-include ../Makefile.cfg
+
+LDFLAGS += -laxwin3
+
+OBJ = main.o
+BIN = terminal
+DIR := Apps/AxWin/3.0
+
+-include ../Makefile.tpl
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.h
+ * - RichText Termianl Translation
+ */
+#ifndef _DISPLAY_H_
+#define _DISPLAY_H_
+
+extern void Display_AddText(int Length, const char *UTF8Text);
+extern void Display_Newline(int bCarriageReturn);
+extern void Display_SetCursor(int Row, int Col);
+extern void Display_MoveCursor(int RelRow, int RelCol);
+extern void Display_ClearLine(int Dir); // 0: All, 1: Forward, -1: Reverse
+extern void Display_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse
+extern void Display_SetForeground(uint32_t RGB);
+extern void Display_SetBackground(uint32_t RGB);
+
+#endif
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * vt100.h
+ * - VT100/xterm emulation
+ */
+#ifndef _VT100_H_
+#define _VT100_H_
+
+/**
+ * Returns either a positive or negative byte count.
+ * Positive means that many bytes were used as part of the escape sequence
+ * and should not be sent to the display.
+ * Negative means that there were that many bytes before the next escape
+ * sequence (and hence those should be displayed).
+ */
+extern int Term_HandleVT100(int Len, const char *Buf);
+
+
+#endif
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/menu.h>
+#include <axwin3/richtext.h>
+#include <stdio.h>
+#include "include/display.h"
+#include "include/vt100.h"
+
+// === PROTOTYPES ===
+ int main(int argc, char *argv[], const char **envp);
+ int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
+ int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+
+// === GLOBALS ===
+tHWND gMainWindow;
+tHWND gMenuWindow;
+ int giChildStdin;
+ int giChildStdout;
+
+// === CODE ===
+int main(int argc, char *argv[], const char **envp)
+{
+ AxWin3_Connect(NULL);
+
+ // --- Build up window
+ gMainWindow = AxWin3_RichText_CreateWindow(NULL, 0);
+ AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info
+
+ gMenuWindow = AxWin3_Menu_Create(gMainWindow);
+ AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, 0, NULL);
+ AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, 0, NULL);
+ // TODO: Populate menu
+
+
+ // TODO: Tabs?
+
+ AxWin3_RichText_SetKeyHandler (gMainWindow, Term_KeyHandler);
+ AxWin3_RichText_SetMouseHandler (gMainWindow, Term_MouseHandler);
+ AxWin3_RichText_SetDefaultColour(gMainWindow, 0xFFFFFF);
+ AxWin3_RichText_SetBackground (gMainWindow, 0x000000);
+ AxWin3_RichText_SetFont (gMainWindow, "#monospace", 10);
+ AxWin3_RichText_SetCursorPos (gMainWindow, 0, 0);
+ AxWin3_RichText_SetCursorType (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV);
+ AxWin3_RichText_SetCursorBlink (gMainWindow, 1);
+
+ // <testing>
+ AxWin3_RichText_SetLineCount(gMainWindow, 3);
+ AxWin3_RichText_SendLine(gMainWindow, 0, "First line!");
+ AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red");
+ // </testing>
+
+ AxWin3_ResizeWindow(gMainWindow, 600, 400);
+ AxWin3_MoveWindow(gMainWindow, 50, 50);
+ AxWin3_ShowWindow(gMainWindow, 1);
+ AxWin3_FocusWindow(gMainWindow);
+
+ // Spawn shell
+ giChildStdout = open("/Devices/FIFO/anon", O_RDWR);
+ giChildStdin = open("/Devices/FIFO/anon", O_RDWR);
+
+ {
+ int fds[] = {giChildStdin, giChildStdout, giChildStdout};
+ const char *argv[] = {"CLIShell", NULL};
+ _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ }
+
+ // Main loop
+ for( ;; )
+ {
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(giChildStdout, &fds);
+ AxWin3_MessageSelect(giChildStdout + 1, &fds);
+
+ if( FD_ISSET(giChildStdout, &fds) )
+ {
+ // Read and update screen
+ char buf[32];
+ int len = read(giChildStdout, buf, sizeof(buf));
+ if( len <= 0 ) break;
+
+ Term_HandleOutput(len, buf);
+ }
+ }
+
+ return 0;
+}
+
+int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
+{
+ static int ctrl_state = 0;
+
+ // Handle modifiers
+ #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=1<<(bit);}while(0)
+ switch(KeySym)
+ {
+ case KEY_LCTRL:
+ _bitset(ctrl_state, 0, bPress);
+ return 0;
+ case KEY_RCTRL:
+ _bitset(ctrl_state, 0, bPress);
+ return 0;
+ }
+ #undef _bitset
+
+ // Handle shortcuts
+ // - Ctrl-A -- Ctrl-Z
+ if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z )
+ {
+ Translated = KeySym - KEY_a + 1;
+ }
+
+ if( Translated )
+ {
+ // Encode and send
+
+ return 0;
+ }
+
+ // No translation, look for escape sequences to send
+ switch(KeySym)
+ {
+ case KEY_LEFTARROW:
+ // str = "\x1b[D";
+ break;
+ }
+ return 0;
+}
+
+int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
+{
+ return 0;
+}
+
+void Term_HandleOutput(int Len, const char *Buf)
+{
+ // TODO: Handle graphical / accelerated modes
+
+ int ofs = 0;
+ int esc_len = 0;
+
+ while( ofs < Len )
+ {
+ esc_len = Term_HandleVT100(Len - ofs, Buf + ofs);
+ if( esc_len < 0 ) {
+ Display_AddText(-esc_len, Buf + ofs);
+ esc_len = -esc_len;
+ }
+ Len -= esc_len;
+ ofs += esc_len;
+ }
+}
+
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <string.h>
+#include "include/vt100.h"
+#include "include/display.h"
+
+int Term_HandleVT100(int Len, const char *Buf)
+{
+ const int max_length = 16;
+ static char inc_buf[max_length]
+ static int inc_len = 0;
+
+ if( inc_len > 0 || *Buf == '\x1b' )
+ {
+ memcpy(inc_buf + inc_len, Buf, min(max_length - inc_len, Len));
+ // Handle VT100 (like) escape sequence
+
+ inc_len = 0;
+ return 1;
+ }
+
+ switch( *Buf )
+ {
+ case '\b':
+ // TODO: Backspace
+ return 1;
+ case '\t':
+ // TODO: tab
+ return 1;
+ case '\n':
+ Display_Newline(1);
+ return 1;
+ case '\r':
+ // TODO: Carriage return
+ return ;
+ }
+
+ int ret = 0;
+ while( ret < Len )
+ {
+ if( *Buf == '\n' )
+ break;
+ if( *Buf == '\x1b' )
+ break;
+ ret ++;
+ Buf ++;
+ }
+ return -ret;
+}
// - Start virtual terminals
for( i = 0; i < NUM_TERMS; i++ )
{
- tid = clone(CLONE_VM, 0);
+ tid = _SysClone(CLONE_VM, 0);
if(tid == 0)
{
termpath[sizeof(DEFAULT_TERMINAL)-2] = '0' + i;
- open(termpath, OPENFLAG_READ); // Stdin
- open(termpath, OPENFLAG_WRITE); // Stdout
- open(termpath, OPENFLAG_WRITE); // Stderr
- execve(DEFAULT_SHELL, child_argv, NULL);
- for(;;) sleep();
+ _SysOpen(termpath, OPENFLAG_READ); // Stdin
+ _SysOpen(termpath, OPENFLAG_WRITE); // Stdout
+ _SysOpen(termpath, OPENFLAG_WRITE); // Stderr
+ _SysExecVE(DEFAULT_SHELL, child_argv, NULL);
+ for(;;) ;
}
}
// TODO: Implement message watching
- for(;;) sleep();
+ for(;;)
+ _SysWaitEvent(THREAD_EVENT_IPCMSG);
return 42;
}
{
int dp, ret;
- dp = open(IPSTACK_ROOT, OPENFLAG_READ);
- ret = ioctl(dp, 4, (void*)Device);
- close(dp);
+ dp = _SysOpen(IPSTACK_ROOT, OPENFLAG_READ);
+ ret = _SysIOCtl(dp, 4, (void*)Device);
+ _SysClose(dp);
if( ret < 0 ) {
fprintf(stderr, "Unable to add '%s' as a network interface\n", Device);
// Open file
sprintf(path, IPSTACK_ROOT"/%i", IFNum);
- fd = open(path, OPENFLAG_READ);
+ fd = _SysOpen(path, OPENFLAG_READ);
if( fd == -1 ) {
fprintf(stderr, "Unable to open '%s'\n", path);
return -1;
}
tmp = type;
- tmp = ioctl(fd, ioctl(fd, 3, "getset_type"), &tmp);
+ tmp = _SysIOCtl(fd, _SysIOCtl(fd, 3, "getset_type"), &tmp);
if( tmp != type ) {
fprintf(stderr, "Error in setting address type (got %i, expected %i)\n", tmp, type);
- close(fd);
+ _SysClose(fd);
return -1;
}
// Set Address
- ioctl(fd, ioctl(fd, 3, "set_address"), addr);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_address"), addr);
// Set Subnet
- ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "getset_subnet"), &subnet);
- close(fd);
+ _SysClose(fd);
// Dump!
//DumpInterface( path+sizeof(IPSTACK_ROOT)+1 );
int dp;
char filename[FILENAME_MAX+1];
- dp = open(IPSTACK_ROOT, OPENFLAG_READ);
+ dp = _SysOpen(IPSTACK_ROOT, OPENFLAG_READ);
- while( SysReadDir(dp, filename) )
+ while( _SysReadDir(dp, filename) )
{
if(filename[0] == '.') continue;
DumpInterface(filename);
}
- close(dp);
+ _SysClose(dp);
}
/**
strcat(path, Name);
- fd = open(path, OPENFLAG_READ);
+ fd = _SysOpen(path, OPENFLAG_READ);
if(fd == -1) {
fprintf(stderr, "Bad interface name '%s' (%s does not exist)\t", Name, path);
return ;
}
- type = ioctl(fd, 4, NULL);
+ type = _SysIOCtl(fd, 4, NULL);
// Ignore -1 values
if( type == -1 ) {
printf("%s:\t", Name);
{
- int call_num = ioctl(fd, 3, "get_device");
- int len = ioctl(fd, call_num, NULL);
+ int call_num = _SysIOCtl(fd, 3, "get_device");
+ int len = _SysIOCtl(fd, call_num, NULL);
char *buf = malloc(len+1);
- ioctl(fd, call_num, buf);
+ _SysIOCtl(fd, call_num, buf);
printf("'%s'\n", buf);
free(buf);
}
uint8_t ip[4];
int subnet;
printf("IPv4\t");
- ioctl(fd, 5, ip); // Get IP Address
- subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
+ _SysIOCtl(fd, 5, ip); // Get IP Address
+ subnet = _SysIOCtl(fd, 7, NULL); // Get Subnet Bits
printf("%i.%i.%i.%i/%i\n", ip[0], ip[1], ip[2], ip[3], subnet);
}
break;
uint16_t ip[8];
int subnet;
printf("IPv6\t");
- ioctl(fd, 5, ip); // Get IP Address
- subnet = ioctl(fd, 7, NULL); // Get Subnet Bits
+ _SysIOCtl(fd, 5, ip); // Get IP Address
+ subnet = _SysIOCtl(fd, 7, NULL); // Get Subnet Bits
printf("%x:%x:%x:%x:%x:%x:%x:%x/%i\n",
ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]),
ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]),
break;
}
- close(fd);
+ _SysClose(fd);
}
// === PROTOTYPES ===
int Routes_main(int argc, char *argv[]);
void DumpRoutes(void);
-void DumpRoute(const char *Name);
+void DumpRoute(int PFD, const char *Name);
void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop);
// === CODE ===
}
// Destination IP
- addrType = ParseIPAddress(argv[3], dest, &subnetBits);
+ addrType = ParseIPAddress(argv[2], dest, &subnetBits);
if( subnetBits == -1 ) {
subnetBits = Net_GetAddressSize(addrType)*8;
}
// Interface Name / Next Hop
- if( (nextHopType = ParseIPAddress(argv[4], nextHop, &nextHopBits)) == 0 )
+ if( (nextHopType = ParseIPAddress(argv[3], nextHop, &nextHopBits)) == 0 )
{
// Interface name
- ifaceName = argv[4];
+ ifaceName = argv[3];
}
else
{
// Metric
if( argc - 3 >= 3 )
{
- metric = atoi(argv[5]);
- if( metric == 0 && argv[5][0] != '0' ) {
+ metric = atoi(argv[4]);
+ if( metric == 0 && argv[4][0] != '0' ) {
fprintf(stderr, "ERROR: Metric should be a number\n");
return -1;
}
int dp;
char filename[FILENAME_MAX+1];
- dp = open(IPSTACK_ROOT"/routes", OPENFLAG_READ);
+ dp = _SysOpen(IPSTACK_ROOT"/routes", OPENFLAG_READ);
printf("Type\tNetwork \tGateway \tMetric\tIFace\n");
- while( SysReadDir(dp, filename) )
+ while( _SysReadDir(dp, filename) )
{
if(filename[0] == '.') continue;
- DumpRoute(filename);
+ DumpRoute(dp, filename);
}
- close(dp);
+ _SysClose(dp);
}
/**
* \brief Dump a route
*/
-void DumpRoute(const char *Name)
+void DumpRoute(int PFD, const char *Name)
{
int fd;
int type;
- char path[sizeof(IPSTACK_ROOT)+8+FILENAME_MAX+1] = IPSTACK_ROOT"/routes/";
- strcat(path, Name);
-
- fd = open(path, OPENFLAG_READ);
+ fd = _SysOpenChild(PFD, Name, OPENFLAG_READ);
if(fd == -1) {
- printf("%s:\tUnable to open ('%s')\n", Name, path);
+ printf("%s:\tUnable to open\n", Name);
return ;
}
subnet = atoi(Name+ofs);
ofs ++;
metric = atoi(Name+ofs);
- ioctl(fd, ioctl(fd, 3, "get_nexthop"), gw); // Get Gateway/NextHop
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "get_nexthop"), gw); // Get Gateway/NextHop
// Get the address type
switch(type)
// Interface
{
- int call_num = ioctl(fd, 3, "get_interface");
- int len = ioctl(fd, call_num, NULL);
+ int call_num = _SysIOCtl(fd, 3, "get_interface");
+ int len = _SysIOCtl(fd, call_num, NULL);
char *buf = malloc(len+1);
- ioctl(fd, call_num, buf);
+ _SysIOCtl(fd, call_num, buf);
printf("'%s'\t", buf);
free(buf);
}
printf("\n");
- close(fd);
+ _SysClose(fd);
}
void AddRoute(const char *Interface, int AddressType, void *Dest, int MaskBits, int Metric, void *NextHop)
// Open interface
strcpy(ifacePath, IPSTACK_ROOT"/");
strcat(ifacePath, Interface);
- fd = open(ifacePath, 0);
+ fd = _SysOpen(ifacePath, 0);
if( fd == -1 ) {
fprintf(stderr, "Error: Interface '%s' does not exist\n", Interface);
return ;
}
// Get and check type
- num = ioctl(fd, ioctl(fd, 3, "getset_type"), NULL);
+ num = _SysIOCtl(fd, _SysIOCtl(fd, 3, "getset_type"), NULL);
if( num != AddressType ) {
fprintf(stderr, "Error: Passed type does not match interface type (%i != %i)\n",
AddressType, num);
return ;
}
- close(fd);
+ _SysClose(fd);
}
// Create route
sprintf(path+ofs, ":%i:%i", MaskBits, Metric);
}
- fd = open(path, 0);
+ fd = _SysOpen(path, 0);
if( fd != -1 ) {
- close(fd);
+ _SysClose(fd);
fprintf(stderr, "Unable to create route '%s', already exists\n", path);
return ;
}
- fd = open(path, OPENFLAG_CREATE, 0);
+ fd = _SysOpen(path, OPENFLAG_CREATE, 0);
if( fd == -1 ) {
fprintf(stderr, "Unable to create '%s'\n", path);
return ;
}
if( NextHop )
- ioctl(fd, ioctl(fd, 3, "set_nexthop"), NextHop);
- ioctl(fd, ioctl(fd, 3, "set_interface"), (void*)Interface);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_nexthop"), NextHop);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "set_interface"), (void*)Interface);
- close(fd);
+ _SysClose(fd);
// Check if the interface name was allocated by us
if( ifaceToFree )
\r
atexit(ExitHandler);\r
\r
- giTerminal_Width = ioctl(1, 5, NULL); // getset_width\r
- giTerminal_Height = ioctl(1, 6, NULL); // getset_height\r
+ giTerminal_Width = _SysIOCtl(1, 5, NULL); // getset_width\r
+ giTerminal_Height = _SysIOCtl(1, 6, NULL); // getset_height\r
\r
printf("\x1B[?1047h");\r
printf("\x1B[%i;%ir", 0, giTerminal_Height-1);\r
{\r
tServer *srv;\r
for( srv = gpServers; srv; srv = srv->Next )\r
- close(srv->FD);\r
+ _SysClose(srv->FD);\r
}\r
return 0;\r
}\r
// ioctl#8 on a TCP client gets the number of bytes in the recieve buffer\r
// - Used to avoid blocking\r
#if NON_BLOCK_READ\r
- while( (len = ioctl(Server->FD, 8, NULL)) > 0 )\r
+ while( (len = _SysIOCtl(Server->FD, 8, NULL)) > 0 )\r
{\r
#endif\r
// Read data\r
- len = read(Server->FD, &Server->InBuf[Server->ReadPos], BUFSIZ - Server->ReadPos);\r
+ len = _SysRead(Server->FD, &Server->InBuf[Server->ReadPos], BUFSIZ - Server->ReadPos);\r
if( len == -1 ) {\r
return -1;\r
}\r
vsnprintf(buf, len+1, Format, args);\r
va_end(args);\r
\r
- return write(FD, buf, len);\r
+ return _SysWrite(FD, buf, len);\r
}\r
}\r
\r
\r
// Set remote port and address\r
// printf("Setting port and remote address\n");\r
- ioctl(fd, 5, &PortNumber);\r
- ioctl(fd, 6, addrBuffer);\r
+ _SysIOCtl(fd, 5, &PortNumber);\r
+ _SysIOCtl(fd, 6, addrBuffer);\r
\r
// Connect\r
// printf("Initiating connection\n");\r
- if( ioctl(fd, 7, NULL) == 0 ) {\r
+ if( _SysIOCtl(fd, 7, NULL) == 0 ) {\r
// Shouldn't happen :(\r
fprintf(stderr, "Unable to start connection\n");\r
return -1;\r
Row = Col / giTerminal_Width;\r
Col = Col % giTerminal_Width;\r
}\r
- rv = ioctl(1, 9, NULL); // Ugh, constants\r
+ rv = _SysIOCtl(1, 9, NULL); // Ugh, constants\r
printf("\x1B[%i;%iH", Col, Row);\r
return rv;\r
}\r
break;
}
printf("\n");
-
- // Create child process
- pid = clone(CLONE_VM, 0);
+
+ uinfo = GetUserInfo(uid);
+ struct s_sys_spawninfo spawninfo;
+ spawninfo.flags = 0;
+ spawninfo.gid = uinfo->GID;
+ spawninfo.uid = uinfo->UID;
+ const char *child_argv[2] = {"-", 0};
+ const char **child_envp = NULL;
+ int fds[] = {0, 1, 2};
+ pid = _SysSpawn(uinfo->Shell, child_argv, child_envp, 3, fds, &spawninfo);
// Error check
if(pid == -1) {
fprintf(stderr, "Unable to fork the login process!\n");
return -1;
}
- // Spawn shell in a child process
- if(pid == 0)
- {
- char *child_argv[2] = {NULL, 0};
- char **child_envp = NULL;
-
- // Get user information
- uinfo = GetUserInfo(uid);
-
- child_argv[0] = uinfo->Shell;
- // Set Environment
- setgid(uinfo->GID);
- //setuid(uid);
- setuid(uinfo->UID);
-
- execve(uinfo->Shell, child_argv, child_envp);
- exit(-1);
- }
-
// Wait for child to terminate
- waittid(pid, &status);
+ _SysWaitTID(pid, &status);
}
return 0;
ParseArguments(argc, argv);
// Open Directory
- fd = open(gsDirectory, OPENFLAG_READ|OPENFLAG_EXEC);
+ fd = _SysOpen(gsDirectory, OPENFLAG_READ|OPENFLAG_EXEC);
if(fd == -1) {
printf("Unable to open '%s' for reading\n", gsDirectory);
return EXIT_FAILURE;
}
// Check that it is a directory
- finfo(fd, &info, 0);
+ _SysFInfo(fd, &info, 0);
if( !(info.flags & FILEFLAG_DIRECTORY) ) {
fprintf(stderr, "'%s' is not a directory\n", gsDirectory);
- close(fd);
+ _SysClose(fd);
return EXIT_FAILURE;
}
}
// Traverse Directory
- while( (tmp = SysReadDir(fd, buf)) > 0 )
+ while( (tmp = _SysReadDir(fd, buf)) > 0 )
{
// Error check
if(tmp < 0) {
- close(fd);
+ _SysClose(fd);
return EXIT_FAILURE;
}
space += 16;
gFileList = realloc(gFileList, space*sizeof(char*));
if(gFileList == NULL) {
- close(fd);
+ _SysClose(fd);
return EXIT_FAILURE;
}
}
DisplayFile( gFileList[i] );
}
- close(fd);
+ _SysClose(fd);
printf("\n");
return EXIT_SUCCESS;
strcpy(&path[dirLen+1], Filename);
// Get file type
- fd = open(path, 0);
+ fd = _SysOpen(path, 0);
if(fd == -1) {
fprintf(stderr, "Unable to open '%s'\n", path);
}
else {
// Get Info
- finfo(fd, &info, 0);
+ _SysFInfo(fd, &info, 0);
// Get Type
if(info.flags & FILEFLAG_DIRECTORY) {
type = FTYPE_DIR;
if(acl.perms & 8) perms |= 0001; // X
// Close file
- close(fd);
+ _SysClose(fd);
}
free(path); // We're finished with it
*/
#include <stdlib.h>
#include <stdio.h>
-#include <unistd.h>
#include <acess/sys.h>
#define PCI_BASE "/Devices/pci"
// === CODE ===
int main(int argc, char *argv[])
{
- int fd = open(PCI_BASE, OPENFLAG_READ);
+ int fd = _SysOpen(PCI_BASE, OPENFLAG_READ);
char name[256];
- while( SysReadDir(fd, name) )
+ while( _SysReadDir(fd, name) )
{
if(name[0] == '.') continue ;
show_device(fd, name, 0);
}
+ _SysClose(fd);
+
return 0;
}
printf("%s - ERR (open failure)\n", File);
return ;
}
- rv = read(fd, &pciinfo, sizeof(pciinfo));
+ rv = _SysRead(fd, &pciinfo, sizeof(pciinfo));
if( rv != sizeof(pciinfo) ) {
printf("%s - ERR (read %i < %i)\n", File, rv, sizeof(pciinfo));
- close(fd);
+ _SysClose(fd);
return ;
}
uint32_t class_if = pciinfo.revclass >> 8;
printf("\n");
}
- close(fd);
+ _SysClose(fd);
}
int fd;
int i;
char *arg;
+
char *sType = NULL;
char *sDevice = NULL;
char *sDir = NULL;
char *sOptions = NULL;
+ int bUnmount = 0;
// List mounted filesystems
// - This is cheating, isn't it?
{
// -t <driver> :: Filesystem driver to use
case 't': sType = argv[++i]; break;
+ // -o option_list :: Options to pass the driver
case 'o': sOptions = argv[++i]; break;
+ // -u :: Unmount
+ case 'u': bUnmount = 1; break;
case '-':
//TODO: Long Arguments
default:
return EXIT_FAILURE;
}
+ if( bUnmount )
+ {
+ // TODO: Check for a match in the fstab
+
+ if( sDir ) {
+ fprintf(stderr, "`mount -u` takes one argument\n");
+ }
+
+ sDir = sDevice;
+ if( _SysMount(NULL, sDir, NULL, NULL) ) // Unmount (Dev=NULL means unmount)
+ {
+ fprintf(stderr, "Unmount failed\n");
+ }
+ return EXIT_SUCCESS;
+ }
+
// Check if we even got a device/mountpoint
if(sDevice == NULL) {
ShowUsage(argv[0]);
}
// Check Device
- fd = open(sDevice, OPENFLAG_READ);
+ fd = _SysOpen(sDevice, OPENFLAG_READ);
if(fd == -1) {
printf("Device '%s' cannot be opened for reading\n", sDevice);
return EXIT_FAILURE;
}
- close(fd);
+ _SysClose(fd);
// Check Mount Point
- fd = open(sDir, OPENFLAG_EXEC);
+ fd = _SysOpen(sDir, OPENFLAG_EXEC);
if(fd == -1) {
printf("Directory '%s' does not exist\n", sDir);
return EXIT_FAILURE;
}
- close(fd);
+ _SysClose(fd);
// Replace sOptions with an empty string if it is still NULL
if(sOptions == NULL) sOptions = "";
// Let's Mount!
if( _SysMount(sDevice, sDir, sType, sOptions) ) {
+// perror("_SysMount");
if( !sType )
fprintf(stderr, "Filesystem autodetection failed, please pass a type\n");
+ else {
+ fprintf(stderr, "Mount %s:'%s'=>'%s' failed\n", sType, sDevice, sDir);
+ }
}
return 0;
free(iface); // TODO: Handle when this is not heap
iface = _iface;
printf("iface = '%s'\n", iface);
- fd = open(iface, OPENFLAG_EXEC);
+ fd = _SysOpen(iface, OPENFLAG_EXEC);
if(fd == -1) {
fprintf(stderr, "ERROR: Unable to open interface '%s'\n", iface);
return 1;
}
}
- call = ioctl(fd, 3, "ping");
+ call = _SysIOCtl(fd, 3, "ping");
if(call == 0) {
fprintf(stderr, "ERROR: '%s' does not have a 'ping' call\n", iface);
return 1;
for( i = 0; i < giNumberOfPings; i ++ )
{
- ping = ioctl(fd, call, addr);
+ ping = _SysIOCtl(fd, call, addr);
printf("ping = %i\n", ping);
}
- close(fd);
+ _SysClose(fd);
return 0;
}
// Read from server, and write to stdout\r
do\r
{\r
- len = read(server_fd, buffer, BUFSIZ);\r
- write(1, buffer, len);\r
+ len = _SysRead(server_fd, buffer, BUFSIZ);\r
+ _SysWrite(1, buffer, len);\r
} while( len == BUFSIZ );\r
}\r
\r
char *line = Readline_NonBlock(readline_info);\r
if( line )\r
{\r
- write(server_fd, line, strlen(line));\r
- write(server_fd, "\n", 1);\r
+ _SysWrite(server_fd, line, strlen(line));\r
+ _SysWrite(server_fd, "\n", 1);\r
}\r
}\r
else\r
{\r
do\r
{\r
- len = read(0, buffer, BUFSIZ);\r
- write(server_fd, buffer, len);\r
- write(1, buffer, len);\r
+ len = _SysRead(0, buffer, BUFSIZ);\r
+ _SysWrite(server_fd, buffer, len);\r
+ _SysWrite(1, buffer, len);\r
} while( len == BUFSIZ );\r
}\r
}\r
}\r
}\r
\r
- close(server_fd);\r
+ _SysClose(server_fd);\r
return 0;\r
}\r
\r
}\r
\r
// Set remote port and address\r
- ioctl(fd, 5, &PortNumber);\r
- ioctl(fd, 6, addrBuffer);\r
+ _SysIOCtl(fd, 5, &PortNumber);\r
+ _SysIOCtl(fd, 6, addrBuffer);\r
\r
// Connect\r
- if( ioctl(fd, 7, NULL) == 0 ) {\r
+ if( _SysIOCtl(fd, 7, NULL) == 0 ) {\r
fprintf(stderr, "Unable to start connection\n");\r
return -1;\r
}\r
/*
+ * Acess2 Telnet Server (TCP server test case)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - All
*/
#include <stddef.h>
#include <net.h>
-#include <unistd.h>
#include <stdio.h>
+#include <acess/sys.h>
// === TYPES ===
typedef struct sClient
int addrtype = Net_ParseAddress("10.0.2.10", data);
int port = 23;
giServerFD = Net_OpenSocket(addrtype, data, "tcps");
- ioctl(giServerFD, 4, &port); // Set port and start listening
+ _SysIOCtl(giServerFD, 4, &port); // Set port and start listening
}
// Event loop
}
// Select!
- select( maxfd+1, &fds, NULL, NULL, NULL );
+ _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
// Check events
if( FD_ISSET(giServerFD, &fds) )
if( giNumClients == giConfig_MaxClients )
{
// Open, reject
- close( _SysOpenChild(FD, "", O_RDWR) );
+ _SysClose( _SysOpenChild(FD, "", OPENFLAG_READ) );
return ;
}
}
}
// Accept the connection
- clt->Socket = _SysOpenChild(FD, "", O_RDWR);
+ clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE);
giNumClients ++;
// Create stdin/stdout
- clt->stdin = open("/Devices/fifo/anon", O_RDWR);
- clt->stdout = open("/Devices/fifo/anon", O_RDWR);
+ clt->stdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+ clt->stdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
// TODO: Arguments and envp
{
int fds[3] = {clt->stdin, clt->stdout, clt->stdout};
const char *argv[] = {NULL};
- _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds);
+ _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
}
}
char buf[BUFSIZ];
int len;
- len = read(Client->Socket, buf, BUFSIZ);
+ len = _SysRead(Client->Socket, buf, BUFSIZ);
if( len <= 0 ) return ;
- write(Client->stdin, buf, len);
+ _SysWrite(Client->stdin, buf, len);
}
void HandleClientBoundData(tClient *Client)
char buf[BUFSIZ];
int len;
- len = read(Client->stdout, buf, BUFSIZ);
+ len = _SysRead(Client->stdout, buf, BUFSIZ);
if( len <= 0 ) return ;
- write(Client->Socket, buf, len);
+ _SysWrite(Client->Socket, buf, len);
}
#include <string.h>
#include <unistd.h>
#include <netdb.h>
+#include <acess/sys.h> // _SysDebug
enum eProcols
{
if( state == 2 )
{
_SysDebug("RXing %i bytes to '%s'", bytes_wanted, outfile);
- int outfd = open(outfile, O_WR|O_CREAT, 0666);
+ int outfd = open(outfile, O_WRONLY|O_CREAT, 0666);
if( outfd == -1 ) {
fprintf(stderr, "Unable to open '%s' for writing\n", outfile);
}
@mkdir -p $(dir $(_BIN))
@echo [LD] -o $(BIN) $(OBJ)
@$(LD) $(LDFLAGS) -o $(_BIN) $(OBJ) $(shell $(CC) -print-libgcc-file-name)
- @$(DISASM) -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
+ @$(DISASM) -D -S $(_BIN) > $(_OBJPREFIX)$(BIN).dsm
$(_OBJPREFIX)%.o: %.c
@echo [CC] -o $@
@mkdir -p $(dir $@)
@$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(_OBJPREFIX)%.ao: %.$(ASSUFFIX)
@echo [AS] -o $@
INCFILES := sys/sys.h
CFLAGS = -g -Wall -fno-builtin -fno-leading-underscore -fno-stack-protector -fPIC
-CFLAGS += $(CPPFLAGS)
+CFLAGS += $(CPPFLAGS) -Werror
LDFLAGS = -g -T arch/$(ARCHDIR).ld -Map map.txt --export-dynamic
include ../Makefile.tpl
#define SYSCALL5(name,num) void name(void){}
#define SYSCALL6(name,num) void name(void){}
+#define NO_SYSCALL_STRS
#include "arch/syscalls.s.h"
// libgcc functions
svc #0x1001
mov pc, lr
-@ DEST
-@ SRC
-@_memcpy:
-@ push rbp
-@ mov rbp, rsp
-@
-@ ; RDI - First Param
-@ ; RSI - Second Param
-@ mov rcx, rdx ; RDX - Third
-@ rep movsb
-@
-@ pop rbp
-@ ret
-@
+
+@ >r0: PC
+@ >r1: Pointer to item count
+@ <r0: Address
+@ STUBBED
+__gnu_Unwind_Find_exidx:
+ mov r0, #0
+ str r0, [r1]
+ mov pc, lr
+
+.section .data
.globl _errno
_errno: .long 0 @ Placed in .text, to allow use of relative addressing
+.section .text
.macro syscall0 _name, _num
.globl \_name
\_name:
push {lr}
svc #\_num
- str r2, _errno
+ @mrc p15, 0, r3, c13, c0, 2
+ ldr r3, =_errno
+ str r2, [r3]
pop {pc}
.endm
push {r4, lr}
ldr r4, [sp,#8]
svc #\_num
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
pop {r4, pc}
.endm
ldr r4, [sp,#12]
ldr r5, [sp,#16]
svc #\_num
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
pop {r4,r5,pc}
.endm
push {r4}
mov r4, r1
svc #SYS_CLONE
- str r2, _errno
+ ldr r3, =_errno
+ str r2, [r3]
tst r4, r4
beq _clone_ret
@ If in child, set SP
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
}
+ __exidx_start = .;
.text : AT(ADDR(.text)) {
code = .;
*(.text)
*(.rodata*)
}
+ __exidx_end = .;
.data ALIGN (0x1000) : AT(ADDR(.data)) {
data = .;
// --- Process Control ---
SYSCALL1(_exit, SYS_EXIT)
-SYSCALL2(clone, SYS_CLONE)
-SYSCALL2(kill, SYS_KILL)
-SYSCALL0(yield, SYS_YIELD)
-SYSCALL0(sleep, SYS_SLEEP)
+SYSCALL2(_SysClone, SYS_CLONE)
+SYSCALL2(_SysKill, SYS_KILL)
+//SYSCALL0(yield, SYS_YIELD)
+//SYSCALL0(sleep, SYS_SLEEP)
SYSCALL1(_SysWaitEvent, SYS_WAITEVENT)
-SYSCALL2(waittid, SYS_WAITTID)
+SYSCALL2(_SysWaitTID, SYS_WAITTID)
SYSCALL0(gettid, SYS_GETTID)
SYSCALL0(getpid, SYS_GETPID)
SYSCALL1(setuid, SYS_SETUID)
SYSCALL1(setgid, SYS_SETGID)
-SYSCALL1(SysSetName, SYS_SETNAME)
-SYSCALL2(SysGetName, SYS_GETNAME)
+SYSCALL1(_SysSetName, SYS_SETNAME)
+SYSCALL2(_SysGetName, SYS_GETNAME)
SYSCALL0(_SysTimestamp, SYS_GETTIME)
-SYSCALL1(SysSetPri, SYS_SETPRI)
+SYSCALL1(_SysSetPri, SYS_SETPRI)
-SYSCALL3(SysSendMessage, SYS_SENDMSG)
-SYSCALL3(SysGetMessage, SYS_GETMSG)
+SYSCALL3(_SysSendMessage, SYS_SENDMSG)
+SYSCALL3(_SysGetMessage, SYS_GETMSG)
SYSCALL5(_SysSpawn, SYS_SPAWN)
-SYSCALL3(execve, SYS_EXECVE)
-SYSCALL2(SysLoadBin, SYS_LOADBIN)
-SYSCALL1(SysUnloadBin, SYS_UNLOADBIN)
+SYSCALL3(_SysExecVE, SYS_EXECVE)
+SYSCALL2(_SysLoadBin, SYS_LOADBIN)
+SYSCALL1(_SysUnloadBin, SYS_UNLOADBIN)
SYSCALL1(_SysSetFaultHandler, SYS_SETFAULTHANDLER)
SYSCALL6(_SysDebug, 0x100)
SYSCALL1(_SysGetPhys, SYS_GETPHYS) // uint64_t _SysGetPhys(uint addr)
SYSCALL1(_SysAllocate, SYS_ALLOCATE) // uint64_t _SysAllocate(uint addr)
+SYSCALL3(_SysSetMemFlags, SYS_SETFLAGS) // uint32_t SysSetMemFlags(uint addr, uint flags, uint mask)
// VFS System calls
-SYSCALL2(open, SYS_OPEN) // char*, int
-SYSCALL3(reopen, SYS_REOPEN) // int, char*, int
-SYSCALL1(close, SYS_CLOSE) // int
-SYSCALL3(read, SYS_READ) // int, uint, void*
-SYSCALL3(write, SYS_WRITE) // int, uint, void*
-SYSCALL4(seek, SYS_SEEK) // int, uint64_t, int
-SYSCALL1(tell, SYS_TELL) // int
-SYSCALL3(finfo, SYS_FINFO) // int, void*, int
-SYSCALL2(SysReadDir, SYS_READDIR) // int, char*
+SYSCALL2(_SysOpen, SYS_OPEN) // char*, int
+SYSCALL3(_SysOpenChild, SYS_OPENCHILD) // int, char*, int
+SYSCALL3(_SysReopen, SYS_REOPEN) // int, char*, int
+SYSCALL1(_SysClose, SYS_CLOSE) // int
+SYSCALL3(_SysRead, SYS_READ) // int, uint, void*
+SYSCALL3(_SysWrite, SYS_WRITE) // int, uint, void*
+SYSCALL4(_SysSeek, SYS_SEEK) // int, uint64_t, int
+SYSCALL1(_SysTell, SYS_TELL) // int
+SYSCALL3(_SysFInfo, SYS_FINFO) // int, void*, int
+SYSCALL2(_SysReadDir, SYS_READDIR) // int, char*
SYSCALL2(_SysGetACL,SYS_GETACL) // int, void*
-SYSCALL1(chdir, SYS_CHDIR) // char*
-SYSCALL3(ioctl, SYS_IOCTL) // int, int, void*
+SYSCALL1(_SysChdir, SYS_CHDIR) // char*
+SYSCALL3(_SysIOCtl, SYS_IOCTL) // int, int, void*
SYSCALL4(_SysMount, SYS_MOUNT) // char*, char*, char*, char*
SYSCALL6(_SysSelect, SYS_SELECT) // int, fd_set*, fd_set*, fd_set*, tTime*, uint32_t
+SYSCALL1(_SysUnlink, SYS_UNLINK) // const char*
-SYSCALL3(_SysOpenChild, SYS_OPENCHILD)
#include <stddef.h>
#include <stdarg.h>
#include <stdint.h>
+#include <acess/sys.h>
typedef uintptr_t Uint;
typedef uint8_t Uint8;
// === Library/Symbol Manipulation ==
extern void *LoadLibrary(const char *Filename, const char *SearchDir, char **envp);
extern void AddLoaded(const char *File, void *base);
-extern void *GetSymbol(const char *name, size_t *size);
+extern int GetSymbol(const char *Name, void **Value, size_t *size);
extern int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
// === Library Functions ===
extern void *memcpy(void *dest, const void *src, size_t len);
// === System Calls ===
-extern void _exit(int retval);
-extern void SysDebug(const char *fmt, ...); //!< Now implemented in main.c
-extern void SysDebugV(const char *fmt, ...);
-extern void *SysLoadBin(const char *path, void **entry);
-extern int SysUnloadBin(void *Base);
-extern void SysSetFaultHandler(int (*Hanlder)(int));
-extern int open(const char *filename, int flags, ...);
-extern int close(int fd);
// === ELF Loader ===
extern void *ElfRelocate(void *Base, char **envp, const char *Filename);
# define DEBUG 0
#endif
+#ifndef PAGE_SIZE
+# define PAGE_SIZE 4096
+#endif
+
#include "common.h"
#include <stdint.h>
#include "elf32.h"
int ElfGetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
void *Elf32Relocate(void *Base, char **envp, const char *Filename);
int Elf32GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
-void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
-void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff);
+ int elf_doRelocate_unk(uint32_t , uint32_t *, Elf32_Addr , int , int , const char *, intptr_t);
#ifdef SUPPORT_ELF64
void *Elf64Relocate(void *Base, char **envp, const char *Filename);
int Elf64GetSymbol(void *Base, const char *Name, void **Ret, size_t *Size);
}
}
-void elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_386(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type,
+ int bRela, const char *Sym, intptr_t iBaseDiff)
{
- intptr_t val;
+ void *symval;
switch( type )
{
// Standard 32 Bit Relocation (S+A)
case R_386_32:
- val = (intptr_t) GetSymbol(Sym, NULL);
- DEBUGS(" elf_doRelocate: R_386_32 *0x%x += 0x%x('%s')",
- ptr, val, Sym);
- *ptr = val + addend;
+ if( !GetSymbol(Sym, &symval, NULL) )
+ return 1;
+ DEBUGS(" elf_doRelocate: R_386_32 *0x%x += %p('%s')",
+ ptr, symval, Sym);
+ *ptr = (intptr_t)symval + addend;
break;
// 32 Bit Relocation wrt. Offset (S+A-P)
case R_386_PC32:
DEBUGS(" elf_doRelocate: '%s'", Sym);
- val = (intptr_t) GetSymbol(Sym, NULL);
- DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%x - 0x%x",
- ptr, *ptr, val, (intptr_t)ptr );
- *ptr = val + addend - (intptr_t)ptr;
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: R_386_PC32 *0x%x = 0x%x + 0x%p - 0x%x",
+ ptr, *ptr, symval, (intptr_t)ptr );
+ *ptr = (intptr_t)symval + addend - (intptr_t)ptr;
//*ptr = val + addend - ((Uint)ptr - iBaseDiff);
break;
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
DEBUGS(" elf_doRelocate: '%s'", Sym);
- val = (intptr_t) GetSymbol( Sym, NULL );
- DEBUGS(" elf_doRelocate: %s *0x%x = 0x%x", csaR_NAMES[type], ptr, val);
- *ptr = val;
+ if( !GetSymbol(Sym, &symval, NULL) ) return 1;
+ DEBUGS(" elf_doRelocate: %s *0x%x = %p", csaR_NAMES[type], ptr, symval);
+ *ptr = (intptr_t)symval;
break;
// Base Address (B+A)
case R_386_COPY: {
size_t size;
- void *src = GetSymbol(Sym, &size);
- DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, src, size);
- memcpy(ptr, src, size);
+ if( !GetSymbol(Sym, &symval, &size) ) return 1;
+ DEBUGS(" elf_doRelocate_386: R_386_COPY (%p, %p, %i)", ptr, symval, size);
+ memcpy(ptr, symval, size);
break; }
default:
SysDebug("elf_doRelocate_386: Unknown relocation %i", type);
- break;
+ return 2;
}
+ return 0;
}
-void elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+int elf_doRelocate_arm(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
{
uint32_t val;
switch(type)
// (S + A) | T
case R_ARM_ABS32:
DEBUGS(" elf_doRelocate_arm: R_ARM_ABS32 %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
case R_ARM_GLOB_DAT:
DEBUGS(" elf_doRelocate_arm: R_ARM_GLOB_DAT %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
case R_ARM_JUMP_SLOT:
if(!bRela) addend = 0;
DEBUGS(" elf_doRelocate_arm: R_ARM_JUMP_SLOT %p (%s + %x)", ptr, Sym, addend);
- val = (intptr_t)GetSymbol(Sym, NULL);
+ if( !GetSymbol(Sym, (void**)&val, NULL) ) return 1;
*ptr = val + addend;
break;
// Copy
case R_ARM_COPY: {
size_t size;
- void *src = GetSymbol(Sym, &size);
+ void *src;
+ if( !GetSymbol(Sym, &src, &size) ) return 1;
DEBUGS(" elf_doRelocate_arm: R_ARM_COPY (%p, %p, %i)", ptr, src, size);
memcpy(ptr, src, size);
break; }
// Delta between link and runtime locations + A
case R_ARM_RELATIVE:
+ DEBUGS(" elf_doRelocate_arm: R_ARM_RELATIVE %p (0x%x + 0x%x)", ptr, iBaseDiff, addend);
if(Sym[0] != '\0') {
// TODO: Get delta for a symbol
SysDebug("elf_doRelocate_arm: TODO - Implment R_ARM_RELATIVE for symbols");
+ return 2;
}
else {
*ptr = iBaseDiff + addend;
break;
default:
SysDebug("elf_doRelocate_arm: Unknown Relocation, %i", type);
- break;
+ return 2;
}
+ return 0;
+}
+
+int elf_doRelocate_unk(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, int type, int bRela, const char *Sym, intptr_t iBaseDiff)
+{
+ return 1;
}
void *Elf32Relocate(void *Base, char **envp, const char *Filename)
Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer
char *dynstrtab = NULL; // .dynamic String Table
Elf32_Sym *dynsymtab;
- void (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
- auto void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend);
+ int (*do_relocate)(uint32_t t_info, uint32_t *ptr, Elf32_Addr addend, int Type, int bRela, const char *Sym, intptr_t iBaseDiff);
DEBUGS("ElfRelocate: (Base=0x%x)", Base);
// Adjust "Real" Base
iBaseDiff = (intptr_t)Base - iRealBase;
-
+
// hdr->entrypoint += iBaseDiff; // Adjust Entrypoint
// Check if a PT_DYNAMIC segement was found
SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
}
-
+
+ // Allow writing to read-only segments, just in case they need to be relocated
+ // - Will be reversed at the end of the function
+ for( i = 0; i < iSegmentCount; i ++ )
+ {
+ if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
+ uintptr_t addr = phtab[i].VAddr + iBaseDiff;
+ uintptr_t end = addr + phtab[i].MemSize;
+ for( ; addr < end; addr += PAGE_SIZE )
+ _SysSetMemFlags(addr, 0, 1); // Unset RO
+ }
+ }
+
// Adjust Dynamic Table
dynamicTab = (void *)( (intptr_t)dynamicTab + iBaseDiff );
// === Get Symbol table and String Table ===
+ dynsymtab = NULL;
for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)
{
switch(dynamicTab[j].d_tag)
DEBUGS(" elf_relocate: Beginning Relocation");
- void _doRelocate(uint32_t r_info, uint32_t *ptr, int bRela, Elf32_Addr addend)
- {
- int type = ELF32_R_TYPE(r_info);
- int sym = ELF32_R_SYM(r_info);
- const char *symname = dynstrtab + dynsymtab[sym].nameOfs;
- do_relocate(r_info, ptr, addend, type, bRela, symname, iBaseDiff);
- }
+ int fail = 0;
switch(hdr->machine)
{
break;
default:
SysDebug("Elf32Relocate: Unknown machine type %i", hdr->machine);
+ do_relocate = elf_doRelocate_unk;
+ fail = 1;
break;
}
DEBUGS("do_relocate = %p (%p or %p)", do_relocate, &elf_doRelocate_386, &elf_doRelocate_arm);
+ #define _doRelocate(r_info, ptr, bRela, addend) \
+ do_relocate(r_info, ptr, addend, ELF32_R_TYPE(r_info), bRela, \
+ dynstrtab + dynsymtab[ELF32_R_SYM(r_info)].nameOfs, iBaseDiff);
+
// Parse Relocation Entries
if(rel && relSz)
{
{
//DEBUGS(" Rel %i: 0x%x+0x%x", i, iBaseDiff, rel[i].r_offset);
ptr = (void*)(iBaseDiff + rel[i].r_offset);
- _doRelocate(rel[i].r_info, ptr, 0, *ptr);
+ fail |= _doRelocate(rel[i].r_info, ptr, 0, *ptr);
}
}
// Parse Relocation Entries
for( i = 0; i < j; i++ )
{
ptr = (void*)(iBaseDiff + rela[i].r_offset);
- _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
+ fail |= _doRelocate(rel[i].r_info, ptr, 1, rela[i].r_addend);
}
}
for(i=0;i<j;i++)
{
ptr = (void*)(iBaseDiff + pltRel[i].r_offset);
- _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
+ fail |= _doRelocate(pltRel[i].r_info, ptr, 0, *ptr);
}
}
else
for(i=0;i<j;i++)
{
ptr = (void*)(iRealBase + pltRela[i].r_offset);
- _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
+ fail |= _doRelocate(pltRela[i].r_info, ptr, 1, pltRela[i].r_addend);
}
}
}
-
+
+ // Re-set readonly
+ for( i = 0; i < iSegmentCount; i ++ )
+ {
+ // If load and not writable
+ if(phtab[i].Type == PT_LOAD && !(phtab[i].Flags & PF_W) ) {
+ uintptr_t addr = phtab[i].VAddr + iBaseDiff;
+ uintptr_t end = addr + phtab[i].MemSize;
+ for( ; addr < end; addr += PAGE_SIZE )
+ _SysSetMemFlags(addr, 1, 1); // Unset RO
+ }
+ }
+
+ if( fail ) {
+ DEBUGS("ElfRelocate: Failure");
+ return NULL;
+ }
+
+ #undef _doRelocate
+
DEBUGS("ElfRelocate: RETURN 0x%x to %p", hdr->entrypoint + iBaseDiff, __builtin_return_address(0));
return (void*)(intptr_t)( hdr->entrypoint + iBaseDiff );
}
int i;
Elf64_Ehdr *hdr = Base;
Elf64_Phdr *phtab;
- Elf64_Dyn *dyntab;
+ Elf64_Dyn *dyntab = NULL;
Elf64_Addr compiledBase = -1, baseDiff;
Elf64_Sym *symtab = NULL;
char *strtab = NULL;
DEBUGS("Elf64Relocate: e_phnum = %i", hdr->e_phnum);
// Scan for the dynamic table (and find the compiled base)
- phtab = Base + hdr->e_phoff;
+ phtab = (void*)((uintptr_t)Base + (uintptr_t)hdr->e_phoff);
for( i = 0; i < hdr->e_phnum; i ++ )
{
if(phtab[i].p_type == PT_DYNAMIC)
}
// Relocation function
- void _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
+ auto int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend);
+ int _Elf64DoReloc(Elf64_Xword r_info, void *ptr, Elf64_Sxword addend)
{
int sym = ELF64_R_SYM(r_info);
int type = ELF64_R_TYPE(r_info);
const char *symname = strtab + symtab[sym].st_name;
+ void *symval;
+ //DEBUGS("_Elf64DoReloc: %s", symname);
switch( type )
{
case R_X86_64_NONE:
break;
case R_X86_64_64:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL) + addend;
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval + addend;
break;
case R_X86_64_COPY: {
size_t size;
- void *sym = GetSymbol(symname, &size);
- memcpy(ptr, sym, size);
+ if( !GetSymbol(symname, &symval, &size) ) return 1;
+ memcpy(ptr, symval, size);
} break;
case R_X86_64_GLOB_DAT:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval;
break;
case R_X86_64_JUMP_SLOT:
- *(uint64_t*)ptr = (uintptr_t)GetSymbol(symname, NULL);
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval;
break;
case R_X86_64_RELATIVE:
*(uint64_t*)ptr = (uintptr_t)Base + addend;
break;
default:
SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type);
- break;
+ return 2;
}
+ //DEBUGS("_Elf64DoReloc: - Good");
+ return 0;
}
+ int fail = 0;
if( rel )
{
DEBUGS("rel_count = %i", rel_count);
for( i = 0; i < rel_count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( rel[i].r_offset + baseDiff );
- _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
+ fail |= _Elf64DoReloc( rel[i].r_info, ptr, *ptr);
}
}
for( i = 0; i < rela_count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( rela[i].r_offset + baseDiff );
- _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
+ fail |= _Elf64DoReloc( rela[i].r_info, ptr, rela[i].r_addend );
}
}
for( i = 0; i < count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
- _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
+ fail |= _Elf64DoReloc( plt[i].r_info, ptr, *ptr);
}
}
else {
for( i = 0; i < count; i ++ )
{
uint64_t *ptr = (void *)(uintptr_t)( plt[i].r_offset + baseDiff );
- _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
+ fail |= _Elf64DoReloc( plt[i].r_info, ptr, plt[i].r_addend);
}
}
}
+ if( fail ) {
+ DEBUGS("Elf64Relocate: Failure");
+ return NULL;
+ }
+
{
void *ret = (void *)(uintptr_t)(hdr->e_entry + baseDiff);
DEBUGS("Elf64Relocate: Relocations done, return %p", ret);
int j;
// Locate the tables
- phtab = (void*)( (intptr_t)Base + hdr->e_phoff );
+ phtab = (void*)( (intptr_t)Base + (uintptr_t)hdr->e_phoff );
for( i = 0; i < hdr->e_phnum; i ++ )
{
if(phtab[i].p_type == PT_LOAD && iBaseDiff > phtab[i].p_vaddr)
extern uint32_t __udivsi3(uint32_t Num, uint32_t Den);
extern uint32_t __umodsi3(uint32_t Num, uint32_t Den);
-
#define _STR(x) #x
#define STR(x) _STR(x)
#define EXP(sym) {&sym, STR(sym)}
#define __ASSEMBLER__
#include "arch/syscalls.s.h"
#undef __ASSEMBLER__
+
+ #ifdef ARCHDIR_is_armv7
+ {0, "__gnu_Unwind_Find_exidx"},
+ {0, "__cxa_call_unexpected"},
+ {0, "__cxa_type_match"},
+ {0, "__cxa_begin_cleanup"},
+ #endif
#if 0
EXP(__umoddi3),
EXP(__udivdi3),
--- /dev/null
+/*
+ * Acess2 Dynamic Linker
+ * - By John Hodge (thePowersGang)
+ *
+ * acess/fd_set.h
+ * - fd_set structure used by select()
+ */
+#ifndef _ACESS__FD_SET_H_
+#define _ACESS__FD_SET_H_
+
+#define FD_SETSIZE 128
+
+typedef unsigned short fd_set_ent_t;
+
+/**
+ * \brief fd_set for select()
+ */
+typedef struct
+{
+ fd_set_ent_t flags[FD_SETSIZE/16];
+} fd_set;
+
+
+extern void FD_ZERO(fd_set *fdsetp);
+extern void FD_CLR(int fd, fd_set *fdsetp);
+extern void FD_SET(int fd, fd_set *fdsetp);
+extern int FD_ISSET(int fd, fd_set *fdsetp);
+
+#endif
+++ /dev/null
-/*
- */
-#ifndef _ACESS_INTDEFS_H_
-#define _ACESS_INTDEFS_H_
-
-#define INT_MIN -0x80000000
-#define INT_MAX 0x7FFFFFFF
-
-typedef unsigned char __uint8_t;
-typedef unsigned short __uint16_t;
-typedef unsigned int __uint32_t;
-typedef unsigned long long __uint64_t;
-
-typedef signed char __int8_t;
-typedef signed short __int16_t;
-typedef signed int __int32_t;
-typedef signed long long __int64_t;
-
-#if defined(ARCHDIR_is_x86)
-typedef __int32_t __intptr_t;
-typedef __uint32_t __uintptr_t;
-#elif defined(ARCHDIR_is_x86_64)
-typedef __int64_t __intptr_t;
-typedef __uint64_t __uintptr_t;
-#elif defined(ARCHDIR_is_armv7) | defined(ARCHDIR_is_armv6)
-typedef __int32_t __intptr_t;
-typedef __uint32_t __uintptr_t;
-#else
-# error "Unknown pointer size"
-#endif
-
-//typedef uint64_t off_t;
-
-#endif
-
#define _ACESS_SYS_H_
#include <stdint.h>
-#include "../sys/types.h"
+#include <stddef.h> // size_t
+#include "syscall_types.h"
// === CONSTANTS ===
#ifndef NULL
#define OPENFLAG_EXEC 0x01
#define OPENFLAG_READ 0x02
#define OPENFLAG_WRITE 0x04
+#define OPENFLAG_RDWR (OPENFLAG_READ|OPENFLAG_WRITE)
+#define OPENFLAG_TRUNCATE 0x10
+#define OPENFLAG_APPEND 0x20
#define OPENFLAG_NOLINK 0x40
#define OPENFLAG_CREATE 0x80
#ifndef SEEK_CUR
extern void _SysDebug(const char *format, ...);
// --- Proc ---
extern void _exit(int status) __attribute__((noreturn));
-extern void sleep(void);
-extern void yield(void);
-extern int kill(int pid, int sig);
-//extern void wait(int miliseconds);
+extern int _SysKill(int pid, int sig);
extern int _SysWaitEvent(int EventMask);
-extern int waittid(int id, int *status);
-extern int clone(int flags, void *stack);
-extern int execve(char *path, char **argv, char **envp);
-extern int _SysSpawn(const char *Path, const char **argv, const char **envp, int nFDs, int *FDs);
+extern int _SysWaitTID(int id, int *status);
+extern int _SysClone(int flags, void *stack);
+extern int _SysExecVE(const char *path, char **argv, char **envp);
+extern int _SysSpawn(const char *Path, const char **argv, const char **envp, int nFDs, int *FDs, struct s_sys_spawninfo *info);
extern int gettid(void);
extern int getpid(void);
extern int _SysSetFaultHandler(int (*Handler)(int));
-extern void SysSetName(const char *Name);
-extern int SysGetName(char *NameDest);
-extern int SysSetPri(int Priority);
+extern void _SysSetName(const char *Name);
+extern int _SysGetName(char *NameDest);
+extern int _SysSetPri(int Priority);
+// --- Timekeeping ---
extern int64_t _SysTimestamp(void);
// --- Permissions ---
extern void setgid(int id);
// --- VFS ---
-extern int chdir(const char *dir);
-extern int open(const char *path, int flags, ...);
-extern int reopen(int fd, const char *path, int flags);
-extern int close(int fd);
-extern uint read(int fd, void *buffer, uint length);
-extern uint write(int fd, const void *buffer, uint length);
-extern int seek(int fd, int64_t offset, int whence);
-extern uint64_t tell(int fd);
-extern int ioctl(int fd, int id, void *data);
-extern int finfo(int fd, t_sysFInfo *info, int maxacls);
-extern int SysReadDir(int fd, char *dest);
+extern int _SysChdir(const char *dir);
+extern int _SysChroot(const char *dir);
+
+extern int _SysOpen(const char *path, int flags, ...);
extern int _SysOpenChild(int fd, const char *name, int flags);
+extern int _SysOpenPipe(int *read, int *write, int flags);
+extern int _SysReopen(int fd, const char *path, int flags);
+extern int _SysCopyFD(int srcfd, int dstfd);
+extern size_t _SysRead(int fd, void *buffer, size_t length);
+extern int _SysClose(int fd);
+extern int _SysFDCtl(int fd, int option, ...);
+extern size_t _SysWrite(int fd, const void *buffer, size_t length);
+extern int _SysSeek(int fd, int64_t offset, int whence);
+extern uint64_t _SysTell(int fd);
+extern int _SysIOCtl(int fd, int id, void *data);
+extern int _SysFInfo(int fd, t_sysFInfo *info, int maxacls);
+extern int _SysReadDir(int fd, char *dest);
extern int _SysGetACL(int fd, t_sysACL *dest);
extern int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options);
extern int _SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *err, int64_t *timeout, unsigned int extraevents);
#define select(nfs, rdfds, wrfds, erfds, timeout) _SysSelect(nfs, rdfds, wrfds, erfds, timeout, 0)
+extern int _SysUnlink(const char *pathname);
// --- IPC ---
-extern int SysSendMessage(pid_t dest, uint length, const void *Data);
-extern int SysGetMessage(pid_t *src, void *Data);
+extern int _SysSendMessage(int dest, size_t length, const void *Data);
+extern int _SysGetMessage(int *src, size_t buflen, void *Data);
// --- MEMORY ---
-uint64_t _SysGetPhys(uint vaddr);
-uint64_t _SysAllocate(uint vaddr);
+extern uint64_t _SysGetPhys(uintptr_t vaddr);
+extern uint64_t _SysAllocate(uintptr_t vaddr);
+extern uint32_t _SysSetMemFlags(uintptr_t vaddr, uint32_t flags, uint32_t mask);
+extern void *_SysLoadBin(const char *path, void **entry);
+extern int _SysUnloadBin(void *base);
+extern void SysSetFaultHandler(int (*Hanlder)(int));
#endif
--- /dev/null
+/*
+ * Acess2 Dynamic Linker
+ * - By John Hodge (thePowersGang)
+ *
+ * acess/syscall_types.h
+ * - Structures used for syscalls
+ */
+#ifndef _ACESS__SYSCALL_TYPES_H_
+#define _ACESS__SYSCALL_TYPES_H_
+
+#include "fd_set.h"
+
+struct s_sysACL {
+ unsigned long object; /*!< Group or user (bit 31 determines) */
+ unsigned long perms; /*!< Inverted by bit 31 */
+};
+struct s_sysFInfo {
+ unsigned int mount;
+ unsigned long long inode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int flags;
+ unsigned long long size;
+ int64_t atime;
+ int64_t mtime;
+ int64_t ctime;
+ int numacls;
+ struct s_sysACL acls[];
+} __attribute__((packed));
+typedef struct s_sysFInfo t_sysFInfo;
+typedef struct s_sysACL t_sysACL;
+
+struct s_sys_spawninfo
+{
+ unsigned int flags;
+ unsigned int uid;
+ unsigned int gid;
+};
+
+#endif
+
+++ /dev/null
-#ifndef _STDDEF_H_
-#define _STDDEF_H_
-
-#include "acess/intdefs.h"
-
-#ifndef NULL
-# define NULL ((void*)0)
-#endif
-
-typedef __intptr_t size_t;
-
-#endif
--- /dev/null
+/*
+ * Acess2 Dynamic Linker
+ * - By John Hodge (thePowersGang)
+ *
+ * sys/param.h
+ * - System Parameters (?)
+ */
+#ifndef _SYS__PARAM_H_
+#define _SYS__PARAM_H_
+
+#endif
+
+++ /dev/null
-/*
- * Acess2 C Library
- * - By John Hodge (thePowersGang)
- */
-#ifndef _SYS_STAT_H_
-#define _SYS_STAT_H_
-
-#include "../acess/intdefs.h" /* Evil */
-#include "../stddef.h"
-
-;
-typedef void *dev_t; /* TODO: How to identify a device with Acess */
-typedef __uint64_t ino_t;
-typedef unsigned int blksize_t;
-typedef __uint64_t blkcnt_t;
-typedef unsigned int nlink_t;
-typedef __uint32_t mode_t;
-
-typedef __uint32_t uid_t;
-typedef __uint32_t gid_t;
-
-#define S_IFMT 0170000 /* type of file */
-#define S_IFDIR 0040000 /* directory */
-#define S_IFCHR 0020000 /* character special */
-#define S_IFBLK 0060000 /* block special */
-#define S_IFREG 0100000 /* regular */
-#define S_IFLNK 0120000 /* symbolic link */
-#define S_IFSOCK 0140000 /* socket */
-#define S_IFIFO 0010000 /* fifo */
-
-
-struct stat
-{
- dev_t st_dev; /* ID of device containing file */
- ino_t st_ino; /* inode number */
- mode_t st_mode; /* protection */
- nlink_t st_nlink; /* number of hard links */
- uid_t st_uid; /* user ID of owner */
- gid_t st_gid; /* group ID of owner */
- dev_t st_rdev; /* device ID (if special file) */
- off_t st_size; /* total size, in bytes */
- blksize_t st_blksize; /* blocksize for file system I/O */
- blkcnt_t st_blocks; /* number of 512B blocks allocated */
- time_t st_atime; /* time of last access */
- time_t st_mtime; /* time of last modification */
- time_t st_ctime; /* time of last status change */
-};
-
-extern int stat(const char *path, struct stat *buf);
-extern int fstat(int fd, struct stat *buf);
-
-#endif
+++ /dev/null
-/*\r
- Syscall Definitions\r
-*/\r
-#ifndef _SYS_SYS_H_\r
-#define _SYS_SYS_H_\r
-\r
-#include <acess/sys.h>\r
-\r
-#include <sys/types.h>\r
-\r
-#define O_RDONLY OPENFLAG_READ\r
-#define O_WRONLY OPENFLAG_WRITE\r
-#define O_CREAT (OPENFLAG_CREATE|OPENFLAG_WRITE)\r
-#define O_TRUNC OPENFLAG_WRITE\r
-#define O_APPEND OPENFLAG_WRITE\r
-\r
-\r
-#if 0\r
-#define OPEN_FLAG_READ 1\r
-#define OPEN_FLAG_WRITE 2\r
-#define OPEN_FLAG_EXEC 4\r
-\r
-enum {\r
- K_WAITPID_DIE = 0\r
-};\r
-\r
-// === System Calls ===\r
-extern void _exit(int ret);\r
-extern int brk(int bssend);\r
-extern int execve(char *file, char *args[], char *envp[]);\r
-extern int fork();\r
-extern int yield();\r
-extern int sleep();\r
-\r
-extern int open(char *file, int flags);\r
-extern int close(int fp);\r
-extern int read(int fp, int len, void *buf);\r
-extern int write(int fp, int len, void *buf);\r
-extern int tell(int fp);\r
-extern void seek(int fp, int64_t dist, int flag);\r
-extern int fstat(int fp, t_fstat *st);\r
-extern int ioctl(int fp, int call, void *arg);\r
-extern int readdir(int fp, char *file);\r
-\r
-extern int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errfds, time_t *timeout);\r
-\r
-extern int kdebug(char *fmt, ...);\r
-extern int waitpid(int pid, int action);\r
-extern int gettid(); // Get Thread ID\r
-extern int getpid(); // Get Process ID\r
-extern int sendmsg(int dest, unsigned int *Data);\r
-extern int pollmsg(int *src, unsigned int *Data);\r
-extern int getmsg(int *src, unsigned int *Data);\r
-#endif\r
-\r
-#endif\r
+++ /dev/null
-/*
- */
-#ifndef _SYS_TYPES_H
-#define _SYS_TYPES_H
-
-#include "../acess/intdefs.h"
-
-typedef struct stat t_fstat;
-
-#define FD_SETSIZE 128
-
-
-#define CLONE_VM 0x10
-
-typedef unsigned long pid_t;
-typedef unsigned long tid_t;
-typedef signed long long int time_t;
-typedef long long int off_t;
-
-typedef unsigned int uint;
-
-typedef unsigned short fd_set_ent_t;
-
-/**
- * \brief fd_set for select()
- */
-typedef struct
-{
- fd_set_ent_t flags[FD_SETSIZE/16];
-} fd_set;
-
-struct s_sysACL {
- unsigned long object; /*!< Group or user (bit 31 determines) */
- unsigned long perms; /*!< Inverted by bit 31 */
-};
-struct s_sysFInfo {
- unsigned int mount;
- unsigned long long inode;
- unsigned int uid;
- unsigned int gid;
- unsigned int flags;
- unsigned long long size;
- time_t atime;
- time_t mtime;
- time_t ctime;
- int numacls;
- struct s_sysACL acls[];
-} __attribute__((packed));
-typedef struct s_sysFInfo t_sysFInfo;
-typedef struct s_sysACL t_sysACL;
-
-extern void FD_ZERO(fd_set *fdsetp);
-extern void FD_CLR(int fd, fd_set *fdsetp);
-extern void FD_SET(int fd, fd_set *fdsetp);
-extern int FD_ISSET(int fd, fd_set *fdsetp);
-
-typedef __uint8_t u_int8_t;
-typedef __uint16_t u_int16_t;
-typedef __uint32_t u_int32_t;
-
-#include "../sys/stat.h"
-
-#endif
+++ /dev/null
-#ifndef _UNISTD_H_
-#define _UNISTD_H_
-
-#define O_RDWR (OPENFLAG_READ|OPENFLAG_WRITE)
-#define O_WR (OPENFLAG_WRITE)
-#define O_RD (OPENFLAG_READ)
-#define O_CREAT (OPENFLAG_CREATE)
-
-#include "acess/sys.h"
-
-
-#endif
-
int file_exists(const char *filename)
{
int fd;
- //fd = open(filename, OPENFLAG_READ);
- fd = open(filename, 0);
+ fd = _SysOpen(filename, 0);
if(fd == -1) return 0;
- close(fd);
+ _SysClose(fd);
return 1;
}
*/
#include "common.h"
#include <stdint.h>
+#include <acess/sys.h>
#define DEBUG 0
// === PROTOTYPES ===
void *IsFileLoaded(const char *file);
- int GetSymbolFromBase(void *base, const char *name, void **ret, size_t *size);
// === IMPORTS ===
extern const struct {
DEBUGS(" LoadLibrary: SysLoadBin()");
// Load Library
- base = SysLoadBin(filename, (void**)&fEntry);
+ base = _SysLoadBin(filename, (void**)&fEntry);
if(!base) {
DEBUGS("LoadLibrary: RETURN 0");
return 0;
// Load Symbols
fEntry = DoRelocate( base, envp, filename );
+ if( !fEntry ) {
+ return 0;
+ }
// Call Entrypoint
DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
if(id == MAX_LOADED_LIBRARIES) return;
// Unload Binary
- SysUnloadBin( Base );
+ _SysUnloadBin( Base );
// Save String Pointer
str = gLoadedLibraries[id].Name;
\fn Uint GetSymbol(const char *name)
\brief Gets a symbol value from a loaded library
*/
-void *GetSymbol(const char *name, size_t *Size)
+int GetSymbol(const char *name, void **Value, size_t *Size)
{
int i;
- void *ret;
//SysDebug("ciNumLocalExports = %i", ciNumLocalExports);
for(i=0;i<ciNumLocalExports;i++)
{
- if( strcmp(caLocalExports[i].Name, name) == 0 )
- return caLocalExports[i].Value;
+ if( strcmp(caLocalExports[i].Name, name) == 0 ) {
+ *Value = caLocalExports[i].Value;
+ if(Size)
+ *Size = 0;
+ return 1;
+ }
}
// Entry 0 is ld-acess, ignore it
for(i = 1; i < MAX_LOADED_LIBRARIES; i ++)
{
- if(gLoadedLibraries[i].Base == 0) break;
+ if(gLoadedLibraries[i].Base == 0)
+ break;
//SysDebug(" GetSymbol: Trying 0x%x, '%s'",
// gLoadedLibraries[i].Base, gLoadedLibraries[i].Name);
- if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, &ret, Size)) return ret;
+ if(GetSymbolFromBase(gLoadedLibraries[i].Base, name, Value, Size))
+ return 1;
}
SysDebug("GetSymbol: === Symbol '%s' not found ===", name);
return 0;
#endif\r
for(;;);\r
}\r
+\r
+void abort(void)\r
+{\r
+ _exit(-4);\r
+}\r
#define _AXWIN3_AXWIN_H_
#include <stddef.h> // size_t
+#include <unistd.h>
// === CONSTANTS ===
extern void AxWin3_Connect(const char *ServerDesc);
extern tAxWin3_MessageCallback AxWin3_SetMessageCallback(tAxWin3_MessageCallback Callback);
extern void AxWin3_MainLoop(void);
+extern void AxWin3_MessageSelect(int nFD, fd_set *FDs);
// --- Non-Window based functions
extern int AxWin3_GetDisplayCount(void);
--- /dev/null
+/*
+ * Acess2 GUI Version 3 (AxWin3)
+ * - By John Hodge (thePowersGang)
+ *
+ * richtext.h
+ * - Rich Text line editor
+ */
+#ifndef _AXWIN3_RICHTEXT_H_
+#define _AXWIN3_RICHTEXT_H_
+
+#include <stdint.h>
+
+typedef int (*tAxWin3_RichText_KeyHandler)(tHWND Window, int bPress, uint32_t Sym, uint32_t Unicode);
+typedef int (*tAxWin3_RichText_MouseHandler)(tHWND Window, int bPress, int Button, int Row, int Col);
+typedef int (*tAxWin3_RichText_LineHandler)(tHWND Window, int Row);
+
+#define AXWIN3_RICHTEXT_NOSCROLL 0x0001 // Disables server-side scrolling
+#define AXWIN3_RICHTEXT_READONLY 0x0002 // Disables automatic insertion of translated characters
+enum eAxWin3_RichText_CursorType {
+ AXWIN3_RICHTEXT_CURSOR_NONE,
+ AXWIN3_RICHTEXT_CURSOR_VLINE, // Vertical line
+ AXWIN3_RICHTEXT_CURSOR_ULINE, // Underline
+ AXWIN3_RICHTEXT_CURSOR_INV, // Inverted
+};
+
+extern tHWND AxWin3_RichText_CreateWindow(tHWND Parent, int Flags);
+extern void AxWin3_RichText_SetKeyHandler(tHWND Window, tAxWin3_RichText_KeyHandler Handler);
+extern void AxWin3_RichText_SetMouseHandler(tHWND Window, tAxWin3_RichText_MouseHandler Handler);
+/**
+ * \brief Sets the function called when the server requests an update on a line's contents
+ */
+extern void AxWin3_RichText_SetLineHandler(tHWND Window, tAxWin3_RichText_LineHandler Handler);
+extern void AxWin3_RichText_EnableScroll(tHWND Window, int bEnable);
+extern void AxWin3_RichText_SetLineCount(tHWND Window, int Lines);
+extern void AxWin3_RichText_SetColCount(tHWND Window, int Cols);
+extern void AxWin3_RichText_SetBackground(tHWND Window, uint32_t ARGB_Colour);
+extern void AxWin3_RichText_SetDefaultColour(tHWND Window, uint32_t ARGB_Colour);
+extern void AxWin3_RichText_SetFont(tHWND Window, const char *FontName, int PointSize);
+extern void AxWin3_RichText_SetCursorType(tHWND Window, int Type);
+extern void AxWin3_RichText_SetCursorBlink(tHWND Window, int bBlink);
+extern void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column);
+extern void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text);
+
+#endif
+
// --- Element Creation
extern tAxWin3_Widget *AxWin3_Widget_AddWidget(tAxWin3_Widget *Parent, int Type, int Flags, const char *DebugName);
+extern tAxWin3_Widget *AxWin3_Widget_AddWidget_SubWindow(tAxWin3_Widget *Parent, tHWND Window, int Flags, const char *DebugName);
extern void AxWin3_Widget_DelWidget(tAxWin3_Widget *Widget);
// --- Callbacks
-include ../Makefile.cfg\r
\r
CPPFLAGS += \r
-CFLAGS += \r
+CFLAGS += -Werror -Wextra\r
ASFLAGS +=\r
-LDFLAGS += -soname libc.so -Map map.txt -lgcc\r
+LDFLAGS += -soname libc.so -Map map.txt\r
\r
INCFILES := stdio.h stdlib.h\r
\r
-OBJ = stub.o heap.o stdlib.o env.o fileIO.o string.o select.o rand.o\r
+OBJ = stub.o heap.o stdlib.o env.o stdio.o string.o select.o rand.o\r
+OBJ += perror.o scanf.o signals.o strtoi.o\r
OBJ += arch/$(ARCHDIR).ao\r
# signals.o\r
DEPFILES := $(OBJ:%.o=%.d)\r
+++ /dev/null
-/*\r
- * AcessOS Basic C Library\r
- * stdio.c\r
- */\r
-#include "config.h"\r
-#include <acess/sys.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include "lib.h"\r
-#include "stdio_int.h"\r
-\r
-#define WRITE_STR(_fd, _str) write(_fd, _str, sizeof(_str))\r
-\r
-#define DEBUG_BUILD 0\r
-\r
-// === CONSTANTS ===\r
-#define _stdin 0\r
-#define _stdout 1\r
-\r
-// === PROTOTYPES ===\r
-EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned);\r
-struct sFILE *get_file_struct();\r
-\r
-// === GLOBALS ===\r
-struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer\r
-struct sFILE *stdin; // Standard Input\r
-struct sFILE *stdout; // Standard Output\r
-struct sFILE *stderr; // Standard Error\r
-///\note Initialised in SoMain\r
-\r
-// === CODE ===\r
-/**\r
- * \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
- */\r
-EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
-{\r
- int openFlags = 0;\r
- int i;\r
- \r
- // Sanity Check Arguments\r
- if(!fp || !file || !mode) return NULL;\r
- \r
- if(fp->Flags) {\r
- fflush(fp);\r
- } else\r
- fp->FD = -1;\r
- \r
- // Get main mode\r
- switch(mode[0])\r
- {\r
- case 'r': fp->Flags = FILE_FLAG_MODE_READ; break;\r
- case 'w': fp->Flags = FILE_FLAG_MODE_WRITE; break;\r
- case 'a': fp->Flags = FILE_FLAG_MODE_APPEND; break;\r
- case 'x': fp->Flags = FILE_FLAG_MODE_EXEC; break;\r
- default:\r
- return NULL;\r
- }\r
- // Get Modifiers\r
- for(i=1;mode[i];i++)\r
- {\r
- switch(mode[i])\r
- {\r
- case '+': fp->Flags |= FILE_FLAG_M_EXT;\r
- }\r
- }\r
- \r
- // Get Open Flags\r
- switch(mode[0])\r
- {\r
- // Read\r
- case 'r': openFlags = OPENFLAG_READ;\r
- if(fp->Flags & FILE_FLAG_M_EXT)\r
- openFlags |= OPENFLAG_WRITE;\r
- break;\r
- // Write\r
- case 'w': openFlags = OPENFLAG_WRITE;\r
- if(fp->Flags & FILE_FLAG_M_EXT)\r
- openFlags |= OPENFLAG_READ;\r
- break;\r
- // Execute\r
- case 'x': openFlags = OPENFLAG_EXEC;\r
- break;\r
- }\r
-\r
- //Open File\r
- if(fp->FD != -1)\r
- fp->FD = reopen(fp->FD, file, openFlags);\r
- else\r
- fp->FD = open(file, openFlags);\r
- if(fp->FD == -1) {\r
- fp->Flags = 0;\r
- return NULL;\r
- }\r
- \r
- if(mode[0] == 'a') {\r
- seek(fp->FD, 0, SEEK_END); //SEEK_END\r
- }\r
- \r
- return fp;\r
-}\r
-/**\r
- \fn FILE *fopen(const char *file, const char *mode)\r
- \brief Opens a file and returns the pointer\r
- \param file String - Filename to open\r
- \param mode Mode to open in\r
-*/\r
-EXPORT FILE *fopen(const char *file, const char *mode)\r
-{\r
- FILE *retFile;\r
- \r
- // Sanity Check Arguments\r
- if(!file || !mode) return NULL;\r
- \r
- // Create Return Structure\r
- retFile = get_file_struct();\r
- \r
- return freopen(file, mode, retFile);\r
-}\r
-\r
-EXPORT int fclose(FILE *fp)\r
-{\r
- close(fp->FD);\r
- fp->Flags = 0;\r
- fp->FD = -1;\r
- return 0;\r
-}\r
-\r
-EXPORT void fflush(FILE *fp)\r
-{\r
- ///\todo Implement\r
-}\r
-\r
-EXPORT off_t ftell(FILE *fp)\r
-{\r
- if(!fp || !fp->FD) return -1;\r
- \r
- return tell(fp->FD);\r
-}\r
-\r
-EXPORT int fseek(FILE *fp, long int amt, int whence)\r
-{\r
- if(!fp || !fp->FD) return -1;\r
- \r
- return seek(fp->FD, amt, whence);\r
-}\r
-\r
-\r
-/**\r
- * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
- * \brief Print to a file from a variable argument list\r
- */\r
-EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
-{\r
- va_list tmpList;\r
- int size;\r
-\r
- if(!fp || !format) return -1;\r
-\r
- va_copy(tmpList, args);\r
- \r
- size = vsnprintf(NULL, 0, (char*)format, tmpList);\r
- char buf[size+1];\r
- vsnprintf(buf, size+1, (char*)format, args);\r
- \r
- // Write to stream\r
- write(fp->FD, buf, size);\r
- \r
- // Free buffer\r
- free(buf);\r
- \r
- // Return written byte count\r
- return size;\r
-}\r
-\r
-/**\r
- * \fn int fprintf(FILE *fp, const char *format, ...)\r
- * \brief Print a formatted string to a stream\r
- */\r
-EXPORT int fprintf(FILE *fp, const char *format, ...)\r
-{\r
- va_list args;\r
- int ret;\r
- \r
- // Get Size\r
- va_start(args, format);\r
- ret = vfprintf(fp, (char*)format, args);\r
- va_end(args);\r
- \r
- return ret;\r
-}\r
-\r
-/**\r
- * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
- * \brief Write to a stream\r
- */\r
-EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
-{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
- \r
- ret = write(fp->FD, ptr, size*num);\r
- \r
- return ret;\r
-}\r
-\r
-/**\r
- * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
- * \brief Read from a stream\r
- */\r
-EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
-{\r
- int ret;\r
- if(!fp || !fp->FD) return -1;\r
-\r
- // TODO: Fit the spec better with the return value \r
- ret = read(fp->FD, ptr, size*num);\r
- \r
- return ret;\r
-}\r
-\r
-/**\r
- * \fn EXPORT int fputc(int c, FILE *fp)\r
- * \brief Write a single character to the stream\r
- */\r
-EXPORT int fputc(int c, FILE *fp)\r
-{\r
- if(!fp || !fp->FD) return -1;\r
- return write(fp->FD, &c, 1);\r
-}\r
-\r
-EXPORT int putchar(int c)\r
-{\r
- c &= 0xFF;\r
- return write(_stdout, &c, 1);\r
-}\r
-\r
-/**\r
- * \fn EXPORT int fgetc(FILE *fp)\r
- * \brief Read a character from the stream\r
- */\r
-EXPORT int fgetc(FILE *fp)\r
-{\r
- char ret = 0;\r
- if(!fp) return -1;\r
- if(read(fp->FD, &ret, 1) == -1) return -1;\r
- return ret;\r
-}\r
-\r
-EXPORT int getchar(void)\r
-{\r
- char ret = 0;\r
- if(read(_stdin, &ret, 1) != 1) return -1;\r
- return ret;\r
-}\r
-\r
-// --- INTERNAL ---\r
-/**\r
- * \fn FILE *get_file_struct()\r
- * \brief Returns a file descriptor structure\r
- */\r
-FILE *get_file_struct()\r
-{\r
- int i;\r
- for(i=0;i<STDIO_MAX_STREAMS;i++)\r
- {\r
- if(_iob[i].Flags == 0) return &_iob[i];\r
- }\r
- return NULL;\r
-}\r
-\r
-EXPORT int puts(const char *str)\r
-{\r
- int len;\r
- \r
- if(!str) return 0;\r
- len = strlen(str);\r
- \r
- len = write(_stdout, str, len);\r
- write(_stdout, "\n", 1);\r
- return len;\r
-}\r
-\r
-EXPORT int vsprintf(char * __s, const char *__format, va_list __args)\r
-{\r
- return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
-}\r
-\r
-//sprintfv\r
-/**\r
- * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
- * \brief Prints a formatted string to a buffer\r
- * \param buf Pointer - Destination Buffer\r
- * \param format String - Format String\r
- * \param args VarArgs List - Arguments\r
- */\r
-EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)\r
-{\r
- char tmp[65];\r
- int c, minSize, precision, len;\r
- int pos = 0;\r
- char *p;\r
- char pad;\r
- uint64_t arg;\r
- int bLongLong, bPadLeft;\r
-\r
- void _addchar(char ch)\r
- {\r
- if(buf && pos < __maxlen) buf[pos] = ch;\r
- pos ++;\r
- }\r
-\r
- tmp[32] = '\0';\r
- \r
- while((c = *format++) != 0)\r
- {\r
- // Non-control character\r
- if (c != '%') {\r
- _addchar(c);\r
- continue;\r
- }\r
- \r
- // Control Character\r
- c = *format++;\r
- if(c == '%') { // Literal %\r
- _addchar('%');\r
- continue;\r
- }\r
- \r
- bPadLeft = 0;\r
- bLongLong = 0;\r
- minSize = 0;\r
- precision = -1;\r
- pad = ' ';\r
- \r
- // Padding Character\r
- if(c == '0') {\r
- pad = '0';\r
- c = *format++;\r
- }\r
- // Padding length\r
- if( c == '*' ) {\r
- // Variable length\r
- minSize = va_arg(args, size_t);\r
- c = *format++;\r
- }\r
- else {\r
- if('1' <= c && c <= '9')\r
- {\r
- minSize = 0;\r
- while('0' <= c && c <= '9')\r
- {\r
- minSize *= 10;\r
- minSize += c - '0';\r
- c = *format++;\r
- }\r
- }\r
- }\r
-\r
- // Precision\r
- if(c == '.') {\r
- c = *format++;\r
- if(c == '*') {\r
- precision = va_arg(args, size_t);\r
- c = *format++;\r
- }\r
- else if('1' <= c && c <= '9')\r
- {\r
- precision = 0;\r
- while('0' <= c && c <= '9')\r
- {\r
- precision *= 10;\r
- precision += c - '0';\r
- c = *format++;\r
- }\r
- }\r
- }\r
- \r
- // Check for long long\r
- bLongLong = 0;\r
- if(c == 'l')\r
- {\r
- c = *format++;\r
- if(c == 'l') {\r
- bLongLong = 1;\r
- }\r
- }\r
- \r
- // Just help things along later\r
- p = tmp;\r
- \r
- // Get Type\r
- switch( c )\r
- {\r
- // Signed Integer\r
- case 'd': case 'i':\r
- // Get Argument\r
- if(bLongLong) arg = va_arg(args, int64_t);\r
- else arg = va_arg(args, int32_t);\r
- itoa(tmp, arg, 10, minSize, pad, 1);\r
- precision = -1;\r
- goto sprintf_puts;\r
- \r
- // Unsigned Integer\r
- case 'u':\r
- // Get Argument\r
- if(bLongLong) arg = va_arg(args, uint64_t);\r
- else arg = va_arg(args, uint32_t);\r
- itoa(tmp, arg, 10, minSize, pad, 0);\r
- precision = -1;\r
- goto sprintf_puts;\r
- \r
- // Pointer\r
- case 'p':\r
- _addchar('*');\r
- _addchar('0');\r
- _addchar('x');\r
- arg = va_arg(args, intptr_t);\r
- itoa(tmp, arg, 16, minSize, pad, 0);\r
- precision = -1;\r
- goto sprintf_puts;\r
- // Unsigned Hexadecimal\r
- case 'x':\r
- if(bLongLong) arg = va_arg(args, uint64_t);\r
- else arg = va_arg(args, uint32_t);\r
- itoa(tmp, arg, 16, minSize, pad, 0);\r
- precision = -1;\r
- goto sprintf_puts;\r
- \r
- // Unsigned Octal\r
- case 'o':\r
- if(bLongLong) arg = va_arg(args, uint64_t);\r
- else arg = va_arg(args, uint32_t);\r
- itoa(tmp, arg, 8, minSize, pad, 0);\r
- precision = -1;\r
- goto sprintf_puts;\r
- \r
- // Unsigned binary\r
- case 'b':\r
- if(bLongLong) arg = va_arg(args, uint64_t);\r
- else arg = va_arg(args, uint32_t);\r
- itoa(tmp, arg, 2, minSize, pad, 0);\r
- precision = -1;\r
- goto sprintf_puts;\r
-\r
- // String\r
- case 's':\r
- p = va_arg(args, char*);\r
- sprintf_puts:\r
- if(!p) p = "(null)";\r
- //_SysDebug("vsnprintf: p = '%s'", p);\r
- if(precision >= 0)\r
- len = strnlen(p, precision);\r
- else\r
- len = strlen(p);\r
- if(bPadLeft) while(minSize > len++) _addchar(pad);\r
- while( *p ) {\r
- if(precision >= 0 && precision -- == 0)\r
- break;\r
- _addchar(*p++);\r
- }\r
- if(!bPadLeft) while(minSize > len++) _addchar(pad);\r
- break;\r
-\r
- // Unknown, just treat it as a character\r
- default:\r
- arg = va_arg(args, uint32_t);\r
- _addchar(arg);\r
- break;\r
- }\r
- }\r
- _addchar('\0');\r
- pos --;\r
- \r
- //_SysDebug("vsnprintf: buf = '%s'", buf);\r
- \r
- return pos;\r
-}\r
-\r
-const char cUCDIGITS[] = "0123456789ABCDEF";\r
-/**\r
- * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
- * \brief Convert an integer into a character string\r
- * \param buf Destination Buffer\r
- * \param num Number to convert\r
- * \param base Base-n number output\r
- * \param minLength Minimum length of output\r
- * \param pad Padding used to ensure minLength\r
- * \param bSigned Signed number output?\r
- */\r
-EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)\r
-{\r
- char tmpBuf[64];\r
- int pos=0, i;\r
-\r
- if(!buf) return;\r
- if(base > 16 || base < 2) {\r
- buf[0] = 0;\r
- return;\r
- }\r
- \r
- if(bSigned && (int64_t)num < 0)\r
- {\r
- num = -num;\r
- bSigned = 1;\r
- } else\r
- bSigned = 0;\r
- \r
- // Encode into reversed string\r
- while(num > base-1) {\r
- tmpBuf[pos++] = cUCDIGITS[ num % base ];\r
- num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit\r
- }\r
-\r
- tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}\r
- if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed\r
- \r
- i = 0;\r
- minLength -= pos;\r
- while(minLength-- > 0) buf[i++] = pad;\r
- while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters\r
- buf[i] = 0;\r
-}\r
-\r
-/**\r
- * \fn EXPORT int printf(const char *format, ...)\r
- * \brief Print a string to stdout\r
- */\r
-EXPORT int printf(const char *format, ...)\r
-{\r
- #if 1\r
- int size;\r
- va_list args;\r
- \r
- // Get final size\r
- va_start(args, format);\r
- size = vsnprintf(NULL, 0, (char*)format, args);\r
- va_end(args);\r
- char buf[size+1];\r
- // Fill Buffer\r
- va_start(args, format);\r
- vsnprintf(buf, size+1, (char*)format, args);\r
- va_end(args);\r
- \r
- // Send to stdout\r
- write(_stdout, buf, size+1);\r
- \r
- // Free buffer\r
- free(buf);\r
- // Return\r
- return size;\r
- \r
- #else\r
- \r
- int ret;\r
- va_list args;\r
- va_start(args, format);\r
- ret = fprintfv(stdout, (char*)format, args);\r
- va_end(args);\r
- return ret;\r
- #endif\r
-}\r
-\r
-/**\r
- * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
- * \brief Print a formatted string to a buffer\r
- */\r
-EXPORT int sprintf(char *buf, const char *format, ...)\r
-{\r
- int ret;\r
- va_list args;\r
- va_start(args, format);\r
- ret = vsprintf((char*)buf, (char*)format, args);\r
- va_end(args);\r
- return ret;\r
-}\r
-\r
-/**\r
- * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)\r
- * \brief Print a formatted string to a buffer\r
- */\r
-EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)\r
-{\r
- int ret;\r
- va_list args;\r
- va_start(args, format);\r
- ret = vsnprintf((char*)buf, maxlen, (char*)format, args);\r
- va_end(args);\r
- return ret;\r
-}\r
DEBUGS("free(%p) : 0x%x bytes", mem, head->size);\r
\r
//Unify Right\r
- if((intptr_t)head + head->size < (intptr_t)_heap_end)\r
+ if((uintptr_t)head + head->size < (uintptr_t)_heap_end)\r
{\r
heap_head *nextHead = (heap_head*)((intptr_t)head + head->size);\r
if(nextHead->magic == MAGIC_FREE) { //Is the next block free\r
}\r
}\r
//Unify Left\r
- if((intptr_t)head - sizeof(heap_foot) > (intptr_t)_heap_start)\r
+ if((uintptr_t)head - sizeof(heap_foot) > (uintptr_t)_heap_start)\r
{\r
heap_head *prevHead;\r
heap_foot *prevFoot = (heap_foot *)((intptr_t)head - sizeof(heap_foot));\r
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * assert.h
+ * - assert(expr)
+ */
+#ifndef _LIBC__ASSERT_H_
+#define _LIBC__ASSERT_H_
+
+#ifdef NDEBUG
+# define assert(expr) do{}while(0)
+#else
+# define assert(expr) do{if(!(expr)) { fprintf(stderr, "%s:%i: Assertion '%s' failed\n", __FILE__, __LINE__, #expr); exit(-1);}}while(0)
+#endif
+
+#endif
+
if(ch == '\n') return 1;
return 0;
}
+// C99
+static inline int isblank(int ch) {
+ if(ch == ' ') return 1;
+ if(ch == '\t') return 1;
+ return 0;
+}
#endif
--- /dev/null
+
+enum {
+ EOK,
+ ENOSYS, // Invalid Instruction
+ EINVAL, // Invalid Paramater
+ ENOMEM, // No free memory
+ EACCES, // Not permitted
+ EBUSY, // Resource is busy
+ ERANGE, // Value out of range
+ ENOTFOUND, // Item not found
+ EREADONLY, // Read only
+ ENOTIMPL, // Not implemented
+ ENOENT, // No entry?
+ EEXIST, // Already exists
+ ENFILE, // Too many open files
+ ENOTDIR, // Not a directory
+ EIO, // IO Error
+ EINTR, // Operation interrupted (signal)
+
+ EALREADY, // Operation was a NOP
+ EINTERNAL, // Internal Error
+
+ NUM_ERRNO
+};
+
#define strerror(_x) "Unimplemented"
-enum
-{
- EOK,
- EINVAL,
- ERANGE,
- ENODEV,
- EBADF,
- EINTR,
- EAGAIN,
- ENOMEM,
-
- EADDRNOTAVAIL,
- EINPROGRESS,
-
- E_LAST
-};
+#include "errno.enum.h"
#endif
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
+typedef void (*sighandler_t)(int);
+
#define SIG_DFL ((void*)0)
#define SIG_ERR ((void*)-1)
#define SIGPIPE 1001
#define SIGCHLD 1002
+extern int raise(int sig);
+
#endif
extern int vsprintf(char *buf, const char *format, va_list args);
extern int sprintf(char *buf, const char *format, ...);
extern int snprintf(char *buf, size_t maxlen, const char *format, ...);
+extern void perror(const char *s);
extern FILE *fopen(const char *file, const char *mode);
extern FILE *freopen(const char *file, const char *mode, FILE *fp);
extern void fflush(FILE *fp);
extern off_t ftell(FILE *fp);
extern int fseek(FILE *fp, long int amt, int whence);
+extern void clearerr(FILE *stream);
+extern int feof(FILE *stream);
+extern int ferror(FILE *stream);
+extern int fileno(FILE *stream);
extern size_t fread(void *buf, size_t size, size_t n, FILE *fp);
extern size_t fwrite(void *buf, size_t size, size_t n, FILE *fp);
extern int fprintf(FILE *fp, const char *format, ...);
extern int vfprintf(FILE *fp, const char *format, va_list args);
+// scanf
+extern int scanf(const char *format, ...);
+extern int fscanf(FILE *stream, const char *format, ...);
+extern int sscanf(const char *str, const char *format, ...);
+extern int vscanf(const char *format, va_list ap);
+extern int vsscanf(const char *str, const char *format, va_list ap);
+extern int vfscanf(FILE *stream, const char *format, va_list ap);
+
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
\r
/* --- StdLib --- */\r
extern void _exit(int code) __attribute__((noreturn)); /* NOTE: Also defined in acess/sys.h */\r
+\r
extern long long strtoll(const char *ptr, char **end, int base);\r
extern long strtol(const char *ptr, char **end, int base);\r
+extern unsigned long long strtoull(const char *ptr, char **end, int base);\r
+extern unsigned long strtoul(const char *ptr, char **end, int base);\r
extern int atoi(const char *ptr);\r
extern void exit(int status) __attribute__((noreturn));\r
+extern void abort(void);\r
extern void atexit(void (*__func)(void));\r
extern void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));\r
extern int abs(int j);\r
#define LOCAL\r
#endif\r
\r
+#define UNUSED(type, param) __attribute__((unused)) type UNUSED__##param\r
+\r
extern void *memcpy(void *dest, const void *src, size_t n);\r
\r
typedef struct sCPUID tCPUID;\r
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * perror.c
+ * - perror() and friends
+ */
+#include <errno.h>
+#include <stdio.h>
+
+void perror(const char *s)
+{
+ fprintf(stderr, "%s: Error (%i)\n", s, errno);
+}
# Variables
SRCS := stub.c heap.c stdlib.c env.c fileIO.c string.c select.c
+SRCS += perror.c
SRCS += arch/$(ARCHDIR).$(ASSUFFIX)
# signals.c
BIN := $(OUTPUTDIR)Libs/libc.so
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * scanf.c
+ * - *scanf family of functions
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+
+extern void _SysDebug(const char *format, ...);
+
+enum e_vcscanf_types
+{
+ _VCSCANF_NOTYPE,
+ _VCSCANF_INT,
+ _VCSCANF_REAL,
+};
+
+enum e_vcscanf_sizes
+{
+ _VCSCANF_UNDEF,
+ _VCSCANF_CHAR,
+ _VCSCANF_SHORT,
+ _VCSCANF_LONG,
+ _VCSCANF_LONGLONG,
+ _VCSCANF_INTMAX,
+ _VCSCANF_SIZET,
+ _VCSCANF_PTRDIFF,
+ _VCSCANF_LONGDOUBLE
+};
+
+// === CODE ===
+int _vcscanf_int(int (*__getc)(void *), void (*__rewind)(void*), void *h, int base, int maxlen, long long *outval)
+{
+ char ich;
+ int sgn = 1;
+ long long int ret = 0;
+ int n_read = 0;
+
+ // Initialise output to something sane
+ *outval = 0;
+
+ // First character
+ // - maxlen == 0 means no limit
+ ich = __getc(h);
+ n_read ++;
+
+ // Sign?
+ if( ich == '-' || ich == '+' ) {
+ sgn = (ich == '-' ? -1 : 1);
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ }
+
+ // Determine base
+ if( base == 0 ) {
+ if( ich != '0' ) {
+ base = 10;
+ }
+ else {
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ if( ich != 'x' ) {
+ base = 8;
+ }
+ else {
+ base = 16;
+ if( n_read == maxlen )
+ return n_read;
+ ich = __getc(h);
+ n_read ++;
+ }
+ }
+ }
+
+ if( ich == 0 ) {
+ // Oops?
+ return n_read;
+ }
+
+ while( ich )
+ {
+ int next = -1;
+
+ // Get the digit value
+ if( base <= 10 ) {
+ if( '0' <= ich && ich <= '0'+base-1 )
+ next = ich - '0';
+ }
+ else {
+ if( '0' <= ich && ich <= '9' )
+ next = ich - '0';
+ if( 'A' <= ich && ich <= 'A'+base-10-1 )
+ next = ich - 'A' + 10;
+ if( 'a' <= ich && ich <= 'a'+base-10-1 )
+ next = ich - 'a' + 10;
+ }
+ // if it's not a digit, rewind and break
+ if( next < 0 ) {
+ __rewind(h);
+ n_read --;
+ break;
+ }
+
+ // Add to the result
+ ret *= base;
+ ret += next;
+ //_SysDebug("- %i/%i read, 0x%x val", n_read, maxlen, ret);
+
+ // Check if we've reached the limit
+ if( n_read == maxlen )
+ break ;
+
+ // Next character
+ ich = __getc(h);
+ n_read ++;
+ }
+
+ // Apply sign
+ if( sgn == -1 )
+ ret = -ret;
+
+ *outval = ret;
+ return n_read;
+}
+
+int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char *format, va_list ap)
+{
+ char fch, ich;
+ int ret = 0, nch = 0;
+
+ while( (fch = *format++) )
+ {
+ union {
+ void *_void;
+ char *_char;
+ short *_short;
+ int *_int;
+ long *_long;
+ long long *_longlong;
+ } ptr;
+ long long ival;
+ //long double rval;
+ int maxlen = 0, offset = -1;
+ enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
+ enum e_vcscanf_types valtype;
+
+ const char *set_start;
+ int set_len;
+
+ // Whitespace matches any ammount of whitespace (including none)
+ if( isspace(fch) )
+ {
+ while( (ich = __getc(h)) && isspace(ich) )
+ nch ++;
+ continue ;
+ }
+
+ // Any non-whitespace and non-% characters must match exactly
+ if( fch != '%' )
+ {
+ if( __getc(h) != fch )
+ break;
+ nch ++;
+ continue ;
+ }
+
+ // Format specifier
+ fch = *format++;
+ if(!fch) break;
+
+ // Catch '%%' early
+ if( fch == '%' ) {
+ if( __getc(h) != '%' )
+ break;
+ nch ++;
+ continue ;
+ }
+
+ // %n$ - Direct offset selection, shouldn't be mixed with just %
+ for( ; isdigit(fch); fch = *format++ )
+ maxlen = maxlen * 10 + (fch - '0');
+ if( fch == '$' ) {
+ offset = maxlen;
+ maxlen = 0;
+ }
+
+ // Supress assignemnt?
+ if( fch == '*' )
+ {
+ fch = *format++;
+ ptr._void = NULL;
+ ret --;
+ }
+ else
+ ptr._void = va_arg(ap, void*);
+
+ // Max field length
+ while( isdigit(fch) )
+ {
+ maxlen = maxlen * 10 + fch - '0';
+ fch = *format++;
+ }
+
+ // Length modifier
+ switch( fch )
+ {
+ case 'h':
+ // 'short'
+ size = _VCSCANF_SHORT;
+ fch = *format++;
+ if( fch == 'h' ) {
+ // 'char'
+ size = _VCSCANF_CHAR;
+ fch = *format++;
+ }
+ break;
+ case 'l':
+ // 'long'
+ size = _VCSCANF_LONG;
+ fch = *format++;
+ if( fch == 'l' ) {
+ // 'long long'
+ size = _VCSCANF_LONGLONG;
+ fch = *format++;
+ }
+ break;
+ case 'j':
+ // '(u)intmax_t'
+ size = _VCSCANF_INTMAX;
+ fch = *format++;
+ break;
+ case 'z':
+ // 'size_t'
+ size = _VCSCANF_SIZET;
+ fch = *format++;
+ break;
+ case 't':
+ // 'ptrdiff_t'
+ size = _VCSCANF_PTRDIFF;
+ fch = *format++;
+ break;
+ case 'L':
+ // 'long double' (a, A, e, E, f, F, g, G)
+ size = _VCSCANF_LONGDOUBLE;
+ fch = *format++;
+ break;
+ }
+
+ // Format specifiers
+ switch( fch )
+ {
+ // Decimal integer
+ case 'd':
+ nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // variable-base integer
+ case 'i':
+ nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // Octal integer
+ case 'o':
+ nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // Hexadecimal integer
+ case 'x': case 'X':
+ nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ valtype = _VCSCANF_INT;
+ break;
+ // strtod format float
+ case 'a': case 'A':
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'g': case 'G':
+ valtype = _VCSCANF_REAL;
+ break;
+ // `maxlen` or 1 characters
+ case 'c':
+ if( maxlen == 0 )
+ maxlen = 1;
+ while( maxlen -- && (ich = __getc(h)) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ // sequence of non-whitespace characters
+ case 's':
+ if( maxlen == 0 )
+ maxlen = -1;
+
+ ich = 0;
+ while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ if( maxlen >= 0 && ich )
+ __rewind(h);
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ // match a set of characters
+ case '[':
+ fch = *format++;
+ if( fch == '^' ) {
+ // Invert
+ fch = *format;
+ }
+ set_start = format;
+ set_len = 0;
+ // if the first character is ']' it's part of the set
+ do {
+ // permissable character
+ set_len ++;
+ fch = *format++;
+ } while( fch && fch != ']' );
+
+ ich = 0;
+ while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
+ {
+ if(ptr._char) *ptr._char++ = ich;
+ nch ++;
+ }
+ if( maxlen >= 0 && ich )
+ __rewind(h);
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ case 'p': // read back printf("%p")
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ case 'n': // number of read characters to this point
+ if(ptr._int) {
+ *ptr._int = nch;
+ ret --; // negates the ret ++ at the end
+ }
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ default:
+ // Implimentation defined
+ valtype = _VCSCANF_NOTYPE;
+ break;
+ }
+
+ switch(valtype)
+ {
+ case _VCSCANF_NOTYPE:
+ // Used when assignment is done above
+ break;
+ case _VCSCANF_INT:
+ switch(size)
+ {
+ case _VCSCANF_UNDEF: *ptr._int = ival; break;
+ case _VCSCANF_CHAR: *ptr._char = ival; break;
+ case _VCSCANF_SHORT: *ptr._short = ival; break;
+ case _VCSCANF_LONG: *ptr._long = ival; break;
+ case _VCSCANF_LONGLONG: *ptr._longlong = ival; break;
+ default: // ???
+ break;
+ }
+ break;
+ case _VCSCANF_REAL:
+ break;
+ }
+
+ ret ++;
+ }
+
+ return ret;
+}
+
+int _vsscanf_getc(void *h)
+{
+ const char **ibuf = h;
+ return *(*ibuf)++; // Dereference, read for return, increment
+}
+
+void _vsscanf_rewind(void *h)
+{
+ const char **ibuf = h;
+ (*ibuf) --; // NOTE: Breaks if there's a rewind before a getc, but that shouldn't happen
+}
+
+int vscanf(const char *format, va_list ap)
+{
+ return vfscanf(stdin, format, ap);
+}
+
+int vsscanf(const char *str, const char *format, va_list ap)
+{
+ return _vcscanf(_vsscanf_getc, _vsscanf_rewind, &str, format, ap);
+}
+
+int _vfscanf_getc(void *h)
+{
+ return fgetc(h); // TODO: Handle -1 -> 0
+}
+void _vfscanf_rewind(void *h)
+{
+ fseek(h, -1, SEEK_CUR);
+}
+
+int vfscanf(FILE *stream, const char *format, va_list ap)
+{
+ return _vcscanf(_vfscanf_getc, _vfscanf_rewind, stream, format, ap);
+}
+
+int scanf(const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vfscanf(stdin, format, args);
+ va_end(args);
+ return rv;
+}
+int fscanf(FILE *stream, const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vfscanf(stream, format, args);
+ va_end(args);
+ return rv;
+}
+int sscanf(const char *str, const char *format, ...)
+{
+ va_list args;
+ int rv;
+ va_start(args, format);
+ rv = vsscanf(str, format, args);
+ va_end(args);
+ return rv;
+}
+
* AcessOS Basic C Library
* signals.c
*/
-#include <syscalls.h>
+//#include <acess/sys.h>
#include <stdlib.h>
#include <signal.h>
#include "lib.h"
sighandlers[num] = handler;
return prev;
}
+
+int raise(int signal)
+{
+ if( signal < 0 || signal > NUM_SIGNALS )
+ return 1;
+ switch(signal)
+ {
+ case SIGABRT:
+ abort();
+ break;
+ }
+ return 0;
+}
+
+void abort(void)
+{
+ // raise(SIGABRT);
+ _exit(-1);
+}
--- /dev/null
+/*\r
+ * AcessOS Basic C Library\r
+ * stdio.c\r
+ */\r
+#include "config.h"\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "lib.h"\r
+#include "stdio_int.h"\r
+\r
+#define WRITE_STR(_fd, _str) write(_fd, _str, sizeof(_str))\r
+\r
+#define DEBUG_BUILD 0\r
+\r
+// === CONSTANTS ===\r
+#define _stdin 0\r
+#define _stdout 1\r
+\r
+// === PROTOTYPES ===\r
+EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned);\r
+struct sFILE *get_file_struct();\r
+\r
+// === GLOBALS ===\r
+struct sFILE _iob[STDIO_MAX_STREAMS]; // IO Buffer\r
+struct sFILE *stdin; // Standard Input\r
+struct sFILE *stdout; // Standard Output\r
+struct sFILE *stderr; // Standard Error\r
+///\note Initialised in SoMain\r
+\r
+// === CODE ===\r
+int _fopen_modetoflags(const char *mode)\r
+{\r
+ int flags = 0;\r
+ \r
+ // Get main mode\r
+ switch(*mode)\r
+ {\r
+ case 'r': flags = FILE_FLAG_MODE_READ; break;\r
+ case 'w': flags = FILE_FLAG_MODE_WRITE; break;\r
+ case 'a': flags = FILE_FLAG_MODE_APPEND; break;\r
+ case 'x': flags = FILE_FLAG_MODE_EXEC; break; // Acess addon\r
+ default:\r
+ return -1;\r
+ }\r
+ mode ++;\r
+\r
+ // Get Modifiers\r
+ for( ; *mode; mode ++ )\r
+ {\r
+ switch(*mode)\r
+ {\r
+ case 'b': flags |= FILE_FLAG_M_BINARY; break;\r
+ case '+': flags |= FILE_FLAG_M_EXT; break;\r
+ default:\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ return flags;\r
+}\r
+\r
+/**\r
+ * \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
+ */\r
+EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
+{\r
+ int openFlags = 0;\r
+ \r
+ // Sanity Check Arguments\r
+ if(!fp || !file || !mode) return NULL;\r
+ \r
+ if(fp->FD != -1) {\r
+ fflush(fp);\r
+ }\r
+\r
+ // Get stdio flags\r
+ fp->Flags = _fopen_modetoflags(mode);\r
+ if(fp->Flags == -1)\r
+ return NULL;\r
+ \r
+ // Get Open Flags\r
+ switch(fp->Flags & FILE_FLAG_MODE_MASK)\r
+ {\r
+ // Read\r
+ case FILE_FLAG_MODE_READ:\r
+ openFlags = OPENFLAG_READ;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_WRITE;\r
+ break;\r
+ // Write\r
+ case FILE_FLAG_MODE_WRITE:\r
+ openFlags = OPENFLAG_WRITE;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_READ;\r
+ break;\r
+ // Execute\r
+ case FILE_FLAG_MODE_APPEND:\r
+ openFlags = OPENFLAG_APPEND;\r
+ if(fp->Flags & FILE_FLAG_M_EXT)\r
+ openFlags |= OPENFLAG_READ;\r
+ break;\r
+ // Execute\r
+ case FILE_FLAG_MODE_EXEC:\r
+ openFlags = OPENFLAG_EXEC;\r
+ break;\r
+ }\r
+\r
+ //Open File\r
+ if(fp->FD != -1)\r
+ fp->FD = _SysReopen(fp->FD, file, openFlags);\r
+ else\r
+ fp->FD = _SysOpen(file, openFlags);\r
+ if(fp->FD == -1) {\r
+ fp->Flags = 0;\r
+ return NULL;\r
+ }\r
+ \r
+ if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {\r
+ _SysSeek(fp->FD, 0, SEEK_END); //SEEK_END\r
+ }\r
+ \r
+ return fp;\r
+}\r
+/**\r
+ \fn FILE *fopen(const char *file, const char *mode)\r
+ \brief Opens a file and returns the pointer\r
+ \param file String - Filename to open\r
+ \param mode Mode to open in\r
+*/\r
+EXPORT FILE *fopen(const char *file, const char *mode)\r
+{\r
+ FILE *retFile;\r
+ \r
+ // Sanity Check Arguments\r
+ if(!file || !mode) return NULL;\r
+ \r
+ // Create Return Structure\r
+ retFile = get_file_struct();\r
+ \r
+ return freopen(file, mode, retFile);\r
+}\r
+\r
+EXPORT FILE *fmemopen(void *buffer, size_t length, const char *mode)\r
+{\r
+ FILE *ret;\r
+ \r
+ if( !buffer || !mode ) return NULL;\r
+ \r
+ ret = get_file_struct();\r
+ \r
+ ret->FD = -2;\r
+ ret->Flags = _fopen_modetoflags(mode);\r
+ if(ret->Flags == -1) {\r
+ ret->Flags = 0;\r
+ return NULL;\r
+ }\r
+ \r
+ ret->Buffer = buffer;\r
+ ret->BufferStart = 0;\r
+ ret->BufferSize = length;\r
+ \r
+ return ret;\r
+}\r
+\r
+EXPORT int fclose(FILE *fp)\r
+{\r
+ fflush(fp);\r
+ if( fp->FD != -1 ) {\r
+ _SysClose(fp->FD);\r
+ }\r
+ fp->Flags = 0;\r
+ fp->FD = -1;\r
+ return 0;\r
+}\r
+\r
+EXPORT void fflush(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
+ \r
+ if( !(fp->Flags & FILE_FLAG_DIRTY) )\r
+ return ;\r
+ \r
+ // Nothing to do for memory files\r
+ if( fp->FD == -2 )\r
+ return ;\r
+}\r
+\r
+EXPORT void clearerr(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return ;\r
+ \r
+ // TODO: Impliment clearerr()\r
+}\r
+\r
+EXPORT int feof(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
+ return !!(fp->Flags & FILE_FLAG_EOF);\r
+}\r
+\r
+EXPORT int ferror(FILE *fp)\r
+{\r
+ if( !fp || fp->FD == -1 )\r
+ return 0;\r
+ return 0;\r
+}\r
+EXPORT int fileno(FILE *stream)\r
+{\r
+ return stream->FD;\r
+}\r
+\r
+EXPORT off_t ftell(FILE *fp)\r
+{\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 )\r
+ return fp->Pos; \r
+ else\r
+ return _SysTell(fp->FD);\r
+}\r
+\r
+EXPORT int fseek(FILE *fp, long int amt, int whence)\r
+{\r
+ if(!fp || fp->FD == -1) return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ switch(whence)\r
+ {\r
+ case SEEK_CUR:\r
+ fp->Pos += amt;\r
+ break;\r
+ case SEEK_SET:\r
+ fp->Pos = amt;\r
+ break;\r
+ case SEEK_END:\r
+ if( fp->BufferSize < (size_t)amt )\r
+ fp->Pos = 0;\r
+ else\r
+ fp->Pos = fp->BufferSize - amt;\r
+ break;\r
+ }\r
+ if(fp->Pos > (off_t)fp->BufferSize) {\r
+ fp->Pos = fp->BufferSize;\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ }\r
+ return 0;\r
+ }\r
+ else\r
+ return _SysSeek(fp->FD, amt, whence);\r
+}\r
+\r
+\r
+/**\r
+ * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
+ * \brief Print to a file from a variable argument list\r
+ */\r
+EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
+{\r
+ va_list tmpList;\r
+ int size;\r
+\r
+ if(!fp || !format) return -1;\r
+\r
+ va_copy(tmpList, args);\r
+ \r
+ size = vsnprintf(NULL, 0, (char*)format, tmpList);\r
+ char buf[size+1];\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ \r
+ // Write to stream\r
+ fwrite(buf, size, 1, fp);\r
+ \r
+ // Return written byte count\r
+ return size;\r
+}\r
+\r
+/**\r
+ * \fn int fprintf(FILE *fp, const char *format, ...)\r
+ * \brief Print a formatted string to a stream\r
+ */\r
+EXPORT int fprintf(FILE *fp, const char *format, ...)\r
+{\r
+ va_list args;\r
+ int ret;\r
+ \r
+ // Get Size\r
+ va_start(args, format);\r
+ ret = vfprintf(fp, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
+ * \brief Write to a stream\r
+ */\r
+EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy((char*)fp->Buffer + fp->Pos, ptr, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else { \r
+ ret = _SysWrite(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
+ * \brief Read from a stream\r
+ */\r
+EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
+{\r
+ size_t ret;\r
+ \r
+ if(!fp || fp->FD == -1)\r
+ return -1;\r
+\r
+ if( fp->FD == -2 ) {\r
+ size_t avail = (fp->BufferSize - fp->Pos) / size;\r
+ if( avail == 0 )\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ if( num > avail ) num = avail;\r
+ size_t bytes = num * size;\r
+ memcpy(ptr, (char*)fp->Buffer + fp->Pos, bytes);\r
+ fp->Pos += bytes;\r
+ ret = num;\r
+ }\r
+ else {\r
+ ret = _SysRead(fp->FD, ptr, size*num);\r
+ ret /= size;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int fputc(int c, FILE *fp)\r
+ * \brief Write a single character to the stream\r
+ */\r
+EXPORT int fputc(int c, FILE *fp)\r
+{\r
+ return fwrite(&c, 1, 1, fp);\r
+}\r
+\r
+EXPORT int putchar(int c)\r
+{\r
+ c &= 0xFF;\r
+ return _SysWrite(_stdout, &c, 1);\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int fgetc(FILE *fp)\r
+ * \brief Read a character from the stream\r
+ */\r
+EXPORT int fgetc(FILE *fp)\r
+{\r
+ char ret = 0;\r
+ if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+ return -1;\r
+ return ret;\r
+}\r
+\r
+EXPORT int getchar(void)\r
+{\r
+ char ret = 0;\r
+ if(_SysRead(_stdin, &ret, 1) != 1) return -1;\r
+ return ret;\r
+}\r
+\r
+// --- INTERNAL ---\r
+/**\r
+ * \fn FILE *get_file_struct()\r
+ * \brief Returns a file descriptor structure\r
+ */\r
+FILE *get_file_struct()\r
+{\r
+ int i;\r
+ for(i=0;i<STDIO_MAX_STREAMS;i++)\r
+ {\r
+ if(_iob[i].Flags & FILE_FLAG_ALLOC)\r
+ continue ;\r
+ _iob[i].Flags |= FILE_FLAG_ALLOC;\r
+ _iob[i].FD = -1;\r
+ _iob[i].Pos = 0;\r
+ return &_iob[i];\r
+ }\r
+ return NULL;\r
+}\r
+\r
+EXPORT int puts(const char *str)\r
+{\r
+ int len;\r
+ \r
+ if(!str) return 0;\r
+ len = strlen(str);\r
+ \r
+ len = _SysWrite(_stdout, str, len);\r
+ _SysWrite(_stdout, "\n", 1);\r
+ return len;\r
+}\r
+\r
+EXPORT int vsprintf(char * __s, const char *__format, va_list __args)\r
+{\r
+ return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
+}\r
+\r
+//sprintfv\r
+/**\r
+ * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
+ * \brief Prints a formatted string to a buffer\r
+ * \param buf Pointer - Destination Buffer\r
+ * \param format String - Format String\r
+ * \param args VarArgs List - Arguments\r
+ */\r
+EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)\r
+{\r
+ char tmp[65];\r
+ int c, minSize, precision, len;\r
+ size_t pos = 0;\r
+ char *p;\r
+ char pad;\r
+ uint64_t arg;\r
+ int bLongLong, bPadLeft;\r
+\r
+ void _addchar(char ch)\r
+ {\r
+ if(buf && pos < __maxlen) buf[pos] = ch;\r
+ pos ++;\r
+ }\r
+\r
+ tmp[32] = '\0';\r
+ \r
+ while((c = *format++) != 0)\r
+ {\r
+ // Non-control character\r
+ if (c != '%') {\r
+ _addchar(c);\r
+ continue;\r
+ }\r
+ \r
+ // Control Character\r
+ c = *format++;\r
+ if(c == '%') { // Literal %\r
+ _addchar('%');\r
+ continue;\r
+ }\r
+ \r
+ bPadLeft = 0;\r
+ bLongLong = 0;\r
+ minSize = 0;\r
+ precision = -1;\r
+ pad = ' ';\r
+ \r
+ // Padding Character\r
+ if(c == '0') {\r
+ pad = '0';\r
+ c = *format++;\r
+ }\r
+ // Padding length\r
+ if( c == '*' ) {\r
+ // Variable length\r
+ minSize = va_arg(args, size_t);\r
+ c = *format++;\r
+ }\r
+ else {\r
+ if('1' <= c && c <= '9')\r
+ {\r
+ minSize = 0;\r
+ while('0' <= c && c <= '9')\r
+ {\r
+ minSize *= 10;\r
+ minSize += c - '0';\r
+ c = *format++;\r
+ }\r
+ }\r
+ }\r
+\r
+ // Precision\r
+ if(c == '.') {\r
+ c = *format++;\r
+ if(c == '*') {\r
+ precision = va_arg(args, size_t);\r
+ c = *format++;\r
+ }\r
+ else if('1' <= c && c <= '9')\r
+ {\r
+ precision = 0;\r
+ while('0' <= c && c <= '9')\r
+ {\r
+ precision *= 10;\r
+ precision += c - '0';\r
+ c = *format++;\r
+ }\r
+ }\r
+ }\r
+ \r
+ // Check for long long\r
+ bLongLong = 0;\r
+ if(c == 'l')\r
+ {\r
+ c = *format++;\r
+ if(c == 'l') {\r
+ bLongLong = 1;\r
+ }\r
+ }\r
+ \r
+ // Just help things along later\r
+ p = tmp;\r
+ \r
+ // Get Type\r
+ switch( c )\r
+ {\r
+ // Signed Integer\r
+ case 'd': case 'i':\r
+ // Get Argument\r
+ if(bLongLong) arg = va_arg(args, int64_t);\r
+ else arg = va_arg(args, int32_t);\r
+ itoa(tmp, arg, 10, minSize, pad, 1);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned Integer\r
+ case 'u':\r
+ // Get Argument\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 10, minSize, pad, 0);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+ \r
+ // Pointer\r
+ case 'p':\r
+ _addchar('*');\r
+ _addchar('0');\r
+ _addchar('x');\r
+ arg = va_arg(args, intptr_t);\r
+ itoa(tmp, arg, 16, minSize, pad, 0);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+ // Unsigned Hexadecimal\r
+ case 'x':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 16, minSize, pad, 0);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned Octal\r
+ case 'o':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 8, minSize, pad, 0);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+ \r
+ // Unsigned binary\r
+ case 'b':\r
+ if(bLongLong) arg = va_arg(args, uint64_t);\r
+ else arg = va_arg(args, uint32_t);\r
+ itoa(tmp, arg, 2, minSize, pad, 0);\r
+ precision = -1;\r
+ goto sprintf_puts;\r
+\r
+ // String\r
+ case 's':\r
+ p = va_arg(args, char*);\r
+ sprintf_puts:\r
+ if(!p) p = "(null)";\r
+ //_SysDebug("vsnprintf: p = '%s'", p);\r
+ if(precision >= 0)\r
+ len = strnlen(p, precision);\r
+ else\r
+ len = strlen(p);\r
+ if(bPadLeft) while(minSize > len++) _addchar(pad);\r
+ while( *p ) {\r
+ if(precision >= 0 && precision -- == 0)\r
+ break;\r
+ _addchar(*p++);\r
+ }\r
+ if(!bPadLeft) while(minSize > len++) _addchar(pad);\r
+ break;\r
+\r
+ // Unknown, just treat it as a character\r
+ default:\r
+ arg = va_arg(args, uint32_t);\r
+ _addchar(arg);\r
+ break;\r
+ }\r
+ }\r
+ _addchar('\0');\r
+ pos --;\r
+ \r
+ //_SysDebug("vsnprintf: buf = '%s'", buf);\r
+ \r
+ return pos;\r
+}\r
+\r
+const char cUCDIGITS[] = "0123456789ABCDEF";\r
+/**\r
+ * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
+ * \brief Convert an integer into a character string\r
+ * \param buf Destination Buffer\r
+ * \param num Number to convert\r
+ * \param base Base-n number output\r
+ * \param minLength Minimum length of output\r
+ * \param pad Padding used to ensure minLength\r
+ * \param bSigned Signed number output?\r
+ */\r
+EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)\r
+{\r
+ char tmpBuf[64];\r
+ int pos=0, i;\r
+\r
+ if(!buf) return;\r
+ if(base > 16 || base < 2) {\r
+ buf[0] = 0;\r
+ return;\r
+ }\r
+ \r
+ if(bSigned && (int64_t)num < 0)\r
+ {\r
+ num = -num;\r
+ bSigned = 1;\r
+ } else\r
+ bSigned = 0;\r
+ \r
+ // Encode into reversed string\r
+ while(num > base-1) {\r
+ tmpBuf[pos++] = cUCDIGITS[ num % base ];\r
+ num = (uint64_t) num / (uint64_t)base; // Shift {number} right 1 digit\r
+ }\r
+\r
+ tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of {number}\r
+ if(bSigned) tmpBuf[pos++] = '-'; // Append sign symbol if needed\r
+ \r
+ i = 0;\r
+ minLength -= pos;\r
+ while(minLength-- > 0) buf[i++] = pad;\r
+ while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters\r
+ buf[i] = 0;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int printf(const char *format, ...)\r
+ * \brief Print a string to stdout\r
+ */\r
+EXPORT int printf(const char *format, ...)\r
+{\r
+ int size;\r
+ va_list args;\r
+ \r
+ // Get final size\r
+ va_start(args, format);\r
+ size = vsnprintf(NULL, 0, (char*)format, args);\r
+ va_end(args);\r
+ char buf[size+1];\r
+ // Fill Buffer\r
+ va_start(args, format);\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ va_end(args);\r
+ \r
+ // Send to stdout\r
+ _SysWrite(_stdout, buf, size+1);\r
+ \r
+ // Free buffer\r
+ free(buf);\r
+ // Return\r
+ return size;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
+ * \brief Print a formatted string to a buffer\r
+ */\r
+EXPORT int sprintf(char *buf, const char *format, ...)\r
+{\r
+ int ret;\r
+ va_list args;\r
+ va_start(args, format);\r
+ ret = vsprintf((char*)buf, (char*)format, args);\r
+ va_end(args);\r
+ return ret;\r
+}\r
+\r
+/**\r
+ * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)\r
+ * \brief Print a formatted string to a buffer\r
+ */\r
+EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)\r
+{\r
+ int ret;\r
+ va_list args;\r
+ va_start(args, format);\r
+ ret = vsnprintf((char*)buf, maxlen, (char*)format, args);\r
+ va_end(args);\r
+ return ret;\r
+}\r
* Configuration Options
*/
#ifndef _STDIO_INT_H
-# define _STDIO_INT_H
+#define _STDIO_INT_H
+
+#include <sys/types.h>
+#include <stddef.h>
// === CONSTANTS ===
-#define FILE_FLAG_MODE_MASK 0x07
-#define FILE_FLAG_MODE_READ 0x01
-#define FILE_FLAG_MODE_WRITE 0x02
-#define FILE_FLAG_MODE_EXEC 0x03
-#define FILE_FLAG_MODE_APPEND 0x04
-#define FILE_FLAG_M_EXT 0x10
+#define FILE_FLAG_MODE_MASK 0x0007
+#define FILE_FLAG_MODE_READ 0x0001
+#define FILE_FLAG_MODE_WRITE 0x0002
+#define FILE_FLAG_MODE_EXEC 0x0003
+#define FILE_FLAG_MODE_APPEND 0x0004
+#define FILE_FLAG_M_EXT 0x0010
+#define FILE_FLAG_M_BINARY 0x0020
+#define FILE_FLAG_EOF 0x0100
+#define FILE_FLAG_DIRTY 0x0200
+#define FILE_FLAG_ALLOC 0x1000
// === TYPES ===
struct sFILE {
- int FD;
int Flags;
+ int FD;
+ off_t Pos;
+
#if DEBUG_BUILD
- char *FileName;
- #endif
- #if STDIO_LOCAL_BUFFER
- char *Buffer;
- Uint64 BufferStart;
- int BufferSize;
+ char *FileName; // heap
#endif
+ void *Buffer;
+ off_t BufferStart;
+ size_t BufferSize;
};
#endif
#include <acess/sys.h>\r
#include <stdlib.h>\r
#include <stdio.h>\r
-#include <errno.h>\r
-#include <ctype.h>\r
-#include <limits.h>\r
#include "lib.h"\r
\r
-#define _stdout 1\r
-#define _stdin 0\r
-\r
extern void *_crt0_exit_handler;\r
\r
// === PROTOTYPES ===\r
*/\r
EXPORT void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))\r
{\r
- int i, j, min;\r
+ size_t i, j, min;\r
// With 0 items, there's nothing to do and with 1 its already sorted\r
if(nmemb == 0 || nmemb == 1) return;\r
\r
}\r
}\r
\r
-EXPORT long long strtoll(const char *str, char **end, int base)\r
-{\r
- int neg = 0;\r
- long long ret = 0;\r
- \r
- if( !str || base < 0 || base > 36 || base == 1 ) {\r
- if(end)\r
- *end = (char*)str;\r
- errno = EINVAL;\r
- return 0;\r
- }\r
-\r
- while( isspace(*str) )\r
- str++;\r
- \r
- // Check for negative (or positive) sign\r
- if(*str == '-' || *str == '+') {\r
- neg = (*str == '-');\r
- str++;\r
- }\r
- \r
- if( base == 0 || base == 16 ) {\r
- if( *str == '0' && str[1] == 'x' ) {\r
- str += 2;\r
- base = 16;\r
- }\r
- }\r
- \r
- if( base == 0 && *str == '0' ) {\r
- str ++;\r
- base = 8;\r
- }\r
-\r
- if( base == 0 )\r
- base = 10;\r
-\r
- while( *str )\r
- {\r
- int next = -1;\r
- if( base <= 10 ) {\r
- if( '0' <= *str && *str <= '0'+base-1 )\r
- next = *str - '0';\r
- }\r
- else {\r
- if( '0' <= *str && *str <= '9' )\r
- next = *str - '0';\r
- if( 'A' <= *str && *str <= 'A'+base-10-1 )\r
- next = *str - 'A';\r
- if( 'a' <= *str && *str <= 'a'+base-10-1 )\r
- next = *str - 'a';\r
- }\r
- if( next < 0 )\r
- break;\r
- ret *= base;\r
- ret += next;\r
- str ++;\r
- }\r
-\r
- if( neg )\r
- ret = -ret; \r
-\r
- if(end)\r
- *end = (char*)str;\r
- return ret;\r
-}\r
-\r
-EXPORT long strtol(const char *str, char **end, int base)\r
-{\r
- long long tmp = strtoll(str, end, base);\r
- if( tmp > LONG_MAX || tmp < LONG_MIN ) {\r
- errno = ERANGE;\r
- return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN;\r
- }\r
- return tmp;\r
-}\r
-\r
-/**\r
- * \fn EXPORT int atoi(const char *str)\r
- * \brief Convert a string to an integer\r
- */\r
-EXPORT int atoi(const char *str)\r
-{\r
- long long tmp = strtoll(str, NULL, 0);\r
- if( tmp > INT_MAX || tmp < INT_MIN ) {\r
- errno = ERANGE;\r
- return (tmp > INT_MAX) ? INT_MAX : INT_MIN;\r
- }\r
- return tmp;\r
-}\r
\r
int abs(int j) { return j < 0 ? -j : j; }\r
long int labs(long int j) { return j < 0 ? -j : j; }\r
char *sp = (char *)src;
char *dp = (char *)dest;
// Check if the areas overlap
- if( (intptr_t)src < (intptr_t)dest && (intptr_t)dest < (intptr_t)src+count )
+ if( (uintptr_t)src < (uintptr_t)dest && (uintptr_t)dest < (uintptr_t)src+count )
for(;count--;)
dp[count] = sp[count];
else
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * strtoi.c
+ * - strto[u][l]l/atoi implimentation
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+
+unsigned long long strtoull(const char *str, char **end, int base)
+{
+ long long ret = 0;
+
+ if( !str || base < 0 || base > 36 || base == 1 ) {
+ if(end)
+ *end = (char*)str;
+ errno = EINVAL;
+ return 0;
+ }
+
+ // Trim leading spaces
+ while( isspace(*str) )
+ str++;
+
+ // Handle base detection for hex
+ if( base == 0 || base == 16 ) {
+ if( *str == '0' && str[1] == 'x' ) {
+ str += 2;
+ base = 16;
+ }
+ }
+
+ // Handle base detection for octal
+ if( base == 0 && *str == '0' ) {
+ str ++;
+ base = 8;
+ }
+
+ // Fall back on decimal when unknown
+ if( base == 0 )
+ base = 10;
+
+ while( *str )
+ {
+ int next = -1;
+ if( base <= 10 ) {
+ if( '0' <= *str && *str <= '0'+base-1 )
+ next = *str - '0';
+ }
+ else {
+ if( '0' <= *str && *str <= '9' )
+ next = *str - '0';
+ if( 'A' <= *str && *str <= 'A'+base-10-1 )
+ next = *str - 'A';
+ if( 'a' <= *str && *str <= 'a'+base-10-1 )
+ next = *str - 'a';
+ }
+ if( next < 0 )
+ break;
+ ret *= base;
+ ret += next;
+ str ++;
+ }
+
+ if(end)
+ *end = (char*)str;
+ return ret;
+}
+
+unsigned long strtoul(const char *ptr, char **end, int base)
+{
+ unsigned long long tmp = strtoull(ptr, end, base);
+
+ if( tmp > ULONG_MAX ) {
+ errno = ERANGE;
+ return ULONG_MAX;
+ }
+
+ return tmp;
+}
+
+long long strtoll(const char *str, char **end, int base)
+{
+ int neg = 0;
+ unsigned long long ret;
+
+ if( !str ) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ while( isspace(*str) )
+ str++;
+
+ // Check for negative (or positive) sign
+ if(*str == '-' || *str == '+') {
+ neg = (*str == '-');
+ str++;
+ }
+
+ ret = strtoull(str, end, base);
+
+ if( neg )
+ return -ret;
+ else
+ return ret;
+}
+
+long strtol(const char *str, char **end, int base)
+{
+ long long tmp = strtoll(str, end, base);
+ if( tmp > LONG_MAX || tmp < LONG_MIN ) {
+ errno = ERANGE;
+ return (tmp > LONG_MAX) ? LONG_MAX : LONG_MIN;
+ }
+ return tmp;
+}
+
+/**
+ * \fn int atoi(const char *str)
+ * \brief Convert a string to an integer
+ */
+int atoi(const char *str)
+{
+ long long tmp = strtoll(str, NULL, 0);
+ if( tmp > INT_MAX || tmp < INT_MIN ) {
+ errno = ERANGE;
+ return (tmp > INT_MAX) ? INT_MAX : INT_MIN;
+ }
+ return tmp;
+}
#include "stdio_int.h"\r
#include "lib.h"\r
#include <stdio.h>\r
-#include <sys/sys.h>\r
+#include <acess/sys.h>\r
\r
#define USE_CPUID 0\r
\r
* \param argv Unused - Arguments (NULL for current version of ld-acess)\r
* \param envp Environment Pointer\r
*/\r
-int SoMain(unsigned int BaseAddress, int argc, char **argv, char **envp)\r
+int SoMain(UNUSED(uintptr_t, BaseAddress), UNUSED(int, argc), UNUSED(char **, argv), char **envp)\r
{\r
// Init for env.c\r
_envp = envp;\r
uint32_t *type = (void*)buf;
// Open
- fd = open("/Devices/ip/routes", 0);
+ fd = _SysOpen("/Devices/ip/routes", 0);
if( !fd ) {
fprintf(stderr, "ERROR: Unable to open '/Devices/ip/routes'\n");
return NULL;
// Make structure and ask
*type = AddressType;
memcpy(type+1, Address, size);
- routeNum = ioctl(fd, ioctl(fd, 3, "locate_route"), buf);
+ routeNum = _SysIOCtl(fd, _SysIOCtl(fd, 3, "locate_route"), buf);
// Close
- close(fd);
+ _SysClose(fd);
}
// Check answer validity
sprintf(buf, "/Devices/ip/routes/#%i", routeNum);
// Open route
- fd = open(buf, 0);
+ fd = _SysOpen(buf, 0);
if( fd == -1 ) {
fprintf(stderr, "Net_GetInterface - ERROR: Unable to open %s\n", buf);
return NULL; // Shouldn't happen :/
}
// Allocate space for name
- ret = malloc( ioctl(fd, ioctl(fd, 3, "get_interface"), NULL) + 1 );
+ ret = malloc( _SysIOCtl(fd, _SysIOCtl(fd, 3, "get_interface"), NULL) + 1 );
if( !ret ) {
fprintf(stderr, "malloc() failure - Allocating space for interface name\n");
return NULL;
}
// Get name
- ioctl(fd, ioctl(fd, 3, "get_interface"), ret);
+ _SysIOCtl(fd, _SysIOCtl(fd, 3, "get_interface"), ret);
// Close and return
- close(fd);
+ _SysClose(fd);
return ret;
}
char path[len+1];
snprintf(path, 100, "/Devices/ip/routes/@%i:%s/%s", AddrType, hexAddr, Filename);
_SysDebug("%s", path);
- return open(path, OPENFLAG_READ|OPENFLAG_WRITE);
+ return _SysOpen(path, OPENFLAG_READ|OPENFLAG_WRITE);
}
else
{
int len = snprintf(NULL, 100, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr);
char path[len+1];
snprintf(path, 100, "/Devices/ip/routes/@%i:%s", AddrType, hexAddr);
- return open(path, OPENFLAG_READ);
+ return _SysOpen(path, OPENFLAG_READ);
}
}
int fd = Net_OpenSocket(AddrType, Addr, "tcpc");
if( fd == -1 ) return -1;
- ioctl(fd, 5, &Port); // Remote Port
- ioctl(fd, 6, Addr); // Remote address
- ioctl(fd, 7, NULL); // connect
+ _SysIOCtl(fd, 5, &Port); // Remote Port
+ _SysIOCtl(fd, 6, Addr); // Remote address
+ _SysIOCtl(fd, 7, NULL); // connect
return fd;
}
--- /dev/null
+# Acess2 POSIX Emulation\r
+# Makefile\r
+\r
+-include ../Makefile.cfg\r
+\r
+CPPFLAGS += \r
+CFLAGS += -Werror -Wextra\r
+ASFLAGS +=\r
+LDFLAGS += -soname libposix.so -Map map.txt\r
+\r
+OBJ = main.o unistd.o\r
+DEPFILES := $(OBJ:%.o=%.d)\r
+BIN = libposix.so\r
+\r
+include ../Makefile.tpl\r
+\r
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * dirent.h
+ * - Directory Reading
+ */
+#ifndef _LIBPOSIX__SYS__DIRENT_H_
+#define _LIBPOSIX__SYS__DIRENT_H_
+
+#define NAME_MAX 255
+
+struct dirent
+{
+ ino_t d_ino;
+ char d_name[NAME_MAX+1];
+};
+
+typedef struct DIR_s DIR;
+
+extern int closedir(DIR *);
+extern DIR *opendir(const char *);
+extern struct dirent *readdir(DIR *);
+extern int readdir_r(DIR *, struct dirent *, struct dirent **);
+extern void rewinddir(DIR *);
+extern void seekdir(DIR *, long int);
+extern long int telldir(DIR *);
+
+#endif
+
// Acess doesn't implement lseek
#define lseek(_1,_2,_3) (seek(_1,_2,_3),tell(_1))
+enum e_fcntl_cmds
+{
+ F_SETFL
+};
+
+int fcntl(int fd, int cmd, ...) { return -1; }
+
#endif
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * grp.h
+ * - Group Management
+ */
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * pwd.h
+ * - Password Structure
+ */
+#ifndef _LIBPOSIX__PWD_H_
+#define _LIBPOSIX__PWD_H_
+
+#include <sys/types.h> // gid_t/uid_t
+
+struct passwd
+{
+ char *pw_name;
+ uid_t pw_uid;
+ gid_t pw_gid;
+ char *pw_dir;
+ char *pw_shell;
+};
+
+extern struct passwd *getpwnam(const char *);
+extern struct passwd *getpwuid(uid_t);
+extern int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
+extern int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
+extern void endpwent(void);
+extern struct passwd *getpwent(void);
+extern void setpwent(void);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * sys/resource.h
+ * - (XSI) Resource Operations
+ */
+#ifndef _LIBPOSIX__SYS__RESOURCE_H_
+#define _LIBPOSIX__SYS__RESOURCE_H_
+
+#include <sys/time.h> // struct timeval
+
+// (get|set)priority(which)
+enum
+{
+ PRIO_PROCESS,
+ PRIO_PGRP,
+ PRIO_USER
+};
+
+typedef unsigned int rlim_t;
+#define RLIM_INFINITY -1
+#define RLIM_SAVED_MAX -2
+#define RLIM_SAVED_CUR -3
+
+struct rlimit
+{
+ rlim_t rlim_cur;
+ rlim_t rlim_max;
+};
+
+enum
+{
+ RLIMIT_AS, // Address space size
+ RLIMIT_CORE, // Max core file size
+ RLIMIT_CPU, // CPU time limit in s (SIGXCPU when reached)
+ RLIMIT_DATA,
+ // TODO: More?
+};
+
+struct rusage
+{
+ struct timeval ru_time;
+ struct timeval ru_stime;
+};
+
+extern int getpriority(int, id_t);
+extern int getrlimit(int, struct rlimit *);
+extern int getrusage(int, struct rusage *);
+extern int setpriority(int, id_t, int);
+extern int setrlimit(int, const struct rlimit *);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge
+ *
+ * sys/select.h
+ * - select(2)
+ */
+#ifndef _SYS__SELECT_H_
+#define _SYS__SELECT_H_
+
+#include <acess/fd_set.h>
+
+extern int select(int nfds, fd_set *readfds, fd_set *writefds, struct timeval *timeout);
+// TODO: pselect?
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ */
+#ifndef _SYS_STAT_H_
+#define _SYS_STAT_H_
+
+//#include "../acess/intdefs.h" /* Evil */
+//#include "../stddef.h"
+#include <stdint.h>
+#include "sys/types.h" // off_t
+
+typedef void *dev_t; /* TODO: How to identify a device with Acess */
+typedef uint64_t ino_t;
+typedef unsigned int blksize_t;
+typedef uint64_t blkcnt_t;
+typedef unsigned int nlink_t;
+typedef uint32_t mode_t;
+
+typedef uint32_t uid_t;
+typedef uint32_t gid_t;
+
+#define S_IFMT 0170000 /* type of file */
+#define S_IFDIR 0040000 /* directory */
+#define S_IFCHR 0020000 /* character special */
+#define S_IFBLK 0060000 /* block special */
+#define S_IFREG 0100000 /* regular */
+#define S_IFLNK 0120000 /* symbolic link */
+#define S_IFSOCK 0140000 /* socket */
+#define S_IFIFO 0010000 /* fifo */
+
+
+struct stat
+{
+ dev_t st_dev; /* ID of device containing file */
+ ino_t st_ino; /* inode number */
+ mode_t st_mode; /* protection */
+ nlink_t st_nlink; /* number of hard links */
+ uid_t st_uid; /* user ID of owner */
+ gid_t st_gid; /* group ID of owner */
+ dev_t st_rdev; /* device ID (if special file) */
+ off_t st_size; /* total size, in bytes */
+ blksize_t st_blksize; /* blocksize for file system I/O */
+ blkcnt_t st_blocks; /* number of 512B blocks allocated */
+ time_t st_atime; /* time of last access */
+ time_t st_mtime; /* time of last modification */
+ time_t st_ctime; /* time of last status change */
+};
+
+extern int stat(const char *path, struct stat *buf);
+extern int fstat(int fd, struct stat *buf);
+
+#endif
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * sys/time.h
+ * - Timing calls
+ */
+#ifndef _LIBPOSIX__SYS__TIME_H_
+#define _LIBPOSIX__SYS__TIME_H_
+
+typedef unsigned long suseconds_t;
+
+struct timeval
+{
+ time_t tv_sec;
+ suseconds_t tv_usec;
+};
+
+struct itimerval
+{
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+
+// TODO: This should also define fd_set and select()
+
+extern int getitimer(int, struct itimerval *);
+extern int setitimer(int, const struct itimerval *, struct itimerval *);
+extern int gettimeofday(struct timeval *, void *);
+// select
+extern int utimes(const char *, const struct timeval [2]);
+
+#endif
+
--- /dev/null
+/*
+ */
+#ifndef _SYS_TYPES_H
+#define _SYS_TYPES_H
+
+#include <stdint.h>
+
+//typedef signed int ssize_t;
+//#ifdef __USE_BSD
+typedef unsigned int u_int;
+//#endif
+
+typedef struct stat t_fstat;
+
+
+#define CLONE_VM 0x10
+
+typedef unsigned int id_t;
+typedef unsigned long pid_t;
+typedef unsigned long tid_t;
+typedef signed long long int time_t;
+typedef long long int off_t;
+
+typedef unsigned int uint;
+
+#include "stat.h"
+#include <acess/fd_set.h>
+
+#endif
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * sys/wait.h
+ * - Waiting
+ */
+#ifndef _LIBPOSIX__SYS__WAIT_H_
+#define _LIBPOSIX__SYS__WAIT_H_
+
+// POSIX, waitpid()
+#define WNOHANG 0x01
+#define WUNTRACED 0x02
+
+// POSIX, status values
+#define WEXITSTATUS(v) v
+#define WIFCONTINUED(v) 0
+
+// POSIX/XSI, waitid(options)
+#define WEXITED 0x10
+#define WSTOPPED 0x20
+#define WCONTINUED 0x40
+#define WNOWAIT 0x80
+
+// POSIX/XSI, idtype_t
+typedef enum
+{
+ P_ALL,
+ P_PID,
+ P_PGID
+} idtype_t;
+
+// POSIX
+extern pid_t wait(int *);
+// POSIX/XSI
+//extern int waitid(idtype_t, id_t, siginfo_t *, int);
+// POSIX
+extern pid_t waitpid(pid_t, int *, int);
+
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * syslog.h
+ * - Centra Loggin
+ */
+#ifndef _LIBPOSIX__SYSLOG_H_
+#define _LIBPOSIX__SYSLOG_H_
+
+// openlog(logopt)
+#define LOG_PID 0x01
+#define LOG_CONS 0x02
+#define LOG_NDELAY 0x04
+#define LOG_ODELAY 0x08
+#define LOG_NOWAIT 0x10
+
+// openlog(facility)
+enum {
+ LOG_KERN,
+ LOG_USER,
+ LOG_MAIL,
+ LOG_NEWS,
+ LOG_UUCP,
+ LOG_DAEMON,
+ LOG_AUTH,
+ LOG_CRON,
+ LOG_LPR,
+ LOG_LOCAL0,
+ LOG_LOCAL1,
+ LOG_LOCAL2,
+ LOG_LOCAL3,
+ LOG_LOCAL4,
+ LOG_LOCAL5,
+ LOG_LOCAL6,
+ LOG_LOCAL7
+};
+
+// setlogmask(maskpri)
+#define LOG_MASK(pri) pri
+
+// syslog(priority)
+enum {
+ LOG_EMERG,
+ LOG_ALERT,
+ LOG_CRIT,
+ LOG_ERR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_INFO,
+ LOG_DEBUG
+};
+
+extern void closelog(void);
+extern void openlog(const char *, int, int);
+extern int setlogmask(int);
+extern void syslog(int, const char *, ...);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * termios.h
+ * - Terminal Control
+ */
+#ifndef _LIBPOSIX__TERMIOS_H_
+#define _LIBPOSIX__TERMIOS_H_
+
+typedef unsigned char cc_t;
+typedef unsigned long speed_t;
+typedef unsigned short tcflag_t;
+
+enum {
+ VEOF,
+ VEOL,
+ VERASE,
+ VINTR,
+ VKILL,
+ VMIN,
+ VQUIT,
+ VSTART,
+ VSTOP,
+ VSUSP,
+ VTIME,
+ NCCS
+};
+
+struct termios
+{
+ tcflag_t c_iflag;
+ tcflag_t c_oflag;
+ tcflag_t c_cflag;
+ tcflag_t c_lflag;
+ cc_t c_cc[NCCS];
+};
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge
+ *
+ * unistd.h
+ * -
+ */
+#ifndef _UNISTD_H_
+#define _UNISTD_H_
+
+#include <stddef.h>
+
+//! \brief flags for open(2)
+#define O_WRONLY 0x01
+#define O_RDONLY 0x02
+#define O_RDWR 0x03
+#define O_APPEND 0x04
+#define O_CREAT 0x08
+#define O_DIRECTORY 0x10
+#define O_ASYNC 0x20
+#define O_TRUNC 0x40
+#define O_NOFOLLOW 0x80 // don't follow symlinks
+#define O_EXCL 0x100
+#define O_NOCTTY 0 // unsupported
+#define O_NONBLOCK 0x200
+#define O_SYNC 0 // not supported
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+typedef signed long ssize_t;
+
+#include "sys/stat.h" // mode_t
+
+extern int open(const char *path, int flags, ...);
+extern int creat(const char *path, mode_t mode);
+extern int close(int fd);
+
+extern ssize_t write(int fd, const void *buf, size_t count);
+extern ssize_t read(int fd, void *buf, size_t count);
+
+extern int fork(void);
+extern int execv(const char *b, char *v[]);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge
+ *
+ * main.c
+ * - Stub Main
+ */
+
+// === CODE ===
+int SoMain(void)
+{
+ return 0;
+}
+
--- /dev/null
+/*
+ * Acess2 POSIX Emulation Layer
+ * - By John Hodge
+ *
+ * unistd.c
+ * - POSIX->Acess VFS call translation
+ */
+#include <unistd.h>
+#include <acess/sys.h>
+#include <stdarg.h>
+
+// === CODE ===
+int open(const char *path, int openmode, ...)
+{
+ mode_t create_mode = 0;
+ int openflags = 0;
+
+ switch( openmode & O_RDWR )
+ {
+ case 0: // Special
+ break;
+ case O_RDONLY: openflags |= OPENFLAG_READ; break;
+ case O_WRONLY: openflags |= OPENFLAG_WRITE; break;
+ case O_RDWR: openflags |= OPENFLAG_READ|OPENFLAG_WRITE; break;
+ }
+
+ if( openmode & O_CREAT ) {
+ openflags |= OPENFLAG_CREATE;
+ va_list args;
+ va_start(args, openmode);
+ create_mode = va_arg(args, mode_t);
+ va_end(args);
+ }
+
+ return _SysOpen(path, openflags, create_mode);
+}
+
+int creat(const char *path, mode_t mode)
+{
+ // TODO: Make native call to do this cheaper
+ int fd = _SysOpen(path, OPENFLAG_CREATE, mode);
+ if( fd == -1 ) return -1;
+ _SysClose(fd);
+ return 0;
+}
+
+int close(int fd)
+{
+ _SysClose(fd);
+ return 0;
+}
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+ return _SysWrite(fd, buf, count);
+}
+
+ssize_t read(int fd, void *buf, size_t count)
+{
+ return _SysRead(fd, buf, count);
+}
+
+int fork(void)
+{
+ return _SysClone(CLONE_VM, 0);
+}
+
+int execv(const char *b, char *v[])
+{
+ return _SysExecVE(b, v, NULL);
+}
--- /dev/null
+
+extern char *mkstr(const char *format, ...);
--- /dev/null
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * arpa/inet.h
+ * -
+ */
+#ifndef _LIBPSOCKET__ARPA__INET_H_
+#define _LIBPSOCKET__ARPA__INET_H_
+
+#include <netinet/in.h>
+#include <stdint.h> // Should be inttypes.h?
+
+extern uint32_t htonl(uint32_t hostlong);
+extern uint16_t htons(uint16_t hostshort);
+extern uint32_t ntohl(uint32_t netlong);
+extern uint16_t ntohs(uint16_t netshort);
+
+extern in_addr_t inet_addr(const char *cp);
+extern in_addr_t inet_lnaof(struct in_addr in);
+extern struct in_addr inet_makeaddr(in_addr_t net, in_addr_t lna);
+extern in_addr_t inet_netof(struct in_addr in);
+extern in_addr_t inet_network(const char *cp);
+extern char *inet_ntoa(struct in_addr in);
+
+#endif
+
#include <stdint.h>
+typedef uint32_t in_addr_t;
+
struct in_addr
{
- unsigned long s_addr;
+ in_addr_t s_addr;
};
struct sockaddr_in
struct in_addr sin_addr;
};
+#define INADDR_ANY 0x00000000
+#define INADDR_BROADCAST 0xFFFFFFFF
+
+// getsockopt/setsockopt(level)
+enum {
+ IPPROTO_IP = 1,
+ IPPROTO_ICMP,
+ IPPROTO_TCP,
+ IPPROTO_UDP
+};
+
struct in6_addr
{
unsigned char s6_addr[16];
--- /dev/null
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * netinet/tcp.h
+ * - TCP Options
+ */
+#ifndef _NETINET__TCP_H_
+#define _NETINET__TCP_H_
+
+
+/**
+ * \brief Values for \a option_name in setsockopt/getsockopt
+ */
+enum eSockOpts_TCP
+{
+ TCP_NODELAY
+};
+
+#endif
+
/*
- * Acess2 C Library
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
*
* sys/sockets.h
* - POSIX Sockets
- *
- * By John Hodge (thePowersGang)
*/
#ifndef _SYS_SOCKETS_H_
#define _SYS_SOCKETS_H_
#include <sys/types.h>
+#include <stddef.h> // size_t
-typedef int socklen_t;
+typedef uint32_t socklen_t;
typedef enum
{
AF_UNSPEC = 0,
AF_PACKET = 1,
+ AF_LOCAL = 2,
AF_INET = 4,
AF_INET6 = 6,
} sa_family_t;
+#define AF_UNIX AF_LOCAL
struct sockaddr
{
char sa_data[16];
};
+struct msghdr
+{
+ void *msg_name;
+ socklen_t msg_namelen;
+ struct iovec *msg_iov;
+ int msg_iovlen;
+ void *msg_control;
+ socklen_t msg_controllen;
+ int msg_flags;
+};
+
+struct cmsghdr
+{
+ socklen_t cmsg_len;
+ int cmsg_level;
+ int cmsg_type;
+};
+
+#define SCM_RIGHTS 0x1
+
+#define CMSG_DATA(cmsg) ((unsigned char*)(cmsg + 1))
+#define CMSG_NXTHDR(mhdr, cmsg) 0
+#define CMSG_FIRSTHDR(mhdr) 0
+
+struct linger
+{
+ int l_onoff;
+ int l_linger;
+};
+
+enum eSocketTypes
+{
+ SOCK_STREAM, //!< Stream (TCP)
+ SOCK_DGRAM, //!< Datagram (UDP)
+ SOCK_SEQPACKET, //!<
+ SOCK_RAW, //!< Raw packet access
+ SOCK_RDM //!< Reliable non-ordered datagrams
+};
+
/**
* \brief Values for \a domain of socket()
*/
enum eSocketDomains
{
+ PF_UNSPEC,
PF_LOCAL, //!< Machine-local comms
PF_INET, //!< IPv4
PF_INET6, //!< IPv6
};
#define PF_UNIX PF_LOCAL
-enum eSocketTypes
+// getsockopt/setsockopt level
+enum
{
- SOCK_STREAM, //!< Stream (TCP)
- SOCK_DGRAM, //!< Datagram (UDP)
- SOCK_SEQPACKET, //!<
- SOCK_RAW, //!< Raw packet access
- SOCK_RDM //!< Reliable non-ordered datagrams
+ SOL_SOCKET
+};
+
+
+// SOL_SOCKET getsockopt/setsockopt names
+enum
+{
+ SO_REUSEADDR,
+ SO_LINGER
};
/**
extern int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen);
extern int send(int sockfd, void *buffer, size_t length, int flags);
+extern int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
+extern int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len);
+
+extern int getsockname(int socket, struct sockaddr *addr, socklen_t *addrlen);
+extern int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen);
+
#endif
--- /dev/null
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * sys/un.h
+ * - UNIX Domain Sockets
+ */
+#ifndef _LIBPSOCKET__SYS__UN_H_
+#define _LIBPSOCKET__SYS__UN_H_
+
+#define _SUN_PATH_MAX 108
+
+// POSIX Defined
+struct sockaddr_un
+{
+ sa_family_t sun_family;
+ char sun_path[_SUN_PATH_MAX];
+};
+
+#endif
+
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
+#include "common.h"
int SoMain(void)
{
* - sys/socket.h calls
*/
#include <sys/socket.h>
-#include <unistd.h>
+#include <acess/sys.h>
#include <stdlib.h> // malloc/free
#include <string.h>
#include <netinet/in.h>
+#include "common.h"
#define MAXFD 32
si = _GetInfo(0);
if( !si ) return -1;
- int fd = open("/Devices/null", O_RDWR);
+ int fd = _SysOpen("/Devices/null", OPENFLAG_RDWR);
if( fd == -1 ) return -1;
giNumPreinit ++;
else
path = mkstr("/Devices/ip/*%i/%s", si->local->sa_family, file);
- reopen(si->fd, path, O_RDWR);
+ _SysReopen(si->fd, path, OPENFLAG_RDWR);
// TODO: Error-check
free(path);
int child;
- child = _SysOpenChild(sockfd, "", O_RDWR);
+ child = _SysOpenChild(sockfd, "", OPENFLAG_RDWR);
if( child == -1 ) return -1;
- ioctl(child, 8, clientaddr);
+ _SysIOCtl(child, 8, clientaddr);
+
return child;
}
{
_CommitClient(sockfd);
// TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
- return read(sockfd, buffer, length);
+ return _SysRead(sockfd, buffer, length);
}
int recv(int sockfd, void *buffer, size_t length, int flags)
{
_CommitClient(sockfd);
- return read(sockfd, buffer, length);
+ return _SysRead(sockfd, buffer, length);
}
int sendto(int sockfd, const void *buffer, size_t length, int flags, const struct sockaddr *clientaddr, socklen_t addrlen)
{
_CommitClient(sockfd);
// TODO: Determine socket type (TCP/UDP) and use a bounce-buffer for UDP
- return write(sockfd, buffer, length);
+ return _SysWrite(sockfd, buffer, length);
}
int send(int sockfd, void *buffer, size_t length, int flags)
{
_CommitClient(sockfd);
- return write(sockfd, buffer, length);
+ return _SysWrite(sockfd, buffer, length);
}
int len, i;
// Read as much as possible (appending to remaining data)
- len = read(STDIN_FD, Info->ReadBuffer, READ_BUFFER_SIZE - 1 - Info->ReadBufferLen);
+ len = _SysRead(STDIN_FD, Info->ReadBuffer, READ_BUFFER_SIZE - 1 - Info->ReadBufferLen);
if( len <= 0 ) return NULL;
Info->ReadBuffer[Info->ReadBufferLen + len] = '\0';
// Move to the beginning of the line
pos = oldLen;
- while(pos--) write(STDOUT_FD, "\x1B[D", 3);
+ while(pos--) _SysWrite(STDOUT_FD, "\x1B[D", 3);
// Update state
Info->CurBuffer = Info->History[--Info->HistoryPos];
Info->BufferSize = Info->BufferUsed = strlen(Info->CurBuffer);
- write(STDOUT_FD, Info->CurBuffer, Info->BufferUsed);
+ _SysWrite(STDOUT_FD, Info->CurBuffer, Info->BufferUsed);
Info->BufferWritePos = Info->BufferUsed;
// Clear old characters (if needed)
if( oldLen > Info->BufferWritePos ) {
pos = oldLen - Info->BufferWritePos;
- while(pos--) write(STDOUT_FD, " ", 1);
+ while(pos--) _SysWrite(STDOUT_FD, " ", 1);
pos = oldLen - Info->BufferWritePos;
- while(pos--) write(STDOUT_FD, "\x1B[D", 3);
+ while(pos--) _SysWrite(STDOUT_FD, "\x1B[D", 3);
}
}
break;
// Move to the beginning of the line
pos = oldLen;
- while(pos--) write(STDOUT_FD, "\x1B[D", 3);
+ while(pos--) _SysWrite(STDOUT_FD, "\x1B[D", 3);
// Update state
Info->CurBuffer = Info->History[Info->HistoryPos++];
Info->BufferSize = Info->BufferUsed = strlen(Info->CurBuffer);
// Write new line
- write(STDOUT_FD, Info->CurBuffer, Info->BufferUsed);
+ _SysWrite(STDOUT_FD, Info->CurBuffer, Info->BufferUsed);
Info->BufferWritePos = Info->BufferUsed;
// Clear old characters (if needed)
if( oldLen > Info->BufferWritePos ) {
pos = oldLen - Info->BufferWritePos;
- while(pos--) write(STDOUT_FD, " ", 1);
+ while(pos--) _SysWrite(STDOUT_FD, " ", 1);
pos = oldLen - Info->BufferWritePos;
- while(pos--) write(STDOUT_FD, "\x1B[D", 3);
+ while(pos--) _SysWrite(STDOUT_FD, "\x1B[D", 3);
}
}
break;
case 'D': // Left
if(Info->BufferWritePos == 0) break;
Info->BufferWritePos --;
- write(STDOUT_FD, "\x1B[D", 3);
+ _SysWrite(STDOUT_FD, "\x1B[D", 3);
break;
case 'C': // Right
if(Info->BufferWritePos == Info->BufferUsed) break;
Info->BufferWritePos ++;
- write(STDOUT_FD, "\x1B[C", 3);
+ _SysWrite(STDOUT_FD, "\x1B[C", 3);
break;
}
break;
case '\b':
if(Info->BufferWritePos <= 0) break; // Protect against underflows
// Write the backsapce
- write(STDOUT_FD, &ch, 1);
+ _SysWrite(STDOUT_FD, &ch, 1);
if(Info->BufferWritePos == Info->BufferUsed) // Simple case: End of string
{
Info->BufferUsed --;
buf[3] += (delta/10) % 10;
buf[4] += (delta) % 10;
// Write everything save for the deleted character
- write(STDOUT_FD,
+ _SysWrite(STDOUT_FD,
&Info->CurBuffer[Info->BufferWritePos],
Info->BufferUsed - Info->BufferWritePos
);
- ch = ' '; write(STDOUT_FD, &ch, 1); ch = '\b'; // Clear old last character
- write(STDOUT_FD, buf, 7); // Update Cursor
+ ch = ' '; _SysWrite(STDOUT_FD, &ch, 1); ch = '\b'; // Clear old last character
+ _SysWrite(STDOUT_FD, buf, 7); // Update Cursor
// Alter Buffer
memmove(&Info->CurBuffer[Info->BufferWritePos-1],
&Info->CurBuffer[Info->BufferWritePos],
buf[2] += (delta/100) % 10;
buf[3] += (delta/10) % 10;
buf[4] += (delta) % 10;
- write(STDOUT_FD, &ch, 1); // Print new character
- write(STDOUT_FD,
+ _SysWrite(STDOUT_FD, &ch, 1); // Print new character
+ _SysWrite(STDOUT_FD,
&Info->CurBuffer[Info->BufferWritePos],
Info->BufferUsed - Info->BufferWritePos
);
- write(STDOUT_FD, buf, 7); // Update Cursor
+ _SysWrite(STDOUT_FD, buf, 7); // Update Cursor
// Move buffer right
memmove(
&Info->CurBuffer[Info->BufferWritePos+1],
}
// Simple append
else {
- write(STDOUT_FD, &ch, 1);
+ _SysWrite(STDOUT_FD, &ch, 1);
}
Info->CurBuffer[ Info->BufferWritePos ++ ] = ch;
Info->BufferUsed ++;
size_t URI_file_Read(int Handle, size_t Bytes, void *Buffer);
size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer);
void URI_file_Close(int Handle);
-size_t URI_file_GetSize(int Handle);
+off_t URI_file_GetSize(int Handle);
// === CONSTANTS ===
// Builtin URI protocol handlers
// printf("URI_file_Open: open('%s', 0x%x)\n", Path, smode);
{
int ret;
- ret = open(Path, smode);
+ ret = _SysOpen(Path, smode);
return ret;
}
}
{
// printf("URI_file_Read: (Handle=%i, Buffer=%p, Bytes=%i)\n",
// Handle, Buffer, (int)Bytes);
- return read(Handle, Buffer, Bytes);
+ return _SysRead(Handle, Buffer, Bytes);
}
size_t URI_file_Write(int Handle, size_t Bytes, void *Buffer)
{
- return write(Handle, Buffer, Bytes);
+ return _SysWrite(Handle, Buffer, Bytes);
}
void URI_file_Close(int Handle)
{
- close(Handle);
+ _SysClose(Handle);
}
-size_t URI_file_GetSize(int Handle)
+off_t URI_file_GetSize(int Handle)
{
- uint64_t curpos = tell(Handle);
- size_t ret;
- seek(Handle, 0, SEEK_END);
- ret = tell(Handle);
- seek(Handle, curpos, SEEK_SET);
+ uint64_t curpos = _SysTell(Handle);
+ off_t ret;
+ _SysSeek(Handle, 0, SEEK_END);
+ ret = _SysTell(Handle);
+ _SysSeek(Handle, curpos, SEEK_SET);
return ret;
}