From: John Hodge Date: Tue, 22 Jan 2013 06:27:11 +0000 (+0800) Subject: Merge branch 'master' of git://localhost/acess2 X-Git-Tag: rel0.15~598 X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=be5123fe1f4aa66b76ce8ef589362ad21b6bbf72;hp=35dd0489ba760c7d803aed84fd6b1fc7f5793b5d Merge branch 'master' of git://localhost/acess2 --- diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..6154547a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +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" diff --git a/AcessNative/.gitignore b/AcessNative/.gitignore index 82eea121..13714aa5 100644 --- a/AcessNative/.gitignore +++ b/AcessNative/.gitignore @@ -2,3 +2,4 @@ ld-acess ld-acess.exe AcessKernel AcessKernel.exe +Makefile.BuildNum diff --git a/AcessNative/acesskernel_src/helpers.c b/AcessNative/acesskernel_src/helpers.c index 51b96533..6396d166 100644 --- a/AcessNative/acesskernel_src/helpers.c +++ b/AcessNative/acesskernel_src/helpers.c @@ -144,7 +144,6 @@ int strpos(const char *str, char ch) { 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; } @@ -152,7 +151,6 @@ int CheckString(const char *string) { if( (intptr_t)string < 0x1000 ) return 0; - strlen(string); return 1; } @@ -163,3 +161,38 @@ int CheckMem(const void *buf, size_t len) 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; +} + diff --git a/AcessNative/acesskernel_src/nativefs.c b/AcessNative/acesskernel_src/nativefs.c index af25e3c3..cca9e7d8 100644 --- a/AcessNative/acesskernel_src/nativefs.c +++ b/AcessNative/acesskernel_src/nativefs.c @@ -205,8 +205,9 @@ size_t NativeFS_Read(tVFS_Node *Node, _acess_off_t Offset, size_t Length, void * LEAVE('i', 0); return 0; } - LEAVE('-'); - return fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode ); + size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode ); + LEAVE('x', ret); + return ret; } size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer) diff --git a/AcessNative/acesskernel_src/syscalls.c b/AcessNative/acesskernel_src/syscalls.c index 827d6110..44588463 100644 --- a/AcessNative/acesskernel_src/syscalls.c +++ b/AcessNative/acesskernel_src/syscalls.c @@ -30,7 +30,7 @@ typedef int (*tSyscallHandler)(Uint *Errno, const char *Format, void *Args, int 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){\ @@ -281,12 +281,15 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) 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); @@ -297,7 +300,11 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) 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 ++ ) { @@ -318,12 +325,19 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) 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! } } @@ -364,13 +378,6 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) // 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 ) { @@ -406,9 +413,9 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) // ---------- Return - if( ret_errno == 0 ) { - perror("Syscall?"); + if( ret_errno == 0 && errno != 0 ) { ret_errno = errno; + LOG("errno = %i", errno); } // Allocate the return @@ -427,9 +434,18 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) *(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; @@ -450,9 +466,7 @@ tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength) retValueCount ++; } - *ReturnLength = sizeof(tRequestHeader) - + retValueCount * sizeof(tRequestValue) - + retDataLen; + *ReturnLength = ret->MessageLength; return ret; } diff --git a/AcessNative/ld-acess_src/binary.c b/AcessNative/ld-acess_src/binary.c index d04ac6d2..59be8295 100644 --- a/AcessNative/ld-acess_src/binary.c +++ b/AcessNative/ld-acess_src/binary.c @@ -65,9 +65,9 @@ char *Binary_LocateLibrary(const char *Name) 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); } } @@ -84,9 +84,9 @@ char *Binary_LocateLibrary(const char *Name) 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); } } @@ -156,22 +156,22 @@ void *Binary_Load(const char *Filename, uintptr_t *EntryPoint) } } - 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; } @@ -179,7 +179,7 @@ void *Binary_Load(const char *Filename, uintptr_t *EntryPoint) 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 diff --git a/AcessNative/ld-acess_src/common.h b/AcessNative/ld-acess_src/common.h index 376faa58..9f67e9c6 100644 --- a/AcessNative/ld-acess_src/common.h +++ b/AcessNative/ld-acess_src/common.h @@ -36,6 +36,7 @@ static inline int _SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned i return 0; } + extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount); extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits); diff --git a/AcessNative/ld-acess_src/elf_load.c b/AcessNative/ld-acess_src/elf_load.c index d661622e..19a8c13f 100644 --- a/AcessNative/ld-acess_src/elf_load.c +++ b/AcessNative/ld-acess_src/elf_load.c @@ -42,7 +42,7 @@ void *Elf_Load(int FD) Elf64_Ehdr hdr; // Read ELF Header - acess_read(FD, &hdr, sizeof(hdr)); + acess__SysRead(FD, &hdr, sizeof(hdr)); // Check the file type if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') { @@ -89,8 +89,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) return NULL; } LOG("hdr.phoff = 0x%08x\n", hdr->phoff); - acess_seek(FD, hdr->phoff, ACESS_SEEK_SET); - acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount); + acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET); + acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount); // Count Pages iPageCount = 0; @@ -146,8 +146,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) char *tmp; //if(ret->Interpreter) continue; tmp = malloc(phtab[i].FileSize); - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, tmp, phtab[i].FileSize); + acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET); + acess__SysRead(FD, tmp, phtab[i].FileSize); //ret->Interpreter = Binary_RegInterp(tmp); LOG("Interpreter '%s'\n", tmp); free(tmp); @@ -168,8 +168,8 @@ void *Elf32Load(int FD, Elf32_Ehdr *hdr) return NULL; } - acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET); - acess_read(FD, PTRMK(void, addr), phtab[i].FileSize); + acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET); + acess__SysRead(FD, PTRMK(void, addr), phtab[i].FileSize); memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize ); } @@ -211,8 +211,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr) return NULL; } LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff); - acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET); - acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum); + acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET); + acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum); // Count Pages iPageCount = 0; @@ -270,8 +270,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr) //if(ret->Interpreter) continue; tmp = malloc(phtab[i].p_filesz+1); tmp[ phtab[i].p_filesz ] = 0; - acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET); - acess_read(FD, tmp, phtab[i].p_filesz); + acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); + acess__SysRead(FD, tmp, phtab[i].p_filesz); //ret->Interpreter = Binary_RegInterp(tmp); LOG("Interpreter '%s'\n", tmp); free(tmp); @@ -295,8 +295,8 @@ void *Elf64Load(int FD, Elf64_Ehdr *hdr) return NULL; } - acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET); - acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz); + acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET); + acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz); memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz ); } diff --git a/AcessNative/ld-acess_src/exports.c b/AcessNative/ld-acess_src/exports.c index d7e49227..dcfc526a 100644 --- a/AcessNative/ld-acess_src/exports.c +++ b/AcessNative/ld-acess_src/exports.c @@ -42,12 +42,12 @@ char *gsExecutablePath = "./ld-acess"; // === 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 ) { @@ -57,7 +57,8 @@ int acess_open(const char *Path, int Flags) 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)); } @@ -65,12 +66,12 @@ void acess_close(int FD) { _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 ) @@ -78,7 +79,7 @@ size_t acess_read(int FD, void *Dest, size_t Bytes) { return _Syscall(SYS_READ, ">i >i 2 ) @@ -86,7 +87,8 @@ size_t acess_write(int FD, const void *Src, size_t Bytes) { 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); } @@ -94,14 +96,15 @@ int acess_seek(int FD, int64_t Ofs, int 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 @@ -111,7 +114,7 @@ int acess_ioctl(int fd, int id, void *data) { 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 i", @@ -121,7 +124,7 @@ int acess_finfo(int fd, t_sysFInfo *info, int maxacls) { ); } -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 i >s >i", fd, name, flags); @@ -176,7 +173,7 @@ uint64_t acess__SysAllocate(uintptr_t vaddr) } // --- 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"); @@ -212,7 +209,7 @@ int acess_clone(int flags, void *stack) #endif } -int acess_execve(char *path, char **argv, const char **envp) +int acess__SysExecVE(char *path, char **argv, const char **envp) { int i, argc; @@ -289,13 +286,13 @@ int acess__SysSpawn(const char *binary, const char **argv, const char **envp, in 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 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, "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; @@ -276,6 +278,7 @@ uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...) 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; } diff --git a/AcessNative/syscalls.h b/AcessNative/syscalls.h index 21a9cb53..b9661bcf 100644 --- a/AcessNative/syscalls.h +++ b/AcessNative/syscalls.h @@ -35,84 +35,20 @@ typedef struct sRequestHeader { 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 diff --git a/AcessNative/syscalls_list.h b/AcessNative/syscalls_list.h new file mode 100644 index 00000000..9ab9098c --- /dev/null +++ b/AcessNative/syscalls_list.h @@ -0,0 +1,37 @@ +_(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), + diff --git a/BuildConf/armv7/default.mk b/BuildConf/armv7/default.mk index 29ef50a8..7867b163 100644 --- a/BuildConf/armv7/default.mk +++ b/BuildConf/armv7/default.mk @@ -5,5 +5,4 @@ endif # Core ARMv7 modules -MODULES += armv7/GIC MODULES += Filesystems/InitRD diff --git a/BuildConf/armv7/realview_pb.mk b/BuildConf/armv7/realview_pb.mk index abb08e28..ce122f3b 100644 --- a/BuildConf/armv7/realview_pb.mk +++ b/BuildConf/armv7/realview_pb.mk @@ -2,5 +2,6 @@ include $(ACESSDIR)/BuildConf/armv7/default.mk ARM_CPUNAME = cortex-a8 +MODULES += armv7/GIC MODULES += Input/PS2KbMouse MODULES += Display/PL110 diff --git a/BuildConf/armv7/tegra2.mk b/BuildConf/armv7/tegra2.mk index 24eddf53..cd20c371 100644 --- a/BuildConf/armv7/tegra2.mk +++ b/BuildConf/armv7/tegra2.mk @@ -2,5 +2,6 @@ include $(ACESSDIR)/BuildConf/armv7/default.mk ARM_CPUNAME = cortex-a9 +MODULES += armv7/GIC MODULES += Display/Tegra2Vid MODULES += USB/Core USB/EHCI diff --git a/KernelLand/Kernel/arch/armv7/Makefile b/KernelLand/Kernel/arch/armv7/Makefile index 5429fe66..1d9f4369 100644 --- a/KernelLand/Kernel/arch/armv7/Makefile +++ b/KernelLand/Kernel/arch/armv7/Makefile @@ -12,7 +12,7 @@ LDFLAGS += `$(CC) --print-libgcc-file-name` 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) diff --git a/KernelLand/Kernel/arch/armv7/main.c b/KernelLand/Kernel/arch/armv7/main.c index 248c17c5..d05c01e0 100644 --- a/KernelLand/Kernel/arch/armv7/main.c +++ b/KernelLand/Kernel/arch/armv7/main.c @@ -15,6 +15,7 @@ extern void Arch_LoadBootModules(void); 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); @@ -44,7 +45,7 @@ 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 diff --git a/KernelLand/Kernel/arch/armv7/mm_virt.c b/KernelLand/Kernel/arch/armv7/mm_virt.c index 146caea8..80034204 100644 --- a/KernelLand/Kernel/arch/armv7/mm_virt.c +++ b/KernelLand/Kernel/arch/armv7/mm_virt.c @@ -10,7 +10,7 @@ #include #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 diff --git a/KernelLand/Kernel/arch/armv7/platform_realview_pb.c b/KernelLand/Kernel/arch/armv7/platform_realview_pb.c new file mode 100644 index 00000000..4077f691 --- /dev/null +++ b/KernelLand/Kernel/arch/armv7/platform_realview_pb.c @@ -0,0 +1,21 @@ +/* + * Acess2 Kernel ARMv7 Port + * - By John Hodge (thePowersGang) + * + * platform_realviewpb.c + * - RealviewPB core code + */ +#include + +// === PROTOTYPES === +void Time_Setup(void); + +// === GLOBALS === +tPAddr gGIC_DistributorAddr = 0x1e001000; +tPAddr gGIC_InterfaceAddr = 0x1e000000; + +// === CODE === +void Time_Setup(void) +{ + // TODO: +} diff --git a/KernelLand/Kernel/arch/armv7/platform_tegra2.c b/KernelLand/Kernel/arch/armv7/platform_tegra2.c new file mode 100644 index 00000000..36dbb569 --- /dev/null +++ b/KernelLand/Kernel/arch/armv7/platform_tegra2.c @@ -0,0 +1,77 @@ +/* + * Acess2 Kernel ARMv7 Port + * - By John Hodge (thePowersGang) + * + * platform_tegra2.c + * - Tegra2 Core code + */ +#include +#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 diff --git a/KernelLand/Kernel/arch/armv7/platform_tegra2.h b/KernelLand/Kernel/arch/armv7/platform_tegra2.h new file mode 100644 index 00000000..67f75829 --- /dev/null +++ b/KernelLand/Kernel/arch/armv7/platform_tegra2.h @@ -0,0 +1,68 @@ +/* + * 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 + diff --git a/KernelLand/Kernel/arch/armv7/vpci_tegra2.c b/KernelLand/Kernel/arch/armv7/vpci_tegra2.c index d44e9d58..1d01fb0c 100644 --- a/KernelLand/Kernel/arch/armv7/vpci_tegra2.c +++ b/KernelLand/Kernel/arch/armv7/vpci_tegra2.c @@ -11,9 +11,11 @@ // === 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, }, @@ -29,6 +31,7 @@ tVPCI_Device gaVPCI_Devices[] = { .BARs = {0xC5008000,0,0,0,0,0}, .IRQ = 4*32+1, } + #endif }; int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]); diff --git a/KernelLand/Kernel/arch/x86/acpica.c b/KernelLand/Kernel/arch/x86/acpica.c index 43a18549..57d7fe85 100644 --- a/KernelLand/Kernel/arch/x86/acpica.c +++ b/KernelLand/Kernel/arch/x86/acpica.c @@ -5,7 +5,7 @@ * acpica.c * - ACPICA Interface */ -#define ACPI_DEBUG_OUTPUT 1 +#define ACPI_DEBUG_OUTPUT 0 #define DEBUG 0 #define _AcpiModuleName "Shim" #define _COMPONENT "Acess" diff --git a/KernelLand/Kernel/arch/x86/main.c b/KernelLand/Kernel/arch/x86/main.c index 3abf5482..97a7c75b 100644 --- a/KernelLand/Kernel/arch/x86/main.c +++ b/KernelLand/Kernel/arch/x86/main.c @@ -19,7 +19,6 @@ // === 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); diff --git a/KernelLand/Kernel/arch/x86/vm8086.c b/KernelLand/Kernel/arch/x86/vm8086.c index 397ec14f..77b0d1a7 100644 --- a/KernelLand/Kernel/arch/x86/vm8086.c +++ b/KernelLand/Kernel/arch/x86/vm8086.c @@ -77,7 +77,7 @@ int VM8086_Install(char **Arguments) // 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"); @@ -89,7 +89,7 @@ int VM8086_Install(char **Arguments) Uint16 * volatile rmstack; // Real Mode Stack int i; - Log_Debug("VM8086", "Initialising worker"); + //Log_Debug("VM8086", "Initialising worker"); // Set Image Name Threads_SetName("VM8086"); diff --git a/KernelLand/Kernel/arch/x86_64/main.c b/KernelLand/Kernel/arch/x86_64/main.c index a855a474..f4c4a818 100644 --- a/KernelLand/Kernel/arch/x86_64/main.c +++ b/KernelLand/Kernel/arch/x86_64/main.c @@ -53,7 +53,6 @@ void kmain(Uint MbMagic, void *MbInfoPtr) // Adjust Multiboot structure address mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE ); gsBootCmdLine = (char*)( (Uint)mbInfo->CommandLine + KERNEL_BASE); - // TODO: ref above? nPMemMapEnts = Multiboot_LoadMemoryMap(mbInfo, KERNEL_BASE, pmemmap, MAX_PMEMMAP_ENTS, KERNEL_LOAD, (tVAddr)&gKernelEnd - KERNEL_BASE ); @@ -87,6 +86,8 @@ void kmain(Uint MbMagic, void *MbInfoPtr) 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'; diff --git a/KernelLand/Kernel/arch/x86_64/proc.c b/KernelLand/Kernel/arch/x86_64/proc.c index 46e2b21c..b35b5074 100644 --- a/KernelLand/Kernel/arch/x86_64/proc.c +++ b/KernelLand/Kernel/arch/x86_64/proc.c @@ -458,9 +458,8 @@ void Proc_ClearThread(tThread *Thread) 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; @@ -537,11 +536,9 @@ tTID Proc_Clone(Uint Flags) */ 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) { diff --git a/KernelLand/Kernel/debug.c b/KernelLand/Kernel/debug.c index 6132bd90..5e17c0ed 100644 --- a/KernelLand/Kernel/debug.c +++ b/KernelLand/Kernel/debug.c @@ -149,7 +149,7 @@ void Debug(const char *Fmt, ...) va_list args; #if LOCK_DEBUG_OUTPUT - SHORTLOCK(&glDebug_Lock); + if(!CPU_HAS_LOCK(&glDebug_Lock)) SHORTLOCK(&glDebug_Lock); #endif Debug_Puts(0, "Debug: "); @@ -227,7 +227,8 @@ void Panic(const char *Fmt, ...) va_list args; #if LOCK_DEBUG_OUTPUT - SHORTLOCK(&glDebug_Lock); + if( !CPU_HAS_LOCK(&glDebug_Lock) ) + SHORTLOCK(&glDebug_Lock); #endif // And never SHORTREL diff --git a/KernelLand/Kernel/drv/fifo.c b/KernelLand/Kernel/drv/fifo.c index 2adaec7c..1e6fcdb7 100644 --- a/KernelLand/Kernel/drv/fifo.c +++ b/KernelLand/Kernel/drv/fifo.c @@ -1,5 +1,9 @@ -/* AcessOS - * FIFO Pipe Driver +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * drv/fifo.c + * - FIFO Pipe Driver */ #define DEBUG 0 #include @@ -126,9 +130,8 @@ tVFS_Node *FIFO_FindDir(tVFS_Node *Node, const char *Filename) 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; } @@ -277,6 +280,7 @@ size_t FIFO_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer) // 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 @@ -312,9 +316,12 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff 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 ) @@ -346,11 +353,14 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff 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); } @@ -360,6 +370,7 @@ size_t FIFO_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff // Mark some flags if( pipe->ReadPos == pipe->WritePos ) { + LOG("Buffer is full"); VFS_MarkFull(Node, 1); // Buffer full } VFS_MarkAvaliable(Node, 1); @@ -384,11 +395,13 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name) 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 @@ -417,6 +430,8 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name) = ret->Node.MTime = ret->Node.ATime = now(); ret->Node.Type = &gFIFO_PipeNodeType; + + LEAVE('p', ret); return ret; } diff --git a/KernelLand/Kernel/drv/pci.c b/KernelLand/Kernel/drv/pci.c index 2e1ce151..1df421ec 100644 --- a/KernelLand/Kernel/drv/pci.c +++ b/KernelLand/Kernel/drv/pci.c @@ -150,9 +150,15 @@ int PCI_Install(char **Arguments) devinfo->revision = gaVPCI_Devices[i].Class & 0xFF; devinfo->class = gaVPCI_Devices[i].Class >> 8; snprintf(devinfo->Name, sizeof(devinfo->Name), "%02x.%02x:%x", 0xFF, i, 0); + + #if LIST_DEVICES + Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i", + 0xFF, i, 0, devinfo->class, + devinfo->vendor, devinfo->device, devinfo->revision); + #endif for(int j = 0; j < 256/4; j ++ ) - devinfo->ConfigCache[i] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4); + devinfo->ConfigCache[j] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4); memset(&devinfo->Node, 0, sizeof(devinfo->Node)); devinfo->Node.Inode = giPCI_DeviceCount; diff --git a/KernelLand/Kernel/drv/vpci.c b/KernelLand/Kernel/drv/vpci.c index 4fccdb85..e4288b6f 100644 --- a/KernelLand/Kernel/drv/vpci.c +++ b/KernelLand/Kernel/drv/vpci.c @@ -22,12 +22,14 @@ Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size) 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 @@ -35,7 +37,8 @@ Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size) // 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; } @@ -66,7 +69,10 @@ void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data) 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; @@ -80,5 +86,6 @@ void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data) 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); } diff --git a/KernelLand/Kernel/drv/vterm.c b/KernelLand/Kernel/drv/vterm.c index 5316ba55..3ff1a53f 100644 --- a/KernelLand/Kernel/drv/vterm.c +++ b/KernelLand/Kernel/drv/vterm.c @@ -129,6 +129,9 @@ int VT_Install(char **Arguments) else if( strcmp(opt, "Scrollback") == 0 ) { giVT_Scrollback = atoi( val ); } + else { + Log_Notice("VTerm", "Unknown option '%s'", opt); + } } } @@ -448,8 +451,8 @@ size_t VT_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer // - 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 ) { diff --git a/KernelLand/Kernel/drv/vterm.h b/KernelLand/Kernel/drv/vterm.h index 55eea0e5..abd786cb 100644 --- a/KernelLand/Kernel/drv/vterm.h +++ b/KernelLand/Kernel/drv/vterm.h @@ -112,7 +112,7 @@ extern void VT_InitInput(void); 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); diff --git a/KernelLand/Kernel/drv/vterm_termbuf.c b/KernelLand/Kernel/drv/vterm_termbuf.c index 7c296566..525f1a4b 100644 --- a/KernelLand/Kernel/drv/vterm_termbuf.c +++ b/KernelLand/Kernel/drv/vterm_termbuf.c @@ -15,24 +15,27 @@ */ 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); } diff --git a/KernelLand/Kernel/drv/vterm_vt100.c b/KernelLand/Kernel/drv/vterm_vt100.c index fb152a30..d86ee0fb 100644 --- a/KernelLand/Kernel/drv/vterm_vt100.c +++ b/KernelLand/Kernel/drv/vterm_vt100.c @@ -211,30 +211,39 @@ void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int * \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 ++; @@ -242,51 +251,64 @@ int VT_int_ParseEscape(tVTerm *Term, const char *Buffer) } // 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; } diff --git a/KernelLand/Kernel/include/acess.h b/KernelLand/Kernel/include/acess.h index 24148e14..e8ca0d3c 100644 --- a/KernelLand/Kernel/include/acess.h +++ b/KernelLand/Kernel/include/acess.h @@ -378,6 +378,10 @@ extern int strpos(const char *Str, char Ch); 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); diff --git a/KernelLand/Kernel/include/events.h b/KernelLand/Kernel/include/events.h index dc9d6543..17143e86 100644 --- a/KernelLand/Kernel/include/events.h +++ b/KernelLand/Kernel/include/events.h @@ -25,6 +25,8 @@ //! 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 diff --git a/KernelLand/Kernel/include/init.h b/KernelLand/Kernel/include/init.h index 6af177dc..876aa789 100644 --- a/KernelLand/Kernel/include/init.h +++ b/KernelLand/Kernel/include/init.h @@ -9,5 +9,6 @@ extern void Arch_LoadBootModules(void); extern void StartupPrint(const char *String); extern void System_Init(char *Commandline); extern void Threads_Init(void); +extern void Heap_Install(void); #endif diff --git a/KernelLand/Kernel/include/threads_int.h b/KernelLand/Kernel/include/threads_int.h index 578fdcf1..48452649 100644 --- a/KernelLand/Kernel/include/threads_int.h +++ b/KernelLand/Kernel/include/threads_int.h @@ -71,7 +71,10 @@ struct sThread 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; diff --git a/KernelLand/Kernel/libc.c b/KernelLand/Kernel/libc.c index 58c2e1af..a16687e4 100644 --- a/KernelLand/Kernel/libc.c +++ b/KernelLand/Kernel/libc.c @@ -15,11 +15,11 @@ #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); diff --git a/KernelLand/Kernel/messages.c b/KernelLand/Kernel/messages.c index 82374233..b9d7a6fd 100644 --- a/KernelLand/Kernel/messages.c +++ b/KernelLand/Kernel/messages.c @@ -88,10 +88,11 @@ int Proc_GetMessage(Uint *Source, Uint BufSize, void *Buffer) 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; } diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index 1f2f7980..635f69ac 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -29,8 +29,8 @@ #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*) ); \ }\ @@ -172,7 +172,8 @@ void SyscallHandler(tSyscallRegs *Regs) 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 diff --git a/KernelLand/Kernel/system.c b/KernelLand/Kernel/system.c index 9224db55..7938723a 100644 --- a/KernelLand/Kernel/system.c +++ b/KernelLand/Kernel/system.c @@ -48,6 +48,8 @@ void System_Init(char *CommandLine) 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); } diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 92a7a576..a86eba07 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -11,6 +11,7 @@ #include #include #include // VFS Handle maintainence +#include // Configuration #define DEBUG_TRACE_TICKETS 0 // Trace ticket counts @@ -442,9 +443,30 @@ tThread *Threads_CloneThreadZero(void) 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 @@ -460,33 +482,14 @@ tTID Threads_WaitTID(int TID, int *Status) } // 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; } @@ -685,8 +688,10 @@ void Threads_Kill(tThread *Thread, int Status) 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); diff --git a/KernelLand/Kernel/vfs/handle.c b/KernelLand/Kernel/vfs/handle.c index 88877aba..cb4fae12 100644 --- a/KernelLand/Kernel/vfs/handle.c +++ b/KernelLand/Kernel/vfs/handle.c @@ -19,6 +19,7 @@ #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 === @@ -195,7 +196,14 @@ void *VFS_SaveHandles(int NumFDs, int *FDs) 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", diff --git a/KernelLand/Kernel/vfs/select.c b/KernelLand/Kernel/vfs/select.c index 412cb1ae..8bd0deba 100644 --- a/KernelLand/Kernel/vfs/select.c +++ b/KernelLand/Kernel/vfs/select.c @@ -129,8 +129,8 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set 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, @@ -140,6 +140,8 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // 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); @@ -149,9 +151,11 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set // 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; } @@ -306,8 +310,10 @@ int VFS_int_Select_Register(tThread *Thread, int MaxHandle, fd_set *Handles, int } // Check for the flag - if( !!*flag == !!wantedFlagValue ) + if( !!*flag == !!wantedFlagValue ) { + LOG(" %i == want %i", !!*flag, !!wantedFlagValue); numFlagged ++; + } } LEAVE('i', numFlagged); @@ -348,8 +354,6 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i 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); @@ -362,6 +366,8 @@ int VFS_int_Select_Deregister(tThread *Thread, int MaxHandle, fd_set *Handles, i // Check for the flag if( !!*flag == !!wantedFlagValue ) { numFlagged ++; + LOG(" %i == want %i", !!*flag, !!wantedFlagValue); + FD_SET(i, Handles); } else { FD_CLR(i, Handles); diff --git a/KernelLand/Modules/Display/BochsGA/bochsvbe.c b/KernelLand/Modules/Display/BochsGA/bochsvbe.c index 5988ee7c..50e76d33 100644 --- a/KernelLand/Modules/Display/BochsGA/bochsvbe.c +++ b/KernelLand/Modules/Display/BochsGA/bochsvbe.c @@ -82,6 +82,7 @@ Uint *gBGA_Framebuffer; const tBGA_Mode *gpBGA_CurrentMode; const tBGA_Mode gBGA_Modes[] = { {640,480,32, 640*480*4}, + {800,480,32, 800*480*4}, // Nice mode for VM testing {800,600,32, 800*600*4}, {1024,768,32, 1024*768*4} }; diff --git a/KernelLand/Modules/Display/RPi/main.c b/KernelLand/Modules/Display/RPi/main.c new file mode 100644 index 00000000..a0df9031 --- /dev/null +++ b/KernelLand/Modules/Display/RPi/main.c @@ -0,0 +1,61 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include + +// === 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); +} + diff --git a/KernelLand/Modules/Display/Tegra2Vid/main.c b/KernelLand/Modules/Display/Tegra2Vid/main.c index e19a5ff7..34b58f11 100644 --- a/KernelLand/Modules/Display/Tegra2Vid/main.c +++ b/KernelLand/Modules/Display/Tegra2Vid/main.c @@ -59,6 +59,7 @@ size_t giTegra2Vid_FramebufferSize; Uint32 *gpTegra2Vid_IOMem; tPAddr gTegra2Vid_FramebufferPhys; void *gpTegra2Vid_Framebuffer; +void *gpTegra2Vid_Cursor; // -- Misc tDrvUtil_Video_BufInfo gTegra2Vid_DrvUtil_BufInfo; tVideo_IOCtl_Pos gTegra2Vid_CursorPos; @@ -69,6 +70,24 @@ inline void _dumpreg(int i) 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) @@ -77,22 +96,9 @@ 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!!! @@ -105,6 +111,7 @@ int Tegra2Vid_Install(char **Arguments) } #endif +#if 0 giTegra2Vid_FramebufferSize = (gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]&0xFFFF) *(gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]>>16)*4; @@ -114,7 +121,9 @@ int Tegra2Vid_Install(char **Arguments) 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); @@ -126,7 +135,8 @@ int Tegra2Vid_Install(char **Arguments) 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; @@ -134,11 +144,12 @@ int Tegra2Vid_Install(char **Arguments) 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 ); @@ -225,8 +236,11 @@ int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data) 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; @@ -234,7 +248,8 @@ int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data) 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; @@ -287,6 +302,8 @@ int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data) 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, @@ -318,16 +335,21 @@ int Tegra2Vid_int_SetMode(int Mode) { 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); @@ -340,13 +362,17 @@ int Tegra2Vid_int_SetMode(int Mode) 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, @@ -360,6 +386,10 @@ int Tegra2Vid_int_SetMode(int Mode) } 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; } diff --git a/KernelLand/Modules/Display/Tegra2Vid/tegra2.h b/KernelLand/Modules/Display/Tegra2Vid/tegra2.h index 7e3fdf5c..9b33668c 100644 --- a/KernelLand/Modules/Display/Tegra2Vid/tegra2.h +++ b/KernelLand/Modules/Display/Tegra2Vid/tegra2.h @@ -19,6 +19,7 @@ const struct sTegra2_Disp_Mode } 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) @@ -160,6 +161,7 @@ enum eTegra2_Disp_Regs 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, @@ -337,6 +339,7 @@ const char * const csaTegra2Vid_RegisterNames[] = { "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", diff --git a/KernelLand/Modules/Filesystems/InitRD/Makefile b/KernelLand/Modules/Filesystems/InitRD/Makefile index 5aa0e653..5758f991 100644 --- a/KernelLand/Modules/Filesystems/InitRD/Makefile +++ b/KernelLand/Modules/Filesystems/InitRD/Makefile @@ -13,4 +13,8 @@ LDFLAGS += @files.$(ARCH).c.ldopts files.$(ARCH).c: GenerateInitRD.php files.lst ARCH=$(ARCH) ACESSDIR=$(ACESSDIR) php GenerateInitRD.php files.lst $@ $@.ldopts $@.dep +# Override default install method, because the floppy is small :) +install: + true + -include files.$(ARCH).c.dep diff --git a/KernelLand/Modules/Filesystems/InitRD/files.lst b/KernelLand/Modules/Filesystems/InitRD/files.lst index ccbbe0c3..5b17070d 100644 --- a/KernelLand/Modules/Filesystems/InitRD/files.lst +++ b/KernelLand/Modules/Filesystems/InitRD/files.lst @@ -13,6 +13,7 @@ Dir "Bin" { 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" { @@ -26,9 +27,10 @@ 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" { @@ -36,6 +38,7 @@ Dir "Apps" { 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" } } diff --git a/KernelLand/Modules/IPStack/udp.c b/KernelLand/Modules/IPStack/udp.c index 1d805692..ae3806b4 100644 --- a/KernelLand/Modules/IPStack/udp.c +++ b/KernelLand/Modules/IPStack/udp.c @@ -268,7 +268,7 @@ size_t UDP_Channel_Write(tVFS_Node *Node, off_t Offset, size_t Length, const voi UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, data, (size_t)Length - ofs); - return 0; + return Length; } /** diff --git a/KernelLand/Modules/Network/VIARhineII/rhine2.c b/KernelLand/Modules/Network/VIARhineII/rhine2.c index f9f4d254..9bdbafb6 100644 --- a/KernelLand/Modules/Network/VIARhineII/rhine2.c +++ b/KernelLand/Modules/Network/VIARhineII/rhine2.c @@ -80,11 +80,9 @@ int Rhine2_Install(char **Options) { 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) ); diff --git a/KernelLand/Modules/Storage/FDDv2/main.c b/KernelLand/Modules/Storage/FDDv2/main.c index f6290d90..90cff7f4 100644 --- a/KernelLand/Modules/Storage/FDDv2/main.c +++ b/KernelLand/Modules/Storage/FDDv2/main.c @@ -115,7 +115,7 @@ int FDD_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]) { if(Pos < 0 || Pos > MAX_DISKS ) return -ENOENT; - if(gaFDD_Disks[Pos].bValid) + if(!gaFDD_Disks[Pos].bValid) return 1; Dest[0] = '0' + Pos; diff --git a/KernelLand/Modules/USB/EHCI/ehci.c b/KernelLand/Modules/USB/EHCI/ehci.c index 2dd86108..a2acca2a 100644 --- a/KernelLand/Modules/USB/EHCI/ehci.c +++ b/KernelLand/Modules/USB/EHCI/ehci.c @@ -94,9 +94,32 @@ int EHCI_Initialise(char **Arguments) // 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; } @@ -137,7 +160,8 @@ int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum) } // 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 ); diff --git a/KernelLand/Modules/armv7/GIC/gic.c b/KernelLand/Modules/armv7/GIC/gic.c index 8dbab3a3..65441791 100644 --- a/KernelLand/Modules/armv7/GIC/gic.c +++ b/KernelLand/Modules/armv7/GIC/gic.c @@ -16,6 +16,8 @@ // === IMPORTS === extern void *gpIRQHandler; +extern tPAddr gGIC_DistributorAddr; +extern tPAddr gGIC_InterfaceAddr; // === TYPES === typedef void (*tIRQ_Handler)(int, void*); @@ -28,18 +30,12 @@ void GIC_IRQHandler(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); diff --git a/Makefile b/Makefile index 32f1ffb4..c2ef59ff 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,12 @@ SUBMAKE = $(MAKE) --no-print-directory 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)) diff --git a/Notes/3D.txt b/Notes/3D.txt new file mode 100644 index 00000000..a530e3cc --- /dev/null +++ b/Notes/3D.txt @@ -0,0 +1,8 @@ +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 + diff --git a/Tools/GCCProxy/gccproxy.sh b/Tools/GCCProxy/gccproxy.sh index a3183d34..477c4766 100755 --- a/Tools/GCCProxy/gccproxy.sh +++ b/Tools/GCCProxy/gccproxy.sh @@ -55,6 +55,16 @@ while [[ $# -gt 0 ]]; do -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" ;; @@ -63,7 +73,7 @@ while [[ $# -gt 0 ]]; do done run() { -# echo --- $* + #echo --- $* $* return $? } @@ -75,6 +85,11 @@ rm $cfgfile #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 @@ -84,8 +99,10 @@ elif [[ $_compile -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 diff --git a/Usermode/Applications/axwin3_src/Interface/main.c b/Usermode/Applications/axwin3_src/Interface/main.c index e8b58348..a0986147 100644 --- a/Usermode/Applications/axwin3_src/Interface/main.c +++ b/Usermode/Applications/axwin3_src/Interface/main.c @@ -111,14 +111,16 @@ void create_sidebar(void) 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) diff --git a/Usermode/Applications/axwin3_src/WM/Makefile b/Usermode/Applications/axwin3_src/WM/Makefile index 1d674507..1112ffea 100644 --- a/Usermode/Applications/axwin3_src/WM/Makefile +++ b/Usermode/Applications/axwin3_src/WM/Makefile @@ -7,7 +7,7 @@ CFLAGS += -std=gnu99 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 @@ -23,7 +23,7 @@ OBJ += renderers/widget/textinput.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 diff --git a/Usermode/Applications/axwin3_src/WM/include/utf8.h b/Usermode/Applications/axwin3_src/WM/include/utf8.h deleted file mode 100644 index 3ecaeb08..00000000 --- a/Usermode/Applications/axwin3_src/WM/include/utf8.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Acess2 GUI (AxWin) Version 3 - * - By John Hodge (thePowersGang) - * - * utf8.h - * - UTF-8 Parsing header - */ -#ifndef _UTF8_H_ -#define _UTF8_H_ - -#include - -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 - diff --git a/Usermode/Applications/axwin3_src/WM/ipc.c b/Usermode/Applications/axwin3_src/WM/ipc.c index 5b600ee8..7874335c 100644 --- a/Usermode/Applications/axwin3_src/WM/ipc.c +++ b/Usermode/Applications/axwin3_src/WM/ipc.c @@ -461,8 +461,8 @@ int IPC_Msg_FocusWindow(tIPC_Client *Client, tAxWin_IPCMessage *Msg) 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; diff --git a/Usermode/Applications/axwin3_src/WM/main.c b/Usermode/Applications/axwin3_src/WM/main.c index 7d2d3914..9db1c15c 100644 --- a/Usermode/Applications/axwin3_src/WM/main.c +++ b/Usermode/Applications/axwin3_src/WM/main.c @@ -66,10 +66,12 @@ int main(int argc, char *argv[]) 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 { @@ -83,7 +85,7 @@ int main(int argc, char *argv[]) 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); } } diff --git a/Usermode/Applications/axwin3_src/WM/renderers/framebuffer.c b/Usermode/Applications/axwin3_src/WM/renderers/framebuffer.c index fc838cb0..68a3f8cc 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/framebuffer.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/framebuffer.c @@ -16,7 +16,6 @@ typedef struct { short W, H; void *Data; - char _data[]; } tFBBuffer; typedef struct { @@ -162,7 +161,7 @@ int _Handle_CreateBuf(tWindow *Target, size_t Len, const void *Data) 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; diff --git a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c index 28be1aeb..c62dd7f5 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c @@ -224,6 +224,27 @@ void Renderer_RichText_Redraw(tWindow *Window) 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) @@ -241,6 +262,10 @@ int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void 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; @@ -298,7 +323,9 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi } line->ByteLength = Len - sizeof(*msg); memcpy(line->Data, msg->LineData, Len - sizeof(*msg)); - + + WM_Invalidate( Window ); + return 0; } @@ -312,6 +339,10 @@ int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const voi 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; } diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c index 6d34a8e3..fc7e1077 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/textinput.c @@ -10,7 +10,7 @@ #include #include "./common.h" #include "./colours.h" -#include +#include #include // TODO: Include a proper keysym header diff --git a/Usermode/Applications/axwin3_src/WM/utf-8.c b/Usermode/Applications/axwin3_src/WM/utf-8.c deleted file mode 100644 index 93e0318b..00000000 --- a/Usermode/Applications/axwin3_src/WM/utf-8.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Acess2 GUI (AxWin) Version 3 - * - By John Hodge (thePowersGang) - * - * utf-8.c - * - UTF-8 Parsing code - */ -#include -#include - -/** - * \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; -} - diff --git a/Usermode/Applications/axwin3_src/WM/video.c b/Usermode/Applications/axwin3_src/WM/video.c index 60f2155e..1b9ffaba 100644 --- a/Usermode/Applications/axwin3_src/WM/video.c +++ b/Usermode/Applications/axwin3_src/WM/video.c @@ -87,7 +87,7 @@ void Video_Update(void) _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"); diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index f9592db5..8886af19 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -173,6 +173,8 @@ void WM_FocusWindow(tWindow *Destination) { struct sWndMsg_Bool _msg; + _SysDebug("WM_FocusWindow(%p)", Destination); + if( gpWM_FocusedWindow == Destination ) return ; if( Destination && !(Destination->Flags & WINFLAG_SHOW) ) diff --git a/Usermode/Applications/axwin3_src/WM/wm_render_text.c b/Usermode/Applications/axwin3_src/WM/wm_render_text.c index 6ad72be6..8258531b 100644 --- a/Usermode/Applications/axwin3_src/WM/wm_render_text.c +++ b/Usermode/Applications/axwin3_src/WM/wm_render_text.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include // INT_MAX // === TYPES === diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c index fd1cf391..9fed5449 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c @@ -10,6 +10,7 @@ #include "include/internal.h" #include #include +#include //#include // === TYPES === @@ -23,6 +24,16 @@ typedef struct sRichText_Window // === 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; } diff --git a/Usermode/Applications/dhcpclient_src/main.c b/Usermode/Applications/dhcpclient_src/main.c index b9b28149..73e85d8e 100644 --- a/Usermode/Applications/dhcpclient_src/main.c +++ b/Usermode/Applications/dhcpclient_src/main.c @@ -528,7 +528,7 @@ void SetAddress(tInterface *Iface, void *Addr, void *Mask, void *Router) _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]); diff --git a/Usermode/Applications/gui_shell_src/Makefile b/Usermode/Applications/gui_shell_src/Makefile index 7ccfff46..a38f1355 100644 --- a/Usermode/Applications/gui_shell_src/Makefile +++ b/Usermode/Applications/gui_shell_src/Makefile @@ -2,9 +2,9 @@ -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 diff --git a/Usermode/Applications/gui_shell_src/display.c b/Usermode/Applications/gui_shell_src/display.c new file mode 100644 index 00000000..1665e448 --- /dev/null +++ b/Usermode/Applications/gui_shell_src/display.c @@ -0,0 +1,250 @@ +/* + * Acess GUI Terminal + * - By John Hodge (thePowersGang) + * + * display.c + * - Abstract display manipulation methods + */ +#include "include/display.h" +#include // _SysDebug +#include // exit +#include +#include +#include +#include +#include + +#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(); +} + diff --git a/Usermode/Applications/gui_shell_src/include/display.h b/Usermode/Applications/gui_shell_src/include/display.h index 80bc69ca..4feaf352 100644 --- a/Usermode/Applications/gui_shell_src/include/display.h +++ b/Usermode/Applications/gui_shell_src/include/display.h @@ -3,11 +3,15 @@ * - By John Hodge (thePowersGang) * * display.h - * - RichText Termianl Translation + * - RichText terminal translation */ #ifndef _DISPLAY_H_ #define _DISPLAY_H_ +#include + +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); @@ -16,6 +20,16 @@ extern void Display_ClearLine(int Dir); // 0: All, 1: Forward, -1: Reverse extern void Display_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse extern void Display_SetForeground(uint32_t RGB); extern void Display_SetBackground(uint32_t RGB); +/** + * \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 diff --git a/Usermode/Applications/gui_shell_src/main.c b/Usermode/Applications/gui_shell_src/main.c index c7aac852..4b82d0e0 100644 --- a/Usermode/Applications/gui_shell_src/main.c +++ b/Usermode/Applications/gui_shell_src/main.c @@ -8,14 +8,19 @@ #include #include #include +#include #include +#include #include "include/display.h" #include "include/vt100.h" +#include +#include // === 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; @@ -52,22 +57,30 @@ int main(int argc, char *argv[], const char **envp) // 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"); // - 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 @@ -81,9 +94,10 @@ int main(int argc, char *argv[], const char **envp) 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); @@ -101,35 +115,51 @@ int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translat #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; } @@ -153,8 +183,10 @@ void Term_HandleOutput(int Len, const char *Buf) 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(); } diff --git a/Usermode/Applications/gui_shell_src/vt100.c b/Usermode/Applications/gui_shell_src/vt100.c index 51c8016f..2a87ca4f 100644 --- a/Usermode/Applications/gui_shell_src/vt100.c +++ b/Usermode/Applications/gui_shell_src/vt100.c @@ -2,42 +2,86 @@ * Acess GUI Terminal * - By John Hodge (thePowersGang) * - * main.c - * - Core + * vt100.c + * - VT100/xterm Emulation */ #include +#include #include "include/vt100.h" #include "include/display.h" +#include // isalpha +#include // _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; @@ -52,3 +96,100 @@ int Term_HandleVT100(int Len, const char *Buf) } 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; +} diff --git a/Usermode/Applications/init_src/common.h b/Usermode/Applications/init_src/common.h new file mode 100644 index 00000000..406fe6fd --- /dev/null +++ b/Usermode/Applications/init_src/common.h @@ -0,0 +1,55 @@ +/* + * 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 + diff --git a/Usermode/Applications/init_src/main.c b/Usermode/Applications/init_src/main.c index 51b91942..a3d737d9 100644 --- a/Usermode/Applications/init_src/main.c +++ b/Usermode/Applications/init_src/main.c @@ -4,16 +4,37 @@ #include #include #include -//#include "common.h" +#include +#include "common.h" +#include // === 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 === /** @@ -22,33 +43,411 @@ */ 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 + // - 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 [78][NOE][012][bB] + 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 + // - 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 + // - 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); } diff --git a/Usermode/Applications/irc_src/main.c b/Usermode/Applications/irc_src/main.c index 9e5a0757..16eee395 100644 --- a/Usermode/Applications/irc_src/main.c +++ b/Usermode/Applications/irc_src/main.c @@ -78,7 +78,7 @@ char *gsNickname = "acess"; tServer *gpServers; tWindow gWindow_Status = { NULL, NULL, NULL, // No next, empty list, no server - 0, "" // No activity, empty name (rendered as status) + 0, {""} // No activity, empty name (rendered as status) }; tWindow *gpWindows = &gWindow_Status; tWindow *gpCurrentWindow = &gWindow_Status; diff --git a/Usermode/Applications/telnetd_src/main.c b/Usermode/Applications/telnetd_src/main.c index a4f5e0da..bf6de999 100644 --- a/Usermode/Applications/telnetd_src/main.c +++ b/Usermode/Applications/telnetd_src/main.c @@ -55,17 +55,17 @@ int main(int argc, char *argv[]) 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); diff --git a/Usermode/Filesystem/Conf/inittab b/Usermode/Filesystem/Conf/inittab new file mode 100644 index 00000000..a64bfc0c --- /dev/null +++ b/Usermode/Filesystem/Conf/inittab @@ -0,0 +1,8 @@ +exec /Acess/Bin/dhcpc + +ktty 0 /Acess/SBin/login +ktty 1 /Acess/SBin/login +stty serial/0 /Acess/SBin/login + + +#vim: ft=text diff --git a/Usermode/Filesystem/Makefile b/Usermode/Filesystem/Makefile index 7eb06940..a49d887d 100644 --- a/Usermode/Filesystem/Makefile +++ b/Usermode/Filesystem/Makefile @@ -5,7 +5,7 @@ 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)) diff --git a/Usermode/Libraries/ld-acess.so_src/Makefile b/Usermode/Libraries/ld-acess.so_src/Makefile index c77ff05b..5475fdc2 100644 --- a/Usermode/Libraries/ld-acess.so_src/Makefile +++ b/Usermode/Libraries/ld-acess.so_src/Makefile @@ -11,7 +11,8 @@ EXTRABIN := libld-acess.so 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 diff --git a/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h b/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h index 2c85b14e..351c8414 100644 --- a/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h +++ b/Usermode/Libraries/ld-acess.so_src/arch/armv7.S.h @@ -100,9 +100,23 @@ _errno: .long 0 @ Placed in .text, to allow use of relative addressing // 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: @@ -120,6 +134,7 @@ _clone_ret: pop {r4} mov pc, lr + .globl _exit _exit: svc #0 diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c index 13347a64..531b32d7 100644 --- a/Usermode/Libraries/ld-acess.so_src/elf.c +++ b/Usermode/Libraries/ld-acess.so_src/elf.c @@ -571,6 +571,47 @@ int Elf32GetSymbol(void *Base, const char *Name, void **ret, size_t *Size) } #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; @@ -711,45 +752,8 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename) } // 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 ) diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h index 8972cbe4..b2367d19 100644 --- a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h +++ b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h @@ -30,17 +30,20 @@ static inline void FD_ZERO(fd_set *fdsetp) 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 diff --git a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h index c7987027..d9d31735 100644 --- a/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h +++ b/Usermode/Libraries/ld-acess.so_src/include_exp/acess/sys.h @@ -33,6 +33,8 @@ #define GETMSG_IGNORE ((void*)-1) #define FILEFLAG_DIRECTORY 0x10 #define FILEFLAG_SYMLINK 0x20 +#define CLONE_VM 0x10 + // === TYPES === diff --git a/Usermode/Libraries/libc.so_src/scanf.c b/Usermode/Libraries/libc.so_src/scanf.c index 6a1d584f..3d45ed13 100644 --- a/Usermode/Libraries/libc.so_src/scanf.c +++ b/Usermode/Libraries/libc.so_src/scanf.c @@ -152,6 +152,8 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char // 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; @@ -161,6 +163,7 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char { while( (ich = __getc(h)) && isspace(ich) ) nch ++; + if(ich) __rewind(h); continue ; } @@ -262,22 +265,30 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char { // 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 @@ -304,13 +315,14 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char 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 @@ -329,6 +341,8 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char fch = *format++; } while( fch && fch != ']' ); + if( maxlen == 0 ) + maxlen = -1; ich = 0; while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) ) { @@ -337,6 +351,7 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char } if( maxlen >= 0 && ich ) __rewind(h); + if(ptr._char) *ptr._char++ = 0; valtype = _VCSCANF_NOTYPE; break; case 'p': // read back printf("%p") @@ -354,7 +369,10 @@ int _vcscanf(int (*__getc)(void*), void (*__rewind)(void*), void *h, const char valtype = _VCSCANF_NOTYPE; break; } - + + if(fail) + break; + switch(valtype) { case _VCSCANF_NOTYPE: @@ -406,7 +424,8 @@ int vsscanf(const char *str, const char *format, va_list ap) 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) { diff --git a/Usermode/Libraries/libc.so_src/stdio.c b/Usermode/Libraries/libc.so_src/stdio.c index 840e24d4..39d37a4b 100644 --- a/Usermode/Libraries/libc.so_src/stdio.c +++ b/Usermode/Libraries/libc.so_src/stdio.c @@ -348,6 +348,12 @@ EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp) } else { ret = _SysRead(fp->FD, ptr, size*num); + if( ret == (size_t)-1) + return -1; + if( ret == 0 && size*num > 0 ) { + fp->Flags |= FILE_FLAG_EOF; + return 0; + } ret /= size; } @@ -403,7 +409,7 @@ EXPORT int putchar(int c) EXPORT int fgetc(FILE *fp) { char ret = 0; - if( fread(&ret, 1, 1, fp) == (size_t)-1 ) + if( fread(&ret, 1, 1, fp) != 1 ) return -1; return ret; } @@ -452,7 +458,7 @@ EXPORT int vsprintf(char * __s, const char *__format, va_list __args) return vsnprintf(__s, 0x7FFFFFFF, __format, __args); } -//sprintfv + /** * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args) * \brief Prints a formatted string to a buffer @@ -470,11 +476,11 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg uint64_t arg; int bLongLong, bPadLeft; - void _addchar(char ch) - { - if(buf && pos < __maxlen) buf[pos] = ch; - pos ++; - } + #define _addchar(ch) do { \ + if(buf && pos < __maxlen) buf[pos] = (ch); \ + else (void)(ch); \ + pos ++; \ + } while(0) tmp[32] = '\0'; @@ -637,6 +643,7 @@ EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list arg } _addchar('\0'); pos --; + #undef _addchar //_SysDebug("vsnprintf: buf = '%s'", buf); @@ -708,7 +715,7 @@ EXPORT int printf(const char *format, ...) va_end(args); // Send to stdout - _SysWrite(_stdout, buf, size+1); + _SysWrite(_stdout, buf, size); // Free buffer free(buf); diff --git a/Usermode/Libraries/libposix.so_src/include_exp/sys/types.h b/Usermode/Libraries/libposix.so_src/include_exp/sys/types.h index db78b5a4..9b7aac0f 100644 --- a/Usermode/Libraries/libposix.so_src/include_exp/sys/types.h +++ b/Usermode/Libraries/libposix.so_src/include_exp/sys/types.h @@ -13,8 +13,6 @@ typedef unsigned int u_int; typedef struct stat t_fstat; -#define CLONE_VM 0x10 - typedef unsigned int id_t; typedef unsigned long pid_t; typedef unsigned long tid_t; diff --git a/Usermode/Libraries/libunicode.so_src/Makefile b/Usermode/Libraries/libunicode.so_src/Makefile new file mode 100644 index 00000000..d515f3d0 --- /dev/null +++ b/Usermode/Libraries/libunicode.so_src/Makefile @@ -0,0 +1,14 @@ +# 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 + diff --git a/Usermode/Libraries/libunicode.so_src/include_exp/unicode.h b/Usermode/Libraries/libunicode.so_src/include_exp/unicode.h new file mode 100644 index 00000000..ef0eb56e --- /dev/null +++ b/Usermode/Libraries/libunicode.so_src/include_exp/unicode.h @@ -0,0 +1,31 @@ +/* + * Acess2 "libunicode" UTF Parser + * - By John Hodge (thePowersGang) + * + * unicode.h + * - Main header + */ +#ifndef _LIBUNICODE__UNICODE_H_ +#define _LIBUNICODE__UNICODE_H_ + +#include + +/** + * \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 + diff --git a/Usermode/Libraries/libunicode.so_src/main.c b/Usermode/Libraries/libunicode.so_src/main.c new file mode 100644 index 00000000..e39dc9bb --- /dev/null +++ b/Usermode/Libraries/libunicode.so_src/main.c @@ -0,0 +1,12 @@ +/* + * Acess2 "libunicode" + * - By John Hoge + * + * main.c + * - Stub main + */ + +int SoMain(void) +{ + return 0; +} diff --git a/Usermode/Libraries/libunicode.so_src/utf-8.c b/Usermode/Libraries/libunicode.so_src/utf-8.c new file mode 100644 index 00000000..3aa9d1a8 --- /dev/null +++ b/Usermode/Libraries/libunicode.so_src/utf-8.c @@ -0,0 +1,153 @@ +/* + * Acess2 "libunicode" UTF Parser + * - By John Hodge (thePowersGang) + * + * utf-8.c + * - UTF-8 Parsing code + */ +#include +#include + +/** + * \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; +} +