--- /dev/null
+language: c
+compiler: clang
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq nasm
+env:
+ - ARCH=host HOST_ARCH=x86 USE_ACPICA=0
+ - ARCH=host HOST_ARCH=x86_64 CC="$CC -m64"
+script: "make all"
ld-acess.exe
AcessKernel
AcessKernel.exe
+Makefile.BuildNum
{
const char *retptr = strchr(str, ch);
int rv = retptr ? retptr - str : -1;
- fprintf(stderr, "strpos: str = %p'%s', retptr = %p, rv = %i\n", str, str, retptr, rv);
return rv;
}
{
if( (intptr_t)string < 0x1000 )
return 0;
- strlen(string);
return 1;
}
return 1;
}
+void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
+{
+ static const char cUCDIGITS[] = "0123456789ABCDEF";
+ char tmpBuf[64+1];
+ int pos=0, i;
+ Uint64 rem;
+
+ // Sanity check
+ if(!buf) return;
+
+ // Sanity Check
+ if(base > 16 || base < 2) {
+ buf[0] = 0;
+ return;
+ }
+
+ // Convert
+ while(num > base-1) {
+ rem = num % base;
+ num = num / base; // Shift `num` and get remainder
+ tmpBuf[pos] = cUCDIGITS[ rem ];
+ pos++;
+ }
+ tmpBuf[pos++] = cUCDIGITS[ num ]; // Last digit of `num`
+
+ // Put in reverse
+ i = 0;
+ minLength -= pos;
+ while(minLength-- > 0)
+ buf[i++] = pad;
+ while(pos-- > 0)
+ buf[i++] = tmpBuf[pos]; // Reverse the order of characters
+ buf[i] = 0;
+}
+
LEAVE('i', 0);\r
return 0;\r
}\r
- LEAVE('-');\r
- return fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+ size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+ LEAVE('x', ret);\r
+ return ret;\r
}\r
\r
size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer)\r
a3 = *(_t3*)Args;Args+=sizeof(_t3);\
a4 = *(_t4*)Args;Args+=sizeof(_t4);\
a5 = *(_t5*)Args;Args+=sizeof(_t5);\
- LOG("SYSCALL5 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
+ LOG("SYSCALL6 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
_call\
}
#define SYSCALL5(_name, _fmtstr, _t0, _t1, _t2, _t3, _t4, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
int argListLen = 0;
int i, retVal;
tRequestHeader *ret;
- int retValueCount = 1;
- int retDataLen = sizeof(Uint64);
+ int retValueCount;
+ int retDataLen;
void *returnData[Request->NParams];
int argSizes[Request->NParams];
Uint ret_errno = 0;
+ // Clear errno (Acess verson) at the start of the request
+ errno = 0;
+
// Sanity check
if( Request->CallID >= ciNumSyscalls ) {
Log_Notice("Syscalls", "Unknown syscall number %i", Request->CallID);
Log_Notice("Syscalls", "Unimplemented syscall %i", Request->CallID);
return NULL;
}
-
+
+ // Init return count/size
+ retValueCount = 2;
+ retDataLen = sizeof(Uint64) + sizeof(Uint32);
+
// Get size of argument list
for( i = 0; i < Request->NParams; i ++ )
{
case ARG_TYPE_DATA:
formatString[i] = 'd';
argListLen += sizeof(void*);
+ // Prepare the return values
+ if( Request->Params[i].Flags & ARG_FLAG_RETURN )
+ {
+ retDataLen += Request->Params[i].Length;
+ retValueCount ++;
+ }
break;
case ARG_TYPE_STRING:
formatString[i] = 's';
argListLen += sizeof(char*);
break;
default:
+ Log_Error("Syscalls", "Unknown param type %i", Request->Params[i].Type);
return NULL; // ERROR!
}
}
// Data gets special handling, because only it can be returned to the user
// (ARG_TYPE_DATA is a pointer)
case ARG_TYPE_DATA:
- // Prepare the return values
- if( Request->Params[i].Flags & ARG_FLAG_RETURN )
- {
- retDataLen += Request->Params[i].Length;
- retValueCount ++;
- }
-
// Check for non-resident data
if( Request->Params[i].Length == 0 )
{
// ---------- Return
- if( ret_errno == 0 ) {
- perror("Syscall?");
+ if( ret_errno == 0 && errno != 0 ) {
ret_errno = errno;
+ LOG("errno = %i", errno);
}
// Allocate the return
*(Uint64*)inData = retVal;
inData += sizeof(Uint64);
+ // Static Uint32 errno value
+ ret->Params[1].Type = ARG_TYPE_INT32;
+ ret->Params[1].Flags = 0;
+ ret->Params[1].Length = sizeof(Uint32);
+ *(Uint32*)inData = ret_errno;
+ inData += sizeof(Uint32);
+
+ LOG("Ret: %llx, errno=%i", retVal, ret_errno);
+
//Log_Debug("Syscalls", "Return 0x%llx", retVal);
- retValueCount = 1;
+ retValueCount = 2;
for( i = 0; i < Request->NParams; i ++ )
{
if( Request->Params[i].Type != ARG_TYPE_DATA ) continue;
retValueCount ++;
}
- *ReturnLength = sizeof(tRequestHeader)
- + retValueCount * sizeof(tRequestValue)
- + retDataLen;
+ *ReturnLength = ret->MessageLength;
return ret;
}
strcat(tmp, "/");
strcat(tmp, Name);
- fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ fd = acess__SysOpen(tmp, 4); // OPENFLAG_EXEC
if(fd != -1) {
- acess_close(fd);
+ acess__SysClose(fd);
return strdup(tmp);
}
}
printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
#endif
- fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ fd = acess__SysOpen(tmp, 4); // OPENFLAG_EXEC
if(fd != -1) {
- acess_close(fd);
+ acess__SysClose(fd);
return strdup(tmp);
}
}
}
}
- fd = acess_open(Filename, 2|1); // Execute and Read
+ fd = acess__SysOpen(Filename, 2|1); // Execute and Read
if( fd == -1 ) {
// TODO: Handle libary directories
perror("Opening binary");
return NULL;
}
- acess_read(fd, &dword, 4);
- acess_seek(fd, 0, ACESS_SEEK_SET);
+ acess__SysRead(fd, &dword, 4);
+ acess__SysSeek(fd, 0, ACESS_SEEK_SET);
if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
fmt = &gElf_FormatDef;
}
else {
fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
- acess_close(fd);
+ acess__SysClose(fd);
return NULL;
}
printf("fmt->Load(0x%x)...\n", fd);
#endif
ret = fmt->Load(fd);
- acess_close(fd);
+ acess__SysClose(fd);
#if DEBUG
printf("fmt->Load(0x%x): %p\n", fd, ret);
#endif
return 0;
}
+
extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits);
Elf64_Ehdr hdr;\r
\r
// Read ELF Header\r
- acess_read(FD, &hdr, sizeof(hdr));\r
+ acess__SysRead(FD, &hdr, sizeof(hdr));\r
\r
// Check the file type\r
if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
return NULL;\r
}\r
LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
- acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);\r
- acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
+ acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
\r
// Count Pages\r
iPageCount = 0;\r
char *tmp;\r
//if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].FileSize);\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, tmp, phtab[i].FileSize);\r
+ acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, tmp, phtab[i].FileSize);\r
//ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'\n", tmp);\r
free(tmp);\r
return NULL;\r
}\r
\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, PTRMK(void, addr), phtab[i].FileSize);\r
+ acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, PTRMK(void, addr), phtab[i].FileSize);\r
memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
}\r
\r
return NULL;\r
}\r
LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
- acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
- acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
+ acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
\r
// Count Pages\r
iPageCount = 0;\r
//if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].p_filesz+1);\r
tmp[ phtab[i].p_filesz ] = 0;\r
- acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
- acess_read(FD, tmp, phtab[i].p_filesz);\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, tmp, phtab[i].p_filesz);\r
//ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'\n", tmp);\r
free(tmp);\r
return NULL;\r
}\r
\r
- acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
- acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );\r
}\r
\r
// === CODE ===
// --- VFS Calls
-int acess_chdir(const char *Path)
+int acess__SysChdir(const char *Path)
{
return _Syscall(SYS_CHDIR, ">s", Path);
}
-int acess_open(const char *Path, int Flags)
+int acess__SysOpen(const char *Path, int Flags)
{
if( strncmp(Path, "$$$$", 4) == 0 )
{
return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
}
-void acess_close(int FD) {
+void acess__SysClose(int FD)
+{
if(FD & NATIVE_FILE_MASK) {
return native_close(FD & (NATIVE_FILE_MASK-1));
}
_Syscall(SYS_CLOSE, ">i", FD);
}
-int acess_reopen(int FD, const char *Path, int Flags) {
+int acess__SysReopen(int FD, const char *Path, int Flags) {
DEBUG("reopen(0x%x, \"%s\", 0x%x)", FD, Path, Flags);
return _Syscall(SYS_REOPEN, ">i >s >i", FD, Path, Flags);
}
-size_t acess_read(int FD, void *Dest, size_t Bytes) {
+size_t acess__SysRead(int FD, void *Dest, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_read(FD & (NATIVE_FILE_MASK-1), Dest, Bytes);
// if( FD > 2 )
return _Syscall(SYS_READ, ">i >i <d", FD, Bytes, Bytes, Dest);
}
-size_t acess_write(int FD, const void *Src, size_t Bytes) {
+size_t acess__SysWrite(int FD, const void *Src, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_write(FD & (NATIVE_FILE_MASK-1), Src, Bytes);
// if( FD > 2 )
return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
}
-int acess_seek(int FD, int64_t Ofs, int Dir) {
+int acess__SysSeek(int FD, int64_t Ofs, int Dir)
+{
if(FD & NATIVE_FILE_MASK) {
return native_seek(FD & (NATIVE_FILE_MASK-1), Ofs, Dir);
}
return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
}
-uint64_t acess_tell(int FD) {
+uint64_t acess__SysTell(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_ioctl(int fd, int id, void *data) {
+int acess__SysIOCtl(int fd, int id, void *data) {
int len;
DEBUG("ioctl(%i, %i, %p)", fd, id, data);
// NOTE: The length here is hacky and could break
len = PAGE_SIZE - ((uintptr_t)data % PAGE_SIZE);
return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, len, data);
}
-int acess_finfo(int fd, t_sysFInfo *info, int maxacls) {
+int acess__SysFInfo(int fd, t_sysFInfo *info, int maxacls) {
// DEBUG("offsetof(size, t_sysFInfo) = %i", offsetof(t_sysFInfo, size));
DEBUG("finfo(%i, %p, %i)", fd, info, maxacls);
return _Syscall(SYS_FINFO, ">i <d >i",
);
}
-int acess_SysReadDir(int fd, char *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_select(int nfds, fd_set *read, fd_set *write, fd_set *error, int64_t *timeout)
-{
- return acess__SysSelect(nfds, read, write, error, timeout, 0);
-}
-
-
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);
}
// --- Process Management ---
-int acess_clone(int flags, void *stack)
+int acess__SysClone(int flags, void *stack)
{
#ifdef __WIN32__
Warning("Win32 does not support anything like fork(2), cannot emulate");
#endif
}
-int acess_execve(char *path, char **argv, const char **envp)
+int acess__SysExecVE(char *path, char **argv, const char **envp)
{
int i, argc;
return kernel_tid;
}
-void acess_sleep(void)
-{
- DEBUG("%s()", __func__);
- _Syscall(SYS_SLEEP, "");
-}
+//void acess_sleep(void)
+//{
+// DEBUG("%s()", __func__);
+// _Syscall(SYS_SLEEP, "");
+//}
-int acess_waittid(int TID, int *ExitStatus)
+int acess__SysWaitTID(int TID, int *ExitStatus)
{
DEBUG("%s(%i, %p)", __func__, TID, ExitStatus);
return _Syscall(SYS_WAITTID, ">i <d", TID, sizeof(int), &ExitStatus);
int acess_getuid(void) { return _Syscall(SYS_GETUID, ""); }
int acess_getgid(void) { return _Syscall(SYS_GETGID, ""); }
-int acess_SysSendMessage(int DestTID, int Length, void *Data)
+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, int BufLen, void *Data)
+int acess__SysGetMessage(int *SourceTID, int BufLen, void *Data)
{
DEBUG("%s(%p, %p)", __func__, SourceTID, Data);
return _Syscall(SYS_GETMSG, "<d <d",
const tSym caBuiltinSymbols[] = {
DEFSYM(_exit),
- DEFSYM(chdir),
- DEFSYM(open),
- DEFSYM(close),
- DEFSYM(reopen),
- DEFSYM(read),
- DEFSYM(write),
- DEFSYM(seek),
- DEFSYM(tell),
- DEFSYM(ioctl),
- DEFSYM(finfo),
- DEFSYM(SysReadDir),
- DEFSYM(select),
+ DEFSYM(_SysChdir),
+ DEFSYM(_SysOpen),
DEFSYM(_SysOpenChild),
+ DEFSYM(_SysReopen),
+ DEFSYM(_SysClose),
+ DEFSYM(_SysRead),
+ DEFSYM(_SysWrite),
+ DEFSYM(_SysSeek),
+ DEFSYM(_SysTell),
+ DEFSYM(_SysIOCtl),
+ DEFSYM(_SysFInfo),
+ DEFSYM(_SysReadDir),
DEFSYM(_SysGetACL),
DEFSYM(_SysMount),
DEFSYM(_SysSelect),
- DEFSYM(clone),
- DEFSYM(execve),
+ DEFSYM(_SysClone),
+ DEFSYM(_SysExecVE),
DEFSYM(_SysSpawn),
- DEFSYM(sleep),
+// DEFSYM(sleep),
- DEFSYM(waittid),
+ DEFSYM(_SysWaitTID),
DEFSYM(gettid),
DEFSYM(setuid),
DEFSYM(setgid),
DEFSYM(getuid),
DEFSYM(getgid),
- DEFSYM(SysSendMessage),
- DEFSYM(SysGetMessage),
+ DEFSYM(_SysSendMessage),
+ DEFSYM(_SysGetMessage),
DEFSYM(_SysAllocate),
DEFSYM(_SysSetMemFlags),
// Syscall request (used by acess_*)
extern uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...);
+extern int acess__errno;
+
extern int native_open(const char *Path, int Flags);
extern void native_close(int FD);
extern size_t native_read(int FD, void *Dest, size_t Bytes);
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);
-extern void acess_close(int FD);
-extern size_t acess_read(int FD, void *Dest, size_t Bytes);
-extern int acess_seek(int FD, int64_t Offset, int Dir);
+extern int acess__SysOpen(const char *Path, int Flags);
+extern void acess__SysClose(int FD);
+extern size_t acess__SysRead(int FD, void *Dest, size_t Bytes);
+extern int acess__SysSeek(int FD, int64_t Offset, int Dir);
// Symbol type
typedef struct {
}
if(strcmp(argv[i], "--open") == 0) {
- if( acess_open(argv[++i], 6) == -1 ) { // Read/Write
+ if( acess__SysOpen(argv[++i], 6) == -1 ) { // Read/Write
fprintf(stderr, "Unable to open '%s'\n", argv[i]);
exit(1);
}
#define DEBUG(...) do{}while(0)
#endif
+#define assert(cnd) do{ \
+ if( !(cnd) ) { \
+ fprintf(stderr, "%s:%i - assert failed - " #cnd, __FILE__, __LINE__);\
+ exit(-1); \
+ } \
+}while(0)
+
#define MAX_FPS 16
// === Types ===
{
va_list args;
int paramCount, dataLength;
- int retCount = 1, retLength = sizeof(uint64_t);
+ int retCount = 2, retLength = sizeof(uint64_t) + sizeof(uint32_t);
void **retPtrs; // Pointers to return buffers
const char *str;
tRequestHeader *req;
}
va_end(args);
- // Send syscall request
+ // --- Send syscall request
if( SendRequest(req, dataLength, retLength) < 0 ) {
fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
exit(127);
}
- // Parse return value
- dataPtr = &req->Params[req->NParams];
- retValue = 0;
- if( req->NParams >= 1 )
- {
- switch(req->Params[0].Type)
- {
- case ARG_TYPE_INT64:
- retValue = *(uint64_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- case ARG_TYPE_INT32:
- retValue = *(uint32_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- }
- }
+ Debug("req->NParams = %i", req->NParams);
+ assert(req->NParams >= 2);
+ // return
+ assert(req->Params[0].Type == ARG_TYPE_INT64);
+ assert(req->Params[0].Length == sizeof(uint64_t));
+ retValue = *(uint64_t*)dataPtr;
+ dataPtr += sizeof(uint64_t);
+ // errno
+ assert(req->Params[1].Type == ARG_TYPE_INT32);
+ assert(req->Params[1].Length == sizeof(uint32_t));
+ acess__errno = *(uint32_t*)dataPtr;
+ dataPtr += sizeof(uint32_t);
// Write changes to buffers
- if( req->NParams - 1 != retCount ) {
+ if( req->NParams - 2 != 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 ++ )
+ for( i = 2; i < req->NParams; i ++ )
{
#if 0
int j;
printf(" %02x", ((uint8_t*)dataPtr)[j]);
printf("\n");
#endif
+ assert( req->Params[i].Type == ARG_TYPE_DATA );
memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length );
dataPtr += req->Params[i].Length;
}
tRequestValue Params[];
} tRequestHeader;
-enum eSyscalls {
- SYS_NULL,
-
- SYS_EXIT,
-
- SYS_OPEN,
- SYS_CLOSE,
- SYS_READ,
- SYS_WRITE,
- SYS_SEEK,
- SYS_TELL,
- SYS_IOCTL,
- SYS_FINFO,
- SYS_READDIR,
- SYS_OPENCHILD,
- SYS_GETACL,
- SYS_MOUNT,
- SYS_REOPEN,
- SYS_CHDIR,
-
- SYS_WAITTID,
- SYS_SETUID,
- SYS_SETGID,
-
- SYS_GETTID,
- SYS_GETPID,
- SYS_GETUID,
- SYS_GETGID,
- // IPC
- SYS_SLEEP,
- SYS_AN_FORK,
- SYS_AN_SPAWN,
- SYS_SENDMSG,
- SYS_GETMSG,
- SYS_SELECT,
- SYS_WAITEVENT,
-
+enum eSyscalls {
+ #define _(n) n
+ #include "syscalls_list.h"
+ #undef _
N_SYSCALLS
};
#ifndef DONT_INCLUDE_SYSCALL_NAMES
static const char * casSYSCALL_NAMES[] = {
- "SYS_NULL",
-
- "SYS_EXIT",
-
- "SYS_OPEN",
- "SYS_CLOSE",
- "SYS_READ",
- "SYS_WRITE",
- "SYS_SEEK",
- "SYS_TELL",
- "SYS_IOCTL",
- "SYS_FINFO",
- "SYS_READDIR",
- "SYS_OPENCHILD",
- "SYS_GETACL",
- "SYS_MOUNT",
- "SYS_REOPEN",
- "SYS_CHDIR",
-
- "SYS_WAITTID",
- "SYS_SETUID",
- "SYS_SETGID",
-
- "SYS_GETTID",
- "SYS_GETPID",
- "SYS_GETUID",
- "SYS_GETGID",
-
- // IPC
- "SYS_SLEEP",
- "SYS_AN_FORK",
- "SYS_SENDMSG",
- "SYS_GETMSG",
- "SYS_SELECT",
- "SYS_WAITEVENT"
+ #define _(n) #n
+ #include "syscalls_list.h"
+ #undef _
+ "-"
};
#endif
--- /dev/null
+_(SYS_NULL),
+
+_(SYS_EXIT),
+
+_(SYS_OPEN),
+_(SYS_CLOSE),
+_(SYS_READ),
+_(SYS_WRITE),
+_(SYS_SEEK),
+_(SYS_TELL),
+_(SYS_IOCTL),
+_(SYS_FINFO),
+_(SYS_READDIR),
+_(SYS_OPENCHILD),
+_(SYS_GETACL),
+_(SYS_MOUNT),
+_(SYS_REOPEN),
+_(SYS_CHDIR),
+
+_(SYS_WAITTID),
+_(SYS_SETUID),
+_(SYS_SETGID),
+
+_(SYS_GETTID),
+_(SYS_GETPID),
+_(SYS_GETUID),
+_(SYS_GETGID),
+
+// IPC
+_(SYS_SLEEP),
+_(SYS_AN_FORK),
+_(SYS_AN_SPAWN),
+_(SYS_SENDMSG),
+_(SYS_GETMSG),
+_(SYS_SELECT),
+_(SYS_WAITEVENT),
+
# Core ARMv7 modules
-MODULES += armv7/GIC
MODULES += Filesystems/InitRD
include $(ACESSDIR)/BuildConf/armv7/default.mk
ARM_CPUNAME = cortex-a8
+MODULES += armv7/GIC
MODULES += Input/PS2KbMouse
MODULES += Display/PL110
include $(ACESSDIR)/BuildConf/armv7/default.mk
ARM_CPUNAME = cortex-a9
+MODULES += armv7/GIC
MODULES += Display/Tegra2Vid
MODULES += USB/Core USB/EHCI
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
+A_OBJ += vpci_$(PLATFORM).o platform_$(PLATFORM).o
#main.c: Makefile.BuildNum.$(ARCH)
extern void Heap_Install(void);
extern void Threads_Init(void);
extern void System_Init(const char *Commandline);
+extern void Time_Setup(void);
// === PROTOTYPES ===
int kmain(void);
//
LogF("Moving to arch-independent init\n");
#if PLATFORM_is_tegra2
- System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=Tegra2Vid");
+ System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=Tegra2Vid -USB_EHCI:C5000000-14,C5004000-15");
#else
System_Init("Acess2.armv7.bin /Acess=initrd: -VTerm:Video=PL110");
#endif
#include <hal_proc.h>
#define TRACE_MAPS 0
-#define TRACE_COW 1
+#define TRACE_COW 0
#define AP_KRW_ONLY 1 // Kernel page
#define AP_KRO_ONLY 5 // Kernel RO page
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * platform_realviewpb.c
+ * - RealviewPB core code
+ */
+#include <acess.h>
+
+// === PROTOTYPES ===
+void Time_Setup(void);
+
+// === GLOBALS ===
+tPAddr gGIC_DistributorAddr = 0x1e001000;
+tPAddr gGIC_InterfaceAddr = 0x1e000000;
+
+// === CODE ===
+void Time_Setup(void)
+{
+ // TODO:
+}
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * platform_tegra2.c
+ * - Tegra2 Core code
+ */
+#include <acess.h>
+#include "platform_tegra2.h"
+
+// === CONSTANTS ===
+#define TIMER0_INT (0*32+0) // Pri #0
+#define TIMER1_INT (0*32+1) // Pri #1
+#define TIMER2_INT (1*32+9) // Sec #9
+#define TIMER3_INT (1*32+10) // Sec #10
+
+// === Imports ===
+extern volatile Sint64 giTimestamp;
+extern volatile Uint64 giTicks;
+extern volatile Uint64 giPartMiliseconds;
+extern void Timer_CallTimers(void);
+
+// === PROTORTYPES ===
+void Timer_IRQHandler_SysClock(int IRQ, void *_unused);
+void Time_Setup(void);
+
+// === GLOBALS ===
+// - Addresses for the GIC to use
+tPAddr gGIC_InterfaceAddr = 0x50040000;
+tPAddr gGIC_DistributorAddr = 0x50041000;
+// - Map of timer registers
+struct sTimersMap *gpTimersMap;
+// - Interrupt controller code commented out, because the Tegra2 also has a GIC
+#if 0
+struct sIRQMap gpIRQMap;
+#endif
+
+// === CODE ===
+
+// -- Timers --
+void Timer_IRQHandler_SysClock(int IRQ, void *_unused)
+{
+ giTimestamp += 100;
+ gpTimersMap->TMR0.PCR_0 = (1<<31);
+}
+
+void Time_Setup(void)
+{
+ gpTimersMap = (void*)MM_MapHWPages(0x60005000, 1);
+ // Timer 1 (used for system timekeeping)
+ IRQ_AddHandler(0*32+0, Timer_IRQHandler_SysClock, NULL);
+ gpTimersMap->TMR0.PTV_0 = (1<31)|(1<30)|(100*1000); // enable, periodic, 100 ms
+}
+
+#if 0
+// -- Interrupt Controller --
+void IRQ_CtrlrHandler(struct sIRQRegs *Ctrlr, int Ofs)
+{
+ // Primary CPU only?
+ // TODO:
+}
+
+void IRQ_RootHandler(void)
+{
+ IRQ_CtrlrHandler(&gpIRQMap->Pri, 0*32);
+ IRQ_CtrlrHandler(&gpIRQMap->Sec, 1*32);
+ IRQ_CtrlrHandler(&gpIRQMap->Tri, 2*32);
+ IRQ_CtrlrHandler(&gpIRQMap->Quad, 3*32);
+}
+
+void IRQ_Setup(void)
+{
+ gpIRQMap = (void*)MM_MapHWPages(0x60004000, 1);
+
+ gpIRQHandler = IRQ_RootHandler;
+}
+#endif
--- /dev/null
+/*
+ * Acess2 Kernel ARMv7 Port
+ * - By John Hodge (thePowersGang)
+ *
+ * platform_tegra2.c
+ * - Tegra2 Core code
+ */
+#ifndef _PLATFORM__TEGRA2_H_
+#define _PLATFORM__TEGRA2_H_
+
+struct sTimerRegs
+{
+ Uint32 PTV_0; // Control / Target value
+ Uint32 PCR_0; // Current value / IRQ clear
+};
+struct sTimersMap
+{
+ struct sTimerRegs TMR0;
+ struct sTimerRegs TMR1;
+ // TMRUS
+ char _padding[ 0x50-0x10 ];
+
+ struct sTimerRegs TMR2;
+ struct sTimerRegs TMR3;
+};
+
+#if 0
+struct sIRQRegs
+{
+ Uint32 VIRQ_CPU;
+ Uint32 VIRQ_COP;
+ Uint32 VFIQ_CPU;
+ Uint32 VFIQ_COP;
+ Uint32 ISR;
+ Uint32 FIR; // Force interrupt status
+ Uint32 FIR_SET; // Set bit in FIR
+ Uint32 FIR_CLR; // Clear bit in FIR
+ Uint32 CPU_IER; // RO - Interrupt Enable register
+ Uint32 CPU_IER_SET;
+ Uint32 CPU_IER_CLR;
+ Uint32 CPU_IEP; // 1 = FIQ
+ Uint32 COP_IER; // RO - Interrupt Enable register
+ Uint32 COP_IER_SET;
+ Uint32 COP_IER_CLR;
+ Uint32 COP_IEP; // 1 = FIQ
+};
+struct sArbGntRegs
+{
+ Uint32 CPU_Status;
+ Uint32 CPU_Enable;
+ Uint32 COP_Status;
+ Uint32 COP_Enable;
+};
+struct sIRQMap
+{
+ struct sIRQRegs Pri;
+ struct sArbGntRegs Arb;
+ char _pad1[0x100-sizeof(struct sIRQRegs)-sizeof(struct sIRQRegs)];
+ struct sIRQRegs Sec;
+ char _pad2[0x100-sizeof(struct sIRQRegs)];
+ struct sIRQRegs Tri;
+ char _pad3[0x100-sizeof(struct sIRQRegs)];
+ struct sIRQRegs Quad;
+};
+#endif
+
+#endif
+
// === GLOBALS ===
tVPCI_Device gaVPCI_Devices[] = {
+ // NOTE: USB Controllers moved to command line arguments
+ #if 0
{
.Vendor=0x0ACE,.Device=0x1100,
- .Class = 0x0C032000, // Serial, USB, ECHI
+ .Class = 0x0C032100, // Serial, USB, ECHI
.BARs = {0xC5000000,0,0,0,0,0},
.IRQ = 0*32+20,
},
.BARs = {0xC5008000,0,0,0,0,0},
.IRQ = 4*32+1,
}
+ #endif
};
int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]);
* acpica.c
* - ACPICA Interface
*/
-#define ACPI_DEBUG_OUTPUT 1
+#define ACPI_DEBUG_OUTPUT 0
#define DEBUG 0
#define _AcpiModuleName "Shim"
#define _COMPONENT "Acess"
// === IMPORTS ===
extern char gKernelEnd[];
-extern void Heap_Install(void);
extern void MM_PreinitVirtual(void);
extern void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges);
extern void MM_InstallVirtual(void);
// Create BIOS Call process
pid = Proc_Clone(CLONE_VM);
- Log_Debug("VM8086", "pid = %i", pid);
+ //Log_Debug("VM8086", "pid = %i", pid);
if(pid == -1)
{
Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
Uint16 * volatile rmstack; // Real Mode Stack
int i;
- Log_Debug("VM8086", "Initialising worker");
+ //Log_Debug("VM8086", "Initialising worker");
// Set Image Name
Threads_SetName("VM8086");
// 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
);
Log_Log("Arch", "Starting VFS...");
VFS_Init();
+ // Multiboot_InitFramebuffer(mbInfo);
+
gaArch_BootModules = Multiboot_LoadModules(mbInfo, KERNEL_BASE, &giArch_NumBootModules);
*(Uint16*)(KERNEL_BASE|0xB8000) = 0x1F00|'Z';
tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
{
Uint rsp;
- tThread *newThread, *cur;
+ tThread *newThread;
- cur = Proc_GetCurThread();
newThread = Threads_CloneTCB(0);
if(!newThread) return -1;
*/
tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
{
- tThread *new, *cur;
+ tThread *new;
Uint stack_contents[3];
- cur = Proc_GetCurThread();
-
// Create new thread
new = Threads_CloneThreadZero();
if(!new) {
va_list args;
#if LOCK_DEBUG_OUTPUT
- SHORTLOCK(&glDebug_Lock);
+ if(!CPU_HAS_LOCK(&glDebug_Lock)) SHORTLOCK(&glDebug_Lock);
#endif
Debug_Puts(0, "Debug: ");
va_list args;
#if LOCK_DEBUG_OUTPUT
- SHORTLOCK(&glDebug_Lock);
+ if( !CPU_HAS_LOCK(&glDebug_Lock) )
+ SHORTLOCK(&glDebug_Lock);
#endif
// And never SHORTREL
-/* AcessOS
- * FIFO Pipe Driver
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/fifo.c
+ * - FIFO Pipe Driver
*/
#define DEBUG 0
#include <acess.h>
if(Filename[0] == '\0') return NULL;
// Anon Pipe
- if(Filename[0] == 'a' && Filename[1] == 'n'
- && Filename[2] == 'o' && Filename[3] == 'n'
- && Filename[4] == '\0') {
+ if( strcmp(Filename, "anon") == 0 )
+ {
tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
return &tmp->Node;
}
// Mark some flags
if( pipe->ReadPos == pipe->WritePos ) {
+ LOG("%i == %i, marking none to read", pipe->ReadPos, pipe->WritePos);
VFS_MarkAvaliable(Node, 0);
}
VFS_MarkFull(Node, 0); // Buffer can't still be full
while(remaining)
{
// Wait for buffer to empty
- if(pipe->Flags & PF_BLOCKING) {
- if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
+ if(pipe->Flags & PF_BLOCKING)
+ {
+ if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize ) {
+ LOG("Blocking write on FIFO");
VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
+ }
len = remaining;
if( pipe->ReadPos > pipe->WritePos )
if(len > pipe->BufSize - pipe->WritePos)
{
int ofs = pipe->BufSize - pipe->WritePos;
+ LOG("pipe->Buffer = %p, pipe->WritePos = %i, ofs=%i, len=%i",
+ pipe->Buffer, pipe->WritePos, ofs, len);
memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
- memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
+ memcpy(&pipe->Buffer[0], (Uint8*)Buffer + ofs, len-ofs);
}
else
{
+ LOG("pipe->Buffer = %p, pipe->WritePos = %i", pipe->Buffer, pipe->WritePos);
memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
}
// Mark some flags
if( pipe->ReadPos == pipe->WritePos ) {
+ LOG("Buffer is full");
VFS_MarkFull(Node, 1); // Buffer full
}
VFS_MarkAvaliable(Node, 1);
tPipe *ret;
int namelen = strlen(Name) + 1;
int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
-
+
+ ENTER("iSize sName", Size, Name);
+
ret = calloc(1, allocsize);
- if(!ret) return NULL;
+ if(!ret) LEAVE_RET('n', NULL);
- // Clear Return
+ // Set default flags
ret->Flags = PF_BLOCKING;
// Allocate Buffer
= ret->Node.MTime
= ret->Node.ATime = now();
ret->Node.Type = &gFIFO_PipeNodeType;
+
+ LEAVE('p', ret);
return ret;
}
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
+ #if LIST_DEVICES\r
+ Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i",\r
+ 0xFF, i, 0, devinfo->class,\r
+ devinfo->vendor, devinfo->device, devinfo->revision);\r
+ #endif\r
\r
for(int j = 0; j < 256/4; j ++ )\r
- devinfo->ConfigCache[i] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4);\r
+ devinfo->ConfigCache[j] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4);\r
\r
memset(&devinfo->Node, 0, sizeof(devinfo->Node));\r
devinfo->Node.Inode = giPCI_DeviceCount;\r
case 0: // Vendor[0:15], Device[16:31]
tmp_dword = (Dev->Vendor) | (Dev->Device << 16);
break;
+ // 1: Command[0:15], Status[16:31]
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
+ case 4 ... 9: // 4-9: BARs
+ tmp_dword = Dev->BARs[ (Offset>>2) - 4 ];
+ break;
// 10: Unused (Cardbus CIS Pointer)
// 11: Subsystem Vendor ID, Subsystem ID
// 12: Expansion ROM Address
// 14: Reserved
// 15: Interrupt Line, Interrupt Pin, Min Grant, Max Latency
default:
- tmp_dword = Dev->Read(Dev->Ptr, Offset >> 2);
+ if( Dev->Read )
+ tmp_dword = Dev->Read(Dev->Ptr, Offset >> 2);
break;
}
return ;
}
- tmp_dword = Dev->Read(Dev->Ptr, Offset>>2);
+ if( Size != 4 && Dev->Read )
+ tmp_dword = Dev->Read(Dev->Ptr, Offset>>2);
+ else
+ tmp_dword = 0;
switch(Size)
{
case 4: tmp_dword = 0; break;
break;
}
tmp_dword |= Data << ((Offset&3)*8);
- Dev->Write(Dev->Ptr, Offset>>2, tmp_dword);
+ if( Dev->Write )
+ Dev->Write(Dev->Ptr, Offset>>2, tmp_dword);
}
else if( strcmp(opt, "Scrollback") == 0 ) {
giVT_Scrollback = atoi( val );
}
+ else {
+ Log_Notice("VTerm", "Unknown option '%s'", opt);
+ }
}
}
// - Sanity Checking
size = term->Width*term->Height*4;
if( Offset > size ) {
- Log_Notice("VTerm", "VT_Write: Offset (0x%llx) > FBSize (0x%x)",
- Offset, size);
+ Log_Notice("VTerm", "VT_Write: %i Offset (0x%llx) > FBSize (0x%x)",
+ (int)Node->Inode, Offset, size);
return 0;
}
if( Offset + Length > size ) {
extern void VT_KBCallBack(Uint32 Codepoint);
// --- VT100 Emulation ---
extern void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args);
-extern int VT_int_ParseEscape(tVTerm *Term, const char *Buffer);
+extern int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes);
// --- Terminal Buffer ---
extern void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count);
extern void VT_int_PutChar(tVTerm *Term, Uint32 Ch);
*/
void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
{
- Uint32 val;
int i;
// Iterate
for( i = 0; i < Count; i++ )
{
// Handle escape sequences
- if( Buffer[i] == 0x1B )
+ if( Buffer[i] == 0x1B && Count - i > 1 )
{
- i ++;
- i += VT_int_ParseEscape(Term, (const char*)&Buffer[i]) - 1;
- continue;
+ int ret = VT_int_ParseEscape(Term, (const char*)&Buffer[i+1], Count-(i+1));
+ if( ret > 0 )
+ {
+ i += ret;
+ continue;
+ }
}
// Fast check for non UTF-8
if( Buffer[i] < 128 ) // Plain ASCII
VT_int_PutChar(Term, Buffer[i]);
else { // UTF-8
+ Uint32 val;
i += ReadUTF8(&Buffer[i], &val) - 1;
VT_int_PutChar(Term, val);
}
* \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
* \brief Parses a VT100 Escape code
*/
-int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
+int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes)
{
char c;
- int argc = 0, j = 1;
+ int argc = 0, j = 0;
int args[6] = {0,0,0,0};
int bQuestionMark = 0;
-
- switch(Buffer[0])
+
+ if( Bytes == j ) return j;
+ c = Buffer[j++];
+
+ switch(c)
{
//Large Code
case '[':
// Get Arguments
+ if(Bytes == j) return j;
c = Buffer[j++];
if(c == '?') {
bQuestionMark = 1;
+ if(Bytes == j) return j;
c = Buffer[j++];
}
if( '0' <= c && c <= '9' )
{
do {
- if(c == ';') c = Buffer[j++];
+ if(c == ';') {
+ if(Bytes == j) return j;
+ c = Buffer[j++];
+ }
while('0' <= c && c <= '9') {
args[argc] *= 10;
args[argc] += c-'0';
+ if(Bytes == j) return j;
c = Buffer[j++];
}
argc ++;
}
// Get Command
- if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+ if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') )
{
- if( bQuestionMark )
+ // Error
+ return j;
+ }
+
+ if( bQuestionMark )
+ {
+ switch(c)
{
- switch(c)
+ // DEC Private Mode Set
+ case 'h':
+ if(argc != 1) break;
+ switch(args[0])
{
- // DEC Private Mode Set
- case 'h':
- if(argc != 1) break;
- switch(args[0])
- {
- case 25:
- Term->Flags &= ~VT_FLAG_HIDECSR;
- break;
- case 1047:
- VT_int_ToggleAltBuffer(Term, 1);
- break;
- }
+ case 25:
+ Term->Flags &= ~VT_FLAG_HIDECSR;
+ break;
+ case 1047:
+ VT_int_ToggleAltBuffer(Term, 1);
break;
- case 'l':
- if(argc != 1) break;
- switch(args[0])
- {
- case 25:
- Term->Flags |= VT_FLAG_HIDECSR;
- break;
- case 1047:
- VT_int_ToggleAltBuffer(Term, 0);
- break;
- }
+ }
+ break;
+ case 'l':
+ if(argc != 1) break;
+ switch(args[0])
+ {
+ case 25:
+ Term->Flags |= VT_FLAG_HIDECSR;
break;
- default:
- Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+ case 1047:
+ VT_int_ToggleAltBuffer(Term, 0);
break;
}
+ break;
+ default:
+ Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+ break;
}
- else
- {
- VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
- }
+ }
+ else
+ {
+ VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
}
break;
-
+ case '\0':
+ // Ignore \0
+ break;
default:
- Log_Notice("VTerm", "TODO: Handle short escape codes");
+ //Log_Notice("VTerm", "TODO: Handle short escape codes");
+ {
+ static volatile int tmp = 0;
+ if(tmp == 0) {
+ tmp = 1;
+ Debug("VTerm: Unknown short 0x%x", c);
+ tmp = 0;
+ }
+ }
break;
}
extern int strpos8(const char *str, Uint32 search);
extern void itoa(char *buf, Uint64 num, int base, int minLength, char pad);
extern int atoi(const char *string);
+extern unsigned long long strtoull(const char *str, char **end, int base);
+extern unsigned long strtoul(const char *str, char **end, int base);
+extern signed long long strtoll(const char *str, char **end, int base);
+extern signed long strtol(const char *str, char **end, int base);
extern int ParseInt(const char *string, int *Val);
extern int ReadUTF8(const Uint8 *str, Uint32 *Val);
extern int WriteUTF8(Uint8 *str, Uint32 Val);
//! General purpose event for short waits
//! e.g. waiting for an IRQ in a Read() call
#define THREAD_EVENT_SHORTWAIT 0x00000010
+//! Fired when a child process quits
+#define THREAD_EVENT_DEADCHILD 0x00000020
#define THREAD_EVENT_USER1 0x10000000
#define THREAD_EVENT_USER2 0x20000000
extern void StartupPrint(const char *String);
extern void System_Init(char *Commandline);
extern void Threads_Init(void);
+extern void Heap_Install(void);
#endif
struct sProcess *Process; //!< Thread Group / Process
struct sThread *Parent; //!< Parent Thread
char *ThreadName; //!< Name of thread
-
+
+ struct sThread *LastDeadChild; //!< Last child to die (will have the \a DeadChildren lock)
+ tMutex DeadChildLock; //!< Lock to prevent clobbering of \a LastDeadChild, acquired by child, released by parent
+
// --- arch/proc.c's responsibility
//! Kernel Stack Base
tVAddr KernelStack;
#define RANDOM_SPRUCE 0xf12b039
// === PROTOTYPES ===
+#if 0
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);
void itoa(char *buf, Uint64 num, int base, int minLength, char pad);
void *tmp;
tThread *cur = Proc_GetCurThread();
- ENTER("pSource pBuffer", Source, Buffer);
+ ENTER("pSource xBufSize pBuffer", Source, BufSize, Buffer);
// Check if queue has any items
if(!cur->Messages) {
+ LOG("empty queue");
LEAVE('i', 0);
return 0;
}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
- CHECK_NUM_NONULL( tmp, sizeof(char**) ); \
- for(i=0;tmp[i];i++) { \
+ CHECK_NUM_NULLOK( tmp, sizeof(char**) ); \
+ for(i=0;tmp&&tmp[i];i++) { \
CHECK_STR_NONULL( tmp[i] ); \
CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \
}\
CHECK_STR_NONULL((const char*)Regs->Arg1);
CHECK_STR_ARRAY((const char**)Regs->Arg2);
CHECK_STR_ARRAY((const char**)Regs->Arg3);
- CHECK_NUM_NULLOK((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+ if( Regs->Arg4 > 0 )
+ CHECK_NUM_NONULL((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
if(Proc_Clone(CLONE_VM|CLONE_NOUSER) == 0)
{
const char *args[] = {gsInitBinary, 0};
+ VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_READ|VFS_OPENFLAG_USER); // 0: stdin
+ VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_WRITE|VFS_OPENFLAG_USER); // 1: stdout
Proc_Execve(gsInitBinary, args, &args[1], 0);
Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
}
#include <hal_proc.h>
#include <semaphore.h>
#include <vfs_threads.h> // VFS Handle maintainence
+#include <events.h>
// Configuration
#define DEBUG_TRACE_TICKETS 0 // Trace ticket counts
tTID Threads_WaitTID(int TID, int *Status)
{
// Any Child
- if(TID == -1) {
- Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
- return -1;
+ if(TID == -1)
+ {
+ Uint32 ev = Threads_WaitEvents(THREAD_EVENT_DEADCHILD);
+ tTID ret = -1;
+ if( ev & THREAD_EVENT_DEADCHILD )
+ {
+ // A child died, get the TID
+ tThread *us = Proc_GetCurThread();
+ ASSERT(us->LastDeadChild);
+ ret = us->LastDeadChild->TID;
+ // - Mark as dead (as opposed to undead)
+ ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE);
+ us->LastDeadChild->Status = THREAD_STAT_DEAD;
+ // - Set return status
+ if(Status)
+ *Status = us->LastDeadChild->RetStatus;
+ us->LastDeadChild = NULL;
+ Mutex_Release(&us->DeadChildLock);
+ }
+ else
+ {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
+ }
+ return ret;
}
// Any peer/child thread
}
// Specific Thread
- if(TID > 0) {
- tThread *t = Threads_GetThread(TID);
+ if(TID > 0)
+ {
tTID ret;
-
- // Wait for the thread to die!
- // TODO: Handle child also being suspended if wanted
- while(t->Status != THREAD_STAT_ZOMBIE) {
- Threads_Sleep();
- Log_Debug("Threads", "%i waiting for %i, t->Status = %i",
- Threads_GetTID(), t->TID, t->Status);
- }
-
- // Set return status
- ret = t->TID;
- switch(t->Status)
+ // NOTE: Race condition - Other child dies, desired child dies, first death is 'lost'
+ while( (ret = Threads_WaitTID(-1, Status)) != TID )
{
- case THREAD_STAT_ZOMBIE:
- // Kill the thread
- t->Status = THREAD_STAT_DEAD;
- // TODO: Child return value?
- if(Status) *Status = t->RetStatus;
- // add to delete queue
- Threads_Delete( t );
- break;
- default:
- if(Status) *Status = -1;
- break;
+ if( ret == -1 )
+ break;
}
return ret;
}
Thread->Status = THREAD_STAT_ZOMBIE;
SHORTREL( &glThreadListLock );
- // TODO: Send something like SIGCHLD
- Threads_Wake( Thread->Parent );
+ // TODO: It's possible that we could be timer-preempted here, should disable that... somehow
+ Mutex_Acquire( &Thread->Parent->DeadChildLock ); // released by parent
+ Thread->Parent->LastDeadChild = Thread;
+ Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD );
Log("Thread %i went *hurk* (%i)", Thread->TID, Status);
#if 0
tVFS_Handle *VFS_GetHandle(int FD);
#endif
+inline void _ReferenceNode(tVFS_Node *Node);
int VFS_AllocHandle(int FD, tVFS_Node *Node, int Mode);
// === GLOBALS ===
tVFS_Handle *h;
if( FDs == NULL )
h = &gaUserHandles[i];
- else {
+ else if( FDs[i] == -1 )
+ {
+ Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (-1), ignorning", i);
+ memset(&ret[i], 0, sizeof(tVFS_Handle));
+ continue ;
+ }
+ else
+ {
h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
if(!h) {
Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
tThread *thisthread = Proc_GetCurThread();
int ret;
- ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout bIsKernel",
- MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, IsKernel);
+ ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout xExtraEvents bIsKernel",
+ MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, ExtraEvents, IsKernel);
// Notes: The idea is to make sure we only enter wait (Threads_WaitEvents)
// if we are going to be woken up (either by an event at a later time,
// or the semaphore is incremeneted (or both, but never none)
// Register with nodes
+ if( ReadHandles )
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
ret = VFS_int_Select_Register(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
ret += VFS_int_Select_Register(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
ret += VFS_int_Select_Register(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
// If there were events waiting, de-register and return
if( ret > 0 )
{
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
ret = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
LEAVE('i', ret);
return ret;
}
}
// Check for the flag
- if( !!*flag == !!wantedFlagValue )
+ if( !!*flag == !!wantedFlagValue ) {
+ LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
numFlagged ++;
+ }
}
LEAVE('i', numFlagged);
continue;
}
- // Get the type of the listen
-
// Get the type of the listen
if( VFS_int_Select_GetType(Type, handle->Node, &list, &flag, &wantedFlagValue, NULL) ) {
LEAVE('i', 0);
// Check for the flag
if( !!*flag == !!wantedFlagValue ) {
numFlagged ++;
+ LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
+ FD_SET(i, Handles);
}
else {
FD_CLR(i, Handles);
const tBGA_Mode *gpBGA_CurrentMode;\r
const tBGA_Mode gBGA_Modes[] = {\r
{640,480,32, 640*480*4},\r
+ {800,480,32, 800*480*4}, // Nice mode for VM testing\r
{800,600,32, 800*600*4},\r
{1024,768,32, 1024*768*4}\r
};\r
--- /dev/null
+/**
+ * Acess2 Raspberry Pi (BCM2835)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Driver core
+ *
+ * http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/screen01.html
+ */
+#define DEBUG 0
+#define VERSION ((0<<8)|1)
+#include <acess.h>
+#include <errno.h>
+#include <modules.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <api_drv_video.h>
+
+// === PROTOCOLS ===
+ int RPiVid_Install(const char **Arguments);
+// - GPU Communication
+ int RPiVid_int_MBoxCheck(Uint8 Box);
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box);
+void RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, RPiVid, RPiVid_Install, NULL, NULL);
+
+// === CODE ===
+int RPiVid_Install(const char **Arguments)
+{
+ return 0;
+}
+
+
+// --- GPU Comms ---
+int RPiVid_int_MBoxCheck(Uint8 Box)
+{
+ return 0;
+}
+
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box)
+{
+ Uint32 val;
+ do {
+ while( gRPiVid_Mbox->Status & (1 << 30) )
+ ;
+ val = gRPiVid_Mbox->Read;
+ } while( (val & 0xF) != Box );
+
+ return 0;
+}
+
+void RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message)
+{
+ while( gRPiVid_Mbox.Status & (1 << 31) )
+ ;
+ gRPiVid_Mbox.Write = (Message << 4) | (Box & 0xF);
+}
+
Uint32 *gpTegra2Vid_IOMem;
tPAddr gTegra2Vid_FramebufferPhys;
void *gpTegra2Vid_Framebuffer;
+void *gpTegra2Vid_Cursor;
// -- Misc
tDrvUtil_Video_BufInfo gTegra2Vid_DrvUtil_BufInfo;
tVideo_IOCtl_Pos gTegra2Vid_CursorPos;
Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x (%s)", i, gpTegra2Vid_IOMem[i],
(csaTegra2Vid_RegisterNames[i] ? csaTegra2Vid_RegisterNames[i] : "-"));
}
+
+void Tegra2Vid_int_DumpRegisters(void)
+{
+ Log_Debug("Tegra2Vid", "Display CMD Registers");
+ for( int i = 0x000; i <= 0x01A; i ++ ) _dumpreg(i);
+ for( int i = 0x028; i <= 0x043; i ++ ) _dumpreg(i);
+ Log_Debug("Tegra2Vid", "Display COM Registers");
+ for( int i = 0x300; i <= 0x329; i ++ ) _dumpreg(i);
+ Log_Debug("Tegra2Vid", "Display DISP Registers");
+ for( int i = 0x400; i <= 0x446; i ++ ) _dumpreg(i);
+ for( int i = 0x480; i <= 0x484; i ++ ) _dumpreg(i);
+ for( int i = 0x4C0; i <= 0x4C1; i ++ ) _dumpreg(i);
+ Log_Debug("Tegra2Vid", "WINC_A Registers");
+ for( int i = 0x700; i <= 0x714; i ++ ) _dumpreg(i);
+ Log_Debug("Tegra2Vid", "WINBUF_A");
+ for( int i = 0x800; i <= 0x80A; i ++ ) _dumpreg(i);
+}
+
/**
*/
int Tegra2Vid_Install(char **Arguments)
// KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);
gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);
+
#if DUMP_REGISTERS
- {
- Log_Debug("Tegra2Vid", "Display CMD Registers");
- for( int i = 0x000; i <= 0x01A; i ++ ) _dumpreg(i);
- for( int i = 0x028; i <= 0x043; i ++ ) _dumpreg(i);
- Log_Debug("Tegra2Vid", "Display COM Registers");
- for( int i = 0x300; i <= 0x329; i ++ ) _dumpreg(i);
- Log_Debug("Tegra2Vid", "Display DISP Registers");
- for( int i = 0x400; i <= 0x446; i ++ ) _dumpreg(i);
- for( int i = 0x480; i <= 0x484; i ++ ) _dumpreg(i);
- for( int i = 0x4C0; i <= 0x4C1; i ++ ) _dumpreg(i);
- Log_Debug("Tegra2Vid", "WINC_A Registers");
- for( int i = 0x700; i <= 0x714; i ++ ) _dumpreg(i);
- Log_Debug("Tegra2Vid", "WINBUF_A");
- for( int i = 0x800; i <= 0x80A; i ++ ) _dumpreg(i);
- }
+ Tegra2Vid_int_DumpRegisters();
#endif
// HACK!!!
}
#endif
+#if 0
giTegra2Vid_FramebufferSize =
(gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]&0xFFFF)
*(gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]>>16)*4;
gpTegra2Vid_IOMem[DC_WINBUF_A_START_ADDR_0],
(giTegra2Vid_FramebufferSize+PAGE_SIZE-1)/PAGE_SIZE
);
- memset(gpTegra2Vid_Framebuffer, 0xFF, 0x1000);
+ Log_Debug("Tegra2Vid", "gpTegra2Vid_Framebuffer = %p", gpTegra2Vid_Framebuffer);
+ memset(gpTegra2Vid_Framebuffer, 0xFF, giTegra2Vid_FramebufferSize);
+#endif
#if 0
gpTegra2Vid_IOMem[DC_WIN_A_WIN_OPTIONS_0] = (1 << 30);
gTegra2Vid_DrvUtil_BufInfo.Depth = 32;
gTegra2Vid_DrvUtil_BufInfo.Width = 1680;
gTegra2Vid_DrvUtil_BufInfo.Height = 1050;
-#else
+ gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = WIN_A_ACT_REQ;
+#elif 0
gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 13; // Could be 13 (BGR/RGB)
gpTegra2Vid_IOMem[DC_WIN_A_LINE_STRIDE_0] =
gTegra2Vid_DrvUtil_BufInfo.Pitch = 1024*4;
gTegra2Vid_DrvUtil_BufInfo.Width = 1024;
gTegra2Vid_DrvUtil_BufInfo.Height = 768;
gTegra2Vid_DrvUtil_BufInfo.Framebuffer = gpTegra2Vid_Framebuffer;
-#endif
gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = WIN_A_ACT_REQ;
+#endif
+ gpTegra2Vid_Cursor = (void*)MM_AllocDMA(1, 26, NULL);
-// Tegra2Vid_int_SetMode(4);
+ Tegra2Vid_int_SetMode(0);
DevFS_AddDevice( &gTegra2Vid_DriverStruct );
LEAVE_RET('i', 0);
// DEBUG!!!
- mode->width = 1024;
- mode->height = 768;
+ mode->id = 1; mode->width = 1680; mode->height = 1050;
+ mode->id = 0; mode->width = 1024; mode->height = 768;
+
+ // DEBUG!
+ for( int i = 0x800; i <= 0x80A; i ++ ) _dumpreg(i);
break;
ret = 0;
for( int i = 0; i < ciTegra2Vid_ModeCount; i ++ )
{
int area;
- if(mode->width == caTegra2Vid_Modes[i].W && mode->height == caTegra2Vid_Modes[i].H) {
+ if(mode->width == caTegra2Vid_Modes[i].W
+ && mode->height == caTegra2Vid_Modes[i].H) {
mode->id = i;
ret = 1;
break;
DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );
gTegra2Vid_CursorPos = *(tVideo_IOCtl_Pos*)Data;
+ // TODO: Set DC_DISP_CURSOR_POSITION_0
+ // TODO: Set DC_DISP_CURSOR_FOREGROUND_0 etc from image?
if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)
DrvUtil_Video_DrawCursor(
&gTegra2Vid_DrvUtil_BufInfo,
{
const struct sTegra2_Disp_Mode *mode = &caTegra2Vid_Modes[Mode];
int w = mode->W, h = mode->H; // Horizontal/Vertical Active
- gpTegra2Vid_IOMem[DC_DISP_FRONT_PORCH_0] = (mode->VFP << 16) | mode->HFP;
+ gpTegra2Vid_IOMem[DC_DISP_REF_TO_SYNC_0] = (1 << 16) | 11; // TODO: <--
gpTegra2Vid_IOMem[DC_DISP_SYNC_WIDTH_0] = (mode->HS << 16) | mode->HS;
gpTegra2Vid_IOMem[DC_DISP_BACK_PORCH_0] = (mode->VBP << 16) | mode->HBP;
gpTegra2Vid_IOMem[DC_DISP_DISP_ACTIVE_0] = (mode->H << 16) | mode->W;
+ gpTegra2Vid_IOMem[DC_DISP_FRONT_PORCH_0] = (mode->VFP << 16) | mode->HFP;
+ gpTegra2Vid_IOMem[DC_DISP_DISP_COLOR_CONTROL_0] = 0x8; // BASE888 - TODO: useful?
gpTegra2Vid_IOMem[DC_WIN_A_POSITION_0] = 0;
gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0] = (h << 16) | w;
- gpTegra2Vid_IOMem[DC_DISP_DISP_COLOR_CONTROL_0] = 0x8; // BASE888
gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 12; // Could be 13 (BGR/RGB)
gpTegra2Vid_IOMem[DC_WIN_A_PRESCALED_SIZE_0] = (h << 16) | w;
+ gpTegra2Vid_IOMem[DC_WIN_A_LINE_STRIDE_0] = w * 4;
+ gpTegra2Vid_IOMem[DC_WIN_A_DV_CONTROL_0] = 0;
+
+ gpTegra2Vid_IOMem[DC_DISP_BORDER_COLOR_0] = 0x70F010;
Log_Debug("Tegra2Vid", "Mode %i (%ix%i) selected", Mode, w, h);
giTegra2Vid_FramebufferSize = w*h*4;
- // TODO: Does this need RAM or unmapped space?
+ // Uses RAM I think
gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA(
(giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE,
32,
&gTegra2Vid_FramebufferPhys
);
- // TODO: Catch allocation failures
+ if( !gpTegra2Vid_Framebuffer ) {
+ Log_Error("Tegra2Vid", "Can't allocate pages for 0x%x byte framebuffer",
+ giTegra2Vid_FramebufferSize);
+ return -1;
+ }
Log_Debug("Tegra2Vid", "0x%x byte framebuffer at %p (%P phys)",
giTegra2Vid_FramebufferSize,
gpTegra2Vid_Framebuffer,
}
gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = WIN_A_ACT_REQ;
+ gpTegra2Vid_IOMem[DC_CMD_STATE_CONTROL_0] = GEN_ACT_REQ;
+
+ // DEBUG!
+ for( int i = 0x800; i <= 0x80A; i ++ ) _dumpreg(i);
return 0;
}
} caTegra2Vid_Modes[] = {
// TODO: VESA timings
{1024, 768, 58, 4, 58, 4, 58, 4}, // 1024x768 (reset), RtS=11,4
+ {1680,1050, 104, 1, 184, 3 , 288, 33}, // 1680x1050 @ 60Hz
// TV Timings
{720, 487, 16,33, 63, 33, 59, 133}, // NTSC 2
{720, 576, 12,33, 63, 33, 69, 193}, // PAL 2 (VFP shown as 2/33, used 33)
DC_WIN_A_DDA_INCREMENT_0,
DC_WIN_A_LINE_STRIDE_0,
DC_WIN_A_BUF_STRIDE_0,
+ _DC_WIN_A_70C,
DC_WIN_A_BUFFER_ADDR_MODE_0,
DC_WIN_A_DV_CONTROL_0,
DC_WIN_A_BLEND_NOKEY_0,
"DC_WIN_A_DDA_INCREMENT_0",
"DC_WIN_A_LINE_STRIDE_0",
"DC_WIN_A_BUF_STRIDE_0",
+ "-",
"DC_WIN_A_BUFFER_ADDR_MODE_0",
"DC_WIN_A_DV_CONTROL_0",
"DC_WIN_A_BLEND_NOKEY_0",
files.$(ARCH).c: GenerateInitRD.php files.lst
+# Override default install method, because the floppy is small :)
+install:
+ true
+
-include files.$(ARCH).c.dep
File "ping" "__BIN__/Bin/ping"
File "telnet" "__BIN__/Bin/telnet"
File "irc" "__BIN__/Bin/irc"
+ File "bomb" "__BIN__/Bin/bomb"
File "dhcpc" "__BIN__/SBin/dhcpc"
}
Dir "Libs" {
File "libaxwin3.so" "__BIN__/Libs/libaxwin3.so"
File "libposix.so" "__BIN__/Libs/libposix.so"
File "libpsocket.so" "__BIN__/Libs/libpsocket.so"
+ File "libunicode.so" "__BIN__/Libs/libunicode.so"
}
Dir "Conf" {
- File "BootConf.cfg" "__FS__/Conf/BootConf.cfg"
+ File "inittab" "__FS__/Conf/inittab"
}
Dir "Apps" {
Dir "AxWin" {
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 "terminal" "__BIN__/Apps/AxWin/3.0/terminal"
File "AcessLogoSmall.sif" "__SRC__/Usermode/Applications/axwin3_src/AcessLogoSmall.sif"
}
}
UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, data, (size_t)Length - ofs);
- return 0;
+ return Length;
}
/**
{
int id = -1;
int i = 0;
-// Uint16 base;
tCard *card;
giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
- Log_Debug("Rhine2", "giRhine2_CardCount = %i", giRhine2_CardCount);
if( giRhine2_CardCount == 0 ) return MODULE_ERR_NOTNEEDED;
gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
{
if(Pos < 0 || Pos > MAX_DISKS )
return -ENOENT;
- if(gaFDD_Disks[Pos].bValid)
+ if(!gaFDD_Disks[Pos].bValid)
return 1;
Dest[0] = '0' + Pos;
// TODO: Detect other forms of failure than "out of slots"
break ;
}
+ }
- // TODO: Register with the USB stack
+ for( int i = 0; Arguments[i]; i ++ )
+ {
+ char *pos = Arguments[i], *next;
+ LOG("pos = '%s'", pos);
+ tPAddr base = strtoull(pos, &next, 16);
+ if( base == 0 )
+ continue;
+ pos = next;
+ LOG("pos = '%s'", pos);
+ if( *pos++ != '-' )
+ continue;
+ LOG("pos = '%s'", pos);
+ int irq = strtol(pos, &next, 16);
+ if( irq == 0 )
+ continue ;
+ if( *next != 0 )
+ continue;
+ LOG("base=%x, irq=%i", base, irq);
+ if( EHCI_InitController(base, irq) )
+ {
+ continue ;
+ }
}
+
return 0;
}
}
// TODO: Error check
if( (cont->CapRegs->CapLength & 3) ) {
- Log_Warning("EHCI", "Controller at %P non-aligned op regs", BaseAddress);
+ Log_Warning("EHCI", "Controller at %P non-aligned op regs (%x)",
+ BaseAddress, cont->CapRegs->CapLength);
goto _error;
}
cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
// === IMPORTS ===
extern void *gpIRQHandler;
+extern tPAddr gGIC_DistributorAddr;
+extern tPAddr gGIC_InterfaceAddr;
// === TYPES ===
typedef void (*tIRQ_Handler)(int, void*);
MODULE_DEFINE(0, 0x100, armv7_GIC, GIC_Install, NULL, NULL);
Uint32 *gpGIC_DistributorBase;
Uint32 *gpGIC_InterfaceBase;
-tPAddr gGIC_DistributorAddr;
-tPAddr gGIC_InterfaceAddr;
tIRQ_Handler gaIRQ_Handlers[N_IRQS];
void *gaIRQ_HandlerData[N_IRQS];
// === CODE ===
int GIC_Install(char **Arguments)
{
- // Realview PB
- gGIC_InterfaceAddr = 0x1e000000;
- gGIC_DistributorAddr = 0x1e001000;
-
// Initialise
gpGIC_InterfaceBase = (void*)MM_MapHWPages(gGIC_InterfaceAddr, 1);
LOG("gpGIC_InterfaceBase = %p", gpGIC_InterfaceBase);
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
+USRLIBS += libimage_sif.so libunicode.so
USRAPPS := init login CLIShell cat ls mount
USRAPPS += bomb lspci
USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3 gui_ate
+USRAPPS += axwin3 gui_ate gui_shell
ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
ALL_MODULES := $(addprefix all-,$(MODULES))
--- /dev/null
+GL control channel:
+ App -> GUI -> VTerm -> Driver
+- App creates 3D window
+- GUI passes X,Y WxH to VTerm (and can issue resize notices upwards)
+- VTerm passes to driver (and can disable display of local regions when VT switch)
+
+Allocates command ring buffer for libgl
+
-l*|-L*)
_libs=$_libs" $1"
;;
+ -v|--version|-V)
+ _verarg=$_verarg" $1"
+ ;;
+ --inv=ld)
+ _actas=ld
+ ;;
+ -print-prog-name=ld)
+ echo $0 --inv=ld
+ exit 0
+ ;;
*)
_miscargs=$_miscargs" $1"
;;
done
run() {
-# echo --- $*
+ #echo --- $*
$*
return $?
}
#echo "_compile = $_compile, _preproc = $_preproc"
+if [[ "x$_actas" == "xld" ]]; then
+ run $_LD $LDFLAGS $_ldflags $_outfile $_miscargs $LIBGCC_PATH $_libs
+ exit $?
+fi
+
if [[ $_preproc -eq 1 ]]; then
run $_CC -E $CFLAGS $_cflags $_miscargs $_outfile
elif [[ $_makedep -eq 1 ]]; then
elif echo " $_miscargs" | grep '\.c' >/dev/null; then
tmpout=`mktemp acess_gccproxy.XXXXXXXXXX.o --tmpdir`
run $_CC $CFLAGS $_cflags $_miscargs -c -o $tmpout
- run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile -lgcc $_libs
+ run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile $LIBGCC_PATH $_libs
+ _rv=$?
rm $tmpout
+ exit $_rv
else
run $_LD$_ldflags $_miscargs $_outfile $LDFLAGS $_libs
fi
void mainmenu_app_textedit(void *unused)
{
- const char *args[] = {"ate",NULL};
// _SysDebug("TODO: Launch text editor");
+ const char *args[] = {"ate",NULL};
_SysSpawn("/Acess/Apps/AxWin/3.0/ate", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_app_terminal(void *unused)
{
- _SysDebug("TODO: Launch terminal emulator");
+ _SysDebug("Launch terminal emulator");
+ const char *args[] = {"terminal",NULL};
+ _SysSpawn("/Acess/Apps/AxWin/3.0/terminal", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_run_dialog(void *unused)
DIR := Apps/AxWin/3.0
BIN := AxWinWM
-OBJ := main.o input.o video.o ipc.o image.o utf-8.o
+OBJ := main.o input.o video.o ipc.o image.o
OBJ += wm.o wm_input.o wm_render.o wm_render_text.o wm_hotkeys.o
OBJ += decorator.o
OBJ += renderers/framebuffer.o
OBJ += renderers/widget/spacer.o
OBJ += renderers/widget/subwin.o
-LDFLAGS += -limage_sif -luri -lnet
+LDFLAGS += -limage_sif -luri -lnet -lunicode
-include ../../Makefile.tpl
+++ /dev/null
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf8.h
- * - UTF-8 Parsing header
- */
-#ifndef _UTF8_H_
-#define _UTF8_H_
-
-#include <stdint.h>
-
-extern int ReadUTF8(const char *Input, uint32_t *Val);
-extern int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
-extern int WriteUTF8(char *buf, uint32_t Val);
-
-#endif
-
ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
// Don't allow the focus to be changed unless the client has the focus
- if(!gpWM_FocusedWindow) return 1;
- if(gpWM_FocusedWindow->Client != Client) return 1;
+// if(!gpWM_FocusedWindow) return 1;
+// if(gpWM_FocusedWindow->Client != Client) return 1;
win = IPC_int_GetWindow(Client, Msg->Window);
if(!win) return 1;
Renderer_RichText_Init();
WM_Initialise();
- // TODO: Config
+ // TODO: Move these to config
uint32_t keys[4];
keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_r;
WM_Hotkey_Register(2, keys, "Interface>Run");
+ keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_t;
+ WM_Hotkey_Register(2, keys, "Interface>Terminal");
// Spawn interface root
{
sprintf(server_info, "AXWIN3_SERVER=%i", server_tid);
// TODO: Does the client need FDs?
int rv = _SysSpawn(csInterfaceApp, argv, envp, 0, NULL, NULL);
- if( rv ) {
+ if( rv < 0 ) {
_SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
}
}
{
short W, H;
void *Data;
- char _data[];
} tFBBuffer;
typedef struct
{
buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
buf->W = msg->W;
buf->H = msg->H;
- buf->Data = buf->_data;
+ buf->Data = buf + 1;
info->Buffers[msg->Buffer] = buf;
Window->W, (info->DispLines-i)*info->LineHeight,
info->DefaultBG
);
+
+ // HACK!
+ info->DispCols = Window->W / 8;
+
+ // TODO: Text cursor
+ _SysDebug("Cursor at %i,%i", info->CursorCol, info->CursorRow);
+ _SysDebug(" Range [%i+%i],[%i+%i]", info->FirstVisRow, info->DispLines, info->FirstVisCol, info->DispCols);
+ if( info->CursorRow >= info->FirstVisRow && info->CursorRow < info->FirstVisRow + info->DispLines )
+ {
+ if( info->CursorCol >= info->FirstVisCol && info->CursorCol < info->FirstVisCol + info->DispCols )
+ {
+ // TODO: Kill hardcoded 8 with cached text distance
+ WM_Render_FillRect(Window,
+ (info->CursorCol - info->FirstVisCol) * 8,
+ (info->CursorRow - info->FirstVisRow) * info->LineHeight,
+ 1,
+ info->LineHeight,
+ info->DefaultFG
+ );
+ }
+ }
}
int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
case _ATTR_DEFFG:
info->DefaultFG = msg->Value;
break;
+ case _ATTR_CURSORPOS:
+ info->CursorRow = msg->Value >> 12;
+ info->CursorCol = msg->Value & 0xFFF;
+ break;
case _ATTR_SCROLL:
// TODO: Set scroll flag
break;
}
line->ByteLength = Len - sizeof(*msg);
memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
-
+
+ WM_Invalidate( Window );
+
return 0;
}
if(Len < sizeof(*msg)) return -1;
info->DispLines = msg->H / info->LineHeight;
return 1; }
+ case WNDMSG_KEYDOWN:
+ case WNDMSG_KEYUP:
+ case WNDMSG_KEYFIRE:
+ return 1;
}
return 0;
}
#include <common.h>
#include "./common.h"
#include "./colours.h"
-#include <utf8.h>
+#include <unicode.h>
#include <string.h>
// TODO: Include a proper keysym header
+++ /dev/null
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf-8.c
- * - UTF-8 Parsing code
- */
-#include <stdint.h>
-#include <utf8.h>
-
-/**
- * \brief Read a UTF-8 character from a string
- * \param Input Source UTF-8 encoded string
- * \param Val Destination for read codepoint
- * \return Number of bytes read/used
- */
-int ReadUTF8(const char *Input, uint32_t *Val)
-{
- const uint8_t *str = (const uint8_t *)Input;
- *Val = 0xFFFD; // Assume invalid character
-
- // ASCII
- if( !(*str & 0x80) ) {
- *Val = *str;
- return 1;
- }
-
- // Middle of a sequence
- if( (*str & 0xC0) == 0x80 ) {
- return 1;
- }
-
- // Two Byte
- if( (*str & 0xE0) == 0xC0 ) {
- *Val = (*str & 0x1F) << 6; // Upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 2;
- }
-
- // Three Byte
- if( (*str & 0xF0) == 0xE0 ) {
- *Val = (*str & 0x0F) << 12; // Upper 4 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 3;
- }
-
- // Four Byte
- if( (*str & 0xF8) == 0xF0 ) {
- *Val = (*str & 0x07) << 18; // Upper 3 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 4;
- }
-
- // UTF-8 Doesn't support more than four bytes
- return 4;
-}
-
-/**
- * \brief Get the UTF-8 character before the
- * \
- */
-int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
-{
- int len = 0;
-
- // Scan backwards for the beginning of the character
- while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
- len ++;
- // Invalid string (no beginning)
- if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
- return len;
-
- len ++; // First character
- if( ReadUTF8(Base+Offset, Val) != len ) {
- *Val = 0xFFFD;
- }
- return len;
-}
-
-/**
- * \brief Write a UTF-8 character sequence to a string
- * \param buf Destination buffer (must have at least 4 bytes available)
- * \param Val Unicode codepoint to write
- * \return Number of bytes written
- * \note Does not NULL terminate the string in \a buf
- */
-int WriteUTF8(char *buf, uint32_t Val)
-{
- uint8_t *str = (void*)buf;
-
- // ASCII
- if( Val < 128 ) {
- if(str) {
- *str = Val;
- }
- return 1;
- }
-
- // Two Byte
- if( Val < 0x8000 ) {
- if(str) {
- *str = 0xC0 | (Val >> 6);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 2;
- }
-
- // Three Byte
- if( Val < 0x10000 ) {
- if(str) {
- *str = 0xE0 | (Val >> 12);
- str ++;
- *str = 0x80 | ((Val >> 6) & 0x3F);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 3;
- }
-
- // Four Byte
- if( Val < 0x110000 ) {
- if(str) {
- *str = 0xF0 | (Val >> 18);
- str ++;
- *str = 0x80 | ((Val >> 12) & 0x3F);
- str ++;
- *str = 0x80 | ((Val >> 6) & 0x3F);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 4;
- }
-
- // UTF-8 Doesn't support more than four bytes
- return 0;
-}
-
_SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
- _SysSeek(giTerminalFD, ofs*4, 1);
+ _SysSeek(giTerminalFD, ofs*4, SEEK_SET);
_SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysWrite(giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysDebug("Video_Update - Done");
{
struct sWndMsg_Bool _msg;
+ _SysDebug("WM_FocusWindow(%p)", Destination);
+
if( gpWM_FocusedWindow == Destination )
return ;
if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
#include <common.h>
#include <wm_internals.h>
#include <stdlib.h>
-#include <utf8.h>
+#include <unicode.h>
#include <limits.h> // INT_MAX
// === TYPES ===
#include "include/internal.h"
#include <richtext_messages.h>
#include <string.h>
+#include <wm_messages.h>
//#include <alloca.h>
// === TYPES ===
// === CODE ===
int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ struct sWndMsg_KeyAction *keyaction = Data;
+ _SysDebug("MessageID = %i", MessageID);
+ switch(MessageID)
+ {
+ case WNDMSG_KEYFIRE:
+ if(Size < sizeof(*keyaction)) return -1;
+ info->KeyCallback(Window, 2, keyaction->KeySym, keyaction->UCS32);
+ return 1;
+ }
return 0;
}
_SysIOCtl(Iface->IfaceFD, 6, Addr);
_SysIOCtl(Iface->IfaceFD, 7, &mask_bits);
- if( Router );
+ if( Router )
{
uint8_t *addr = Router;
_SysDebug("Router %i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
-include ../Makefile.cfg
-LDFLAGS += -laxwin3
+LDFLAGS += -laxwin3 -lunicode
-OBJ = main.o
+OBJ = main.o vt100.o display.o
BIN = terminal
DIR := Apps/AxWin/3.0
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.c
+ * - Abstract display manipulation methods
+ */
+#include "include/display.h"
+#include <acess/sys.h> // _SysDebug
+#include <stdlib.h> // exit
+#include <string.h>
+#include <unicode.h>
+#include <stdio.h>
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+
+#define UNIMPLIMENTED() do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
+
+// === EXTERN ==
+extern tHWND gMainWindow;
+
+// === GLOBALS ===
+ int giDisplayCols;
+ int giDisplayLines;
+ int giDisplayTotalLines;
+ int giDisplayBufSize;
+ int giCurrentLine;
+ int giCurrentLinePos; // byte offset, not column
+ int giCurrentCol;
+ int giFirstDispLine; // First displayed line
+ int giFirstLine; // Ring buffer start
+char **gasDisplayLines;
+ int *gaiDisplayLineSizes;
+char *gabDisplayLinesDirty;
+
+// === CODE ===
+void Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
+{
+ giDisplayCols = Cols;
+ giDisplayLines = Lines;
+ giDisplayTotalLines = Lines + ExtraScrollbackLines;
+ gasDisplayLines = calloc( sizeof(char*), (Lines + ExtraScrollbackLines) );
+ gaiDisplayLineSizes = calloc( sizeof(int), (Lines + ExtraScrollbackLines) );
+ gabDisplayLinesDirty = calloc( sizeof(char), (Lines + ExtraScrollbackLines) );
+
+ AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
+ AxWin3_RichText_SetCursorType(gMainWindow, 1); // TODO: enum
+}
+
+void Display_int_PushString(int Length, const char *Text)
+{
+ _SysDebug("Line %i += %i '%*C'", giCurrentLine, Length, Length, Text);
+ if( !gasDisplayLines[giCurrentLine] || giCurrentLinePos + Length >= gaiDisplayLineSizes[giCurrentLine] )
+ {
+ int reqsize = giCurrentLinePos + Length;
+ gaiDisplayLineSizes[giCurrentLine] = (reqsize + 32-1) & ~(32-1);
+ void *tmp = realloc(gasDisplayLines[giCurrentLine], gaiDisplayLineSizes[giCurrentLine]);
+ if( !tmp ) perror("Display_AddText - realloc");
+ gasDisplayLines[giCurrentLine] = tmp;
+ }
+
+ memcpy(gasDisplayLines[giCurrentLine]+giCurrentLinePos, Text, Length);
+ gabDisplayLinesDirty[giCurrentLine] = 1;
+ gasDisplayLines[giCurrentLine][giCurrentLinePos+Length] = 0;
+ giCurrentLinePos += Length;
+
+}
+
+void Display_AddText(int Length, const char *UTF8Text)
+{
+ _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
+ // Copy as many characters (not bytes, have to trim off the last char) as we can to the current line
+ // - then roll over to the next line
+ while( Length > 0 )
+ {
+ int space = giDisplayCols - giCurrentCol;
+ int bytes = 0;
+ while( space && bytes < Length )
+ {
+ uint32_t cp;
+ bytes += ReadUTF8(UTF8Text+bytes, &cp);
+ if( Unicode_IsPrinting(cp) ) {
+ space --;
+ giCurrentCol ++;
+ }
+ }
+
+ Display_int_PushString(bytes, UTF8Text);
+
+ UTF8Text += bytes;
+ _SysDebug("Length(%i) -= bytes(%i)", Length, bytes);
+ Length -= bytes;
+ if( Length != 0 )
+ {
+ // Next line
+ giCurrentLinePos = 0;
+ giCurrentCol = 0;
+ giCurrentLine ++;
+ }
+ }
+}
+
+void Display_Newline(int bCarriageReturn)
+{
+ Display_Flush();
+
+ // Going down!
+ giCurrentLine ++;
+ if( giCurrentLine == giDisplayLines )
+ giCurrentLine = 0;
+ if( giCurrentLine == giFirstLine )
+ {
+ giFirstLine ++;
+ if(giFirstLine == giDisplayLines)
+ giFirstLine = 0;
+ }
+
+ if( bCarriageReturn ) {
+ giCurrentLinePos = 0;
+ giCurrentCol = 0;
+ }
+ else {
+ giCurrentLinePos = 0;
+ int i = giCurrentCol;
+ if( !gasDisplayLines[giCurrentLine] )
+ {
+ giCurrentCol = 0;
+ while(i--)
+ Display_AddText(1, " ");
+ }
+ else
+ {
+ while( i -- )
+ {
+ uint32_t cp;
+ giCurrentLinePos += ReadUTF8(gasDisplayLines[giCurrentLine]+giCurrentLinePos, &cp);
+ if( !Unicode_IsPrinting(cp) )
+ i ++;
+ }
+ }
+ }
+}
+
+void Display_SetCursor(int Row, int Col)
+{
+ UNIMPLIMENTED();
+}
+
+void Display_MoveCursor(int RelRow, int RelCol)
+{
+ if( RelRow < 0 )
+ {
+ for( ; RelRow < 0; RelRow ++ )
+ {
+ uint32_t cp;
+ int delta = ReadUTF8Rev(gasDisplayLines[giCurrentLine], giCurrentLinePos, &cp);
+ if( !Unicode_IsPrinting(cp) )
+ RelRow --;
+ else
+ giCurrentCol --;
+ giCurrentLinePos -= delta;
+ }
+ }
+ else
+ {
+ UNIMPLIMENTED();
+ }
+}
+
+void Display_ClearLine(int Dir) // 0: All, 1: Forward, -1: Reverse
+{
+ if( Dir == 0 )
+ {
+ // Completely clear line
+ if( gasDisplayLines[giCurrentLine] )
+ free(gasDisplayLines[giCurrentLine]);
+ gasDisplayLines[giCurrentLine] = NULL;
+ gabDisplayLinesDirty[giCurrentLine] = 1;
+ }
+ else if( Dir == 1 )
+ {
+ // Forward clear (truncate)
+ }
+ else if( Dir == -1 )
+ {
+ // Reverse clear (replace with spaces)
+ }
+ else
+ {
+ // BUGCHECK
+ }
+}
+
+void Display_ClearLines(int Dir) // 0: All, 1: Forward, -1: Reverse
+{
+ if( Dir == 0 )
+ {
+ // Push giDisplayLines worth of empty lines
+ // Move cursor back up by giDisplayLines
+ }
+ else if( Dir == 1 )
+ {
+ // Push (giDisplayLines - (giCurrentLine-giFirstDispLine)) and reverse
+ }
+ else if( Dir == -1 )
+ {
+ // Reverse clear (replace with spaces)
+ }
+ else
+ {
+ // BUGCHECK
+ }
+}
+
+void Display_SetForeground(uint32_t RGB)
+{
+ char buf[7+1];
+ sprintf(buf, "\1%06x", RGB&0xFFFFFF);
+ Display_int_PushString(7, buf);
+}
+
+void Display_SetBackground(uint32_t RGB)
+{
+ char buf[7+1];
+ sprintf(buf, "\2%06x", RGB&0xFFFFFF);
+ Display_int_PushString(7, buf);
+}
+
+void Display_Flush(void)
+{
+ int i;
+ for( i = 0; i < giDisplayCols; i ++ )
+ {
+ int line = (giFirstLine + i) % giDisplayTotalLines;
+ if( !gabDisplayLinesDirty[line] )
+ continue;
+ _SysDebug("Line %i+%i '%s'", giFirstLine, i, gasDisplayLines[line]);
+ AxWin3_RichText_SendLine(gMainWindow, giFirstLine + i, gasDisplayLines[line] );
+ gabDisplayLinesDirty[line] = 0;
+ }
+
+ // force redraw?
+ AxWin3_RichText_SetCursorPos(gMainWindow, giCurrentLine, giCurrentCol);
+}
+
+void Display_ShowAltBuffer(int AltBufEnabled)
+{
+ UNIMPLIMENTED();
+}
+
* - By John Hodge (thePowersGang)
*
* display.h
- * - RichText Termianl Translation
+ * - RichText terminal translation
*/
#ifndef _DISPLAY_H_
#define _DISPLAY_H_
+#include <stdint.h>
+
+extern void Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+
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_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse
extern void Display_SetForeground(uint32_t RGB);
extern void Display_SetBackground(uint32_t RGB);
+/**
+ * \brief Ensure that recent updates are flushed to the server
+ * \note Called at the end of an "input" buffer
+ */
+extern void Display_Flush(void);
+
+/**
+ * \brief Switch the display to the alternate buffer (no scrollback)
+ */
+extern void Display_ShowAltBuffer(int AltBufEnabled);
#endif
#include <axwin3/axwin.h>
#include <axwin3/menu.h>
#include <axwin3/richtext.h>
+#include <axwin3/keysyms.h>
#include <stdio.h>
+#include <acess/sys.h>
#include "include/display.h"
#include "include/vt100.h"
+#include <string.h>
+#include <unicode.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);
+void Term_HandleOutput(int Len, const char *Buf);
// === GLOBALS ===
tHWND gMainWindow;
// <testing>
AxWin3_RichText_SetLineCount(gMainWindow, 3);
AxWin3_RichText_SendLine(gMainWindow, 0, "First line!");
- AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red");
+ AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \1ff0000A red");
// </testing>
- AxWin3_ResizeWindow(gMainWindow, 600, 400);
- AxWin3_MoveWindow(gMainWindow, 50, 50);
+ Display_Init(80, 25, 100);
+ AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
+ AxWin3_MoveWindow(gMainWindow, 20, 50);
AxWin3_ShowWindow(gMainWindow, 1);
AxWin3_FocusWindow(gMainWindow);
// Spawn shell
- giChildStdout = open("/Devices/FIFO/anon", O_RDWR);
- giChildStdin = open("/Devices/FIFO/anon", O_RDWR);
+ giChildStdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+ giChildStdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+ if( giChildStdout == -1 || giChildStdin == -1 ) {
+ perror("Oh, fsck");
+ _SysDebug("out,in = %i,%i", giChildStdout, giChildStdin);
+ return -1;
+ }
{
int fds[] = {giChildStdin, giChildStdout, giChildStdout};
const char *argv[] = {"CLIShell", NULL};
- _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ if( pid < 0 )
+ _SysDebug("ERROR: Shell spawn failed");
}
// Main loop
if( FD_ISSET(giChildStdout, &fds) )
{
+ _SysDebug("Activity on child stdout");
// Read and update screen
char buf[32];
- int len = read(giChildStdout, buf, sizeof(buf));
+ int len = _SysRead(giChildStdout, buf, sizeof(buf));
if( len <= 0 ) break;
Term_HandleOutput(len, buf);
#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);
+ case KEYSYM_LEFTCTRL:
+ _bitset(ctrl_state, 0, bPress!=0);
return 0;
- case KEY_RCTRL:
- _bitset(ctrl_state, 0, bPress);
+ case KEYSYM_RIGHTCTRL:
+ _bitset(ctrl_state, 1, bPress!=0);
return 0;
}
#undef _bitset
// Handle shortcuts
// - Ctrl-A -- Ctrl-Z
- if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z )
+ if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z )
{
- Translated = KeySym - KEY_a + 1;
+ Translated = KeySym - KEYSYM_a + 1;
}
- if( Translated )
+ // == 2 :: FIRE
+ if( bPress == 2 )
{
- // Encode and send
+ if( Translated )
+ {
+ char buf[6];
+ int len;
+
+ // Encode and send
+ len = WriteUTF8(buf, Translated);
+
+ _SysDebug("Keystroke translated to '%.*s'", len, buf);
+ _SysWrite(giChildStdin, buf, len);
+
+ return 0;
+ }
- return 0;
- }
-
- // No translation, look for escape sequences to send
- switch(KeySym)
- {
- case KEY_LEFTARROW:
- // str = "\x1b[D";
- break;
+ // No translation, look for escape sequences to send
+ const char *str = NULL;
+ switch(KeySym)
+ {
+ case KEYSYM_LEFTARROW:
+ str = "\x1b[D";
+ break;
+ }
+ if( str )
+ {
+ _SysWrite(giChildStdin, str, strlen(str));
+ }
}
return 0;
}
Display_AddText(-esc_len, Buf + ofs);
esc_len = -esc_len;
}
- Len -= esc_len;
ofs += esc_len;
+ _SysDebug("Len = %i, ofs = %i", Len, ofs);
}
+
+ Display_Flush();
}
* Acess GUI Terminal
* - By John Hodge (thePowersGang)
*
- * main.c
- * - Core
+ * vt100.c
+ * - VT100/xterm Emulation
*/
#include <string.h>
+#include <limits.h>
#include "include/vt100.h"
#include "include/display.h"
+#include <ctype.h> // isalpha
+#include <acess/sys.h> // _SysDebug
+
+const uint32_t caVT100Colours[] = {
+ // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
+ // Same again, but bright
+ 0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
+ 0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
+};
+
+ int Term_HandleVT100_Long(int Len, const char *Buf);
+
+static inline int min(int a, int b)
+{
+ return a < b ? a : b;
+}
int Term_HandleVT100(int Len, const char *Buf)
{
- const int max_length = 16;
- static char inc_buf[max_length]
+ #define MAX_VT100_ESCAPE_LEN 16
+ static char inc_buf[MAX_VT100_ESCAPE_LEN];
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;
+ int new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
+ int ret = 0, old_inc_len = inc_len;
+ memcpy(inc_buf + inc_len, Buf, new_bytes);
+
+ inc_len += new_bytes;
+
+ if( inc_len <= 1 )
+ return 1; // Skip 1 character (the '\x1b')
+
+ switch(inc_buf[1])
+ {
+ case '[': // Multibyte, funtime starts
+ ret = Term_HandleVT100_Long(inc_len-2, inc_buf+2);
+ if( ret > 0 ) {
+ ret += 2;
+ }
+ break;
+ default:
+ ret = 2;
+ break;
+ }
+
+ if( ret != 0 ) {
+ inc_len = 0;
+ ret -= old_inc_len; // counter cached bytes
+ }
+ return ret;
}
switch( *Buf )
{
case '\b':
// TODO: Backspace
+ Display_MoveCursor(-1, 0);
+ Display_AddText(1, " ");
+ Display_MoveCursor(-1, 0);
return 1;
case '\t':
- // TODO: tab
+ // TODO: tab (get current cursor pos, space until multiple of 8)
return 1;
case '\n':
Display_Newline(1);
return 1;
case '\r':
// TODO: Carriage return
- return ;
+ Display_MoveCursor(INT_MIN, 0);
+ return 1;
}
int ret = 0;
}
return -ret;
}
+
+int Term_HandleVT100_Long(int Len, const char *Buffer)
+{
+ char c;
+ int argc = 0, j = 0;
+ int args[6] = {0,0,0,0,0,0};
+ int bQuestionMark = 0;
+
+ // Get Arguments
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ if(c == '?') {
+ bQuestionMark = 1;
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ if( '0' <= c && c <= '9' )
+ {
+ do {
+ if(c == ';') {
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ while('0' <= c && c <= '9') {
+ args[argc] *= 10;
+ args[argc] += c-'0';
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ argc ++;
+ } while(c == ';');
+ }
+
+ // Get Command
+ if( !isalpha(c) ) {
+ // Bother.
+ _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
+ return 1;
+ }
+
+ if( bQuestionMark )
+ {
+ // Special commands
+ switch( c )
+ {
+ default:
+ _SysDebug("Unknown VT100 extended escape char 0x%x", c);
+ break;
+ }
+ }
+ else
+ {
+ // Standard commands
+ switch( c )
+ {
+ case 'J':
+ if( argc == 0 )
+ Display_ClearLine(0);
+ else if( args[0] == 2 )
+ Display_ClearLines(0); // Entire screen!
+ else
+ _SysDebug("TODO: VT100 %i J", args[0]);
+ break;
+ case 'm':
+ if( argc == 0 )
+ {
+ // Reset
+ }
+ else
+ {
+ int i;
+ for( i = 0; i < argc; i ++ )
+ {
+ if( args[i] < 8 )
+ {
+ // Flags?
+ }
+ else if( 30 <= args[i] && args[i] <= 37 )
+ {
+ // TODO: Bold/bright
+ Display_SetForeground( caVT100Colours[ args[i]-30 ] );
+ }
+ else if( 40 <= args[i] && args[i] <= 47 )
+ {
+ // TODO: Bold/bright
+ Display_SetBackground( caVT100Colours[ args[i]-30 ] );
+ }
+ }
+ }
+ break;
+ default:
+ _SysDebug("Unknown VT100 escape char 0x%x", c);
+ break;
+ }
+ }
+ return j;
+}
--- /dev/null
+/*
+ * Acess2 Userland init(8)
+ * - Userland root process
+ *
+ * common.h
+ * - Common type definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+typedef struct sInitProgram tInitProgram;
+
+struct sKTerm
+{
+ int ID;
+};
+
+struct sSTerm
+{
+ uint32_t FormatBits;
+ unsigned int BaudRate;
+ char Path[];
+};
+
+struct sDaemon
+{
+ char *StdoutPath; // heap
+ char *StderrPath; // heap
+};
+
+union uProgTypes
+{
+ struct sKTerm KTerm;
+ struct sSTerm STerm;
+ struct sDaemon Daemon;
+};
+
+enum eProgType
+{
+ PT_KTERM,
+ PT_STERM,
+ PT_DAEMON
+};
+
+struct sInitProgram
+{
+ tInitProgram *Next;
+ enum eProgType Type;
+ int CurrentPID;
+ char **Command;
+ union uProgTypes TypeInfo;
+};
+
+#endif
+
#include <acess/sys.h>
#include <stdlib.h>
#include <stdio.h>
-//#include "common.h"
+#include <string.h>
+#include "common.h"
+#include <ctype.h>
// === CONSTANTS ===
-#define NUM_TERMS 4
-#define DEFAULT_TERMINAL "/Devices/VTerm/0"
#define DEFAULT_SHELL "/Acess/SBin/login"
+#define INITTAB_FILE "/Acess/Conf/inittab"
#define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0])))
// === PROTOTYPES ===
+ int ProcessInittab(const char *Path);
+char *ReadQuotedString(FILE *FP);
+char **ReadCommand(FILE *FP);
+void FreeCommand(char **Command);
+
+tInitProgram *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace);
+void RespawnProgam(tInitProgram *Program);
+
+ int AddKTerminal(int TerminalSpec, char **Command);
+ int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command);
+ int AddDaemon(char *StdoutPath, char *StderrPath, char **Command);
+
+ int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV);
+ int SpawnKTerm(tInitProgram *Program);
+ int SpawnSTerm(tInitProgram *Program);
+ int SpawnDaemon(tInitProgram *Program);
+
+// === GLOBALS ===
+const char *gsInittabPath = INITTAB_FILE;
+tInitProgram *gpInitPrograms;
// === CODE ===
/**
*/
int main(int argc, char *argv[])
{
- int tid;
- int i;
- char termpath[sizeof(DEFAULT_TERMINAL)] = DEFAULT_TERMINAL;
- char *child_argv[2] = {DEFAULT_SHELL, 0};
+ // Parse commandline args
+ // TODO: cmdline
+
+ // TODO: Behave differently if not invoked as first process?
+
+ // Begin init process
+ if( ProcessInittab(gsInittabPath) != 0 )
+ {
+ // No inittab file found, default to:
+ _SysDebug("inittab '%s' is invalid, falling back to one VT", gsInittabPath);
+
+ #if 0
+ for( ;; )
+ {
+ int pid = SpawnCommand(0, 1, 1, (char *[]){DEFAULT_SHELL, NULL});
+ // TODO: Detect errors
+ _SysWaitTID(pid, NULL);
+ }
+ #else
+ return 41;
+ #endif
+ }
+
+ // TODO: Implement message watching
+ for(;;)
+ {
+ int pid, status;
+ pid = _SysWaitTID(-1, &status);
+ _SysDebug("PID %i died, looking for respawn entry", pid);
+ }
- // - Parse init script
+ return 42;
+}
+
+char *ReadQuotedString(FILE *FP)
+{
+ char ch;
+
+ while( isblank(ch = fgetc(FP)) )
+ ;
+
+ if( ch == '\n' ) {
+ return NULL;
+ }
+
+ char *retstr = NULL;
+ int mode = 0;
+ int pos = 0, space = 0;
+ for( ; !feof(FP); ch = fgetc(FP) )
+ {
+ int skip;
+ skip = 1;
+ if( mode & 4 ) {
+ // Add escaped/special character
+ skip = 0;
+ mode &= 3;
+ }
+ else if( mode == 0 )
+ {
+ if( isspace(ch) ) {
+ fseek(FP, -1, SEEK_CUR);
+ break;
+ }
+ else if( ch == '\\' )
+ mode |= 4;
+ else if( ch == '"' )
+ mode = 1;
+ else if( ch == '\'')
+ mode = 2;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Double-quoted string
+ else if( mode == 1 )
+ {
+ if( ch == '"' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Single-quoted string
+ else if( mode == 2 )
+ {
+ if( ch == '\'' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
- // - Start virtual terminals
- for( i = 0; i < NUM_TERMS; i++ )
- {
- tid = _SysClone(CLONE_VM, 0);
- if(tid == 0)
+ if( !skip )
{
- termpath[sizeof(DEFAULT_TERMINAL)-2] = '0' + i;
+ if( pos == space ) {
+ space += 32;
+ void *tmp = realloc(retstr, space+1);
+ if( !tmp ) {
+ _SysDebug("ReadQuotedString - realloc(%i) failure", space+1);
+ free(retstr);
+ return NULL;
+ }
+ retstr = tmp;
+ }
+ retstr[pos++] = ch;
+ }
+ }
+ retstr[pos] = '\0';
+ return retstr;
+}
+
+char **ReadCommand(FILE *FP)
+{
+ const int space = 8;
+ int pos = 0;
+ char **ret = malloc(space*sizeof(char*));
+ char *arg;
+ do {
+ arg = ReadQuotedString(FP);
+ if(arg == NULL)
+ break;
+ if( pos == space - 1 ) {
+ _SysDebug("Too many arguments %i", pos);
+ ret[pos] = NULL;
+ FreeCommand(ret);
+ return NULL;
+ }
+ ret[pos++] = arg;
+ } while(arg != NULL);
+ ret[pos] = NULL;
+ return ret;
+}
+
+void FreeCommand(char **Command)
+{
+ int pos = 0;
+ while( Command[pos] )
+ {
+ free(Command[pos]);
+ pos ++;
+ }
+ free(Command);
+}
+
+int ProcessInittab(const char *Path)
+{
+ FILE *fp = fopen(Path, "r");
+
+ if( !fp )
+ return 1;
+
+ while(!feof(fp))
+ {
+ char cmdbuf[64+1];
+
+ int rv;
+ if( (rv = fscanf(fp, "%64s%*[ \t]", &cmdbuf)) != 1 ) {
+ _SysDebug("fscanf rv %i != exp 1", rv);
+ break;
+ }
+
+ // Clear comments
+ if( cmdbuf[0] == '#' ) {
+ while( !feof(fp) && fgetc(fp) != '\n' )
+ ;
+ continue ;
+ }
+ if( cmdbuf[0] == '\0' ) {
+ char ch = fgetc(fp);
+ if( ch != '\n' && ch != -1 ) {
+ fclose(fp);
+ _SysDebug("Unexpected char 0x%x, expecting EOL", ch);
+ return 2; // Unexpected character?
+ }
+ continue ;
+ }
+
+ // Check commands
+ if( strcmp(cmdbuf, "ktty") == 0 ) {
+ // ktty <ID> <command...>
+ // - Spins off a console on the specified kernel TTY
+ int id = 0;
+ if( fscanf(fp, "%d ", &id) != 1 ) {
+ _SysDebug("init[ktty] - TTY ID read failed");
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command ) {
+ _SysDebug("init[ktty] - Command read failure");
+ goto lineError;
+ }
+ AddKTerminal(id, command);
+ free(command);
+ }
+ else if(strcmp(cmdbuf, "stty") == 0 ) {
+ // stty <devpath> [78][NOE][012][bB]<baud> <command...>
+ char path_seg[32+1];
+ char modespec[4+6+1];
+ if( fscanf(fp, "%32s %6s ", &path_seg, &modespec) != 2 ) {
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command )
+ goto lineError;
+ AddSerialTerminal(path_seg, modespec, command);
+ }
+ else if(strcmp(cmdbuf, "daemon") == 0 ) {
+ // daemon <stdout> <stderr> <command...>
+ // - Runs a daemon (respawning) that logs to the specified files
+ // - Will append a header whenever the daemon starts
+ char *stdout_path = ReadQuotedString(fp);
+ char *stderr_path = ReadQuotedString(fp);
+ char **command = ReadCommand(fp);
- _SysOpen(termpath, OPENFLAG_READ); // Stdin
- _SysOpen(termpath, OPENFLAG_WRITE); // Stdout
- _SysOpen(termpath, OPENFLAG_WRITE); // Stderr
- _SysExecVE(DEFAULT_SHELL, child_argv, NULL);
- for(;;) ;
+ AddDaemon(stdout_path, stderr_path, command);
+ }
+ else if(strcmp(cmdbuf, "exec") == 0 ) {
+ // exec <command...>
+ // - Runs a command and waits for it to complete before continuing
+ // - NOTE: No other commands will respawn while this is running
+ char **command = ReadCommand(fp);
+ if(!command)
+ goto lineError;
+
+ int handles[] = {0, 1, 2};
+ int pid = _SysSpawn(command[0], (const char **)command, NULL, 3, handles, NULL);
+ int retstatus;
+ _SysWaitTID(pid, &retstatus);
+ _SysDebug("Command '%s' returned %i", command[0], retstatus);
+
+ FreeCommand(command);
+ }
+ else {
+ // Unknown command.
+ _SysDebug("Unknown command '%s'", cmdbuf);
+ goto lineError;
}
+ fscanf(fp, " ");
+ continue;
+ lineError:
+ _SysDebug("label lineError: goto'd");
+ while( !feof(fp) && fgetc(fp) != '\n' )
+ ;
+ continue ;
}
+
+ fclose(fp);
+ return 0;
+}
+
+tInitProgram *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace)
+{
+ tInitProgram *ret;
- // TODO: Implement message watching
- for(;;)
- _SysWaitEvent(THREAD_EVENT_IPCMSG);
+ ret = malloc( sizeof(tInitProgram) - sizeof(union uProgTypes) + ExtraSpace );
+ ret->Next = NULL;
+ ret->CurrentPID = 0;
+ ret->Type = Type;
+ ret->Command = Command;
- return 42;
+ // Append
+ ret->Next = gpInitPrograms;
+ gpInitPrograms = ret;
+
+ return ret;
+}
+
+void RespawnProgam(tInitProgram *Program)
+{
+ int rv = 0;
+ switch(Program->Type)
+ {
+ case PT_KTERM: rv = SpawnKTerm(Program); break;
+ case PT_STERM: rv = SpawnSTerm(Program); break;
+ case PT_DAEMON: rv = SpawnDaemon(Program); break;
+ default:
+ _SysDebug("BUGCHECK - Program Type %i unknown", Program->Type);
+ break;
+ }
+ if( !rv ) {
+ _SysDebug("Respawn failure!");
+ // TODO: Remove from list?
+ }
+}
+
+int AddKTerminal(int TerminalID, char **Command)
+{
+ // TODO: Smarter validation
+ if( TerminalID < 0 || TerminalID > 7 )
+ return -1;
+
+ tInitProgram *ent = AllocateProgram(Command, PT_KTERM, sizeof(struct sKTerm));
+ ent->TypeInfo.KTerm.ID = TerminalID;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command)
+{
+ char dbit, parity, sbit;
+ int baud;
+
+ // Parse mode string
+ if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 5 ) {
+ // Oops?
+ return -1;
+ }
+
+ // Validate baud rate / build mode word
+ // TODO: Does baud rate need validation?
+ uint32_t modeword = 0;
+ modeword |= (dbit == '7' ? 1 : 0) << 0;
+ modeword |= (parity == 'O' ? 1 : (parity == 'E' ? 2 : 0)) << 1;
+ modeword |= (sbit - '0') << 3;
+
+ // Create info
+ const char DEVPREFIX[] = "/Devices/";
+ int pathlen = sizeof(DEVPREFIX) + strlen(DevPathSegment);
+ tInitProgram *ent = AllocateProgram(Command, PT_STERM, sizeof(struct sSTerm)+pathlen);
+ ent->TypeInfo.STerm.FormatBits = modeword;
+ ent->TypeInfo.STerm.BaudRate = baud;
+ strcpy(ent->TypeInfo.STerm.Path, DEVPREFIX);
+ strcat(ent->TypeInfo.STerm.Path, DevPathSegment);
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddDaemon(char *StdoutPath, char *StderrPath, char **Command)
+{
+ tInitProgram *ent = AllocateProgram(Command, PT_DAEMON, sizeof(struct sDaemon));
+ ent->TypeInfo.Daemon.StdoutPath = StdoutPath;
+ ent->TypeInfo.Daemon.StderrPath = StderrPath;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV)
+{
+ int handles[] = {c_stdin, c_stdout, c_stderr};
+
+ int rv = _SysSpawn(ArgV[0], (const char **)ArgV, NULL, 3, handles, NULL);
+
+ _SysClose(c_stdin);
+ if( c_stdout != c_stdin )
+ _SysClose(c_stdout);
+ if( c_stderr != c_stdin && c_stderr != c_stdout )
+ _SysClose(c_stderr);
+
+ return rv;
+}
+
+int SpawnKTerm(tInitProgram *Program)
+{
+ const char fmt[] = "/Devices/VTerm/%i";
+ char path[sizeof(fmt)];
+
+ snprintf(path, sizeof(path), fmt, Program->TypeInfo.KTerm.ID);
+
+ int in = _SysOpen(path, OPENFLAG_READ);
+ int out = _SysOpen(path, OPENFLAG_WRITE);
+
+ return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnSTerm(tInitProgram *Program)
+{
+ int in = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_READ);
+ int out = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_WRITE);
+
+ #if 0
+ if( _SysIOCtl(in, 0, NULL) != DRV_TYPE_SERIAL )
+ {
+ // Oops?
+ return -2;
+ }
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETBAUD, &Program->TypeInfo.STerm.BaudRate);
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETFORMAT, &Program->TypeInfo.STerm.FormatBits);
+ #endif
+
+ return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnDaemon(tInitProgram *Program)
+{
+ int in = _SysOpen("/Devices/null", OPENFLAG_READ);
+ int out = _SysOpen(Program->TypeInfo.Daemon.StdoutPath, OPENFLAG_WRITE);
+ int err = _SysOpen(Program->TypeInfo.Daemon.StderrPath, OPENFLAG_WRITE);
+
+ if( in == -1 || out == -1 || err == -1 ) {
+ _SysClose(in);
+ _SysClose(out);
+ _SysClose(err);
+ return -2;
+ }
+
+ return SpawnCommand(in, out, err, Program->Command);
}
tServer *gpServers;\r
tWindow gWindow_Status = {\r
NULL, NULL, NULL, // No next, empty list, no server\r
- 0, "" // No activity, empty name (rendered as status)\r
+ 0, {""} // No activity, empty name (rendered as status)\r
};\r
tWindow *gpWindows = &gWindow_Status;\r
tWindow *gpCurrentWindow = &gWindow_Status;\r
return 0;
}
+static void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
+{
+ FD_SET(fd, set);
+ if(*maxfd < fd) *maxfd = fd;
+}
+
void EventLoop(void)
{
fd_set fds;
int maxfd;
- void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
- {
- FD_SET(fd, set);
- if(*maxfd < fd) *maxfd = fd;
- }
-
for( ;; )
{
FD_ZERO(&fds);
--- /dev/null
+exec /Acess/Bin/dhcpc
+
+ktty 0 /Acess/SBin/login
+ktty 1 /Acess/SBin/login
+stty serial/0 /Acess/SBin/login
+
+
+#vim: ft=text
DIRS = Bin SBin Libs Modules Apps
DIRS += Conf Conf/Auth
-FILES = Conf/BootConf.cfg
+FILES = Conf/inittab
# Conf/Auth/Users Conf/Auth/Passwords Conf/Auth/Groups
#DIRS := $(addprefix $(DISTROOT)/,$(DIRS))
EXTRACLEAN := $(_OBJPREFIX)_stublib.o
INCFILES := sys/sys.h
-CFLAGS = -g -Wall -fno-builtin -fno-leading-underscore -fno-stack-protector -fPIC
+CFLAGS = -g -Wall -fno-builtin -fno-stack-protector -fPIC
+# -fno-leading-underscore
CFLAGS += $(CPPFLAGS) -Werror
LDFLAGS = -g -T arch/$(ARCHDIR).ld -Map map.txt --export-dynamic
// Override the clone syscall
#define _exit _exit_raw
#define _clone _clone_raw
+#define _SysSeek _SysSeek_borken
#include "syscalls.s.h"
#undef _exit
#undef _clone
+#undef _SysSeek
+
+// NOTE: _SysSeek needs special handling for alignment
+.globl _SysSeek
+_SysSeek:
+ push {lr}
+ mov r1,r2
+ mov r2,r3
+ ldr r3, [sp,#4]
+ svc #SYS_SEEK
+ ldr r3, =_errno
+ str r2, [r3]
+ pop {pc}
.globl _clone
_clone:
pop {r4}
mov pc, lr
+
.globl _exit
_exit:
svc #0
}
#ifdef SUPPORT_ELF64
+typedef int (*t_elf64_doreloc)(void *Base, const char *strtab, Elf64_Sym *symtab, Elf64_Xword r_info, void *ptr, Elf64_Sxword addend);
+
+int _Elf64DoReloc_X86_64(void *Base, const char *strtab, Elf64_Sym *symtab, 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:
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval + addend;
+ break;
+ case R_X86_64_COPY: {
+ size_t size;
+ if( !GetSymbol(symname, &symval, &size) ) return 1;
+ memcpy(ptr, symval, size);
+ } break;
+ case R_X86_64_GLOB_DAT:
+ if( !GetSymbol(symname, &symval, NULL) ) return 1;
+ *(uint64_t*)ptr = (uintptr_t)symval;
+ break;
+ case R_X86_64_JUMP_SLOT:
+ 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);
+ return 2;
+ }
+ //DEBUGS("_Elf64DoReloc: - Good");
+ return 0;
+}
+
void *Elf64Relocate(void *Base, char **envp, const char *Filename)
{
int i;
}
// Relocation function
- 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:
- if( !GetSymbol(symname, &symval, NULL) ) return 1;
- *(uint64_t*)ptr = (uintptr_t)symval + addend;
- break;
- case R_X86_64_COPY: {
- size_t size;
- if( !GetSymbol(symname, &symval, &size) ) return 1;
- memcpy(ptr, symval, size);
- } break;
- case R_X86_64_GLOB_DAT:
- if( !GetSymbol(symname, &symval, NULL) ) return 1;
- *(uint64_t*)ptr = (uintptr_t)symval;
- break;
- case R_X86_64_JUMP_SLOT:
- 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);
- return 2;
- }
- //DEBUGS("_Elf64DoReloc: - Good");
- return 0;
- }
+ t_elf64_doreloc fpElf64DoReloc = &_Elf64DoReloc_X86_64;
+ #define _Elf64DoReloc(info, ptr, addend) fpElf64DoReloc(Base, strtab, symtab, info, ptr, addend)
int fail = 0;
if( rel )
static inline void FD_CLR(int fd, fd_set *fdsetp)
{
if(fd < 0 || fd > FD_SETSIZE) return;
- fdsetp->flags[fd/16] &= (fd_set_ent_t) ((~1 << (fd%16))) & 0xFFFF;
+ fd_set_ent_t mask = 1 << (fd % 16);
+ fdsetp->flags[fd/16] &= ~mask;
}
static inline void FD_SET(int fd, fd_set *fdsetp)
{
if(fd < 0 || fd > FD_SETSIZE) return;
- fdsetp->flags[fd/16] |= (fd_set_ent_t) (1 << (fd%16));
+ fd_set_ent_t mask = 1 << (fd % 16);
+ fdsetp->flags[fd/16] |= mask;
}
static inline int FD_ISSET(int fd, fd_set *fdsetp)
{
if(fd < 0 || fd > FD_SETSIZE) return 0;
- return !!( fdsetp->flags[fd/16] & (1<<(fd%16)) );
+ fd_set_ent_t mask = 1 << (fd % 16);
+ return !!( fdsetp->flags[fd/16] & mask );
}
#endif
#define GETMSG_IGNORE ((void*)-1)
#define FILEFLAG_DIRECTORY 0x10
#define FILEFLAG_SYMLINK 0x20
+#define CLONE_VM 0x10
+
// === TYPES ===
// int offset = -1;
enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
enum e_vcscanf_types valtype;
+ int fail = 0;
+ int nnewch;
const char *set_start;
int set_len;
{
while( (ich = __getc(h)) && isspace(ich) )
nch ++;
+ if(ich) __rewind(h);
continue ;
}
{
// Decimal integer
case 'd':
- nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// variable-base integer
case 'i':
- nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// Octal integer
case 'o':
- nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// Hexadecimal integer
case 'x': case 'X':
- nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// strtod format float
maxlen = -1;
ich = 0;
- while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
+ while( maxlen -- && (ich = __getc(h)) && !isspace(ich) )
{
if(ptr._char) *ptr._char++ = ich;
nch ++;
}
if( maxlen >= 0 && ich )
__rewind(h);
+ if(ptr._char) *ptr._char++ = 0;
valtype = _VCSCANF_NOTYPE;
break;
// match a set of characters
fch = *format++;
} while( fch && fch != ']' );
+ if( maxlen == 0 )
+ maxlen = -1;
ich = 0;
while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
{
}
if( maxlen >= 0 && ich )
__rewind(h);
+ if(ptr._char) *ptr._char++ = 0;
valtype = _VCSCANF_NOTYPE;
break;
case 'p': // read back printf("%p")
valtype = _VCSCANF_NOTYPE;
break;
}
-
+
+ if(fail)
+ break;
+
switch(valtype)
{
case _VCSCANF_NOTYPE:
int _vfscanf_getc(void *h)
{
- return fgetc(h); // TODO: Handle -1 -> 0
+ int ch = fgetc(h);
+ return ch == -1 ? 0 : ch;
}
void _vfscanf_rewind(void *h)
{
}\r
else {\r
ret = _SysRead(fp->FD, ptr, size*num);\r
+ if( ret == (size_t)-1)\r
+ return -1;\r
+ if( ret == 0 && size*num > 0 ) {\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ return 0;\r
+ }\r
ret /= size;\r
}\r
\r
EXPORT int fgetc(FILE *fp)\r
{\r
char ret = 0;\r
- if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+ if( fread(&ret, 1, 1, fp) != 1 )\r
return -1;\r
return ret;\r
}\r
return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
}\r
\r
-//sprintfv\r
+\r
/**\r
* \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
* \brief Prints a formatted string to a buffer\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
+ #define _addchar(ch) do { \\r
+ if(buf && pos < __maxlen) buf[pos] = (ch); \\r
+ else (void)(ch); \\r
+ pos ++; \\r
+ } while(0)\r
\r
tmp[32] = '\0';\r
\r
}\r
_addchar('\0');\r
pos --;\r
+ #undef _addchar\r
\r
//_SysDebug("vsnprintf: buf = '%s'", buf);\r
\r
va_end(args);\r
\r
// Send to stdout\r
- _SysWrite(_stdout, buf, size+1);\r
+ _SysWrite(_stdout, buf, size);\r
\r
// Free buffer\r
free(buf);\r
typedef struct stat t_fstat;
-#define CLONE_VM 0x10
-
typedef unsigned int id_t;
typedef unsigned long pid_t;
typedef unsigned long tid_t;
--- /dev/null
+# Acess 2 "libunicode"
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS += -Wall
+LDFLAGS += -lc -soname libunicode.so
+
+OBJ = main.o utf-8.o
+BIN = libunicode.so
+
+include ../Makefile.tpl
+
--- /dev/null
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * unicode.h
+ * - Main header
+ */
+#ifndef _LIBUNICODE__UNICODE_H_
+#define _LIBUNICODE__UNICODE_H_
+
+#include <stdint.h>
+
+/**
+ * \breif Read a single codepoint from a UTF-8 stream
+ * \return Number of bytes read
+ */
+extern int ReadUTF8(const char *Input, uint32_t *Val);
+/**
+ * \brief Read backwards in the stream
+ */
+extern int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
+/**
+ * \breif Write a single codepoint to a UTF-8 stream
+ */
+extern int WriteUTF8(char *buf, uint32_t Val);
+
+
+static inline int Unicode_IsPrinting(uint32_t Codepoint) { return 1; }
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 "libunicode"
+ * - By John Hoge
+ *
+ * main.c
+ * - Stub main
+ */
+
+int SoMain(void)
+{
+ return 0;
+}
--- /dev/null
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * utf-8.c
+ * - UTF-8 Parsing code
+ */
+#include <stdint.h>
+#include <unicode.h>
+
+/**
+ * \brief Read a UTF-8 character from a string
+ * \param Input Source UTF-8 encoded string
+ * \param Val Destination for read codepoint
+ * \return Number of bytes read/used
+ */
+int ReadUTF8(const char *Input, uint32_t *Val)
+{
+ const uint8_t *str = (const uint8_t *)Input;
+ *Val = 0xFFFD; // Assume invalid character
+
+ // ASCII
+ if( !(*str & 0x80) ) {
+ *Val = *str;
+ return 1;
+ }
+
+ // Middle of a sequence
+ if( (*str & 0xC0) == 0x80 ) {
+ return 1;
+ }
+
+ // Two Byte
+ if( (*str & 0xE0) == 0xC0 ) {
+ *Val = (*str & 0x1F) << 6; // Upper 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 2;
+ }
+
+ // Three Byte
+ if( (*str & 0xF0) == 0xE0 ) {
+ *Val = (*str & 0x0F) << 12; // Upper 4 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 3;
+ }
+
+ // Four Byte
+ if( (*str & 0xF8) == 0xF0 ) {
+ *Val = (*str & 0x07) << 18; // Upper 3 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 4;
+ }
+
+ // UTF-8 Doesn't support more than four bytes
+ return 4;
+}
+
+/**
+ * \brief Get the UTF-8 character before the
+ * \
+ */
+int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
+{
+ int len = 0;
+
+ // Scan backwards for the beginning of the character
+ while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
+ len ++;
+ // Invalid string (no beginning)
+ if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
+ return len;
+
+ len ++; // First character
+ if( ReadUTF8(Base+Offset, Val) != len ) {
+ *Val = 0xFFFD;
+ }
+ return len;
+}
+
+/**
+ * \brief Write a UTF-8 character sequence to a string
+ * \param buf Destination buffer (must have at least 4 bytes available)
+ * \param Val Unicode codepoint to write
+ * \return Number of bytes written
+ * \note Does not NULL terminate the string in \a buf
+ */
+int WriteUTF8(char *buf, uint32_t Val)
+{
+ uint8_t *str = (void*)buf;
+
+ // ASCII
+ if( Val < 128 ) {
+ if(str) {
+ *str = Val;
+ }
+ return 1;
+ }
+
+ // Two Byte
+ if( Val < 0x8000 ) {
+ if(str) {
+ *str = 0xC0 | (Val >> 6);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 2;
+ }
+
+ // Three Byte
+ if( Val < 0x10000 ) {
+ if(str) {
+ *str = 0xE0 | (Val >> 12);
+ str ++;
+ *str = 0x80 | ((Val >> 6) & 0x3F);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 3;
+ }
+
+ // Four Byte
+ if( Val < 0x110000 ) {
+ if(str) {
+ *str = 0xF0 | (Val >> 18);
+ str ++;
+ *str = 0x80 | ((Val >> 12) & 0x3F);
+ str ++;
+ *str = 0x80 | ((Val >> 6) & 0x3F);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 4;
+ }
+
+ // UTF-8 Doesn't support more than four bytes
+ return 0;
+}
+